diff --git a/.changeset/some-areas-fail.md b/.changeset/some-areas-fail.md new file mode 100644 index 000000000..bbcd706b1 --- /dev/null +++ b/.changeset/some-areas-fail.md @@ -0,0 +1,5 @@ +--- +"@sei-js/mcp-server": patch +--- + +Disable wallet based tools by default, add ability to add more wallet providers diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 1dc5c5d58..79122477a 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/packages/mcp-server/.env.example b/packages/mcp-server/.env.example index be62ae84c..8ced7e400 100644 --- a/packages/mcp-server/.env.example +++ b/packages/mcp-server/.env.example @@ -1,6 +1,15 @@ # Sei MCP Server Environment Variables +# Wallet Configuration +# Wallet mode: private-key | dynamic | porto | disabled +# - disabled: Disable all wallet functionality (default - safest for production) +# - private-key: Use PRIVATE_KEY environment variable +WALLET_MODE=disabled + # Private key for blockchain transactions (without 0x prefix) -# This is used when no private key is provided in the request +# Used when WALLET_MODE=private-key # SECURITY: Never commit your actual private key to version control PRIVATE_KEY=your_private_key_here + +# Wallet API Key (future use with wallet providers) +# WALLET_API_KEY=your_wallet_api_key_here diff --git a/packages/mcp-server/bin/cli.js b/packages/mcp-server/bin/cli.js index f52db9cb7..7670a8842 100755 --- a/packages/mcp-server/bin/cli.js +++ b/packages/mcp-server/bin/cli.js @@ -13,6 +13,24 @@ const require = createRequire(import.meta.url); const args = process.argv.slice(2); const httpMode = args.includes('--http') || args.includes('-h'); +// Parse wallet mode argument +let walletMode = null; +const walletModeIndex = args.findIndex(arg => arg === '--wallet-mode'); +if (walletModeIndex !== -1 && walletModeIndex + 1 < args.length) { + walletMode = args[walletModeIndex + 1]; +} + +// Set environment variables based on CLI arguments +if (walletMode) { + const validModes = ['private-key', 'disabled']; + if (validModes.includes(walletMode)) { + process.env.WALLET_MODE = walletMode; + } else { + console.error(`Invalid wallet mode: ${walletMode}. Valid modes are: ${validModes.join(', ')}`); + process.exit(1); + } +} + // Determine which file to execute const scriptPath = resolve(__dirname, '../dist/esm', httpMode ? '/server/http-server.js' : 'index.js'); @@ -45,6 +63,10 @@ try { } catch (error) { console.error('Error: Server files not found. The package may not be built correctly.'); console.error('Please try reinstalling the package or contact the maintainers.'); + console.error('\nUsage:'); + console.error(' mcp-server # Start in STDIO mode (default)'); + console.error(' mcp-server --http # Start in HTTP mode'); + console.error(' mcp-server --wallet-mode MODE # Set wallet mode (private-key|dynamic|porto|disabled)'); console.error(error); process.exit(1); } \ No newline at end of file diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index b7e3a38eb..035793524 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -28,6 +28,8 @@ "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.21.2", + "jest": "^30.0.3", + "tsx": "^4.20.3", "viem": "^2.30.5", "zod": "^3.24.2" }, diff --git a/packages/mcp-server/src/core/config.ts b/packages/mcp-server/src/core/config.ts index 31d6dc268..b4ce21e6f 100644 --- a/packages/mcp-server/src/core/config.ts +++ b/packages/mcp-server/src/core/config.ts @@ -5,9 +5,14 @@ import type { Hex } from 'viem'; // Load environment variables from .env file dotenv.config(); +// Wallet mode types +export type WalletMode = 'private-key' | 'disabled'; + // Define environment variable schema const envSchema = z.object({ - PRIVATE_KEY: z.string().optional() + PRIVATE_KEY: z.string().optional(), + WALLET_MODE: z.enum(['private-key', 'disabled']).default('disabled'), + WALLET_API_KEY: z.string().optional() // Used for wallet providers }); // Parse and validate environment variables @@ -23,7 +28,9 @@ export const formatPrivateKey = (key?: string): string | undefined => { // Export validated environment variables with formatted private key export const config = { - privateKey: env.success ? formatPrivateKey(env.data.PRIVATE_KEY) : undefined + privateKey: env.success ? formatPrivateKey(env.data.PRIVATE_KEY) : undefined, + walletMode: (env.success ? env.data.WALLET_MODE : 'disabled') as WalletMode, + walletApiKey: env.success ? env.data.WALLET_API_KEY : undefined }; /** @@ -34,3 +41,19 @@ export const config = { export function getPrivateKeyAsHex(): Hex | undefined { return config.privateKey as Hex | undefined; } + +/** + * Check if wallet functionality is enabled based on configuration + * @returns True if wallet functionality should be available + */ +export function isWalletEnabled(): boolean { + return config.walletMode !== 'disabled'; +} + +/** + * Get the current wallet mode + * @returns The configured wallet mode + */ +export function getWalletMode(): WalletMode { + return config.walletMode; +} diff --git a/packages/mcp-server/src/core/prompts.ts b/packages/mcp-server/src/core/prompts.ts index 009fc9eb3..d509c9e60 100644 --- a/packages/mcp-server/src/core/prompts.ts +++ b/packages/mcp-server/src/core/prompts.ts @@ -1,12 +1,29 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import { DEFAULT_NETWORK } from './chains.js'; +import { isWalletEnabled } from './config.js'; /** * Register all EVM-related prompts with the MCP server * @param server The MCP server instance */ export function registerEVMPrompts(server: McpServer) { + // Register read-only prompts (always available) + registerReadOnlyPrompts(server); + + // Register wallet-dependent prompts (only if wallet is enabled) + if (isWalletEnabled()) { + registerWalletPrompts(server); + } else { + console.error('Wallet functionality is disabled. Wallet-dependent prompts will not be available.'); + } +} + +/** + * Register read-only prompts that don't require wallet functionality + * @param server The MCP server instance + */ +function registerReadOnlyPrompts(server: McpServer) { // Basic block explorer prompt server.prompt( 'explore_block', @@ -57,18 +74,7 @@ export function registerEVMPrompts(server: McpServer) { }) ); - // Get wallet address from private key prompt - server.prompt('my_wallet_address', 'What is my wallet EVM address', {}, () => ({ - messages: [ - { - role: 'user', - content: { - type: 'text', - text: 'Please retrieve my wallet EVM address using tools get_address_from_private_key via MCP server.' - } - } - ] - })); + // Address analysis prompt server.prompt( @@ -199,3 +205,67 @@ export function registerEVMPrompts(server: McpServer) { } ); } + +/** + * Register wallet-dependent prompts that require wallet functionality + * @param server The MCP server instance + */ +function registerWalletPrompts(server: McpServer) { + // Get wallet address from private key prompt + server.prompt('my_wallet_address', 'What is my wallet EVM address', {}, () => ({ + messages: [ + { + role: 'user', + content: { + type: 'text', + text: 'Please retrieve my wallet EVM address using tools get_address_from_private_key via MCP server.' + } + } + ] + })); + + // Send transaction prompt + server.prompt( + 'send_transaction_guidance', + 'Get guidance on sending a transaction', + { + toAddress: z.string().describe('The recipient address'), + amount: z.string().describe('The amount to send (in SEI)'), + network: z.string().optional().describe('Network name or chain ID. Defaults to Sei mainnet.') + }, + ({ toAddress, amount, network = DEFAULT_NETWORK }) => ({ + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `I want to send ${amount} SEI to ${toAddress} on the ${network} network. Please guide me through this process, including checking my balance first, estimating gas, and executing the transaction safely.` + } + } + ] + }) + ); + + // Token transfer guidance + server.prompt( + 'token_transfer_guidance', + 'Get guidance on transferring tokens', + { + tokenAddress: z.string().describe('The token contract address'), + toAddress: z.string().describe('The recipient address'), + amount: z.string().describe('The amount to transfer'), + network: z.string().optional().describe('Network name or chain ID. Defaults to Sei mainnet.') + }, + ({ tokenAddress, toAddress, amount, network = DEFAULT_NETWORK }) => ({ + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `I want to transfer ${amount} tokens from contract ${tokenAddress} to ${toAddress} on the ${network} network. Please guide me through this process, including checking my balance first, approving the token if needed, and executing the transfer safely.` + } + } + ] + }) + ); +} diff --git a/packages/mcp-server/src/core/services/clients.ts b/packages/mcp-server/src/core/services/clients.ts index aff5963d3..609585394 100644 --- a/packages/mcp-server/src/core/services/clients.ts +++ b/packages/mcp-server/src/core/services/clients.ts @@ -1,6 +1,7 @@ import { http, type Address, type Hex, type PublicClient, type WalletClient, createPublicClient, createWalletClient } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; import { DEFAULT_NETWORK, getChain, getRpcUrl } from '../chains.js'; +import { getWalletProvider } from '../wallet/index.js'; // Cache for clients to avoid recreating them for each request const clientCache = new Map(); @@ -37,26 +38,17 @@ export function getPublicClient(network = DEFAULT_NETWORK): PublicClient { } /** - * Create a wallet client for a specific network and private key + * Get a wallet client using the configured wallet provider */ -export function getWalletClient(privateKey: Hex, network = DEFAULT_NETWORK): WalletClient { - const chain = getChain(network); - const rpcUrl = getRpcUrl(network); - const account = privateKeyToAccount(privateKey); - - return createWalletClient({ - account, - chain, - transport: http(rpcUrl) - }); +export async function getWalletClientFromProvider(network = DEFAULT_NETWORK): Promise { + const walletProvider = getWalletProvider(); + return walletProvider.getWalletClient(network); } /** - * Get an EVM address from a private key - * @param privateKey The private key in hex format (with or without 0x prefix) - * @returns The EVM address derived from the private key + * Get an EVM address from the configured wallet provider */ -export function getAddressFromPrivateKey(privateKey: Hex): Address { - const account = privateKeyToAccount(privateKey); - return account.address; +export async function getAddressFromProvider(): Promise
{ + const walletProvider = getWalletProvider(); + return walletProvider.getAddress(); } diff --git a/packages/mcp-server/src/core/services/contracts.ts b/packages/mcp-server/src/core/services/contracts.ts index c22c4e669..85130a002 100644 --- a/packages/mcp-server/src/core/services/contracts.ts +++ b/packages/mcp-server/src/core/services/contracts.ts @@ -1,7 +1,7 @@ import type { GetLogsParameters, Hash, Hex, Log, ReadContractParameters, WriteContractParameters } from 'viem'; import { DEFAULT_NETWORK } from '../chains.js'; import { getPrivateKeyAsHex } from '../config.js'; -import { getPublicClient, getWalletClient } from './clients.js'; +import { getPublicClient, getWalletClientFromProvider } from './clients.js'; import * as services from './index.js'; /** @@ -27,7 +27,7 @@ export async function writeContract(params: Record, network = DEFAU throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); } - const client = getWalletClient(key, network); + const client = await getWalletClientFromProvider(network); return await client.writeContract(params as any); } @@ -75,7 +75,7 @@ export async function deployContract( throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); } - const client = getWalletClient(key, network); + const client = await getWalletClientFromProvider(network); if (!client.account) { throw new Error('Wallet client account not available for contract deployment.'); diff --git a/packages/mcp-server/src/core/services/transfer.ts b/packages/mcp-server/src/core/services/transfer.ts index 792c360ae..6675bc4a8 100644 --- a/packages/mcp-server/src/core/services/transfer.ts +++ b/packages/mcp-server/src/core/services/transfer.ts @@ -1,7 +1,6 @@ -import { type Address, type Hash, type Hex, getContract, parseEther, parseUnits } from 'viem'; +import { type Address, type Hash, getContract, parseEther, parseUnits } from 'viem'; import { DEFAULT_NETWORK } from '../chains.js'; -import { getPrivateKeyAsHex } from '../config.js'; -import { getPublicClient, getWalletClient } from './clients.js'; +import { getPublicClient, getWalletClientFromProvider } from './clients.js'; import * as services from './index.js'; // Standard ERC20 ABI for transfers @@ -119,14 +118,8 @@ export async function transferSei( network = DEFAULT_NETWORK ): Promise { const validatedToAddress = services.helpers.validateAddress(toAddress); - // Get private key from environment - const privateKey = getPrivateKeyAsHex(); - - if (!privateKey) { - throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); - } - - const client = getWalletClient(privateKey, network); + // Get wallet client from provider + const client = await getWalletClientFromProvider(network); const amountWei = parseEther(amount); // Ensure account exists before using it @@ -169,12 +162,8 @@ export async function transferERC20( }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); - // Get private key from environment - const privateKey = getPrivateKeyAsHex(); - - if (!privateKey) { - throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); - } + // Get wallet client from provider + const walletClient = await getWalletClientFromProvider(network); const publicClient = getPublicClient(network); @@ -192,9 +181,6 @@ export async function transferERC20( // Parse the amount with the correct number of decimals const rawAmount = parseUnits(amount, decimals); - // Create wallet client for sending the transaction - const walletClient = getWalletClient(privateKey, network); - // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); @@ -250,13 +236,8 @@ export async function approveERC20( }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedSpenderAddress = services.helpers.validateAddress(spenderAddress); - - // Get private key from environment - const privateKey = getPrivateKeyAsHex(); - - if (!privateKey) { - throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); - } + // Get wallet client from provider + const walletClient = await getWalletClientFromProvider(network); const publicClient = getPublicClient(network); const contract = getContract({ @@ -272,9 +253,6 @@ export async function approveERC20( // Parse the amount with the correct number of decimals const rawAmount = parseUnits(amount, decimals); - // Create wallet client for sending the transaction - const walletClient = getWalletClient(privateKey, network); - // Ensure account exists before using it if (!walletClient.account) { throw new Error('Wallet account not initialized properly'); @@ -327,15 +305,9 @@ export async function transferERC721( }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); - // Get private key from environment - const privateKey = getPrivateKeyAsHex(); - - if (!privateKey) { - throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); - } - // Create wallet client for sending the transaction - const walletClient = getWalletClient(privateKey, network); + // Get wallet client from provider + const walletClient = await getWalletClientFromProvider(network); // Ensure account exists before using it if (!walletClient.account) { @@ -405,15 +377,8 @@ export async function transferERC1155( }> { const validatedTokenAddress = services.helpers.validateAddress(tokenAddress); const validatedToAddress = services.helpers.validateAddress(toAddress); - // Get private key from environment - const privateKey = getPrivateKeyAsHex(); - - if (!privateKey) { - throw new Error('Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.'); - } - - // Create wallet client for sending the transaction - const walletClient = getWalletClient(privateKey, network); + // Get wallet client from provider + const walletClient = await getWalletClientFromProvider(network); // Ensure account exists before using it if (!walletClient.account) { diff --git a/packages/mcp-server/src/core/tools.ts b/packages/mcp-server/src/core/tools.ts index f8a7c3230..8dd5b56c2 100644 --- a/packages/mcp-server/src/core/tools.ts +++ b/packages/mcp-server/src/core/tools.ts @@ -1,8 +1,9 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import type { Abi, Address, Chain, Hash, Hex, WriteContractParameters } from 'viem'; +import type { Address, Hash, Hex } from 'viem'; import { z } from 'zod'; import { DEFAULT_NETWORK, getRpcUrl, getSupportedNetworks } from './chains.js'; -import { getPrivateKeyAsHex } from './config.js'; +import { isWalletEnabled } from './config.js'; +import { getWalletProvider } from './wallet/index.js'; import * as services from './services/index.js'; /** @@ -11,6 +12,21 @@ import * as services from './services/index.js'; * @param server The MCP server instance */ export function registerEVMTools(server: McpServer) { + // Register read-only tools (always available) + registerReadOnlyTools(server); + + // Register wallet-dependent tools (only if wallet is enabled) + if (isWalletEnabled()) { + registerWalletTools(server); + } else { + console.error('Wallet functionality is disabled. Wallet-dependent tools will not be available.'); + } +} + +/** + * Register read-only tools that don't require wallet functionality + */ +function registerReadOnlyTools(server: McpServer) { // NETWORK INFORMATION TOOLS // Get chain information @@ -429,7 +445,12 @@ export function registerEVMTools(server: McpServer) { } } ); +} +/** + * Register wallet-dependent tools that require wallet functionality + */ +function registerWalletTools(server: McpServer) { // TRANSFER TOOLS // Transfer Sei @@ -797,7 +818,7 @@ export function registerEVMTools(server: McpServer) { // Parse ABI if it's a string const parsedAbi = typeof abi === 'string' ? JSON.parse(abi) : abi; - const contractParams: Record = { + const contractParams: Record = { address: contractAddress as Address, abi: parsedAbi, functionName, @@ -843,7 +864,12 @@ export function registerEVMTools(server: McpServer) { { bytecode: z.string().describe("The compiled contract bytecode as a hex string (e.g., '0x608060405234801561001057600080fd5b50...')"), abi: z.array(z.any()).describe('The contract ABI (Application Binary Interface) as a JSON array, needed for constructor function'), - args: z.array(z.any()).optional().describe("The constructor arguments to pass during deployment, as an array (e.g., ['param1', 'param2']). Leave empty if constructor has no parameters."), + args: z + .array(z.any()) + .optional() + .describe( + "The constructor arguments to pass during deployment, as an array (e.g., ['param1', 'param2']). Leave empty if constructor has no parameters." + ), network: z.string().optional().describe("Network name (e.g., 'sei', 'sei-testnet', 'sei-devnet') or chain ID. Defaults to Sei mainnet.") }, async ({ bytecode, abi, args = [], network = DEFAULT_NETWORK }) => { @@ -852,7 +878,7 @@ export function registerEVMTools(server: McpServer) { const parsedAbi = typeof abi === 'string' ? JSON.parse(abi) : abi; // Ensure bytecode is a proper hex string - const formattedBytecode = bytecode.startsWith('0x') ? bytecode as Hex : `0x${bytecode}` as Hex; + const formattedBytecode = bytecode.startsWith('0x') ? (bytecode as Hex) : (`0x${bytecode}` as Hex); const result = await services.deployContract(formattedBytecode, parsedAbi, args, network); @@ -1294,20 +1320,20 @@ export function registerEVMTools(server: McpServer) { async () => { // Handler function starts here try { - const privateKeyValue = getPrivateKeyAsHex(); - if (!privateKeyValue) { + const walletProvider = getWalletProvider(); + if (!walletProvider.isAvailable()) { return { content: [ { type: 'text', - text: 'Error: The PRIVATE_KEY environment variable is not set. Please set this variable with your private key and restart the MCP server for this tool to function.' + text: `Error: Wallet provider '${walletProvider.getName()}' is not available. Please configure the wallet provider and restart the MCP server.` } ], isError: true }; } - const address = services.getAddressFromPrivateKey(privateKeyValue); + const address = await services.getAddressFromProvider(); return { content: [ diff --git a/packages/mcp-server/src/core/wallet/index.ts b/packages/mcp-server/src/core/wallet/index.ts new file mode 100644 index 000000000..c0a278e45 --- /dev/null +++ b/packages/mcp-server/src/core/wallet/index.ts @@ -0,0 +1,43 @@ +import { getWalletMode } from '../config.js'; +import { DisabledWalletProvider } from './providers/disabled.js'; +import { PrivateKeyWalletProvider } from './providers/private-key.js'; +import type { WalletProvider } from './types.js'; + +// Cache wallet provider instance +let walletProviderInstance: WalletProvider | null = null; + +/** + * Get the wallet provider instance based on configuration + */ +export function getWalletProvider(): WalletProvider { + if (walletProviderInstance) { + return walletProviderInstance; + } + + const mode = getWalletMode(); + + switch (mode) { + case 'private-key': + walletProviderInstance = new PrivateKeyWalletProvider(); + break; + case 'disabled': + walletProviderInstance = new DisabledWalletProvider(); + break; + default: + throw new Error(`Unknown wallet mode: ${mode}`); + } + + return walletProviderInstance; +} + +/** + * Reset the wallet provider instance (useful for testing) + */ +export function resetWalletProvider(): void { + walletProviderInstance = null; +} + +// Export types and classes +export * from './types.js'; +export { PrivateKeyWalletProvider } from './providers/private-key.js'; +export { DisabledWalletProvider } from './providers/disabled.js'; diff --git a/packages/mcp-server/src/core/wallet/providers/disabled.ts b/packages/mcp-server/src/core/wallet/providers/disabled.ts new file mode 100644 index 000000000..cd6e2838b --- /dev/null +++ b/packages/mcp-server/src/core/wallet/providers/disabled.ts @@ -0,0 +1,41 @@ +import type { Address, Hash, WalletClient } from 'viem'; +import type { TransactionRequest, WalletProvider } from '../types.js'; +import { WalletProviderError } from '../types.js'; + +/** + * Disabled Wallet Provider + * Throws errors for all wallet operations when wallet functionality is disabled + */ +export class DisabledWalletProvider implements WalletProvider { + isAvailable(): boolean { + return false; + } + + async getAddress(): Promise
{ + throw new WalletProviderError( + 'Wallet functionality is disabled. Enable wallet functionality to use this feature.', + 'disabled', + 'WALLET_DISABLED' + ); + } + + async signTransaction(tx: TransactionRequest): Promise { + throw new WalletProviderError( + 'Wallet functionality is disabled. Enable wallet functionality to sign transactions.', + 'disabled', + 'WALLET_DISABLED' + ); + } + + async getWalletClient(network: string): Promise { + throw new WalletProviderError( + 'Wallet functionality is disabled. Enable wallet functionality to create wallet clients.', + 'disabled', + 'WALLET_DISABLED' + ); + } + + getName(): string { + return 'disabled'; + } +} diff --git a/packages/mcp-server/src/core/wallet/providers/private-key.ts b/packages/mcp-server/src/core/wallet/providers/private-key.ts new file mode 100644 index 000000000..24ba8d232 --- /dev/null +++ b/packages/mcp-server/src/core/wallet/providers/private-key.ts @@ -0,0 +1,77 @@ +import type { Address, Hash, WalletClient } from 'viem'; +import { createWalletClient, http } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { getChain, getRpcUrl } from '../../chains.js'; +import { getPrivateKeyAsHex } from '../../config.js'; +import type { TransactionRequest, WalletProvider } from '../types.js'; +import { WalletProviderError } from '../types.js'; + +/** + * Private Key Wallet Provider + * Uses a private key from environment variables + */ +export class PrivateKeyWalletProvider implements WalletProvider { + private privateKey: string | undefined; + + constructor() { + this.privateKey = getPrivateKeyAsHex(); + } + + isAvailable(): boolean { + return this.privateKey !== undefined; + } + + async getAddress(): Promise
{ + if (!this.privateKey) { + throw new WalletProviderError( + 'Private key not configured. Set PRIVATE_KEY environment variable.', + 'private-key', + 'MISSING_PRIVATE_KEY' + ); + } + + const account = privateKeyToAccount(this.privateKey as `0x${string}`); + return account.address; + } + + async signTransaction(tx: TransactionRequest): Promise { + if (!this.privateKey) { + throw new WalletProviderError( + 'Private key not configured. Cannot sign transaction.', + 'private-key', + 'MISSING_PRIVATE_KEY' + ); + } + + // For now, return a placeholder - full implementation would involve actual signing + throw new WalletProviderError( + 'Direct transaction signing not implemented for private key provider.', + 'private-key', + 'NOT_IMPLEMENTED' + ); + } + + async getWalletClient(network: string): Promise { + if (!this.privateKey) { + throw new WalletProviderError( + 'Private key not configured. Cannot create wallet client.', + 'private-key', + 'MISSING_PRIVATE_KEY' + ); + } + + const chain = getChain(network); + const rpcUrl = getRpcUrl(network); + const account = privateKeyToAccount(this.privateKey as `0x${string}`); + + return createWalletClient({ + account, + chain, + transport: http(rpcUrl) + }); + } + + getName(): string { + return 'private-key'; + } +} diff --git a/packages/mcp-server/src/core/wallet/types.ts b/packages/mcp-server/src/core/wallet/types.ts new file mode 100644 index 000000000..f895fda2b --- /dev/null +++ b/packages/mcp-server/src/core/wallet/types.ts @@ -0,0 +1,60 @@ +import type { Address, Hash, Hex, WalletClient } from 'viem'; + +/** + * Transaction request interface for wallet providers + */ +export interface TransactionRequest { + to?: Address; + value?: bigint; + data?: Hex; + gas?: bigint; + gasPrice?: bigint; + maxFeePerGas?: bigint; + maxPriorityFeePerGas?: bigint; + nonce?: number; +} + +/** + * Abstract wallet provider interface + * Allows different wallet implementations to be used interchangeably + */ +export interface WalletProvider { + /** + * Check if this wallet provider is available and configured + */ + isAvailable(): boolean; + + /** + * Get the wallet address + */ + getAddress(): Promise
; + + /** + * Sign a transaction + */ + signTransaction(tx: TransactionRequest): Promise; + + /** + * Get a wallet client for the specified network + */ + getWalletClient(network: string): Promise; + + /** + * Get the wallet provider name + */ + getName(): string; +} + +/** + * Wallet provider error class + */ +export class WalletProviderError extends Error { + constructor( + message: string, + public readonly provider: string, + public readonly code?: string + ) { + super(message); + this.name = 'WalletProviderError'; + } +} diff --git a/packages/mcp-server/src/tests/core/config.test.ts b/packages/mcp-server/src/tests/core/config.test.ts index c68288220..599a0374f 100644 --- a/packages/mcp-server/src/tests/core/config.test.ts +++ b/packages/mcp-server/src/tests/core/config.test.ts @@ -101,4 +101,63 @@ describe('Config Module - Actual Implementation', () => { expect(getPrivateKeyAsHex()).toBe('0xabcdef1234567890'); }); }); + + describe('isWalletEnabled', () => { + test('should return true when wallet mode is private-key', () => { + // Set environment variable for private-key mode + process.env.WALLET_MODE = 'private-key'; + + // Force re-evaluation of config module + jest.resetModules(); + const { isWalletEnabled } = require('../../core/config.js'); + + expect(isWalletEnabled()).toBe(true); + }); + + test('should return false when wallet mode is disabled', () => { + // Set environment variable for disabled mode + process.env.WALLET_MODE = 'disabled'; + + // Force re-evaluation of config module + jest.resetModules(); + const { isWalletEnabled } = require('../../core/config.js'); + + expect(isWalletEnabled()).toBe(false); + }); + + test('should return false when wallet mode is not set (defaults to disabled)', () => { + // Remove wallet mode env var to test default + delete process.env.WALLET_MODE; + + // Force re-evaluation of config module + jest.resetModules(); + const { isWalletEnabled } = require('../../core/config.js'); + + expect(isWalletEnabled()).toBe(false); + }); + }); + + describe('getWalletMode', () => { + test('should return the configured wallet mode', () => { + // Set environment variable + process.env.WALLET_MODE = 'private-key'; + + // Force re-evaluation of config module + jest.resetModules(); + const { getWalletMode } = require('../../core/config.js'); + + expect(getWalletMode()).toBe('private-key'); + }); + + test('should return disabled as default when not set', () => { + // Remove wallet mode env var to test default + delete process.env.WALLET_MODE; + + // Force re-evaluation of config module + jest.resetModules(); + const { getWalletMode } = require('../../core/config.js'); + + expect(getWalletMode()).toBe('disabled'); + }); + }); }); diff --git a/packages/mcp-server/src/tests/core/helpers/tool-test-helpers.ts b/packages/mcp-server/src/tests/core/helpers/tool-test-helpers.ts index d954138a3..3c5a03943 100644 --- a/packages/mcp-server/src/tests/core/helpers/tool-test-helpers.ts +++ b/packages/mcp-server/src/tests/core/helpers/tool-test-helpers.ts @@ -6,7 +6,7 @@ import type { Address, Hash } from 'viem'; type ToolSchema = Record; type ToolHandler = (params: Record) => Promise; -interface Tool { +export interface Tool { name: string; description: string; schema: ToolSchema; diff --git a/packages/mcp-server/src/tests/core/services/clients.test.ts b/packages/mcp-server/src/tests/core/services/clients.test.ts index 822f2ed62..fe3d05100 100644 --- a/packages/mcp-server/src/tests/core/services/clients.test.ts +++ b/packages/mcp-server/src/tests/core/services/clients.test.ts @@ -1,8 +1,9 @@ import { describe, test, expect, jest, beforeEach, afterEach } from '@jest/globals'; -import { getPublicClient, getWalletClient, getAddressFromPrivateKey } from '../../../core/services/clients.js'; +import { getPublicClient, getAddressFromPrivateKey, getWalletClientFromProvider, getAddressFromProvider } from '../../../core/services/clients.js'; import { createPublicClient, createWalletClient, http } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; import { getChain, getRpcUrl } from '../../../core/chains.js'; +import { getWalletProvider } from '../../../core/wallet/index.js'; // Mock dependencies jest.mock('viem', () => { @@ -25,6 +26,10 @@ jest.mock('../../../core/chains.js', () => ({ getRpcUrl: jest.fn() })); +jest.mock('../../../core/wallet/index.js', () => ({ + getWalletProvider: jest.fn() +})); + describe('Client Service', () => { const mockChain = { id: 1, name: 'Sei' }; const mockRpcUrl = 'https://rpc.sei.io'; @@ -139,36 +144,50 @@ describe('Client Service', () => { }); }); - describe('getWalletClient', () => { - test('should create and return a wallet client', () => { - const client = getWalletClient(mockPrivateKey, 'sei'); + describe('getWalletClientFromProvider', () => { + const mockWalletProvider = { + getWalletClient: jest.fn() + }; + + beforeEach(() => { + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); + mockWalletProvider.getWalletClient.mockResolvedValue(mockWalletClient); + }); + + test('should get wallet client from provider with default network', async () => { + const client = await getWalletClientFromProvider(); - expect(getChain).toHaveBeenCalledWith('sei'); - expect(getRpcUrl).toHaveBeenCalledWith('sei'); - expect(privateKeyToAccount).toHaveBeenCalledWith(mockPrivateKey); - expect(http).toHaveBeenCalledWith(mockRpcUrl); - expect(createWalletClient).toHaveBeenCalledWith({ - account: mockAccount, - chain: mockChain, - transport: mockHttpTransport - }); + expect(getWalletProvider).toHaveBeenCalled(); + expect(mockWalletProvider.getWalletClient).toHaveBeenCalledWith('sei'); expect(client).toBe(mockWalletClient); }); - test('should use default network when none is specified', () => { - getWalletClient(mockPrivateKey); + test('should get wallet client from provider with specified network', async () => { + const client = await getWalletClientFromProvider('sei-testnet'); - expect(getChain).toHaveBeenCalledWith('sei'); - expect(getRpcUrl).toHaveBeenCalledWith('sei'); + expect(getWalletProvider).toHaveBeenCalled(); + expect(mockWalletProvider.getWalletClient).toHaveBeenCalledWith('sei-testnet'); + expect(client).toBe(mockWalletClient); }); }); - describe('getAddressFromPrivateKey', () => { - test('should return the address derived from the private key', () => { - const address = getAddressFromPrivateKey(mockPrivateKey); + describe('getAddressFromProvider', () => { + const mockWalletProvider = { + getAddress: jest.fn() + }; + const mockAddress = '0x1234567890123456789012345678901234567890'; + + beforeEach(() => { + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); + mockWalletProvider.getAddress.mockResolvedValue(mockAddress); + }); + + test('should get address from provider', async () => { + const address = await getAddressFromProvider(); - expect(privateKeyToAccount).toHaveBeenCalledWith(mockPrivateKey); - expect(address).toBe(mockAccount.address); + expect(getWalletProvider).toHaveBeenCalled(); + expect(mockWalletProvider.getAddress).toHaveBeenCalled(); + expect(address).toBe(mockAddress); }); }); }); diff --git a/packages/mcp-server/src/tests/core/services/contracts.test.ts b/packages/mcp-server/src/tests/core/services/contracts.test.ts index 9a1635c90..627c2fa2b 100644 --- a/packages/mcp-server/src/tests/core/services/contracts.test.ts +++ b/packages/mcp-server/src/tests/core/services/contracts.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect, jest, beforeEach } from '@jest/globals'; import { readContract, writeContract, getLogs, isContract, deployContract } from '../../../core/services/contracts.js'; -import { getPublicClient, getWalletClient } from '../../../core/services/clients.js'; +import { getPublicClient, getWalletClientFromProvider } from '../../../core/services/clients.js'; import { getPrivateKeyAsHex } from '../../../core/config.js'; import type { Hash, Abi, Address, GetLogsParameters, ReadContractParameters, WriteContractParameters } from 'viem'; import * as services from '../../../core/services'; @@ -40,7 +40,7 @@ describe('Contract Service', () => { // Setup default mock implementations (getPublicClient as jest.Mock).mockReturnValue(mockPublicClient); - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClient); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClient)); (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); // Use mockImplementation instead of mockResolvedValue to properly type the return values @@ -83,7 +83,7 @@ describe('Contract Service', () => { const result = await writeContract(params, 'sei'); expect(getPrivateKeyAsHex).toHaveBeenCalled(); - expect(getWalletClient).toHaveBeenCalledWith(mockPrivateKey, 'sei'); + expect(getWalletClientFromProvider).toHaveBeenCalledWith('sei'); expect(mockWalletClient.writeContract).toHaveBeenCalledWith(params); expect(result).toBe(mockHash); }); @@ -99,7 +99,7 @@ describe('Contract Service', () => { } as unknown as WriteContractParameters; await expect(writeContract(params, 'sei')).rejects.toThrow('Private key not available'); - expect(getWalletClient).not.toHaveBeenCalled(); + expect(getWalletClientFromProvider).not.toHaveBeenCalled(); }); test('should use default network when none is specified', async () => { @@ -113,7 +113,7 @@ describe('Contract Service', () => { await writeContract(params); - expect(getWalletClient).toHaveBeenCalledWith(mockPrivateKey, 'sei'); + expect(getWalletClientFromProvider).toHaveBeenCalledWith('sei'); }); }); @@ -213,7 +213,7 @@ describe('Contract Service', () => { const result = await deployContract(mockBytecode, mockAbi, mockArgs, 'sei'); expect(getPrivateKeyAsHex).toHaveBeenCalled(); - expect(getWalletClient).toHaveBeenCalledWith(mockPrivateKey, 'sei'); + expect(getWalletClientFromProvider).toHaveBeenCalledWith('sei'); expect(mockWalletClient.deployContract).toHaveBeenCalledWith({ abi: mockAbi, bytecode: mockBytecode, @@ -248,7 +248,7 @@ describe('Contract Service', () => { test('should use default network when none is specified', async () => { await deployContract(mockBytecode, mockAbi, mockArgs); - expect(getWalletClient).toHaveBeenCalledWith(mockPrivateKey, 'sei'); + expect(getWalletClientFromProvider).toHaveBeenCalledWith('sei'); expect(getPublicClient).toHaveBeenCalledWith('sei'); }); @@ -258,7 +258,7 @@ describe('Contract Service', () => { await expect(deployContract(mockBytecode, mockAbi, mockArgs, 'sei')).rejects.toThrow( 'Private key not available. Set the PRIVATE_KEY environment variable and restart the MCP server.' ); - expect(getWalletClient).not.toHaveBeenCalled(); + expect(getWalletClientFromProvider).not.toHaveBeenCalled(); }); test('should throw error when wallet client account is not available', async () => { @@ -266,7 +266,7 @@ describe('Contract Service', () => { ...mockWalletClient, account: undefined }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(deployContract(mockBytecode, mockAbi, mockArgs, 'sei')).rejects.toThrow( 'Wallet client account not available for contract deployment.' diff --git a/packages/mcp-server/src/tests/core/services/transfer.test.ts b/packages/mcp-server/src/tests/core/services/transfer.test.ts index d11c6f055..eda53c704 100644 --- a/packages/mcp-server/src/tests/core/services/transfer.test.ts +++ b/packages/mcp-server/src/tests/core/services/transfer.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect, beforeEach, jest } from '@jest/globals'; -import { getPublicClient, getWalletClient, transferSei, transferERC20, approveERC20, transferERC721, transferERC1155 } from '../../../core/services'; +import { getPublicClient, getWalletClientFromProvider, transferSei, transferERC20, approveERC20, transferERC721, transferERC1155 } from '../../../core/services'; import { getPrivateKeyAsHex } from '../../../core/config.js'; import type { Hash } from 'viem'; @@ -35,7 +35,7 @@ describe('Transfer Service', () => { // Setup default mock implementations with type assertions (getPublicClient as jest.Mock).mockReturnValue(mockPublicClient); - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClient); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClient)); (getPrivateKeyAsHex as jest.MockedFunction).mockReturnValue( '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' ); @@ -57,10 +57,10 @@ describe('Transfer Service', () => { }); }); - test('should throw error when private key is not available', async () => { - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(null); + test('should throw error when wallet provider fails', async () => { + (getWalletClientFromProvider as jest.Mock).mockRejectedValue(new Error('Wallet provider unavailable')); - await expect(transferSei('0x1234567890123456789012345678901234567890', '1.0')).rejects.toThrow('Private key not available'); + await expect(transferSei('0x1234567890123456789012345678901234567890', '1.0')).rejects.toThrow('Wallet provider unavailable'); }); test('should throw error when wallet account is not initialized', async () => { @@ -69,7 +69,7 @@ describe('Transfer Service', () => { ...mockWalletClient, account: null }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(transferSei('0x1234567890123456789012345678901234567890', '1.0')).rejects.toThrow('Wallet account not initialized properly'); }); @@ -104,10 +104,10 @@ describe('Transfer Service', () => { }); }); - test('should throw error when private key is not available', async () => { - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(null); + test('should throw error when wallet provider fails', async () => { + (getWalletClientFromProvider as jest.Mock).mockRejectedValue(new Error('Wallet provider unavailable')); - await expect(transferERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Private key not available'); + await expect(transferERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Wallet provider unavailable'); }); test('should throw error when wallet account is not initialized', async () => { @@ -116,7 +116,7 @@ describe('Transfer Service', () => { ...mockWalletClient, account: null }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(transferERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Wallet account not initialized properly'); }); @@ -151,10 +151,10 @@ describe('Transfer Service', () => { }); }); - test('should throw error when private key is not available', async () => { - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(null); + test('should throw error when wallet provider fails', async () => { + (getWalletClientFromProvider as jest.Mock).mockRejectedValue(new Error('Wallet provider unavailable')); - await expect(approveERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Private key not available'); + await expect(approveERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Wallet provider unavailable'); }); test('should throw error when wallet account is not initialized', async () => { @@ -163,7 +163,7 @@ describe('Transfer Service', () => { ...mockWalletClient, account: null }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(approveERC20('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', '1.0')).rejects.toThrow('Wallet account not initialized properly'); }); @@ -195,10 +195,10 @@ describe('Transfer Service', () => { }); }); - test('should throw error when private key is not available', async () => { - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(null); + test('should throw error when wallet provider fails', async () => { + (getWalletClientFromProvider as jest.Mock).mockRejectedValue(new Error('Wallet provider unavailable')); - await expect(transferERC721('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n)).rejects.toThrow('Private key not available'); + await expect(transferERC721('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n)).rejects.toThrow('Wallet provider unavailable'); }); test('should throw error when wallet account is not initialized', async () => { @@ -207,7 +207,7 @@ describe('Transfer Service', () => { ...mockWalletClient, account: null }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(transferERC721('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n)).rejects.toThrow('Wallet account not initialized properly'); }); @@ -254,10 +254,10 @@ describe('Transfer Service', () => { }); }); - test('should throw error when private key is not available', async () => { - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(null); + test('should throw error when wallet provider fails', async () => { + (getWalletClientFromProvider as jest.Mock).mockRejectedValue(new Error('Wallet provider unavailable')); - await expect(transferERC1155('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n, '1')).rejects.toThrow('Private key not available'); + await expect(transferERC1155('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n, '1')).rejects.toThrow('Wallet provider unavailable'); }); test('should throw error when wallet account is not initialized', async () => { @@ -266,7 +266,7 @@ describe('Transfer Service', () => { ...mockWalletClient, account: null }; - (getWalletClient as jest.Mock).mockReturnValue(mockWalletClientWithoutAccount); + (getWalletClientFromProvider as jest.Mock).mockReturnValue(Promise.resolve(mockWalletClientWithoutAccount)); await expect(transferERC1155('0x1234567890123456789012345678901234567890', '0x0987654321098765432109876543210987654321', 1n, '1')).rejects.toThrow('Wallet account not initialized properly'); }); diff --git a/packages/mcp-server/src/tests/core/tools.test.ts b/packages/mcp-server/src/tests/core/tools.test.ts index 164e898f2..dec096775 100644 --- a/packages/mcp-server/src/tests/core/tools.test.ts +++ b/packages/mcp-server/src/tests/core/tools.test.ts @@ -14,16 +14,19 @@ import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globa */ import type { Address } from 'viem'; +import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { getRpcUrl, getSupportedNetworks } from '../../core/chains.js'; -import { getPrivateKeyAsHex } from '../../core/config.js'; +import { getPrivateKeyAsHex, isWalletEnabled, getWalletMode } from '../../core/config.js'; import { registerEVMTools } from '../../core/tools.js'; import * as services from '../../core/services/index.js'; -import { createMockServer, setupBalanceMocks, setupTransactionMocks, testToolError, testToolSuccess, verifyErrorResponse, verifySuccessResponse } from './helpers/tool-test-helpers.js'; +import { getWalletProvider } from '../../core/wallet/index.js'; +import { createMockServer, setupBalanceMocks, setupTransactionMocks, testToolError, testToolSuccess, verifyErrorResponse, verifySuccessResponse, type Tool } from './helpers/tool-test-helpers.js'; // Mock all service functions jest.mock('../../core/services/index.js'); jest.mock('../../core/chains.js'); jest.mock('../../core/config.js'); +jest.mock('../../core/wallet/index.js'); describe('EVM Tools', () => { // Common test variables @@ -33,21 +36,40 @@ describe('EVM Tools', () => { const mockNetwork = 'sei'; const mockError = new Error('Test error'); - // Setup mock server and tools - const { server, registeredTools } = createMockServer(); - - // Register tools with the mock server - do this once before all tests - registerEVMTools(server); + // Variables to hold server and registeredTools + let server: McpServer; + let registeredTools: Map; beforeEach(() => { - // Default mock implementations + // Create fresh mock server for each test + const mockServerResult = createMockServer(); + server = mockServerResult.server; + registeredTools = mockServerResult.registeredTools; + + // Setup configuration mocks first (getRpcUrl as jest.Mock).mockReturnValue('https://rpc.sei.io'); (getSupportedNetworks as jest.Mock).mockReturnValue(['sei', 'sei-testnet']); (getPrivateKeyAsHex as jest.Mock).mockReturnValue('0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'); - (services.getAddressFromPrivateKey as jest.Mock).mockReturnValue(mockAddress); + (isWalletEnabled as jest.Mock).mockReturnValue(true); // Enable wallet for testing + (getWalletMode as jest.Mock).mockReturnValue('private-key'); // Set wallet mode + + // Mock wallet provider + const mockWalletProvider = { + isAvailable: jest.fn().mockReturnValue(true), + getName: jest.fn().mockReturnValue('private-key'), + getAddress: jest.fn().mockResolvedValue(mockAddress), + getWalletClient: jest.fn().mockResolvedValue({ account: { address: mockAddress } }) + }; + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); + + // Mock service functions + (services.getAddressFromProvider as jest.Mock).mockResolvedValue(mockAddress); (services.getChainId as jest.Mock).mockResolvedValue(1 as never); (services.getBlockNumber as jest.Mock).mockResolvedValue(BigInt(12345678) as never); + // Register tools after mocks are set up + registerEVMTools(server); + // Mock formatJson function // Create a type for the helpers object to avoid read-only property error type ServiceHelpers = typeof services.helpers; @@ -735,11 +757,11 @@ describe('EVM Tools', () => { (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); // Mock the service function - (services.getAddressFromPrivateKey as jest.Mock).mockReturnValue(mockAddress); + (services.getAddressFromProvider as jest.Mock).mockResolvedValue(mockAddress); const response = await testToolSuccess(tool, {}); - expect(services.getAddressFromPrivateKey).toHaveBeenCalledWith(mockPrivateKey); + expect(services.getAddressFromProvider).toHaveBeenCalled(); expect(response).toHaveProperty('content'); expect(response.content[0]).toHaveProperty('type', 'text'); @@ -748,52 +770,52 @@ describe('EVM Tools', () => { expect(parsedResponse).toEqual({ address: mockAddress }); }); - test('get_address_from_private_key - private key not set', async () => { + test('get_address_from_private_key - wallet not available', async () => { const tool = checkToolExists('get_address_from_private_key'); if (!tool) return; - // Mock the config function to return undefined (private key not set) - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(undefined); + // Mock wallet provider to be unavailable + const mockWalletProvider = { + isAvailable: jest.fn().mockReturnValue(false), + getName: jest.fn().mockReturnValue('private-key') + }; + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); - // For this test, we're not using a mock function to throw an error - // Instead, we're directly calling the handler and expecting it to return an error response - const response = await tool.handler({}); + const response = await testToolSuccess(tool, {}); - verifyErrorResponse(response, 'Error: The PRIVATE_KEY environment variable is not set'); - expect(services.getAddressFromPrivateKey).not.toHaveBeenCalled(); + verifyErrorResponse(response, "Error: Wallet provider 'private-key' is not available"); }); test('get_address_from_private_key - error path', async () => { const tool = checkToolExists('get_address_from_private_key'); if (!tool) return; - const mockPrivateKey = '0x1234567890abcdef'; - - // Mock the config function - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); - - // Mock the service function to throw an error - const error = new Error('Invalid private key format'); - const mockFn = services.getAddressFromPrivateKey as jest.Mock; + // Mock wallet provider as available + const mockWalletProvider = { + isAvailable: jest.fn().mockReturnValue(true), + getName: jest.fn().mockReturnValue('private-key') + }; + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); - const response = await testToolError(tool, {}, mockFn, error); + const response = await testToolError(tool, {}, services.getAddressFromProvider as jest.Mock, mockError); - verifyErrorResponse(response, 'Error deriving address from private key: Invalid private key format'); - expect(services.getAddressFromPrivateKey).toHaveBeenCalledWith(mockPrivateKey); + verifyErrorResponse(response, 'Error deriving address from private key: Test error'); }); test('get_address_from_private_key - error with non-Error object', async () => { const tool = checkToolExists('get_address_from_private_key'); if (!tool) return; - const mockPrivateKey = '0x1234567890abcdef'; - - // Mock the config function - (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + // Mock wallet provider as available + const mockWalletProvider = { + isAvailable: jest.fn().mockReturnValue(true), + getName: jest.fn().mockReturnValue('private-key') + }; + (getWalletProvider as jest.Mock).mockReturnValue(mockWalletProvider); // Mock the service function to throw a non-Error object const nonErrorObject = "This is a string error"; - (services.getAddressFromPrivateKey as jest.Mock).mockImplementationOnce(() => { + (services.getAddressFromProvider as jest.Mock).mockImplementationOnce(() => { throw nonErrorObject; }); @@ -801,9 +823,41 @@ describe('EVM Tools', () => { expect(response).toHaveProperty('isError', true); expect(response.content[0].text).toContain('Error deriving address from private key: This is a string error'); - expect(services.getAddressFromPrivateKey).toHaveBeenCalledWith(mockPrivateKey); }); - }); + }); + + // Test disabled wallet scenario + test('should handle disabled wallet mode', () => { + // Create a new server for this test + const mockServerResult = createMockServer(); + const disabledWalletServer = mockServerResult.server; + const disabledWalletTools = mockServerResult.registeredTools; + + // Mock wallet as disabled + (isWalletEnabled as jest.Mock).mockReturnValue(false); + + // Mock console.error to verify it's called + const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); + + // Register tools with disabled wallet + registerEVMTools(disabledWalletServer); + + // Verify console.error was called with the expected message + expect(consoleSpy).toHaveBeenCalledWith('Wallet functionality is disabled. Wallet-dependent tools will not be available.'); + + // Verify wallet tools are not registered + expect(disabledWalletTools.has('get_address_from_private_key')).toBe(false); + expect(disabledWalletTools.has('transfer_sei')).toBe(false); + expect(disabledWalletTools.has('transfer_erc20')).toBe(false); + + // Verify read-only tools are still registered + expect(disabledWalletTools.has('get_chain_info')).toBe(true); + expect(disabledWalletTools.has('get_balance')).toBe(true); + + // Clean up + consoleSpy.mockRestore(); + // Restore wallet enabled for other tests + (isWalletEnabled as jest.Mock).mockReturnValue(true); }); // Verify all expected tools are registered @@ -1053,6 +1107,99 @@ describe('EVM Tools', () => { expect(response).toHaveProperty('isError', true); expect(response.content[0].text).toContain('Error estimating gas: This is a string error'); }); + + test('estimate_gas - with contract call data', async () => { + const tool = checkToolExists('estimate_gas'); + if (!tool) return; + + const params = { + to: '0x1234567890123456789012345678901234567890', + value: '0.5', + data: '0xa9059cbb000000000000000000000000742d35cc6cd6b4c0532a6b329dc52b4eca13a623000000000000000000000000000000000000000000000000016345785d8a0000', + network: mockNetwork + }; + + // Mock the estimateGas function to return a specific value for contract calls + (services.estimateGas as jest.Mock).mockImplementationOnce((txParams, network) => { + return Promise.resolve(BigInt('45000')); // Higher gas for contract calls + }); + + // Mock the parseEther function + (services.helpers.parseEther as jest.Mock).mockReturnValueOnce(BigInt('500000000000000000')); // 0.5 ETH + + const response = await tool.handler(params); + + expect(services.estimateGas).toHaveBeenCalledWith({ + to: params.to as `0x${string}`, + value: BigInt('500000000000000000'), + data: params.data as `0x${string}` + }, mockNetwork); + + expect(response).toHaveProperty('content'); + expect(response.content[0]).toHaveProperty('type', 'text'); + expect(response.content[0].text).toContain('45000'); + }); + + test('estimate_gas - without data parameter', async () => { + const tool = checkToolExists('estimate_gas'); + if (!tool) return; + + const params = { + to: '0x1234567890123456789012345678901234567890', + value: '1.0', + network: mockNetwork + // No data parameter provided + }; + + // Mock the estimateGas function to return a specific value + (services.estimateGas as jest.Mock).mockImplementationOnce((txParams, network) => { + return Promise.resolve(BigInt('21000')); // Basic transfer gas + }); + + // Mock the parseEther function + (services.helpers.parseEther as jest.Mock).mockReturnValueOnce(BigInt('1000000000000000000')); // 1 ETH + + const response = await tool.handler(params); + + expect(services.estimateGas).toHaveBeenCalledWith({ + to: params.to as `0x${string}`, + value: BigInt('1000000000000000000') + // data should not be included since it wasn't provided + }, mockNetwork); + + expect(response).toHaveProperty('content'); + expect(response.content[0]).toHaveProperty('type', 'text'); + expect(response.content[0].text).toContain('21000'); + }); + + test('estimate_gas - without value parameter', async () => { + const tool = checkToolExists('estimate_gas'); + if (!tool) return; + + const params = { + to: '0x1234567890123456789012345678901234567890', + data: '0xa9059cbb000000000000000000000000742d35cc6cd6b4c0532a6b329dc52b4eca13a623000000000000000000000000000000000000000000000000016345785d8a0000', + network: mockNetwork + // No value parameter provided + }; + + // Mock the estimateGas function to return a specific value + (services.estimateGas as jest.Mock).mockImplementationOnce((txParams, network) => { + return Promise.resolve(BigInt('35000')); // Contract call without value + }); + + const response = await tool.handler(params); + + expect(services.estimateGas).toHaveBeenCalledWith({ + to: params.to as `0x${string}`, + data: params.data as `0x${string}` + // value should not be included since it wasn't provided + }, mockNetwork); + + expect(response).toHaveProperty('content'); + expect(response.content[0]).toHaveProperty('type', 'text'); + expect(response.content[0].text).toContain('35000'); + }); }); // Group 5: Transfer Tools @@ -2773,3 +2920,4 @@ describe('EVM Tools', () => { expect(response.content[0].text).toContain('Address does not own this NFT'); }); }); +}); diff --git a/packages/mcp-server/src/tests/core/wallet/index.test.ts b/packages/mcp-server/src/tests/core/wallet/index.test.ts new file mode 100644 index 000000000..c9fa01d68 --- /dev/null +++ b/packages/mcp-server/src/tests/core/wallet/index.test.ts @@ -0,0 +1,124 @@ +import { describe, test, expect, jest, beforeEach } from '@jest/globals'; +import { getWalletProvider, resetWalletProvider } from '../../../core/wallet/index.js'; +import { PrivateKeyWalletProvider } from '../../../core/wallet/providers/private-key.js'; +import { DisabledWalletProvider } from '../../../core/wallet/providers/disabled.js'; + +// Mock dependencies +jest.mock('../../../core/config.js', () => ({ + getWalletMode: jest.fn() +})); + +jest.mock('../../../core/wallet/providers/private-key.js', () => ({ + PrivateKeyWalletProvider: jest.fn() +})); + +jest.mock('../../../core/wallet/providers/disabled.js', () => ({ + DisabledWalletProvider: jest.fn() +})); + +import { getWalletMode } from '../../../core/config.js'; + +describe('Wallet Provider', () => { + const mockPrivateKeyProvider = { + getName: () => 'private-key', + isAvailable: () => true + }; + + const mockDisabledProvider = { + getName: () => 'disabled', + isAvailable: () => false + }; + + beforeEach(() => { + // Reset wallet provider instance before each test + resetWalletProvider(); + + // Reset all mocks + jest.resetAllMocks(); + + // Setup default mock implementations + (PrivateKeyWalletProvider as jest.Mock).mockImplementation(() => mockPrivateKeyProvider); + (DisabledWalletProvider as jest.Mock).mockImplementation(() => mockDisabledProvider); + }); + + describe('getWalletProvider', () => { + test('should create and return PrivateKeyWalletProvider for private-key mode', () => { + (getWalletMode as jest.Mock).mockReturnValue('private-key'); + + const provider = getWalletProvider(); + + expect(getWalletMode).toHaveBeenCalled(); + expect(PrivateKeyWalletProvider).toHaveBeenCalled(); + expect(provider).toBe(mockPrivateKeyProvider); + }); + + test('should create and return DisabledWalletProvider for disabled mode', () => { + (getWalletMode as jest.Mock).mockReturnValue('disabled'); + + const provider = getWalletProvider(); + + expect(getWalletMode).toHaveBeenCalled(); + expect(DisabledWalletProvider).toHaveBeenCalled(); + expect(provider).toBe(mockDisabledProvider); + }); + + test('should return cached provider on subsequent calls', () => { + (getWalletMode as jest.Mock).mockReturnValue('private-key'); + + // First call + const provider1 = getWalletProvider(); + + // Reset mocks to verify they aren't called again + jest.clearAllMocks(); + + // Second call should return cached provider + const provider2 = getWalletProvider(); + + expect(getWalletMode).not.toHaveBeenCalled(); + expect(PrivateKeyWalletProvider).not.toHaveBeenCalled(); + expect(provider2).toBe(provider1); + }); + + test('should throw error for unknown wallet mode', () => { + (getWalletMode as jest.Mock).mockReturnValue('unknown-mode'); + + expect(() => getWalletProvider()).toThrow('Unknown wallet mode: unknown-mode'); + }); + }); + + describe('resetWalletProvider', () => { + test('should reset the wallet provider instance', () => { + (getWalletMode as jest.Mock).mockReturnValue('private-key'); + + // Create separate mock instances for each call + const mockProvider1 = { + getName: () => 'private-key', + isAvailable: () => true + }; + const mockProvider2 = { + getName: () => 'private-key', + isAvailable: () => true + }; + + // Mock constructor to return different instances on each call + (PrivateKeyWalletProvider as jest.Mock) + .mockImplementationOnce(() => mockProvider1) + .mockImplementationOnce(() => mockProvider2); + + // Create provider instance + const provider1 = getWalletProvider(); + expect(provider1).toBe(mockProvider1); + + // Reset the provider + resetWalletProvider(); + + // Create new provider instance + const provider2 = getWalletProvider(); + expect(provider2).toBe(mockProvider2); + + // Should have created a new instance + expect(PrivateKeyWalletProvider).toHaveBeenCalledTimes(2); + expect(provider2).not.toBe(provider1); + }); + }); +}); diff --git a/packages/mcp-server/src/tests/core/wallet/providers/disabled.test.ts b/packages/mcp-server/src/tests/core/wallet/providers/disabled.test.ts new file mode 100644 index 000000000..06dd07c7e --- /dev/null +++ b/packages/mcp-server/src/tests/core/wallet/providers/disabled.test.ts @@ -0,0 +1,46 @@ +import { describe, test, expect } from '@jest/globals'; +import { DisabledWalletProvider } from '../../../../core/wallet/providers/disabled.js'; +import { WalletProviderError } from '../../../../core/wallet/types.js'; + +describe('DisabledWalletProvider', () => { + let provider: DisabledWalletProvider; + + beforeEach(() => { + provider = new DisabledWalletProvider(); + }); + + describe('isAvailable', () => { + test('should return false', () => { + expect(provider.isAvailable()).toBe(false); + }); + }); + + describe('getName', () => { + test('should return "disabled"', () => { + expect(provider.getName()).toBe('disabled'); + }); + }); + + describe('getAddress', () => { + test('should throw WalletProviderError', async () => { + await expect(provider.getAddress()).rejects.toThrow(WalletProviderError); + await expect(provider.getAddress()).rejects.toThrow('Wallet functionality is disabled'); + }); + }); + + describe('signTransaction', () => { + test('should throw WalletProviderError', async () => { + const mockTx = { to: '0x123', value: '0x1' }; + + await expect(provider.signTransaction(mockTx)).rejects.toThrow(WalletProviderError); + await expect(provider.signTransaction(mockTx)).rejects.toThrow('Wallet functionality is disabled'); + }); + }); + + describe('getWalletClient', () => { + test('should throw WalletProviderError', async () => { + await expect(provider.getWalletClient('sei')).rejects.toThrow(WalletProviderError); + await expect(provider.getWalletClient('sei')).rejects.toThrow('Wallet functionality is disabled'); + }); + }); +}); diff --git a/packages/mcp-server/src/tests/core/wallet/providers/private-key.test.ts b/packages/mcp-server/src/tests/core/wallet/providers/private-key.test.ts new file mode 100644 index 000000000..71a20f2a3 --- /dev/null +++ b/packages/mcp-server/src/tests/core/wallet/providers/private-key.test.ts @@ -0,0 +1,149 @@ +import { describe, test, expect, jest, beforeEach } from '@jest/globals'; +import { PrivateKeyWalletProvider } from '../../../../core/wallet/providers/private-key.js'; +import { WalletProviderError } from '../../../../core/wallet/types.js'; +import { createWalletClient, http } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; + +// Mock dependencies +jest.mock('../../../../core/config.js', () => ({ + getPrivateKeyAsHex: jest.fn() +})); + +jest.mock('../../../../core/chains.js', () => ({ + getChain: jest.fn(), + getRpcUrl: jest.fn() +})); + +jest.mock('viem', () => ({ + createWalletClient: jest.fn(), + http: jest.fn() +})); + +jest.mock('viem/accounts', () => ({ + privateKeyToAccount: jest.fn() +})); + +import { getPrivateKeyAsHex } from '../../../../core/config.js'; +import { getChain, getRpcUrl } from '../../../../core/chains.js'; + +describe('PrivateKeyWalletProvider', () => { + const mockPrivateKey = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; + const mockAddress = '0x1234567890123456789012345678901234567890'; + const mockAccount = { address: mockAddress }; + const mockChain = { id: 1, name: 'Sei' }; + const mockRpcUrl = 'https://rpc.sei.io'; + const mockTransport = {}; + const mockWalletClient = { account: mockAccount, chain: mockChain }; + + beforeEach(() => { + jest.resetAllMocks(); + + // Setup default mocks + (getChain as jest.Mock).mockReturnValue(mockChain); + (getRpcUrl as jest.Mock).mockReturnValue(mockRpcUrl); + (http as jest.Mock).mockReturnValue(mockTransport); + (privateKeyToAccount as jest.Mock).mockReturnValue(mockAccount); + (createWalletClient as jest.Mock).mockReturnValue(mockWalletClient); + }); + + describe('constructor and isAvailable', () => { + test('should be available when private key is configured', () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + + const provider = new PrivateKeyWalletProvider(); + + expect(provider.isAvailable()).toBe(true); + expect(getPrivateKeyAsHex).toHaveBeenCalled(); + }); + + test('should not be available when private key is not configured', () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(undefined); + + const provider = new PrivateKeyWalletProvider(); + + expect(provider.isAvailable()).toBe(false); + }); + }); + + describe('getName', () => { + test('should return "private-key"', () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + + const provider = new PrivateKeyWalletProvider(); + + expect(provider.getName()).toBe('private-key'); + }); + }); + + describe('getAddress', () => { + test('should return address when private key is configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + + const provider = new PrivateKeyWalletProvider(); + const address = await provider.getAddress(); + + expect(privateKeyToAccount).toHaveBeenCalledWith(mockPrivateKey); + expect(address).toBe(mockAddress); + }); + + test('should throw WalletProviderError when private key is not configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(undefined); + + const provider = new PrivateKeyWalletProvider(); + + await expect(provider.getAddress()).rejects.toThrow(WalletProviderError); + await expect(provider.getAddress()).rejects.toThrow('Private key not configured'); + }); + }); + + describe('signTransaction', () => { + test('should throw not implemented error when private key is configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + + const provider = new PrivateKeyWalletProvider(); + const mockTx = { to: '0x123', value: '0x1' }; + + await expect(provider.signTransaction(mockTx)).rejects.toThrow(WalletProviderError); + await expect(provider.signTransaction(mockTx)).rejects.toThrow('Direct transaction signing not implemented'); + }); + + test('should throw private key error when private key is not configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(undefined); + + const provider = new PrivateKeyWalletProvider(); + const mockTx = { to: '0x123', value: '0x1' }; + + await expect(provider.signTransaction(mockTx)).rejects.toThrow(WalletProviderError); + await expect(provider.signTransaction(mockTx)).rejects.toThrow('Private key not configured'); + }); + }); + + describe('getWalletClient', () => { + test('should create and return wallet client when private key is configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(mockPrivateKey); + + const provider = new PrivateKeyWalletProvider(); + const client = await provider.getWalletClient('sei'); + + expect(getChain).toHaveBeenCalledWith('sei'); + expect(getRpcUrl).toHaveBeenCalledWith('sei'); + expect(http).toHaveBeenCalledWith(mockRpcUrl); + expect(privateKeyToAccount).toHaveBeenCalledWith(mockPrivateKey); + expect(createWalletClient).toHaveBeenCalledWith({ + account: mockAccount, + chain: mockChain, + transport: mockTransport + }); + expect(client).toBe(mockWalletClient); + }); + + test('should throw WalletProviderError when private key is not configured', async () => { + (getPrivateKeyAsHex as jest.Mock).mockReturnValue(undefined); + + const provider = new PrivateKeyWalletProvider(); + + await expect(provider.getWalletClient('sei')).rejects.toThrow(WalletProviderError); + await expect(provider.getWalletClient('sei')).rejects.toThrow('Private key not configured'); + }); + }); +}); diff --git a/packages/mcp-server/src/tests/core/wallet/types.test.ts b/packages/mcp-server/src/tests/core/wallet/types.test.ts new file mode 100644 index 000000000..0ad7eedf0 --- /dev/null +++ b/packages/mcp-server/src/tests/core/wallet/types.test.ts @@ -0,0 +1,46 @@ +import { describe, test, expect } from '@jest/globals'; +import { WalletProviderError } from '../../../core/wallet/types.js'; + +describe('WalletProviderError', () => { + test('should create error with message, provider, and code properties', () => { + const message = 'Test error message'; + const provider = 'test-provider'; + const code = 'TEST_CODE'; + + const error = new WalletProviderError(message, provider, code); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(WalletProviderError); + expect(error.message).toBe(message); + expect(error.provider).toBe(provider); + expect(error.code).toBe(code); + expect(error.name).toBe('WalletProviderError'); + }); + + test('should have correct error name', () => { + const error = new WalletProviderError('Test message', 'test-provider', 'TEST_CODE'); + + expect(error.name).toBe('WalletProviderError'); + }); + + test('should be throwable and catchable', () => { + const message = 'Test error'; + const provider = 'test-provider'; + const code = 'TEST_CODE'; + + expect(() => { + throw new WalletProviderError(message, provider, code); + }).toThrow(WalletProviderError); + + try { + throw new WalletProviderError(message, provider, code); + } catch (error) { + expect(error).toBeInstanceOf(WalletProviderError); + if (error instanceof WalletProviderError) { + expect(error.message).toBe(message); + expect(error.provider).toBe(provider); + expect(error.code).toBe(code); + } + } + }); +}); diff --git a/yarn.lock b/yarn.lock index fcb66c740..822d2ede1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,6 +40,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/code-frame@npm:7.27.1" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.27.1" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/5dd9a18baa5fce4741ba729acc3a3272c49c25cb8736c4b18e113099520e7ef7b545a4096a26d600e4416157e63e87d66db46aa3fbf0a5f2286da2705c12da00 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.26.8": version: 7.26.8 resolution: "@babel/compat-data@npm:7.26.8" @@ -47,6 +58,13 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.27.2": + version: 7.27.7 + resolution: "@babel/compat-data@npm:7.27.7" + checksum: 10c0/08f2d3bd1b38e7e8cd159c5ddeb458696338ef7cd3fe0cc4384a0af5353ef8577ee3f25f01f0a88544c0e7ada972d0d2826a06744c695b211bfb172b76c0ca38 + languageName: node + linkType: hard + "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": version: 7.26.10 resolution: "@babel/core@npm:7.26.10" @@ -70,6 +88,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.27.4": + version: 7.27.7 + resolution: "@babel/core@npm:7.27.7" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.27.5" + "@babel/helper-compilation-targets": "npm:^7.27.2" + "@babel/helper-module-transforms": "npm:^7.27.3" + "@babel/helpers": "npm:^7.27.6" + "@babel/parser": "npm:^7.27.7" + "@babel/template": "npm:^7.27.2" + "@babel/traverse": "npm:^7.27.7" + "@babel/types": "npm:^7.27.7" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/02c0cd475821c5333d5ee5eb9a0565af1a38234b37859ae09c4c95d7171bbc11a23a6f733c31b3cb12dc523311bdc8f7f9d705136f33eeb6704b7fbd6e6468ca + languageName: node + linkType: hard + "@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.27.0, @babel/generator@npm:^7.7.2": version: 7.27.0 resolution: "@babel/generator@npm:7.27.0" @@ -83,6 +124,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.27.5": + version: 7.27.5 + resolution: "@babel/generator@npm:7.27.5" + dependencies: + "@babel/parser": "npm:^7.27.5" + "@babel/types": "npm:^7.27.3" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" + jsesc: "npm:^3.0.2" + checksum: 10c0/8f649ef4cd81765c832bb11de4d6064b035ffebdecde668ba7abee68a7b0bce5c9feabb5dc5bb8aeba5bd9e5c2afa3899d852d2bd9ca77a711ba8c8379f416f0 + languageName: node + linkType: hard + "@babel/helper-compilation-targets@npm:^7.26.5": version: 7.27.0 resolution: "@babel/helper-compilation-targets@npm:7.27.0" @@ -96,6 +150,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/helper-compilation-targets@npm:7.27.2" + dependencies: + "@babel/compat-data": "npm:^7.27.2" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/f338fa00dcfea931804a7c55d1a1c81b6f0a09787e528ec580d5c21b3ecb3913f6cb0f361368973ce953b824d910d3ac3e8a8ee15192710d3563826447193ad1 + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-module-imports@npm:7.25.9" @@ -106,6 +173,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-module-imports@npm:7.27.1" + dependencies: + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10c0/e00aace096e4e29290ff8648455c2bc4ed982f0d61dbf2db1b5e750b9b98f318bf5788d75a4f974c151bd318fd549e81dbcab595f46b14b81c12eda3023f51e8 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.26.0": version: 7.26.0 resolution: "@babel/helper-module-transforms@npm:7.26.0" @@ -119,6 +196,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.27.3": + version: 7.27.3 + resolution: "@babel/helper-module-transforms@npm:7.27.3" + dependencies: + "@babel/helper-module-imports": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + "@babel/traverse": "npm:^7.27.3" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/fccb4f512a13b4c069af51e1b56b20f54024bcf1591e31e978a30f3502567f34f90a80da6a19a6148c249216292a8074a0121f9e52602510ef0f32dbce95ca01 + languageName: node + linkType: hard + "@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.25.9, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.26.5 resolution: "@babel/helper-plugin-utils@npm:7.26.5" @@ -126,6 +216,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-plugin-utils@npm:7.27.1" + checksum: 10c0/94cf22c81a0c11a09b197b41ab488d416ff62254ce13c57e62912c85700dc2e99e555225787a4099ff6bae7a1812d622c80fbaeda824b79baa10a6c5ac4cf69b + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-string-parser@npm:7.25.9" @@ -133,6 +230,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10c0/8bda3448e07b5583727c103560bcf9c4c24b3c1051a4c516d4050ef69df37bb9a4734a585fe12725b8c2763de0a265aa1e909b485a4e3270b7cfd3e4dbe4b602 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-validator-identifier@npm:7.25.9" @@ -140,6 +244,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-identifier@npm:7.27.1" + checksum: 10c0/c558f11c4871d526498e49d07a84752d1800bf72ac0d3dad100309a2eaba24efbf56ea59af5137ff15e3a00280ebe588560534b0e894a4750f8b1411d8f78b84 + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-validator-option@npm:7.25.9" @@ -147,6 +258,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10c0/6fec5f006eba40001a20f26b1ef5dbbda377b7b68c8ad518c05baa9af3f396e780bdfded24c4eef95d14bb7b8fd56192a6ed38d5d439b97d10efc5f1a191d148 + languageName: node + linkType: hard + "@babel/helpers@npm:^7.26.10": version: 7.27.0 resolution: "@babel/helpers@npm:7.27.0" @@ -157,6 +275,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.27.6": + version: 7.27.6 + resolution: "@babel/helpers@npm:7.27.6" + dependencies: + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.27.6" + checksum: 10c0/448bac96ef8b0f21f2294a826df9de6bf4026fd023f8a6bb6c782fe3e61946801ca24381490b8e58d861fee75cd695a1882921afbf1f53b0275ee68c938bd6d3 + languageName: node + linkType: hard + "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.27.0": version: 7.27.0 resolution: "@babel/parser@npm:7.27.0" @@ -168,6 +296,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.5, @babel/parser@npm:^7.27.7": + version: 7.27.7 + resolution: "@babel/parser@npm:7.27.7" + dependencies: + "@babel/types": "npm:^7.27.7" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/f6202faeb873f0b3083022e50a5046fe07266d337c0a3bd80a491f8435ba6d9e383d49725e3dcd666b3b52c0dccb4e0f1f1004915762345f7eeed5ba54ea9fd2 + languageName: node + linkType: hard + "@babel/plugin-syntax-async-generators@npm:^7.8.4": version: 7.8.4 resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" @@ -245,6 +384,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/bc5afe6a458d5f0492c02a54ad98c5756a0c13bd6d20609aae65acd560a9e141b0876da5f358dce34ea136f271c1016df58b461184d7ae9c4321e0f98588bc84 + languageName: node + linkType: hard + "@babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.25.9 resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" @@ -344,6 +494,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/11589b4c89c66ef02d57bf56c6246267851ec0c361f58929327dc3e070b0dab644be625bbe7fb4c4df30c3634bfdfe31244e1f517be397d2def1487dbbe3c37d + languageName: node + linkType: hard + "@babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.25.9 resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" @@ -375,6 +536,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/template@npm:7.27.2" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/parser": "npm:^7.27.2" + "@babel/types": "npm:^7.27.1" + checksum: 10c0/ed9e9022651e463cc5f2cc21942f0e74544f1754d231add6348ff1b472985a3b3502041c0be62dc99ed2d12cfae0c51394bf827452b98a2f8769c03b87aadc81 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10": version: 7.27.0 resolution: "@babel/traverse@npm:7.27.0" @@ -390,6 +562,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.27.3, @babel/traverse@npm:^7.27.7": + version: 7.27.7 + resolution: "@babel/traverse@npm:7.27.7" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.27.5" + "@babel/parser": "npm:^7.27.7" + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.27.7" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: 10c0/941fecd0248546f059d58230590a2765d128ef072c8521c9e0bcf6037abf28a0ea4736003d0d695513128d07fe00a7bc57acaada2ed905941d44619b9f49cf0c + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.0, @babel/types@npm:^7.3.3": version: 7.27.0 resolution: "@babel/types@npm:7.27.0" @@ -400,6 +587,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.27.6, @babel/types@npm:^7.27.7": + version: 7.27.7 + resolution: "@babel/types@npm:7.27.7" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + checksum: 10c0/1d1dcb5fa7cfba2b4034a3ab99ba17049bfc4af9e170935575246cdb1cee68b04329a0111506d9ae83fb917c47dbd4394a6db5e32fbd041b7834ffbb17ca086b + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -1000,6 +1197,209 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/core@npm:1.4.3" + dependencies: + "@emnapi/wasi-threads": "npm:1.0.2" + tslib: "npm:^2.4.0" + checksum: 10c0/e30101d16d37ef3283538a35cad60e22095aff2403fb9226a35330b932eb6740b81364d525537a94eb4fb51355e48ae9b10d779c0dd1cdcd55d71461fe4b45c7 + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/3b7ab72d21cb4e034f07df80165265f85f445ef3f581d1bc87b67e5239428baa00200b68a7d5e37a0425c3a78320b541b07f76c5530f6f6f95336a6294ebf30b + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.0.2": + version: 1.0.2 + resolution: "@emnapi/wasi-threads@npm:1.0.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f0621b1fc715221bd2d8332c0ca922617bcd77cdb3050eae50a124eb8923c54fa425d23982dc8f29d505c8798a62d1049bace8b0686098ff9dd82270e06d772e + languageName: node + linkType: hard + +"@esbuild/aix-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/aix-ppc64@npm:0.25.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm64@npm:0.25.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm@npm:0.25.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-x64@npm:0.25.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-arm64@npm:0.25.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-x64@npm:0.25.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-arm64@npm:0.25.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-x64@npm:0.25.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm64@npm:0.25.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm@npm:0.25.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ia32@npm:0.25.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-loong64@npm:0.25.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-mips64el@npm:0.25.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ppc64@npm:0.25.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-riscv64@npm:0.25.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-s390x@npm:0.25.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-x64@npm:0.25.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-arm64@npm:0.25.5" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-x64@npm:0.25.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-arm64@npm:0.25.5" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-x64@npm:0.25.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/sunos-x64@npm:0.25.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-arm64@npm:0.25.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-ia32@npm:0.25.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-x64@npm:0.25.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@ethersproject/abi@npm:^5.7.0": version: 5.8.0 resolution: "@ethersproject/abi@npm:5.8.0" @@ -1274,6 +1674,20 @@ __metadata: languageName: node linkType: hard +"@jest/console@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/console@npm:30.0.2" + dependencies: + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + jest-message-util: "npm:30.0.2" + jest-util: "npm:30.0.2" + slash: "npm:^3.0.0" + checksum: 10c0/24ef330985ff020963e1d82088d0c3a7fbe981a62bc810b7afb71e6565b8c6cbcb5e789d494d3973762efc2dc351770ad05b96568517d370ad9cd8fd33f5acd0 + languageName: node + linkType: hard + "@jest/console@npm:^29.7.0": version: 29.7.0 resolution: "@jest/console@npm:29.7.0" @@ -1288,6 +1702,47 @@ __metadata: languageName: node linkType: hard +"@jest/core@npm:30.0.3": + version: 30.0.3 + resolution: "@jest/core@npm:30.0.3" + dependencies: + "@jest/console": "npm:30.0.2" + "@jest/pattern": "npm:30.0.1" + "@jest/reporters": "npm:30.0.2" + "@jest/test-result": "npm:30.0.2" + "@jest/transform": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + exit-x: "npm:^0.2.2" + graceful-fs: "npm:^4.2.11" + jest-changed-files: "npm:30.0.2" + jest-config: "npm:30.0.3" + jest-haste-map: "npm:30.0.2" + jest-message-util: "npm:30.0.2" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.0.2" + jest-resolve-dependencies: "npm:30.0.3" + jest-runner: "npm:30.0.3" + jest-runtime: "npm:30.0.3" + jest-snapshot: "npm:30.0.3" + jest-util: "npm:30.0.2" + jest-validate: "npm:30.0.2" + jest-watcher: "npm:30.0.2" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.0.2" + slash: "npm:^3.0.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/0608245c0af4d69b8454628488ecdc44ed5cc8fee27d21640ed8c76bef26d34f8f0058f390e7350484d824d8de4f05a3b8b125cea950ca16251df8defe7cffe5 + languageName: node + linkType: hard + "@jest/core@npm:^29.7.0": version: 29.7.0 resolution: "@jest/core@npm:29.7.0" @@ -1329,6 +1784,25 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: 10c0/3a840404e6021725ef7f86b11f7b2d13dd02846481264db0e447ee33b7ee992134e402cdc8b8b0ac969d37c6c0183044e382dedee72001cdf50cfb3c8088de74 + languageName: node + linkType: hard + +"@jest/environment@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/environment@npm:30.0.2" + dependencies: + "@jest/fake-timers": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + jest-mock: "npm:30.0.2" + checksum: 10c0/b16683337bd61f4c1134035c9221f92b958b79965be16d4105a5008169a22705edb004ef06cb10f42cbc23464b69bbc0eb5746d60931f764b2cbf2455477b430 + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -1341,6 +1815,15 @@ __metadata: languageName: node linkType: hard +"@jest/expect-utils@npm:30.0.3": + version: 30.0.3 + resolution: "@jest/expect-utils@npm:30.0.3" + dependencies: + "@jest/get-type": "npm:30.0.1" + checksum: 10c0/b3f662fd02980f12e4ec7b3657a728c13b1343a31b85eafd34363ea8c9a666b60ad156ffa33c1f8d2fce1cb1e06c1236361849eb52b6e31a1442195ed3b3eae0 + languageName: node + linkType: hard + "@jest/expect-utils@npm:^29.7.0": version: 29.7.0 resolution: "@jest/expect-utils@npm:29.7.0" @@ -1350,6 +1833,16 @@ __metadata: languageName: node linkType: hard +"@jest/expect@npm:30.0.3": + version: 30.0.3 + resolution: "@jest/expect@npm:30.0.3" + dependencies: + expect: "npm:30.0.3" + jest-snapshot: "npm:30.0.3" + checksum: 10c0/d76f727891df37bd1e93fff73ed4f12d6d77db33adf47cc12500b85951e7e6373e3e6f99d5826ff7c571e578d636e8a1260fd171ba0da0755b9a23b1ef75edbe + languageName: node + linkType: hard + "@jest/expect@npm:^29.7.0": version: 29.7.0 resolution: "@jest/expect@npm:29.7.0" @@ -1360,6 +1853,20 @@ __metadata: languageName: node linkType: hard +"@jest/fake-timers@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/fake-timers@npm:30.0.2" + dependencies: + "@jest/types": "npm:30.0.1" + "@sinonjs/fake-timers": "npm:^13.0.0" + "@types/node": "npm:*" + jest-message-util: "npm:30.0.2" + jest-mock: "npm:30.0.2" + jest-util: "npm:30.0.2" + checksum: 10c0/896e727a1146948780998d62e7807214f9e2b0a724e283f19baca4dfe326fb8fb885244eee6d201bc5e1385336c176c093179f080e0fae03b20ec25c02604352 + languageName: node + linkType: hard + "@jest/fake-timers@npm:^29.7.0": version: 29.7.0 resolution: "@jest/fake-timers@npm:29.7.0" @@ -1374,6 +1881,25 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/get-type@npm:30.0.1" + checksum: 10c0/92437ae42d0df57e8acc2d067288151439db4752cde4f5e680c73c8a6e34568bbd8c1c81a2f2f9a637a619c2aac8bc87553fb80e31475b59e2ed789a71e5e540 + languageName: node + linkType: hard + +"@jest/globals@npm:30.0.3": + version: 30.0.3 + resolution: "@jest/globals@npm:30.0.3" + dependencies: + "@jest/environment": "npm:30.0.2" + "@jest/expect": "npm:30.0.3" + "@jest/types": "npm:30.0.1" + jest-mock: "npm:30.0.2" + checksum: 10c0/b080a924de4ff0cfb5fef4098eb7764efa5bc33de4a59b27116defc8c91ec76e6103c9e9a60cd33e00d060f03302e6c5a56ef8c4fc28133e29ae011b1be78d8e + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -1386,6 +1912,52 @@ __metadata: languageName: node linkType: hard +"@jest/pattern@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/pattern@npm:30.0.1" + dependencies: + "@types/node": "npm:*" + jest-regex-util: "npm:30.0.1" + checksum: 10c0/32c5a7bfb6c591f004dac0ed36d645002ed168971e4c89bd915d1577031672870032594767557b855c5bc330aa1e39a2f54bf150d2ee88a7a0886e9cb65318bc + languageName: node + linkType: hard + +"@jest/reporters@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/reporters@npm:30.0.2" + dependencies: + "@bcoe/v8-coverage": "npm:^0.2.3" + "@jest/console": "npm:30.0.2" + "@jest/test-result": "npm:30.0.2" + "@jest/transform": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@jridgewell/trace-mapping": "npm:^0.3.25" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + collect-v8-coverage: "npm:^1.0.2" + exit-x: "npm:^0.2.2" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" + istanbul-lib-coverage: "npm:^3.0.0" + istanbul-lib-instrument: "npm:^6.0.0" + istanbul-lib-report: "npm:^3.0.0" + istanbul-lib-source-maps: "npm:^5.0.0" + istanbul-reports: "npm:^3.1.3" + jest-message-util: "npm:30.0.2" + jest-util: "npm:30.0.2" + jest-worker: "npm:30.0.2" + slash: "npm:^3.0.0" + string-length: "npm:^4.0.2" + v8-to-istanbul: "npm:^9.0.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10c0/4931fd1f3ae1236fba8f6068b8949b3788fe367ff2eaaa88293988344f50dcb5c15a4063a65cc4485546504bb3b85e2e6667c68acca249d3597b97425bbc2ee5 + languageName: node + linkType: hard + "@jest/reporters@npm:^29.7.0": version: 29.7.0 resolution: "@jest/reporters@npm:29.7.0" @@ -1423,6 +1995,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/schemas@npm:30.0.1" + dependencies: + "@sinclair/typebox": "npm:^0.34.0" + checksum: 10c0/27977359edc4b33293af7c85c53de5014a87c29b9ab98b0a827fedfc6635abdb522aad8c3ff276080080911f519699b094bd6f4e151b43f0cc5856ccc83c04a7 + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -1432,6 +2013,29 @@ __metadata: languageName: node linkType: hard +"@jest/snapshot-utils@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/snapshot-utils@npm:30.0.1" + dependencies: + "@jest/types": "npm:30.0.1" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + natural-compare: "npm:^1.4.0" + checksum: 10c0/a90f09733ca98e695bc2850afdbb0a9d958f4f8805b0e5420cba210422c5bfeb097de57bf66436006f3d5cc3da4109e1e65f6c3e2947474a4911f4d22a8496e8 + languageName: node + linkType: hard + +"@jest/source-map@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/source-map@npm:30.0.1" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.25" + callsites: "npm:^3.1.0" + graceful-fs: "npm:^4.2.11" + checksum: 10c0/e7bda2786fc9f483d9dd7566c58c4bd948830997be862dfe80a3ae5550ff3f84753abb52e705d02ebe9db9f34ba7ebec4c2db11882048cdeef7a66f6332b3897 + languageName: node + linkType: hard + "@jest/source-map@npm:^29.6.3": version: 29.6.3 resolution: "@jest/source-map@npm:29.6.3" @@ -1443,6 +2047,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-result@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/test-result@npm:30.0.2" + dependencies: + "@jest/console": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + collect-v8-coverage: "npm:^1.0.2" + checksum: 10c0/f2a1d5b3f1c8f786acc76b77c72a73dc314e579a4ea91ad5ad19e9906156ffa17b56a69cab33cffd1d9be32cfc5f98c60a92fceedd4c700280933b8a14de4e35 + languageName: node + linkType: hard + "@jest/test-result@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-result@npm:29.7.0" @@ -1455,6 +2071,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-sequencer@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/test-sequencer@npm:30.0.2" + dependencies: + "@jest/test-result": "npm:30.0.2" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.0.2" + slash: "npm:^3.0.0" + checksum: 10c0/5d6d74a8c530db1fac4ba085b6a27e98b52a196e2d88d53462771f3a8e8165d3f593a3cea28ed73951cbaf95ba80c7389719c58e99cb3700f0ad122376d1430b + languageName: node + linkType: hard + "@jest/test-sequencer@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-sequencer@npm:29.7.0" @@ -1467,6 +2095,29 @@ __metadata: languageName: node linkType: hard +"@jest/transform@npm:30.0.2": + version: 30.0.2 + resolution: "@jest/transform@npm:30.0.2" + dependencies: + "@babel/core": "npm:^7.27.4" + "@jest/types": "npm:30.0.1" + "@jridgewell/trace-mapping": "npm:^0.3.25" + babel-plugin-istanbul: "npm:^7.0.0" + chalk: "npm:^4.1.2" + convert-source-map: "npm:^2.0.0" + fast-json-stable-stringify: "npm:^2.1.0" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.0.2" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.0.2" + micromatch: "npm:^4.0.8" + pirates: "npm:^4.0.7" + slash: "npm:^3.0.0" + write-file-atomic: "npm:^5.0.1" + checksum: 10c0/2ab4c049b2c4851dd7abc9f837565c7b3feb5d395955608d929c5caffc0052955a0216c20bf5db1eebef9b9a888cec508a1ea3b6237648cc1f77fea00b2321dd + languageName: node + linkType: hard + "@jest/transform@npm:^29.7.0": version: 29.7.0 resolution: "@jest/transform@npm:29.7.0" @@ -1490,6 +2141,21 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/types@npm:30.0.1" + dependencies: + "@jest/pattern": "npm:30.0.1" + "@jest/schemas": "npm:30.0.1" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + "@types/istanbul-reports": "npm:^3.0.4" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.33" + chalk: "npm:^4.1.2" + checksum: 10c0/407469331e74f9bb1ffd40202c3a8cece2fd07ba535adeb60557bdcee13713cf2f14cf78869ba7ef50a7e6fe0ed7cc97ec775056dd640fc0a332e8fbfaec1ee8 + languageName: node + linkType: hard + "@jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" @@ -1546,6 +2212,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.23": + version: 0.3.27 + resolution: "@jridgewell/trace-mapping@npm:0.3.27" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/b323eae6f3a71606e69427931bab7e65c4c2490f4138484e64f0e4d1d09b727fe55eb2ef34712d8abd4a8bad4d1388c6b1af5b0a2a2d3a2dc8d42e7d00a3f91b + languageName: node + linkType: hard + "@ledgerhq/cryptoassets-evm-signatures@npm:^13.5.6": version: 13.5.6 resolution: "@ledgerhq/cryptoassets-evm-signatures@npm:13.5.6" @@ -1770,6 +2446,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.11 + resolution: "@napi-rs/wasm-runtime@npm:0.2.11" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.9.0" + checksum: 10c0/049bd14c58b99fbe0967b95e9921c5503df196b59be22948d2155f17652eb305cff6728efd8685338b855da7e476dd2551fbe3a313fc2d810938f0717478441e + languageName: node + linkType: hard + "@noble/ciphers@npm:^1.3.0": version: 1.3.0 resolution: "@noble/ciphers@npm:1.3.0" @@ -1897,6 +2584,13 @@ __metadata: languageName: node linkType: hard +"@pkgr/core@npm:^0.2.4": + version: 0.2.7 + resolution: "@pkgr/core@npm:0.2.7" + checksum: 10c0/951f5ebf2feb6e9dbc202d937f1a364d60f2bf0e3e53594251bcc1d9d2ed0df0a919c49ba162a9499fce73cf46ebe4d7959a8dfbac03511dbe79b69f5fedb804 + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -2061,6 +2755,8 @@ __metadata: cors: "npm:^2.8.5" dotenv: "npm:^16.5.0" express: "npm:^4.21.2" + jest: "npm:^30.0.3" + tsx: "npm:^4.20.3" typescript: "npm:^5.8.3" viem: "npm:^2.30.5" zod: "npm:^3.24.2" @@ -2168,7 +2864,14 @@ __metadata: languageName: node linkType: hard -"@sinonjs/commons@npm:^3.0.0": +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.37 + resolution: "@sinclair/typebox@npm:0.34.37" + checksum: 10c0/22fff01853d8f35e8a1f0be004e91a0c3ced16f35b8d7e915392e91bf021190bcba45102cd148679c53440c4ed228b31d7a2635461ea5d089ef581f6254ecfb4 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0, @sinonjs/commons@npm:^3.0.1": version: 3.0.1 resolution: "@sinonjs/commons@npm:3.0.1" dependencies: @@ -2186,7 +2889,25 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14": +"@sinonjs/fake-timers@npm:^13.0.0": + version: 13.0.5 + resolution: "@sinonjs/fake-timers@npm:13.0.5" + dependencies: + "@sinonjs/commons": "npm:^3.0.1" + checksum: 10c0/a707476efd523d2138ef6bba916c83c4a377a8372ef04fad87499458af9f01afc58f4f245c5fd062793d6d70587309330c6f96947b5bd5697961c18004dc3e26 + languageName: node + linkType: hard + +"@tybys/wasm-util@npm:^0.9.0": + version: 0.9.0 + resolution: "@tybys/wasm-util@npm:0.9.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d + languageName: node + linkType: hard + +"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -2322,7 +3043,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7 @@ -2338,7 +3059,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3.0.0": +"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -2431,7 +3152,7 @@ __metadata: languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0": +"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" checksum: 10c0/1f4658385ae936330581bcb8aa3a066df03867d90281cdf89cc356d404bd6579be0f11902304e1f775d92df22c6dd761d4451c804b0a4fba973e06211e9bd77c @@ -2468,7 +3189,7 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^17.0.8": +"@types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": version: 17.0.33 resolution: "@types/yargs@npm:17.0.33" dependencies: @@ -2477,6 +3198,148 @@ __metadata: languageName: node linkType: hard +"@ungap/structured-clone@npm:^1.3.0": + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.9.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.9.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.9.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.9.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.9.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.9.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.9.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.9.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.9.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.9.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.9.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.9.2" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.9.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.9.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.9.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.9.2" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.9.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.9.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.9.2": + version: 1.9.2 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.9.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@vue/reactivity@npm:^3.4.21": version: 3.5.13 resolution: "@vue/reactivity@npm:3.5.13" @@ -2659,7 +3522,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df @@ -2673,7 +3536,7 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": +"anymatch@npm:^3.0.3, anymatch@npm:^3.1.3, anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" dependencies: @@ -2756,6 +3619,23 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:30.0.2": + version: 30.0.2 + resolution: "babel-jest@npm:30.0.2" + dependencies: + "@jest/transform": "npm:30.0.2" + "@types/babel__core": "npm:^7.20.5" + babel-plugin-istanbul: "npm:^7.0.0" + babel-preset-jest: "npm:30.0.1" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.11.0 + checksum: 10c0/416deec120eea3f870b45166abc8a30ea29b9235d1acb4a2e50a3b7d623f401589621fa6502dcd4abfffbfaa506eccf20dbbef2c5d0eeac1df9344ec8d8de272 + languageName: node + linkType: hard + "babel-jest@npm:^29.7.0": version: 29.7.0 resolution: "babel-jest@npm:29.7.0" @@ -2786,6 +3666,30 @@ __metadata: languageName: node linkType: hard +"babel-plugin-istanbul@npm:^7.0.0": + version: 7.0.0 + resolution: "babel-plugin-istanbul@npm:7.0.0" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.0.0" + "@istanbuljs/load-nyc-config": "npm:^1.0.0" + "@istanbuljs/schema": "npm:^0.1.3" + istanbul-lib-instrument: "npm:^6.0.2" + test-exclude: "npm:^6.0.0" + checksum: 10c0/79c37bd59ea9bcb16218e874993621e24048776fac7ee72eabe78f0909200851bdb93b32f6eba5b463206f15a1ee7ad40a725af8447952321ae1fdf14e740fe9 + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:30.0.1": + version: 30.0.1 + resolution: "babel-plugin-jest-hoist@npm:30.0.1" + dependencies: + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.27.3" + "@types/babel__core": "npm:^7.20.5" + checksum: 10c0/49087f45c8ac359d68c622f4bd471300376b0ca2b6bd6ecaa1bd254ea87eda8fa3ce6144848e3bbabad337d276474a47e2ac3f6272f82e1f2337924ff49a02bd + languageName: node + linkType: hard + "babel-plugin-jest-hoist@npm:^29.6.3": version: 29.6.3 resolution: "babel-plugin-jest-hoist@npm:29.6.3" @@ -2798,7 +3702,7 @@ __metadata: languageName: node linkType: hard -"babel-preset-current-node-syntax@npm:^1.0.0": +"babel-preset-current-node-syntax@npm:^1.0.0, babel-preset-current-node-syntax@npm:^1.1.0": version: 1.1.0 resolution: "babel-preset-current-node-syntax@npm:1.1.0" dependencies: @@ -2823,6 +3727,18 @@ __metadata: languageName: node linkType: hard +"babel-preset-jest@npm:30.0.1": + version: 30.0.1 + resolution: "babel-preset-jest@npm:30.0.1" + dependencies: + babel-plugin-jest-hoist: "npm:30.0.1" + babel-preset-current-node-syntax: "npm:^1.1.0" + peerDependencies: + "@babel/core": ^7.11.0 + checksum: 10c0/33da0094965929b1742b02e55272b544f189cd487d55bbba60e68d96d62d48f466264fe51f65950454829d4f2271541f2433e1c1c5e6a7ff5b9e91f1303471b7 + languageName: node + linkType: hard + "babel-preset-jest@npm:^29.6.3": version: 29.6.3 resolution: "babel-preset-jest@npm:29.6.3" @@ -3123,7 +4039,7 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^3.0.0": +"callsites@npm:^3.0.0, callsites@npm:^3.1.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 @@ -3137,7 +4053,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.2.0": +"camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 @@ -3178,7 +4094,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -3249,6 +4165,13 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^4.2.0": + version: 4.2.0 + resolution: "ci-info@npm:4.2.0" + checksum: 10c0/37a2f4b6a213a5cf835890eb0241f0d5b022f6cfefde58a69e9af8e3a0e71e06d6ad7754b0d4efb9cd2613e58a7a33996d71b56b0d04242722e86666f3f3d058 + languageName: node + linkType: hard + "cjs-module-lexer@npm:^1.0.0": version: 1.4.3 resolution: "cjs-module-lexer@npm:1.4.3" @@ -3256,6 +4179,13 @@ __metadata: languageName: node linkType: hard +"cjs-module-lexer@npm:^2.1.0": + version: 2.1.0 + resolution: "cjs-module-lexer@npm:2.1.0" + checksum: 10c0/91cf28686dc3948e4a06dfa03a2fccb14b7a97471ffe7ae0124f62060ddf2de28e8e997f60007babe6e122b1b06a47c01a1b72cc015f185824d9cac3ccfa5533 + languageName: node + linkType: hard + "cli-boxes@npm:^3.0.0": version: 3.0.0 resolution: "cli-boxes@npm:3.0.0" @@ -3311,7 +4241,7 @@ __metadata: languageName: node linkType: hard -"collect-v8-coverage@npm:^1.0.0": +"collect-v8-coverage@npm:^1.0.0, collect-v8-coverage@npm:^1.0.2": version: 1.0.2 resolution: "collect-v8-coverage@npm:1.0.2" checksum: 10c0/ed7008e2e8b6852c5483b444a3ae6e976e088d4335a85aa0a9db2861c5f1d31bd2d7ff97a60469b3388deeba661a619753afbe201279fb159b4b9548ab8269a1 @@ -3530,6 +4460,18 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.6.0": + version: 1.6.0 + resolution: "dedent@npm:1.6.0" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 10c0/671b8f5e390dd2a560862c4511dd6d2638e71911486f78cb32116551f8f2aa6fcaf50579ffffb2f866d46b5b80fd72470659ca5760ede8f967619ef7df79e8a5 + languageName: node + linkType: hard + "deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -3537,7 +4479,7 @@ __metadata: languageName: node linkType: hard -"deepmerge@npm:^4.2.2": +"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": version: 4.3.1 resolution: "deepmerge@npm:4.3.1" checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 @@ -3610,7 +4552,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^3.0.0": +"detect-newline@npm:^3.0.0, detect-newline@npm:^3.1.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" checksum: 10c0/c38cfc8eeb9fda09febb44bcd85e467c970d4e3bf526095394e5a4f18bc26dd0cf6b22c69c1fa9969261521c593836db335c2795218f6d781a512aea2fb8209d @@ -3856,6 +4798,92 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:~0.25.0": + version: 0.25.5 + resolution: "esbuild@npm:0.25.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.5" + "@esbuild/android-arm": "npm:0.25.5" + "@esbuild/android-arm64": "npm:0.25.5" + "@esbuild/android-x64": "npm:0.25.5" + "@esbuild/darwin-arm64": "npm:0.25.5" + "@esbuild/darwin-x64": "npm:0.25.5" + "@esbuild/freebsd-arm64": "npm:0.25.5" + "@esbuild/freebsd-x64": "npm:0.25.5" + "@esbuild/linux-arm": "npm:0.25.5" + "@esbuild/linux-arm64": "npm:0.25.5" + "@esbuild/linux-ia32": "npm:0.25.5" + "@esbuild/linux-loong64": "npm:0.25.5" + "@esbuild/linux-mips64el": "npm:0.25.5" + "@esbuild/linux-ppc64": "npm:0.25.5" + "@esbuild/linux-riscv64": "npm:0.25.5" + "@esbuild/linux-s390x": "npm:0.25.5" + "@esbuild/linux-x64": "npm:0.25.5" + "@esbuild/netbsd-arm64": "npm:0.25.5" + "@esbuild/netbsd-x64": "npm:0.25.5" + "@esbuild/openbsd-arm64": "npm:0.25.5" + "@esbuild/openbsd-x64": "npm:0.25.5" + "@esbuild/sunos-x64": "npm:0.25.5" + "@esbuild/win32-arm64": "npm:0.25.5" + "@esbuild/win32-ia32": "npm:0.25.5" + "@esbuild/win32-x64": "npm:0.25.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/aba8cbc11927fa77562722ed5e95541ce2853f67ad7bdc40382b558abc2e0ec57d92ffb820f082ba2047b4ef9f3bc3da068cdebe30dfd3850cfa3827a78d604e + languageName: node + linkType: hard + "escalade@npm:^3.1.1, escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" @@ -3946,7 +4974,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -3963,6 +4991,13 @@ __metadata: languageName: node linkType: hard +"exit-x@npm:^0.2.2": + version: 0.2.2 + resolution: "exit-x@npm:0.2.2" + checksum: 10c0/212a7a095ca5540e9581f1ef2d1d6a40df7a6027c8cc96e78ce1d16b86d1a88326d4a0eff8dff2b5ec1e68bb0c1edd5d0dfdde87df1869bf7514d4bc6a5cbd72 + languageName: node + linkType: hard + "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -3977,6 +5012,20 @@ __metadata: languageName: node linkType: hard +"expect@npm:30.0.3": + version: 30.0.3 + resolution: "expect@npm:30.0.3" + dependencies: + "@jest/expect-utils": "npm:30.0.3" + "@jest/get-type": "npm:30.0.1" + jest-matcher-utils: "npm:30.0.3" + jest-message-util: "npm:30.0.2" + jest-mock: "npm:30.0.2" + jest-util: "npm:30.0.2" + checksum: 10c0/6bb88a42d6fcacbd0b25d4f90c389e2e439cd1d3b68f4b708582bcfe4a9575d1584edb554921e21230bc484ae55f8d639fc8186545ba9e6070a83e82a18655d8 + languageName: node + linkType: hard + "expect@npm:^29.0.0, expect@npm:^29.7.0": version: 29.7.0 resolution: "expect@npm:29.7.0" @@ -4134,7 +5183,7 @@ __metadata: languageName: node linkType: hard -"fb-watchman@npm:^2.0.0": +"fb-watchman@npm:^2.0.0, fb-watchman@npm:^2.0.2": version: 2.0.2 resolution: "fb-watchman@npm:2.0.2" dependencies: @@ -4317,7 +5366,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": +"fsevents@npm:^2.3.2, fsevents@npm:^2.3.3, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -4327,7 +5376,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A^2.3.3#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -4415,6 +5464,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.7.5": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21 + languageName: node + linkType: hard + "github-from-package@npm:0.0.0": version: 0.0.0 resolution: "github-from-package@npm:0.0.0" @@ -4431,7 +5489,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2": +"glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -4499,7 +5557,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -4672,7 +5730,7 @@ __metadata: languageName: node linkType: hard -"import-local@npm:^3.0.2": +"import-local@npm:^3.0.2, import-local@npm:^3.2.0": version: 3.2.0 resolution: "import-local@npm:3.2.0" dependencies: @@ -4791,7 +5849,7 @@ __metadata: languageName: node linkType: hard -"is-generator-fn@npm:^2.0.0": +"is-generator-fn@npm:^2.0.0, is-generator-fn@npm:^2.1.0": version: 2.1.0 resolution: "is-generator-fn@npm:2.1.0" checksum: 10c0/2957cab387997a466cd0bf5c1b6047bd21ecb32bdcfd8996b15747aa01002c1c88731802f1b3d34ac99f4f6874b626418bd118658cf39380fe5fff32a3af9c4d @@ -4919,7 +5977,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^6.0.0": +"istanbul-lib-instrument@npm:^6.0.0, istanbul-lib-instrument@npm:^6.0.2": version: 6.0.3 resolution: "istanbul-lib-instrument@npm:6.0.3" dependencies: @@ -4954,6 +6012,17 @@ __metadata: languageName: node linkType: hard +"istanbul-lib-source-maps@npm:^5.0.0": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f + languageName: node + linkType: hard + "istanbul-reports@npm:^3.1.3": version: 3.1.7 resolution: "istanbul-reports@npm:3.1.7" @@ -4991,6 +6060,17 @@ __metadata: languageName: node linkType: hard +"jest-changed-files@npm:30.0.2": + version: 30.0.2 + resolution: "jest-changed-files@npm:30.0.2" + dependencies: + execa: "npm:^5.1.1" + jest-util: "npm:30.0.2" + p-limit: "npm:^3.1.0" + checksum: 10c0/794c9e47c460974f2303631d9ee44845d03f4ccd5240649a5f736aa94af78fa5931022324ab302c577dad6adb442ed17140dee9b9985bbfa0d43cad3048a7350 + languageName: node + linkType: hard + "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -5002,6 +6082,34 @@ __metadata: languageName: node linkType: hard +"jest-circus@npm:30.0.3": + version: 30.0.3 + resolution: "jest-circus@npm:30.0.3" + dependencies: + "@jest/environment": "npm:30.0.2" + "@jest/expect": "npm:30.0.3" + "@jest/test-result": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + co: "npm:^4.6.0" + dedent: "npm:^1.6.0" + is-generator-fn: "npm:^2.1.0" + jest-each: "npm:30.0.2" + jest-matcher-utils: "npm:30.0.3" + jest-message-util: "npm:30.0.2" + jest-runtime: "npm:30.0.3" + jest-snapshot: "npm:30.0.3" + jest-util: "npm:30.0.2" + p-limit: "npm:^3.1.0" + pretty-format: "npm:30.0.2" + pure-rand: "npm:^7.0.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10c0/cb0838cc9f08984614d92c5fe857ea95f1bdff6de4a510a1b228cc9c0513d18bb2db89dcaf55624e754b11d77fb77bdba1fc56c6af34c1534102c498ce058399 + languageName: node + linkType: hard + "jest-circus@npm:^29.7.0": version: 29.7.0 resolution: "jest-circus@npm:29.7.0" @@ -5030,6 +6138,31 @@ __metadata: languageName: node linkType: hard +"jest-cli@npm:30.0.3": + version: 30.0.3 + resolution: "jest-cli@npm:30.0.3" + dependencies: + "@jest/core": "npm:30.0.3" + "@jest/test-result": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + chalk: "npm:^4.1.2" + exit-x: "npm:^0.2.2" + import-local: "npm:^3.2.0" + jest-config: "npm:30.0.3" + jest-util: "npm:30.0.2" + jest-validate: "npm:30.0.2" + yargs: "npm:^17.7.2" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: ./bin/jest.js + checksum: 10c0/17925e9e885b00069e06672c221fbe073d1bff1d869f228bcba08ac23bf8d2c258c7211ce4d0e8408ca7d0edf0afb8ae4098e3d0f5da253eed22d385b135ca90 + languageName: node + linkType: hard + "jest-cli@npm:^29.7.0": version: 29.7.0 resolution: "jest-cli@npm:29.7.0" @@ -5056,6 +6189,49 @@ __metadata: languageName: node linkType: hard +"jest-config@npm:30.0.3": + version: 30.0.3 + resolution: "jest-config@npm:30.0.3" + dependencies: + "@babel/core": "npm:^7.27.4" + "@jest/get-type": "npm:30.0.1" + "@jest/pattern": "npm:30.0.1" + "@jest/test-sequencer": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + babel-jest: "npm:30.0.2" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + deepmerge: "npm:^4.3.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" + jest-circus: "npm:30.0.3" + jest-docblock: "npm:30.0.1" + jest-environment-node: "npm:30.0.2" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.0.2" + jest-runner: "npm:30.0.3" + jest-util: "npm:30.0.2" + jest-validate: "npm:30.0.2" + micromatch: "npm:^4.0.8" + parse-json: "npm:^5.2.0" + pretty-format: "npm:30.0.2" + slash: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + peerDependencies: + "@types/node": "*" + esbuild-register: ">=3.4.0" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + checksum: 10c0/bcde9e0e715bbc12dd36a135d6e081566291b0726ed7b3ac9a1e2ee2ade7c9bcc25d312ef8a649b72b9c99e2ad6661eb843eeb919ba6206f2ec2acccdd1e57d2 + languageName: node + linkType: hard + "jest-config@npm:^29.7.0": version: 29.7.0 resolution: "jest-config@npm:29.7.0" @@ -5094,6 +6270,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:30.0.3": + version: 30.0.3 + resolution: "jest-diff@npm:30.0.3" + dependencies: + "@jest/diff-sequences": "npm:30.0.1" + "@jest/get-type": "npm:30.0.1" + chalk: "npm:^4.1.2" + pretty-format: "npm:30.0.2" + checksum: 10c0/f6aaed30fc99bdca4b8b4505b283ffc78b780aa1bf33670dfbfe439e124721e7f6198c03217f7ed17a22c7d2ca79363afd6a4245643596fa21ae082b6b4ed4f5 + languageName: node + linkType: hard + "jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -5106,6 +6294,15 @@ __metadata: languageName: node linkType: hard +"jest-docblock@npm:30.0.1": + version: 30.0.1 + resolution: "jest-docblock@npm:30.0.1" + dependencies: + detect-newline: "npm:^3.1.0" + checksum: 10c0/f9bad2651db8afa029867ea7a40f422c9d73c67657360297371846a314a40c8786424be00483261df9137499f52c2af28cd458fbd15a7bf7fac8775b4bcd6ee1 + languageName: node + linkType: hard + "jest-docblock@npm:^29.7.0": version: 29.7.0 resolution: "jest-docblock@npm:29.7.0" @@ -5115,6 +6312,19 @@ __metadata: languageName: node linkType: hard +"jest-each@npm:30.0.2": + version: 30.0.2 + resolution: "jest-each@npm:30.0.2" + dependencies: + "@jest/get-type": "npm:30.0.1" + "@jest/types": "npm:30.0.1" + chalk: "npm:^4.1.2" + jest-util: "npm:30.0.2" + pretty-format: "npm:30.0.2" + checksum: 10c0/6fff0a470d08ba3f0149c58266b7e938e3e183398f99065fe937290f1297ca254635f0f4bca6196514f756fac0a9759144b1c7f67bef97cc0b7fa0b96304df9e + languageName: node + linkType: hard + "jest-each@npm:^29.7.0": version: 29.7.0 resolution: "jest-each@npm:29.7.0" @@ -5128,6 +6338,21 @@ __metadata: languageName: node linkType: hard +"jest-environment-node@npm:30.0.2": + version: 30.0.2 + resolution: "jest-environment-node@npm:30.0.2" + dependencies: + "@jest/environment": "npm:30.0.2" + "@jest/fake-timers": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + jest-mock: "npm:30.0.2" + jest-util: "npm:30.0.2" + jest-validate: "npm:30.0.2" + checksum: 10c0/e58515d26f13704c3be6281d029c4fa0902172d2a55751205badf0153630520c4e651f7923577e1ab0dfbb64c4fedb1e4b78622b53b3a8d8e0515c1923f3adc3 + languageName: node + linkType: hard + "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -5149,6 +6374,28 @@ __metadata: languageName: node linkType: hard +"jest-haste-map@npm:30.0.2": + version: 30.0.2 + resolution: "jest-haste-map@npm:30.0.2" + dependencies: + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + anymatch: "npm:^3.1.3" + fb-watchman: "npm:^2.0.2" + fsevents: "npm:^2.3.3" + graceful-fs: "npm:^4.2.11" + jest-regex-util: "npm:30.0.1" + jest-util: "npm:30.0.2" + jest-worker: "npm:30.0.2" + micromatch: "npm:^4.0.8" + walker: "npm:^1.0.8" + dependenciesMeta: + fsevents: + optional: true + checksum: 10c0/6427b6976beb3fd33cae9a516e24f409d0cc0be2afa12a62e95671001a0d0d61662e8b2185027639b2036fe3e3b055e9d9b4dfd2063e787cf2a5d2140da0b80a + languageName: node + linkType: hard + "jest-haste-map@npm:^29.7.0": version: 29.7.0 resolution: "jest-haste-map@npm:29.7.0" @@ -5172,6 +6419,16 @@ __metadata: languageName: node linkType: hard +"jest-leak-detector@npm:30.0.2": + version: 30.0.2 + resolution: "jest-leak-detector@npm:30.0.2" + dependencies: + "@jest/get-type": "npm:30.0.1" + pretty-format: "npm:30.0.2" + checksum: 10c0/1df28475c40b41024adc6e18af0d3dc8d8d318fdbbf5c3560321fea0af2e0784c57f788b5b152efd83274ab6ea8dc3b36662060a83a2a555ffd8cdf7d628ee76 + languageName: node + linkType: hard + "jest-leak-detector@npm:^29.7.0": version: 29.7.0 resolution: "jest-leak-detector@npm:29.7.0" @@ -5182,6 +6439,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:30.0.3": + version: 30.0.3 + resolution: "jest-matcher-utils@npm:30.0.3" + dependencies: + "@jest/get-type": "npm:30.0.1" + chalk: "npm:^4.1.2" + jest-diff: "npm:30.0.3" + pretty-format: "npm:30.0.2" + checksum: 10c0/4d354f6d8d3992228ba5f0ecc728ec0c46f3693805927253d67e461e754deadc1e1b48ae80918e3f029c22da4abed9aaadb5049da1a1697f6714b0f6076eeafa + languageName: node + linkType: hard + "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -5194,6 +6463,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:30.0.2": + version: 30.0.2 + resolution: "jest-message-util@npm:30.0.2" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@jest/types": "npm:30.0.1" + "@types/stack-utils": "npm:^2.0.3" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.0.2" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10c0/c010d5b7d86e735e2fb4c4a220f57004349f488f5d4663240a7e9f2694d01b5228136540d55036777fde4227b5e0b56f08885b7f69395b295cab878357b1aeb1 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -5211,6 +6497,17 @@ __metadata: languageName: node linkType: hard +"jest-mock@npm:30.0.2": + version: 30.0.2 + resolution: "jest-mock@npm:30.0.2" + dependencies: + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + jest-util: "npm:30.0.2" + checksum: 10c0/7728997c1d654475b88e18b7ba33a2a1b9f89ce33a9082bf2d14dcc3e831f372f80c762e481777886a3a04b4489ea5390ecdeb21c4def57fba5b2c77086a3959 + languageName: node + linkType: hard + "jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" @@ -5222,7 +6519,7 @@ __metadata: languageName: node linkType: hard -"jest-pnp-resolver@npm:^1.2.2": +"jest-pnp-resolver@npm:^1.2.2, jest-pnp-resolver@npm:^1.2.3": version: 1.2.3 resolution: "jest-pnp-resolver@npm:1.2.3" peerDependencies: @@ -5234,6 +6531,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:30.0.1": + version: 30.0.1 + resolution: "jest-regex-util@npm:30.0.1" + checksum: 10c0/f30c70524ebde2d1012afe5ffa5691d5d00f7d5ba9e43d588f6460ac6fe96f9e620f2f9b36a02d0d3e7e77bc8efb8b3450ae3b80ac53c8be5099e01bf54f6728 + languageName: node + linkType: hard + "jest-regex-util@npm:^29.6.3": version: 29.6.3 resolution: "jest-regex-util@npm:29.6.3" @@ -5241,6 +6545,16 @@ __metadata: languageName: node linkType: hard +"jest-resolve-dependencies@npm:30.0.3": + version: 30.0.3 + resolution: "jest-resolve-dependencies@npm:30.0.3" + dependencies: + jest-regex-util: "npm:30.0.1" + jest-snapshot: "npm:30.0.3" + checksum: 10c0/5684e62f05d19c5ab97b2b2262075f056bd48745bf25501671d0b9a03f2a0548ab04370b9cec6e97207d57ead54d706a67ef3254729cacb6d6405ef381cdf511 + languageName: node + linkType: hard + "jest-resolve-dependencies@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve-dependencies@npm:29.7.0" @@ -5251,6 +6565,22 @@ __metadata: languageName: node linkType: hard +"jest-resolve@npm:30.0.2": + version: 30.0.2 + resolution: "jest-resolve@npm:30.0.2" + dependencies: + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.0.2" + jest-pnp-resolver: "npm:^1.2.3" + jest-util: "npm:30.0.2" + jest-validate: "npm:30.0.2" + slash: "npm:^3.0.0" + unrs-resolver: "npm:^1.7.11" + checksum: 10c0/33ae69455b1206a926bb6f7dd46cd4b6cbf5e095387078873a05dfb693bef419b93897e052ee68026b31b5e5f537fdcfce42f2d31af0ce7e64a8179ed7882b51 + languageName: node + linkType: hard + "jest-resolve@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve@npm:29.7.0" @@ -5268,6 +6598,36 @@ __metadata: languageName: node linkType: hard +"jest-runner@npm:30.0.3": + version: 30.0.3 + resolution: "jest-runner@npm:30.0.3" + dependencies: + "@jest/console": "npm:30.0.2" + "@jest/environment": "npm:30.0.2" + "@jest/test-result": "npm:30.0.2" + "@jest/transform": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + emittery: "npm:^0.13.1" + exit-x: "npm:^0.2.2" + graceful-fs: "npm:^4.2.11" + jest-docblock: "npm:30.0.1" + jest-environment-node: "npm:30.0.2" + jest-haste-map: "npm:30.0.2" + jest-leak-detector: "npm:30.0.2" + jest-message-util: "npm:30.0.2" + jest-resolve: "npm:30.0.2" + jest-runtime: "npm:30.0.3" + jest-util: "npm:30.0.2" + jest-watcher: "npm:30.0.2" + jest-worker: "npm:30.0.2" + p-limit: "npm:^3.1.0" + source-map-support: "npm:0.5.13" + checksum: 10c0/d139ee4ed4f2d7aeefc8c496efc906960e938beadc22dce6167e7270db4e10260092eace6748a6efb7ee2a40e3bd3ee5d60cbefc2a1e3459826cfde69cdb9195 + languageName: node + linkType: hard + "jest-runner@npm:^29.7.0": version: 29.7.0 resolution: "jest-runner@npm:29.7.0" @@ -5297,6 +6657,36 @@ __metadata: languageName: node linkType: hard +"jest-runtime@npm:30.0.3": + version: 30.0.3 + resolution: "jest-runtime@npm:30.0.3" + dependencies: + "@jest/environment": "npm:30.0.2" + "@jest/fake-timers": "npm:30.0.2" + "@jest/globals": "npm:30.0.3" + "@jest/source-map": "npm:30.0.1" + "@jest/test-result": "npm:30.0.2" + "@jest/transform": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + cjs-module-lexer: "npm:^2.1.0" + collect-v8-coverage: "npm:^1.0.2" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.11" + jest-haste-map: "npm:30.0.2" + jest-message-util: "npm:30.0.2" + jest-mock: "npm:30.0.2" + jest-regex-util: "npm:30.0.1" + jest-resolve: "npm:30.0.2" + jest-snapshot: "npm:30.0.3" + jest-util: "npm:30.0.2" + slash: "npm:^3.0.0" + strip-bom: "npm:^4.0.0" + checksum: 10c0/01a184b80bf1ae2d6eca280daf37e355b983795e342406de461cf4d45c75ec48a635bf89c08d54fb73f851180e870ef82004fd1f6b335f0329dc07f3bd14a94d + languageName: node + linkType: hard + "jest-runtime@npm:^29.7.0": version: 29.7.0 resolution: "jest-runtime@npm:29.7.0" @@ -5327,6 +6717,35 @@ __metadata: languageName: node linkType: hard +"jest-snapshot@npm:30.0.3": + version: 30.0.3 + resolution: "jest-snapshot@npm:30.0.3" + dependencies: + "@babel/core": "npm:^7.27.4" + "@babel/generator": "npm:^7.27.5" + "@babel/plugin-syntax-jsx": "npm:^7.27.1" + "@babel/plugin-syntax-typescript": "npm:^7.27.1" + "@babel/types": "npm:^7.27.3" + "@jest/expect-utils": "npm:30.0.3" + "@jest/get-type": "npm:30.0.1" + "@jest/snapshot-utils": "npm:30.0.1" + "@jest/transform": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + babel-preset-current-node-syntax: "npm:^1.1.0" + chalk: "npm:^4.1.2" + expect: "npm:30.0.3" + graceful-fs: "npm:^4.2.11" + jest-diff: "npm:30.0.3" + jest-matcher-utils: "npm:30.0.3" + jest-message-util: "npm:30.0.2" + jest-util: "npm:30.0.2" + pretty-format: "npm:30.0.2" + semver: "npm:^7.7.2" + synckit: "npm:^0.11.8" + checksum: 10c0/0af682495b79bc0e640edbb03ada06db073a0784d6a9c0bb11e592afa4d0dca63c63ab485f540e8d1bd7674456418906e194e7f0660cc20107423d4fe11b4d6e + languageName: node + linkType: hard + "jest-snapshot@npm:^29.7.0": version: 29.7.0 resolution: "jest-snapshot@npm:29.7.0" @@ -5365,6 +6784,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:30.0.2": + version: 30.0.2 + resolution: "jest-util@npm:30.0.2" + dependencies: + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.2" + checksum: 10c0/07de384790b8e5a5925fba5448fa1475790a5b52271fbf99958c18e468da1af940f8b45e330d87766576cf6c5d1f4f41ce51c976483a5079653d9fcdba8aac8e + languageName: node + linkType: hard + "jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" @@ -5379,6 +6812,20 @@ __metadata: languageName: node linkType: hard +"jest-validate@npm:30.0.2": + version: 30.0.2 + resolution: "jest-validate@npm:30.0.2" + dependencies: + "@jest/get-type": "npm:30.0.1" + "@jest/types": "npm:30.0.1" + camelcase: "npm:^6.3.0" + chalk: "npm:^4.1.2" + leven: "npm:^3.1.0" + pretty-format: "npm:30.0.2" + checksum: 10c0/9fd1b4f604851187655353eefe8db25db9638dd312d2e29d58868e626d78925edefe94fe2c8eb63305eefd41e5fe7f8aff334e2db9db5aaddeec866f9f6561d8 + languageName: node + linkType: hard + "jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" @@ -5393,6 +6840,22 @@ __metadata: languageName: node linkType: hard +"jest-watcher@npm:30.0.2": + version: 30.0.2 + resolution: "jest-watcher@npm:30.0.2" + dependencies: + "@jest/test-result": "npm:30.0.2" + "@jest/types": "npm:30.0.1" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.3.2" + chalk: "npm:^4.1.2" + emittery: "npm:^0.13.1" + jest-util: "npm:30.0.2" + string-length: "npm:^4.0.2" + checksum: 10c0/7cb09da5feaa6c5558e5149406bde354c3e227ef692b5371efe4d13cf566d42a157c04a55f3a201d191afb7ebc49be84b1ed5a744f46497d9ecccc323d8963f5 + languageName: node + linkType: hard + "jest-watcher@npm:^29.7.0": version: 29.7.0 resolution: "jest-watcher@npm:29.7.0" @@ -5409,6 +6872,19 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:30.0.2": + version: 30.0.2 + resolution: "jest-worker@npm:30.0.2" + dependencies: + "@types/node": "npm:*" + "@ungap/structured-clone": "npm:^1.3.0" + jest-util: "npm:30.0.2" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.1.1" + checksum: 10c0/d7d237e763a2f1aed4eba07f977490442a7bb085f7ab63163afa88776804c2644cc05a1e32da9d05a4b895ad22b2e939ef01a90ffb3024b53fc8c73b8ad1d3f1 + languageName: node + linkType: hard + "jest-worker@npm:^29.7.0": version: 29.7.0 resolution: "jest-worker@npm:29.7.0" @@ -5440,6 +6916,25 @@ __metadata: languageName: node linkType: hard +"jest@npm:^30.0.3": + version: 30.0.3 + resolution: "jest@npm:30.0.3" + dependencies: + "@jest/core": "npm:30.0.3" + "@jest/types": "npm:30.0.1" + import-local: "npm:^3.2.0" + jest-cli: "npm:30.0.3" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: ./bin/jest.js + checksum: 10c0/ae4fbee2756e03b6f99f612438e3b4e25789731599a4d4617ce5002d4c68f169f6223f6b21522fe65cd3d00519e0bb534ac6db6b2cdb7cd46a4ad3ded6542f38 + languageName: node + linkType: hard + "js-sha3@npm:0.8.0": version: 0.8.0 resolution: "js-sha3@npm:0.8.0" @@ -6037,6 +7532,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.2.4": + version: 0.2.5 + resolution: "napi-postinstall@npm:0.2.5" + bin: + napi-postinstall: lib/cli.js + checksum: 10c0/c4a1a8ca61aece10a6a7b46b834d7689321c4bb164710df9d896a273f24544084c5be95b47c55208036a06ae5bfa0afabb6a8886985d4438543ee07344b9c90c + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -6486,7 +7990,7 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.4": +"pirates@npm:^4.0.4, pirates@npm:^4.0.7": version: 4.0.7 resolution: "pirates@npm:4.0.7" checksum: 10c0/a51f108dd811beb779d58a76864bbd49e239fa40c7984cd11596c75a121a8cc789f1c8971d8bb15f0dbf9d48b76c05bb62fcbce840f89b688c0fa64b37e8478a @@ -6549,6 +8053,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:30.0.2": + version: 30.0.2 + resolution: "pretty-format@npm:30.0.2" + dependencies: + "@jest/schemas": "npm:30.0.1" + ansi-styles: "npm:^5.2.0" + react-is: "npm:^18.3.1" + checksum: 10c0/cf542dc2d0be95e2b1c6e3a397a4fc13fce1c9f8feed6b56165c0d23c7a83423abb6b032ed8e3e1b7c1c0709f9b117dd30b5185f107e58f8766616be6de84850 + languageName: node + linkType: hard + "pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -6659,6 +8174,13 @@ __metadata: languageName: node linkType: hard +"pure-rand@npm:^7.0.0": + version: 7.0.1 + resolution: "pure-rand@npm:7.0.1" + checksum: 10c0/9cade41030f5ec95f5d55a11a71404cd6f46b69becaad892097cd7f58e2c6248cd0a933349ca7d21336ab629f1da42ffe899699b671bc4651600eaf6e57f837e + languageName: node + linkType: hard + "qs@npm:6.13.0": version: 6.13.0 resolution: "qs@npm:6.13.0" @@ -6755,7 +8277,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 @@ -7012,6 +8534,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + "send@npm:0.19.0": version: 0.19.0 resolution: "send@npm:0.19.0" @@ -7287,7 +8818,7 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.3": +"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -7303,7 +8834,7 @@ __metadata: languageName: node linkType: hard -"string-length@npm:^4.0.1": +"string-length@npm:^4.0.1, string-length@npm:^4.0.2": version: 4.0.2 resolution: "string-length@npm:4.0.2" dependencies: @@ -7433,7 +8964,7 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^8.0.0": +"supports-color@npm:^8.0.0, supports-color@npm:^8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" dependencies: @@ -7456,6 +8987,15 @@ __metadata: languageName: node linkType: hard +"synckit@npm:^0.11.8": + version: 0.11.8 + resolution: "synckit@npm:0.11.8" + dependencies: + "@pkgr/core": "npm:^0.2.4" + checksum: 10c0/a1de5131ee527512afcaafceb2399b2f3e63678e56b831e1cb2dc7019c972a8b654703a3b94ef4166868f87eb984ea252b467c9d9e486b018ec2e6a55c24dfd8 + languageName: node + linkType: hard + "tar-fs@npm:^2.0.0": version: 2.1.2 resolution: "tar-fs@npm:2.1.2" @@ -7667,13 +9207,29 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0": +"tslib@npm:^2.1.0, tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 languageName: node linkType: hard +"tsx@npm:^4.20.3": + version: 4.20.3 + resolution: "tsx@npm:4.20.3" + dependencies: + esbuild: "npm:~0.25.0" + fsevents: "npm:~2.3.3" + get-tsconfig: "npm:^4.7.5" + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: 10c0/6ff0d91ed046ec743fac7ed60a07f3c025e5b71a5aaf58f3d2a6b45e4db114c83e59ebbb078c8e079e48d3730b944a02bc0de87695088aef4ec8bbc705dc791b + languageName: node + linkType: hard + "tunnel-agent@npm:^0.6.0": version: 0.6.0 resolution: "tunnel-agent@npm:0.6.0" @@ -7833,6 +9389,73 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11": + version: 1.9.2 + resolution: "unrs-resolver@npm:1.9.2" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.9.2" + "@unrs/resolver-binding-android-arm64": "npm:1.9.2" + "@unrs/resolver-binding-darwin-arm64": "npm:1.9.2" + "@unrs/resolver-binding-darwin-x64": "npm:1.9.2" + "@unrs/resolver-binding-freebsd-x64": "npm:1.9.2" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.9.2" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.9.2" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.9.2" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.9.2" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.9.2" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.9.2" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.9.2" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.9.2" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.9.2" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.9.2" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.9.2" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.9.2" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.9.2" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.9.2" + napi-postinstall: "npm:^0.2.4" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10c0/e3481cc19ea4b25f888e2412bbd80a729b13527a41b035e784b71d1a7d4e2109b58b174adce989085eb75c787435e80ffb385db2b1598288474f53beb01438c0 + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.1.1": version: 1.1.3 resolution: "update-browserslist-db@npm:1.1.3" @@ -8093,6 +9716,16 @@ __metadata: languageName: node linkType: hard +"write-file-atomic@npm:^5.0.1": + version: 5.0.1 + resolution: "write-file-atomic@npm:5.0.1" + dependencies: + imurmurhash: "npm:^0.1.4" + signal-exit: "npm:^4.0.1" + checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d + languageName: node + linkType: hard + "ws@npm:8.17.1": version: 8.17.1 resolution: "ws@npm:8.17.1" @@ -8214,7 +9847,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.3.1": +"yargs@npm:^17.3.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: