@manifest-network/manifest-mcp-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__test-utils__/callTool.d.ts +29 -0
- package/dist/__test-utils__/callTool.d.ts.map +1 -0
- package/dist/__test-utils__/callTool.js +45 -0
- package/dist/__test-utils__/callTool.js.map +1 -0
- package/dist/__test-utils__/mocks.d.ts +125 -0
- package/dist/__test-utils__/mocks.d.ts.map +1 -0
- package/dist/__test-utils__/mocks.js +146 -0
- package/dist/__test-utils__/mocks.js.map +1 -0
- package/dist/client.d.ts +67 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +209 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +127 -0
- package/dist/config.js.map +1 -0
- package/dist/cosmos.d.ts +24 -0
- package/dist/cosmos.d.ts.map +1 -0
- package/dist/cosmos.js +85 -0
- package/dist/cosmos.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +20 -0
- package/dist/lcd-adapter.d.ts +15 -0
- package/dist/lcd-adapter.d.ts.map +1 -0
- package/dist/lcd-adapter.js +98 -0
- package/dist/lcd-adapter.js.map +1 -0
- package/dist/logger.d.ts +20 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +43 -0
- package/dist/logger.js.map +1 -0
- package/dist/modules.d.ts +63 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +759 -0
- package/dist/modules.js.map +1 -0
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +78 -0
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js.map +1 -0
- package/dist/node_modules/@vitest/expect/dist/index.d.ts +802 -0
- package/dist/node_modules/@vitest/expect/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/expect/dist/index.js +1457 -0
- package/dist/node_modules/@vitest/expect/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.d.ts +95 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.js +877 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/chunk-tasks.js +91 -0
- package/dist/node_modules/@vitest/runner/dist/chunk-tasks.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/index.js +1381 -0
- package/dist/node_modules/@vitest/runner/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/tasks.d-D2GKpdwQ.d.ts +540 -0
- package/dist/node_modules/@vitest/runner/dist/tasks.d-D2GKpdwQ.d.ts.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/utils.js +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/environment.d-DOJxxZV9.d.ts +16 -0
- package/dist/node_modules/@vitest/snapshot/dist/environment.d-DOJxxZV9.d.ts.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.d.ts +89 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.js +649 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/rawSnapshot.d-U2kJUxDr.d.ts +40 -0
- package/dist/node_modules/@vitest/snapshot/dist/rawSnapshot.d-U2kJUxDr.d.ts.map +1 -0
- package/dist/node_modules/@vitest/spy/dist/index.d.ts +343 -0
- package/dist/node_modules/@vitest/spy/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/spy/dist/index.js +386 -0
- package/dist/node_modules/@vitest/spy/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
- package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/diff.d.ts +14 -0
- package/dist/node_modules/@vitest/utils/dist/diff.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/diff.js +1297 -0
- package/dist/node_modules/@vitest/utils/dist/diff.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/display.d.ts +15 -0
- package/dist/node_modules/@vitest/utils/dist/display.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/display.js +558 -0
- package/dist/node_modules/@vitest/utils/dist/display.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/error.js +30 -0
- package/dist/node_modules/@vitest/utils/dist/error.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/helpers.js +181 -0
- package/dist/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/offset.js +27 -0
- package/dist/node_modules/@vitest/utils/dist/offset.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/serialize.js +77 -0
- package/dist/node_modules/@vitest/utils/dist/serialize.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/source-map.js +367 -0
- package/dist/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/timers.js +37 -0
- package/dist/node_modules/@vitest/utils/dist/timers.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts +38 -0
- package/dist/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/types.d.ts +25 -0
- package/dist/node_modules/@vitest/utils/dist/types.d.ts.map +1 -0
- package/dist/node_modules/chai/index.js +2875 -0
- package/dist/node_modules/chai/index.js.map +1 -0
- package/dist/node_modules/magic-string/dist/magic-string.es.js +939 -0
- package/dist/node_modules/magic-string/dist/magic-string.es.js.map +1 -0
- package/dist/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +85 -0
- package/dist/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js.map +1 -0
- package/dist/node_modules/tinybench/dist/index.d.ts +91 -0
- package/dist/node_modules/tinybench/dist/index.d.ts.map +1 -0
- package/dist/node_modules/tinyrainbow/dist/index.d.ts +9 -0
- package/dist/node_modules/tinyrainbow/dist/index.d.ts.map +1 -0
- package/dist/node_modules/tinyrainbow/dist/index.js +86 -0
- package/dist/node_modules/tinyrainbow/dist/index.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
- package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.D0SlKNbZ.js +41 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.D0SlKNbZ.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.d.DAaHLpsq.d.ts +12 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.d.DAaHLpsq.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/global.d.x-ILCfAE.d.ts +100 -0
- package/dist/node_modules/vitest/dist/chunks/global.d.x-ILCfAE.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +57 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.d.BFMWpdph.d.ts +13 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.d.BFMWpdph.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/test.CTcmp4Su.js +2791 -0
- package/dist/node_modules/vitest/dist/chunks/test.CTcmp4Su.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +44 -0
- package/dist/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js.map +1 -0
- package/dist/node_modules/vitest/dist/index.d.ts +9 -0
- package/dist/queries/auth.d.ts +15 -0
- package/dist/queries/auth.d.ts.map +1 -0
- package/dist/queries/auth.js +58 -0
- package/dist/queries/auth.js.map +1 -0
- package/dist/queries/bank.d.ts +15 -0
- package/dist/queries/bank.d.ts.map +1 -0
- package/dist/queries/bank.js +93 -0
- package/dist/queries/bank.js.map +1 -0
- package/dist/queries/billing.d.ts +15 -0
- package/dist/queries/billing.d.ts.map +1 -0
- package/dist/queries/billing.js +114 -0
- package/dist/queries/billing.js.map +1 -0
- package/dist/queries/distribution.d.ts +15 -0
- package/dist/queries/distribution.d.ts.map +1 -0
- package/dist/queries/distribution.js +73 -0
- package/dist/queries/distribution.js.map +1 -0
- package/dist/queries/gov.d.ts +15 -0
- package/dist/queries/gov.d.ts.map +1 -0
- package/dist/queries/gov.js +98 -0
- package/dist/queries/gov.js.map +1 -0
- package/dist/queries/group.d.ts +15 -0
- package/dist/queries/group.d.ts.map +1 -0
- package/dist/queries/group.js +159 -0
- package/dist/queries/group.js.map +1 -0
- package/dist/queries/index.d.ts +10 -0
- package/dist/queries/index.js +10 -0
- package/dist/queries/sku.d.ts +16 -0
- package/dist/queries/sku.d.ts.map +1 -0
- package/dist/queries/sku.js +85 -0
- package/dist/queries/sku.js.map +1 -0
- package/dist/queries/staking.d.ts +15 -0
- package/dist/queries/staking.d.ts.map +1 -0
- package/dist/queries/staking.js +127 -0
- package/dist/queries/staking.js.map +1 -0
- package/dist/queries/utils.d.ts +54 -0
- package/dist/queries/utils.d.ts.map +1 -0
- package/dist/queries/utils.js +74 -0
- package/dist/queries/utils.js.map +1 -0
- package/dist/retry.d.ts +48 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +106 -0
- package/dist/retry.js.map +1 -0
- package/dist/server-utils.d.ts +61 -0
- package/dist/server-utils.d.ts.map +1 -0
- package/dist/server-utils.js +156 -0
- package/dist/server-utils.js.map +1 -0
- package/dist/tools/fundCredits.d.ts +8 -0
- package/dist/tools/fundCredits.d.ts.map +1 -0
- package/dist/tools/fundCredits.js +9 -0
- package/dist/tools/fundCredits.js.map +1 -0
- package/dist/tools/getBalance.d.ts +26 -0
- package/dist/tools/getBalance.d.ts.map +1 -0
- package/dist/tools/getBalance.js +59 -0
- package/dist/tools/getBalance.js.map +1 -0
- package/dist/tools/stopApp.d.ts +13 -0
- package/dist/tools/stopApp.d.ts.map +1 -0
- package/dist/tools/stopApp.js +15 -0
- package/dist/tools/stopApp.js.map +1 -0
- package/dist/transactions/bank.d.ts +11 -0
- package/dist/transactions/bank.d.ts.map +1 -0
- package/dist/transactions/bank.js +75 -0
- package/dist/transactions/bank.js.map +1 -0
- package/dist/transactions/billing.d.ts +11 -0
- package/dist/transactions/billing.d.ts.map +1 -0
- package/dist/transactions/billing.js +189 -0
- package/dist/transactions/billing.js.map +1 -0
- package/dist/transactions/distribution.d.ts +11 -0
- package/dist/transactions/distribution.d.ts.map +1 -0
- package/dist/transactions/distribution.js +60 -0
- package/dist/transactions/distribution.js.map +1 -0
- package/dist/transactions/gov.d.ts +11 -0
- package/dist/transactions/gov.d.ts.map +1 -0
- package/dist/transactions/gov.js +108 -0
- package/dist/transactions/gov.js.map +1 -0
- package/dist/transactions/group.d.ts +11 -0
- package/dist/transactions/group.d.ts.map +1 -0
- package/dist/transactions/group.js +347 -0
- package/dist/transactions/group.js.map +1 -0
- package/dist/transactions/index.d.ts +10 -0
- package/dist/transactions/index.js +10 -0
- package/dist/transactions/manifest.d.ts +11 -0
- package/dist/transactions/manifest.d.ts.map +1 -0
- package/dist/transactions/manifest.js +59 -0
- package/dist/transactions/manifest.js.map +1 -0
- package/dist/transactions/sku.d.ts +11 -0
- package/dist/transactions/sku.d.ts.map +1 -0
- package/dist/transactions/sku.js +191 -0
- package/dist/transactions/sku.js.map +1 -0
- package/dist/transactions/staking.d.ts +11 -0
- package/dist/transactions/staking.d.ts.map +1 -0
- package/dist/transactions/staking.js +79 -0
- package/dist/transactions/staking.js.map +1 -0
- package/dist/transactions/utils.d.ts +161 -0
- package/dist/transactions/utils.d.ts.map +1 -0
- package/dist/transactions/utils.js +272 -0
- package/dist/transactions/utils.js.map +1 -0
- package/dist/types.d.ts +390 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +30 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +53 -0
- package/dist/validation.js.map +1 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/dist/wallet/index.d.ts +4 -0
- package/dist/wallet/index.js +3 -0
- package/dist/wallet/mnemonic.d.ts +47 -0
- package/dist/wallet/mnemonic.d.ts.map +1 -0
- package/dist/wallet/mnemonic.js +97 -0
- package/dist/wallet/mnemonic.js.map +1 -0
- package/dist/wallet/sign-arbitrary.d.ts +12 -0
- package/dist/wallet/sign-arbitrary.d.ts.map +1 -0
- package/dist/wallet/sign-arbitrary.js +36 -0
- package/dist/wallet/sign-arbitrary.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { Registry } from '@cosmjs/proto-signing';\nimport {\n AminoTypes,\n GasPrice,\n type HttpEndpoint,\n SigningStargateClient,\n} from '@cosmjs/stargate';\nimport {\n cosmosAminoConverters,\n cosmosProtoRegistry,\n liftedinit,\n liftedinitAminoConverters,\n liftedinitProtoRegistry,\n osmosisAminoConverters,\n osmosisProtoRegistry,\n strangeloveVenturesAminoConverters,\n strangeloveVenturesProtoRegistry,\n} from '@manifest-network/manifestjs';\nimport { RateLimiter } from 'limiter';\nimport { DEFAULT_REQUESTS_PER_SECOND } from './config.js';\nimport { createLCDQueryClient } from './lcd-adapter.js';\nimport { withRetry } from './retry.js';\nimport {\n type ManifestMCPConfig,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type WalletProvider,\n} from './types.js';\n\n// Type for the RPC query client from manifestjs liftedinit bundle\n// This includes cosmos modules + liftedinit-specific modules (billing, manifest, sku)\nexport type ManifestQueryClient = Awaited<\n ReturnType<typeof liftedinit.ClientFactory.createRPCQueryClient>\n>;\n\n/**\n * Extract the registry type expected by SigningStargateClient.connectWithSigner.\n *\n * The Registry type from @cosmjs/proto-signing doesn't perfectly match the registry type\n * in SigningStargateClientOptions due to telescope-generated proto types. This type alias\n * extracts the expected registry type from the function signature to enable type-safe casting.\n */\ntype SigningClientRegistry = Parameters<\n typeof SigningStargateClient.connectWithSigner\n>[2] extends { registry?: infer R }\n ? R\n : never;\n\n/** Default timeout for transaction broadcast (60 seconds) */\nconst DEFAULT_BROADCAST_TIMEOUT_MS = 60_000;\n\n/** Default polling interval for transaction confirmation (3 seconds) */\nconst DEFAULT_BROADCAST_POLL_INTERVAL_MS = 3_000;\n\n/**\n * Get combined signing client options with all Manifest registries\n */\nfunction getSigningManifestClientOptions() {\n const registry = new Registry([\n ...cosmosProtoRegistry,\n ...liftedinitProtoRegistry,\n ...strangeloveVenturesProtoRegistry,\n ...osmosisProtoRegistry,\n ]);\n\n const aminoTypes = new AminoTypes({\n ...cosmosAminoConverters,\n ...liftedinitAminoConverters,\n ...strangeloveVenturesAminoConverters,\n ...osmosisAminoConverters,\n });\n\n return { registry, aminoTypes };\n}\n\n/**\n * Manages CosmJS client instances with lazy initialization and singleton pattern\n */\nexport class CosmosClientManager {\n private static instances: Map<string, CosmosClientManager> = new Map();\n\n private config: ManifestMCPConfig;\n private walletProvider: WalletProvider;\n private queryClient: ManifestQueryClient | null = null;\n private signingClient: SigningStargateClient | null = null;\n private rateLimiter: RateLimiter;\n\n // Promises to prevent concurrent client initialization (lazy init race condition)\n private queryClientPromise: Promise<ManifestQueryClient> | null = null;\n private signingClientPromise: Promise<SigningStargateClient> | null = null;\n\n private constructor(\n config: ManifestMCPConfig,\n walletProvider: WalletProvider,\n ) {\n this.config = config;\n this.walletProvider = walletProvider;\n\n // Initialize rate limiter with configured or default requests per second\n const requestsPerSecond =\n config.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND;\n this.rateLimiter = new RateLimiter({\n tokensPerInterval: requestsPerSecond,\n interval: 'second',\n });\n }\n\n /**\n * Get or create a singleton instance for the given config.\n * Instances are keyed by chainId:rpcUrl:restUrl. For existing instances:\n * - Config and walletProvider references are always updated\n * - Signing client is disconnected/recreated if gasPrice or walletProvider changed\n * - Rate limiter is updated if requestsPerSecond changed (without affecting signing client)\n */\n static getInstance(\n config: ManifestMCPConfig,\n walletProvider: WalletProvider,\n ): CosmosClientManager {\n const parts = [config.chainId, config.rpcUrl ?? ''];\n if (config.restUrl) parts.push(config.restUrl);\n const key = parts.join(':');\n let instance = CosmosClientManager.instances.get(key);\n\n if (!instance) {\n instance = new CosmosClientManager(config, walletProvider);\n CosmosClientManager.instances.set(key, instance);\n } else {\n // Check what changed to determine what needs updating\n const signingClientAffected =\n instance.config.gasPrice !== config.gasPrice ||\n instance.walletProvider !== walletProvider;\n\n const rateLimitChanged =\n instance.config.rateLimit?.requestsPerSecond !==\n config.rateLimit?.requestsPerSecond;\n\n // Always update config reference\n instance.config = config;\n instance.walletProvider = walletProvider;\n\n // Only invalidate signing client if fields it depends on changed\n if (signingClientAffected) {\n if (instance.signingClient) {\n instance.signingClient.disconnect();\n instance.signingClient = null;\n }\n // Also clear the promise to allow re-initialization with new config\n instance.signingClientPromise = null;\n }\n\n // Update rate limiter independently (doesn't affect signing client)\n if (rateLimitChanged) {\n const newRps =\n config.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND;\n instance.rateLimiter = new RateLimiter({\n tokensPerInterval: newRps,\n interval: 'second',\n });\n }\n }\n\n return instance;\n }\n\n /**\n * Clear all cached instances (useful for testing or reconnection).\n * Disconnects signing clients and releases query client references before clearing.\n */\n static clearInstances(): void {\n for (const instance of CosmosClientManager.instances.values()) {\n instance.disconnect();\n }\n CosmosClientManager.instances.clear();\n }\n\n /**\n * Get the manifestjs RPC query client with all module extensions\n *\n * Automatically retries on transient connection failures with exponential backoff.\n */\n async getQueryClient(): Promise<ManifestQueryClient> {\n // Return cached client if available\n if (this.queryClient) {\n return this.queryClient;\n }\n\n // If initialization is already in progress, wait for it\n if (this.queryClientPromise) {\n return this.queryClientPromise;\n }\n\n // Start initialization and cache the promise to prevent concurrent init\n this.queryClientPromise = (async () => {\n // Capture reference to detect if superseded by disconnect/config change\n const thisInitPromise = this.queryClientPromise;\n try {\n let client: ManifestQueryClient;\n if (this.config.restUrl) {\n // Use LCD/REST for queries when restUrl is configured\n client = await withRetry(\n () => createLCDQueryClient(this.config.restUrl!),\n {\n config: this.config.retry,\n operationName: 'connect LCD query client',\n },\n );\n } else if (this.config.rpcUrl) {\n // Use RPC (existing behavior)\n client = await withRetry(\n () =>\n liftedinit.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n {\n config: this.config.retry,\n operationName: 'connect query client',\n },\n );\n } else {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'Cannot create query client: neither restUrl nor rpcUrl is configured.',\n );\n }\n // Only store if this is still the active promise\n if (this.queryClientPromise === thisInitPromise) {\n this.queryClient = client;\n this.queryClientPromise = null;\n }\n return client;\n } catch (error) {\n // Clear promise on failure so retry is possible (only if still active)\n if (this.queryClientPromise === thisInitPromise) {\n this.queryClientPromise = null;\n }\n if (error instanceof ManifestMCPError) {\n throw error;\n }\n const endpoint = this.config.restUrl ?? this.config.rpcUrl;\n throw new ManifestMCPError(\n ManifestMCPErrorCode.RPC_CONNECTION_FAILED,\n `Failed to connect to ${this.config.restUrl ? 'REST' : 'RPC'} endpoint: ${error instanceof Error ? error.message : String(error)}`,\n { url: endpoint },\n );\n }\n })();\n\n return this.queryClientPromise;\n }\n\n /**\n * Get a signing client with all Manifest registries (for transactions)\n *\n * Automatically retries on transient connection failures with exponential backoff.\n */\n async getSigningClient(): Promise<SigningStargateClient> {\n if (!this.config.rpcUrl || !this.config.gasPrice) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'Signing client requires rpcUrl and gasPrice configuration. Current config is query-only (REST).',\n );\n }\n\n // Return cached client if available\n if (this.signingClient) {\n return this.signingClient;\n }\n\n // If initialization is already in progress, wait for it\n if (this.signingClientPromise) {\n return this.signingClientPromise;\n }\n\n // Start initialization and cache the promise to prevent concurrent init\n this.signingClientPromise = (async () => {\n // Capture reference to detect if superseded by disconnect/config change\n const thisInitPromise = this.signingClientPromise;\n try {\n const signer = await this.walletProvider.getSigner();\n const gasPrice = GasPrice.fromString(this.config.gasPrice!);\n const { registry, aminoTypes } = getSigningManifestClientOptions();\n\n // Configure endpoint as HttpEndpoint object (required for custom options)\n const endpoint: HttpEndpoint = {\n url: this.config.rpcUrl!,\n headers: {},\n };\n\n // Note: Registry type from @cosmjs/proto-signing doesn't perfectly match\n // SigningStargateClientOptions due to telescope-generated proto types.\n // This is a known limitation with custom cosmos-sdk module registries.\n // Wrap with retry for transient connection failures\n const client = await withRetry(\n () =>\n SigningStargateClient.connectWithSigner(endpoint, signer, {\n registry: registry as SigningClientRegistry,\n aminoTypes,\n gasPrice,\n broadcastTimeoutMs: DEFAULT_BROADCAST_TIMEOUT_MS,\n broadcastPollIntervalMs: DEFAULT_BROADCAST_POLL_INTERVAL_MS,\n }),\n {\n config: this.config.retry,\n operationName: 'connect signing client',\n },\n );\n // Only store if this is still the active promise\n if (this.signingClientPromise === thisInitPromise) {\n this.signingClient = client;\n this.signingClientPromise = null;\n } else {\n // Promise was superseded, clean up the client we just created\n client.disconnect();\n }\n return client;\n } catch (error) {\n // Clear promise on failure so retry is possible (only if still active)\n if (this.signingClientPromise === thisInitPromise) {\n this.signingClientPromise = null;\n }\n if (error instanceof ManifestMCPError) {\n throw error;\n }\n throw new ManifestMCPError(\n ManifestMCPErrorCode.RPC_CONNECTION_FAILED,\n `Failed to connect signing client: ${error instanceof Error ? error.message : String(error)}`,\n { rpcUrl: this.config.rpcUrl },\n );\n }\n })();\n\n return this.signingClientPromise;\n }\n\n /**\n * Get the wallet address\n */\n async getAddress(): Promise<string> {\n return this.walletProvider.getAddress();\n }\n\n /**\n * Get the configuration\n */\n getConfig(): ManifestMCPConfig {\n return this.config;\n }\n\n /**\n * Acquire a rate limit token before making an RPC request.\n * This will wait if the rate limit has been exceeded.\n */\n async acquireRateLimit(): Promise<void> {\n await this.rateLimiter.removeTokens(1);\n }\n\n /**\n * Disconnect the signing client and release query client references.\n * The query client's underlying HTTP transport is stateless and does not\n * require an explicit disconnect.\n */\n disconnect(): void {\n if (this.signingClient) {\n this.signingClient.disconnect();\n this.signingClient = null;\n }\n this.signingClientPromise = null;\n this.queryClient = null;\n this.queryClientPromise = null;\n }\n}\n"],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ManifestMCPConfig } from "./types.js";
|
|
2
|
+
import { DEFAULT_RETRY_CONFIG } from "./retry.js";
|
|
3
|
+
|
|
4
|
+
//#region src/config.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Default requests per second for rate limiting
|
|
7
|
+
*/
|
|
8
|
+
declare const DEFAULT_REQUESTS_PER_SECOND = 10;
|
|
9
|
+
/**
|
|
10
|
+
* Create a configuration object with defaults applied
|
|
11
|
+
*/
|
|
12
|
+
declare function createConfig(input: ManifestMCPConfig): ManifestMCPConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Validation result
|
|
15
|
+
*/
|
|
16
|
+
interface ValidationResult {
|
|
17
|
+
valid: boolean;
|
|
18
|
+
errors: string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate a configuration object
|
|
22
|
+
*/
|
|
23
|
+
declare function validateConfig(config: Partial<ManifestMCPConfig>): ValidationResult;
|
|
24
|
+
/**
|
|
25
|
+
* Create and validate a configuration, throwing on invalid config
|
|
26
|
+
*/
|
|
27
|
+
declare function createValidatedConfig(input: ManifestMCPConfig): ManifestMCPConfig;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DEFAULT_REQUESTS_PER_SECOND, DEFAULT_RETRY_CONFIG, ValidationResult, createConfig, createValidatedConfig, validateConfig };
|
|
30
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;;;;AAeA;cAAa,2BAAA;;;AAkEb;iBAAgB,YAAA,CAAa,KAAA,EAAO,iBAAA,GAAoB,iBAAA;;;;UAsBvC,gBAAA;EACf,KAAA;EACA,MAAA;AAAA;AAFF;;;AAAA,iBAQgB,cAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,iBAAA,IACf,gBAAA;;AAFH;;iBA4HgB,qBAAA,CACd,KAAA,EAAO,iBAAA,GACN,iBAAA"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
import { DEFAULT_RETRY_CONFIG } from "./retry.js";
|
|
3
|
+
//#region src/config.ts
|
|
4
|
+
/**
|
|
5
|
+
* Default address prefix for Manifest Network
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_ADDRESS_PREFIX = "manifest";
|
|
8
|
+
/**
|
|
9
|
+
* Default requests per second for rate limiting
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_REQUESTS_PER_SECOND = 10;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a hostname is localhost (IPv4, IPv6, or hostname)
|
|
14
|
+
* Handles both bracketed and unbracketed IPv6 formats
|
|
15
|
+
*/
|
|
16
|
+
function isLocalhostHostname(hostname) {
|
|
17
|
+
if (hostname === "localhost" || hostname === "127.0.0.1") return true;
|
|
18
|
+
return hostname.replace(/^\[|\]$/g, "") === "::1";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate URL format and check if it uses HTTPS or is localhost (HTTP allowed for local dev)
|
|
22
|
+
* Returns validation result with error reason if invalid
|
|
23
|
+
*/
|
|
24
|
+
function validateEndpointUrl(url, label) {
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = new URL(url);
|
|
28
|
+
} catch {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
reason: `${label} must be a valid URL`
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (parsed.protocol === "https:") return { valid: true };
|
|
35
|
+
if (parsed.protocol === "http:" && isLocalhostHostname(parsed.hostname)) return { valid: true };
|
|
36
|
+
return {
|
|
37
|
+
valid: false,
|
|
38
|
+
reason: `${label} must use HTTPS (got ${parsed.protocol}//). HTTP is only allowed for local development (localhost, 127.0.0.1, ::1).`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate gas price format (e.g., "1.0umfx")
|
|
43
|
+
*/
|
|
44
|
+
function isValidGasPrice(gasPrice) {
|
|
45
|
+
return /^\d+(\.\d+)?[a-zA-Z]+$/.test(gasPrice);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate chain ID format
|
|
49
|
+
*/
|
|
50
|
+
function isValidChainId(chainId) {
|
|
51
|
+
return /^[a-zA-Z0-9][\w-]*$/.test(chainId);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a configuration object with defaults applied
|
|
55
|
+
*/
|
|
56
|
+
function createConfig(input) {
|
|
57
|
+
return {
|
|
58
|
+
chainId: input.chainId,
|
|
59
|
+
rpcUrl: input.rpcUrl,
|
|
60
|
+
gasPrice: input.gasPrice,
|
|
61
|
+
restUrl: input.restUrl,
|
|
62
|
+
addressPrefix: input.addressPrefix ?? DEFAULT_ADDRESS_PREFIX,
|
|
63
|
+
rateLimit: { requestsPerSecond: input.rateLimit?.requestsPerSecond ?? 10 },
|
|
64
|
+
retry: {
|
|
65
|
+
maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
|
|
66
|
+
baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
|
|
67
|
+
maxDelayMs: input.retry?.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Validate a configuration object
|
|
73
|
+
*/
|
|
74
|
+
function validateConfig(config) {
|
|
75
|
+
const errors = [];
|
|
76
|
+
if (!config.chainId) errors.push("chainId is required");
|
|
77
|
+
else if (!isValidChainId(config.chainId)) errors.push("chainId must be alphanumeric with hyphens (e.g., \"manifest-ledger-testnet\")");
|
|
78
|
+
if (!config.rpcUrl && !config.restUrl) errors.push("At least one of rpcUrl or restUrl is required");
|
|
79
|
+
if (config.rpcUrl) {
|
|
80
|
+
const urlCheck = validateEndpointUrl(config.rpcUrl, "rpcUrl");
|
|
81
|
+
if (!urlCheck.valid) errors.push(urlCheck.reason);
|
|
82
|
+
}
|
|
83
|
+
if (config.restUrl) {
|
|
84
|
+
const urlCheck = validateEndpointUrl(config.restUrl, "restUrl");
|
|
85
|
+
if (!urlCheck.valid) errors.push(urlCheck.reason);
|
|
86
|
+
}
|
|
87
|
+
if (config.rpcUrl && !config.gasPrice) errors.push("gasPrice is required when rpcUrl is provided");
|
|
88
|
+
else if (config.gasPrice && !isValidGasPrice(config.gasPrice)) errors.push("gasPrice must be a number followed by denomination (e.g., \"1.0umfx\")");
|
|
89
|
+
if (config.addressPrefix !== void 0) {
|
|
90
|
+
if (!/^[a-z]+$/.test(config.addressPrefix)) errors.push("addressPrefix must be lowercase letters only");
|
|
91
|
+
}
|
|
92
|
+
if (config.rateLimit !== void 0) {
|
|
93
|
+
if (typeof config.rateLimit !== "object" || config.rateLimit === null || Array.isArray(config.rateLimit)) errors.push("rateLimit must be a plain object");
|
|
94
|
+
else if (config.rateLimit.requestsPerSecond !== void 0) {
|
|
95
|
+
if (typeof config.rateLimit.requestsPerSecond !== "number" || config.rateLimit.requestsPerSecond <= 0 || !Number.isInteger(config.rateLimit.requestsPerSecond)) errors.push("rateLimit.requestsPerSecond must be a positive integer");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (config.retry !== void 0) if (typeof config.retry !== "object" || config.retry === null || Array.isArray(config.retry)) errors.push("retry must be a plain object");
|
|
99
|
+
else {
|
|
100
|
+
if (config.retry.maxRetries !== void 0) {
|
|
101
|
+
if (typeof config.retry.maxRetries !== "number" || config.retry.maxRetries < 0 || !Number.isInteger(config.retry.maxRetries)) errors.push("retry.maxRetries must be a non-negative integer");
|
|
102
|
+
}
|
|
103
|
+
if (config.retry.baseDelayMs !== void 0) {
|
|
104
|
+
if (typeof config.retry.baseDelayMs !== "number" || config.retry.baseDelayMs <= 0 || !Number.isInteger(config.retry.baseDelayMs)) errors.push("retry.baseDelayMs must be a positive integer");
|
|
105
|
+
}
|
|
106
|
+
if (config.retry.maxDelayMs !== void 0) {
|
|
107
|
+
if (typeof config.retry.maxDelayMs !== "number" || config.retry.maxDelayMs <= 0 || !Number.isInteger(config.retry.maxDelayMs)) errors.push("retry.maxDelayMs must be a positive integer");
|
|
108
|
+
}
|
|
109
|
+
if (config.retry.baseDelayMs !== void 0 && config.retry.maxDelayMs !== void 0 && config.retry.maxDelayMs < config.retry.baseDelayMs) errors.push("retry.maxDelayMs must be greater than or equal to retry.baseDelayMs");
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
valid: errors.length === 0,
|
|
113
|
+
errors
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create and validate a configuration, throwing on invalid config
|
|
118
|
+
*/
|
|
119
|
+
function createValidatedConfig(input) {
|
|
120
|
+
const validation = validateConfig(input);
|
|
121
|
+
if (!validation.valid) throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_CONFIG, `Invalid configuration: ${validation.errors.join(", ")}`, { errors: validation.errors });
|
|
122
|
+
return createConfig(input);
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
export { DEFAULT_REQUESTS_PER_SECOND, DEFAULT_RETRY_CONFIG, createConfig, createValidatedConfig, validateConfig };
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { DEFAULT_RETRY_CONFIG } from './retry.js';\nimport {\n type ManifestMCPConfig,\n ManifestMCPError,\n ManifestMCPErrorCode,\n} from './types.js';\n\n/**\n * Default address prefix for Manifest Network\n */\nconst DEFAULT_ADDRESS_PREFIX = 'manifest';\n\n/**\n * Default requests per second for rate limiting\n */\nexport const DEFAULT_REQUESTS_PER_SECOND = 10;\n\n// Re-export for consumers\nexport { DEFAULT_RETRY_CONFIG };\n\n/**\n * Check if a hostname is localhost (IPv4, IPv6, or hostname)\n * Handles both bracketed and unbracketed IPv6 formats\n */\nfunction isLocalhostHostname(hostname: string): boolean {\n if (hostname === 'localhost' || hostname === '127.0.0.1') {\n return true;\n }\n // Handle IPv6 localhost - hostname may be '::1' or '[::1]' depending on environment\n const normalizedHostname = hostname.replace(/^\\[|\\]$/g, '');\n return normalizedHostname === '::1';\n}\n\n/**\n * Validate URL format and check if it uses HTTPS or is localhost (HTTP allowed for local dev)\n * Returns validation result with error reason if invalid\n */\nfunction validateEndpointUrl(\n url: string,\n label: string,\n): { valid: true } | { valid: false; reason: string } {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { valid: false, reason: `${label} must be a valid URL` };\n }\n\n if (parsed.protocol === 'https:') {\n return { valid: true };\n }\n\n if (parsed.protocol === 'http:' && isLocalhostHostname(parsed.hostname)) {\n return { valid: true }; // HTTP allowed for localhost\n }\n\n return {\n valid: false,\n reason: `${label} must use HTTPS (got ${parsed.protocol}//). HTTP is only allowed for local development (localhost, 127.0.0.1, ::1).`,\n };\n}\n\n/**\n * Validate gas price format (e.g., \"1.0umfx\")\n */\nfunction isValidGasPrice(gasPrice: string): boolean {\n // Gas price should be a number followed by a denomination\n return /^\\d+(\\.\\d+)?[a-zA-Z]+$/.test(gasPrice);\n}\n\n/**\n * Validate chain ID format\n */\nfunction isValidChainId(chainId: string): boolean {\n // Chain ID should be alphanumeric with hyphens\n return /^[a-zA-Z0-9][\\w-]*$/.test(chainId);\n}\n\n/**\n * Create a configuration object with defaults applied\n */\nexport function createConfig(input: ManifestMCPConfig): ManifestMCPConfig {\n return {\n chainId: input.chainId,\n rpcUrl: input.rpcUrl,\n gasPrice: input.gasPrice,\n restUrl: input.restUrl,\n addressPrefix: input.addressPrefix ?? DEFAULT_ADDRESS_PREFIX,\n rateLimit: {\n requestsPerSecond:\n input.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND,\n },\n retry: {\n maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,\n maxDelayMs: input.retry?.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs,\n },\n };\n}\n\n/**\n * Validation result\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * Validate a configuration object\n */\nexport function validateConfig(\n config: Partial<ManifestMCPConfig>,\n): ValidationResult {\n const errors: string[] = [];\n\n // Required fields\n if (!config.chainId) {\n errors.push('chainId is required');\n } else if (!isValidChainId(config.chainId)) {\n errors.push(\n 'chainId must be alphanumeric with hyphens (e.g., \"manifest-ledger-testnet\")',\n );\n }\n\n // At least one of rpcUrl or restUrl must be provided\n if (!config.rpcUrl && !config.restUrl) {\n errors.push('At least one of rpcUrl or restUrl is required');\n }\n\n if (config.rpcUrl) {\n const urlCheck = validateEndpointUrl(config.rpcUrl, 'rpcUrl');\n if (!urlCheck.valid) {\n errors.push(urlCheck.reason);\n }\n }\n\n if (config.restUrl) {\n const urlCheck = validateEndpointUrl(config.restUrl, 'restUrl');\n if (!urlCheck.valid) {\n errors.push(urlCheck.reason);\n }\n }\n\n // gasPrice required when rpcUrl is provided (needed for signing)\n if (config.rpcUrl && !config.gasPrice) {\n errors.push('gasPrice is required when rpcUrl is provided');\n } else if (config.gasPrice && !isValidGasPrice(config.gasPrice)) {\n errors.push(\n 'gasPrice must be a number followed by denomination (e.g., \"1.0umfx\")',\n );\n }\n\n // Optional fields\n if (config.addressPrefix !== undefined) {\n if (!/^[a-z]+$/.test(config.addressPrefix)) {\n errors.push('addressPrefix must be lowercase letters only');\n }\n }\n\n if (config.rateLimit !== undefined) {\n if (\n typeof config.rateLimit !== 'object' ||\n config.rateLimit === null ||\n Array.isArray(config.rateLimit)\n ) {\n errors.push('rateLimit must be a plain object');\n } else if (config.rateLimit.requestsPerSecond !== undefined) {\n if (\n typeof config.rateLimit.requestsPerSecond !== 'number' ||\n config.rateLimit.requestsPerSecond <= 0 ||\n !Number.isInteger(config.rateLimit.requestsPerSecond)\n ) {\n errors.push('rateLimit.requestsPerSecond must be a positive integer');\n }\n }\n }\n\n if (config.retry !== undefined) {\n if (\n typeof config.retry !== 'object' ||\n config.retry === null ||\n Array.isArray(config.retry)\n ) {\n errors.push('retry must be a plain object');\n } else {\n if (config.retry.maxRetries !== undefined) {\n if (\n typeof config.retry.maxRetries !== 'number' ||\n config.retry.maxRetries < 0 ||\n !Number.isInteger(config.retry.maxRetries)\n ) {\n errors.push('retry.maxRetries must be a non-negative integer');\n }\n }\n if (config.retry.baseDelayMs !== undefined) {\n if (\n typeof config.retry.baseDelayMs !== 'number' ||\n config.retry.baseDelayMs <= 0 ||\n !Number.isInteger(config.retry.baseDelayMs)\n ) {\n errors.push('retry.baseDelayMs must be a positive integer');\n }\n }\n if (config.retry.maxDelayMs !== undefined) {\n if (\n typeof config.retry.maxDelayMs !== 'number' ||\n config.retry.maxDelayMs <= 0 ||\n !Number.isInteger(config.retry.maxDelayMs)\n ) {\n errors.push('retry.maxDelayMs must be a positive integer');\n }\n }\n // Validate maxDelayMs >= baseDelayMs if both are provided\n if (\n config.retry.baseDelayMs !== undefined &&\n config.retry.maxDelayMs !== undefined &&\n config.retry.maxDelayMs < config.retry.baseDelayMs\n ) {\n errors.push(\n 'retry.maxDelayMs must be greater than or equal to retry.baseDelayMs',\n );\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Create and validate a configuration, throwing on invalid config\n */\nexport function createValidatedConfig(\n input: ManifestMCPConfig,\n): ManifestMCPConfig {\n const validation = validateConfig(input);\n\n if (!validation.valid) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `Invalid configuration: ${validation.errors.join(', ')}`,\n { errors: validation.errors },\n );\n }\n\n return createConfig(input);\n}\n"],"mappings":"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"}
|
package/dist/cosmos.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CosmosQueryResult, CosmosTxResult } from "./types.js";
|
|
2
|
+
import { CosmosClientManager } from "./client.js";
|
|
3
|
+
|
|
4
|
+
//#region src/cosmos.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Execute a Cosmos query via manifestjs RPC client
|
|
7
|
+
*
|
|
8
|
+
* Automatically retries on transient failures (network errors, timeouts, 5xx)
|
|
9
|
+
* with exponential backoff. Configure retry behavior via `config.retry`.
|
|
10
|
+
*/
|
|
11
|
+
declare function cosmosQuery(clientManager: CosmosClientManager, module: string, subcommand: string, args?: string[]): Promise<CosmosQueryResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Execute a Cosmos transaction via manifestjs signing client
|
|
14
|
+
*
|
|
15
|
+
* Automatically retries on transient failures (network errors, timeouts, 5xx)
|
|
16
|
+
* with exponential backoff. Configure retry behavior via `config.retry`.
|
|
17
|
+
*
|
|
18
|
+
* Note: Only network-level failures are retried. Transaction validation errors
|
|
19
|
+
* (insufficient funds, invalid args, etc.) are not retried as they won't succeed.
|
|
20
|
+
*/
|
|
21
|
+
declare function cosmosTx(clientManager: CosmosClientManager, module: string, subcommand: string, args?: string[], waitForConfirmation?: boolean): Promise<CosmosTxResult>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { cosmosQuery, cosmosTx };
|
|
24
|
+
//# sourceMappingURL=cosmos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosmos.d.ts","names":[],"sources":["../src/cosmos.ts"],"mappings":";;;;;;AAsCA;;;;iBAAsB,WAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,cACC,OAAA,CAAQ,iBAAA;;;;;;;;;;iBAoDW,QAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,aACA,mBAAA,aACC,OAAA,CAAQ,cAAA"}
|
package/dist/cosmos.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
import { withRetry } from "./retry.js";
|
|
3
|
+
import { getQueryHandler, getTxHandler } from "./modules.js";
|
|
4
|
+
//#region src/cosmos.ts
|
|
5
|
+
const VALID_NAME_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/;
|
|
6
|
+
/**
|
|
7
|
+
* Validate that a string is safe for use as a module or subcommand name.
|
|
8
|
+
* Uses the appropriate UNSUPPORTED_QUERY or UNSUPPORTED_TX code so that
|
|
9
|
+
* the error is immediately classified as non-retryable.
|
|
10
|
+
*/
|
|
11
|
+
function validateName(name, field, errorCode) {
|
|
12
|
+
if (!name || !VALID_NAME_PATTERN.test(name)) throw new ManifestMCPError(errorCode, `Invalid ${field}: "${name}". Only alphanumeric characters, hyphens, and underscores are allowed.`);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Execute a Cosmos query via manifestjs RPC client
|
|
16
|
+
*
|
|
17
|
+
* Automatically retries on transient failures (network errors, timeouts, 5xx)
|
|
18
|
+
* with exponential backoff. Configure retry behavior via `config.retry`.
|
|
19
|
+
*/
|
|
20
|
+
async function cosmosQuery(clientManager, module, subcommand, args = []) {
|
|
21
|
+
validateName(module, "module", ManifestMCPErrorCode.UNSUPPORTED_QUERY);
|
|
22
|
+
validateName(subcommand, "subcommand", ManifestMCPErrorCode.UNSUPPORTED_QUERY);
|
|
23
|
+
const handler = getQueryHandler(module);
|
|
24
|
+
return withRetry(async () => {
|
|
25
|
+
await clientManager.acquireRateLimit();
|
|
26
|
+
const queryClient = await clientManager.getQueryClient();
|
|
27
|
+
try {
|
|
28
|
+
return {
|
|
29
|
+
module,
|
|
30
|
+
subcommand,
|
|
31
|
+
result: await handler(queryClient, subcommand, args)
|
|
32
|
+
};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (error instanceof ManifestMCPError) throw error;
|
|
35
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, `Query ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
36
|
+
}
|
|
37
|
+
}, {
|
|
38
|
+
config: clientManager.getConfig().retry,
|
|
39
|
+
operationName: `query ${module} ${subcommand}`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Execute a Cosmos transaction via manifestjs signing client
|
|
44
|
+
*
|
|
45
|
+
* Automatically retries on transient failures (network errors, timeouts, 5xx)
|
|
46
|
+
* with exponential backoff. Configure retry behavior via `config.retry`.
|
|
47
|
+
*
|
|
48
|
+
* Note: Only network-level failures are retried. Transaction validation errors
|
|
49
|
+
* (insufficient funds, invalid args, etc.) are not retried as they won't succeed.
|
|
50
|
+
*/
|
|
51
|
+
async function cosmosTx(clientManager, module, subcommand, args = [], waitForConfirmation = false) {
|
|
52
|
+
validateName(module, "module", ManifestMCPErrorCode.UNSUPPORTED_TX);
|
|
53
|
+
validateName(subcommand, "subcommand", ManifestMCPErrorCode.UNSUPPORTED_TX);
|
|
54
|
+
const handler = getTxHandler(module);
|
|
55
|
+
return withRetry(async () => {
|
|
56
|
+
await clientManager.acquireRateLimit();
|
|
57
|
+
const signingClient = await clientManager.getSigningClient();
|
|
58
|
+
const senderAddress = await clientManager.getAddress();
|
|
59
|
+
try {
|
|
60
|
+
return await handler(signingClient, senderAddress, subcommand, args, waitForConfirmation);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof ManifestMCPError) {
|
|
63
|
+
if (!error.details?.module) throw new ManifestMCPError(error.code, error.message, {
|
|
64
|
+
...error.details,
|
|
65
|
+
module,
|
|
66
|
+
subcommand,
|
|
67
|
+
args
|
|
68
|
+
});
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Tx ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
72
|
+
module,
|
|
73
|
+
subcommand,
|
|
74
|
+
args
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}, {
|
|
78
|
+
config: clientManager.getConfig().retry,
|
|
79
|
+
operationName: `tx ${module} ${subcommand}`
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { cosmosQuery, cosmosTx };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=cosmos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosmos.js","names":[],"sources":["../src/cosmos.ts"],"sourcesContent":["import type { CosmosClientManager } from './client.js';\nimport { getQueryHandler, getTxHandler } from './modules.js';\nimport { withRetry } from './retry.js';\nimport {\n type CosmosQueryResult,\n type CosmosTxResult,\n ManifestMCPError,\n ManifestMCPErrorCode,\n} from './types.js';\n\n// Validation pattern for module/subcommand names (alphanumeric, hyphens, underscores)\n// First character must not be a hyphen to prevent potential issues\nconst VALID_NAME_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/;\n\n/**\n * Validate that a string is safe for use as a module or subcommand name.\n * Uses the appropriate UNSUPPORTED_QUERY or UNSUPPORTED_TX code so that\n * the error is immediately classified as non-retryable.\n */\nfunction validateName(\n name: string,\n field: string,\n errorCode: ManifestMCPErrorCode,\n): void {\n if (!name || !VALID_NAME_PATTERN.test(name)) {\n throw new ManifestMCPError(\n errorCode,\n `Invalid ${field}: \"${name}\". Only alphanumeric characters, hyphens, and underscores are allowed.`,\n );\n }\n}\n\n/**\n * Execute a Cosmos query via manifestjs RPC client\n *\n * Automatically retries on transient failures (network errors, timeouts, 5xx)\n * with exponential backoff. Configure retry behavior via `config.retry`.\n */\nexport async function cosmosQuery(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n args: string[] = [],\n): Promise<CosmosQueryResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_QUERY);\n validateName(\n subcommand,\n 'subcommand',\n ManifestMCPErrorCode.UNSUPPORTED_QUERY,\n );\n\n // Get handler from registry (throws if module not found) - do this before retry loop\n const handler = getQueryHandler(module);\n\n return withRetry(\n async () => {\n // Apply rate limiting before making RPC request\n await clientManager.acquireRateLimit();\n\n const queryClient = await clientManager.getQueryClient();\n\n try {\n const result = await handler(queryClient, subcommand, args);\n\n return {\n module,\n subcommand,\n result,\n };\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n throw error;\n }\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `Query ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n {\n config: clientManager.getConfig().retry,\n operationName: `query ${module} ${subcommand}`,\n },\n );\n}\n\n/**\n * Execute a Cosmos transaction via manifestjs signing client\n *\n * Automatically retries on transient failures (network errors, timeouts, 5xx)\n * with exponential backoff. Configure retry behavior via `config.retry`.\n *\n * Note: Only network-level failures are retried. Transaction validation errors\n * (insufficient funds, invalid args, etc.) are not retried as they won't succeed.\n */\nexport async function cosmosTx(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n args: string[] = [],\n waitForConfirmation: boolean = false,\n): Promise<CosmosTxResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_TX);\n validateName(subcommand, 'subcommand', ManifestMCPErrorCode.UNSUPPORTED_TX);\n\n // Get handler from registry (throws if module not found) - do this before retry loop\n const handler = getTxHandler(module);\n\n return withRetry(\n async () => {\n // Apply rate limiting before making RPC request\n await clientManager.acquireRateLimit();\n\n const signingClient = await clientManager.getSigningClient();\n const senderAddress = await clientManager.getAddress();\n\n try {\n return await handler(\n signingClient,\n senderAddress,\n subcommand,\n args,\n waitForConfirmation,\n );\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n // Re-throw with enriched context if not already present\n if (!error.details?.module) {\n throw new ManifestMCPError(error.code, error.message, {\n ...error.details,\n module,\n subcommand,\n args,\n });\n }\n throw error;\n }\n throw new ManifestMCPError(\n ManifestMCPErrorCode.TX_FAILED,\n `Tx ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`,\n { module, subcommand, args },\n );\n }\n },\n {\n config: clientManager.getConfig().retry,\n operationName: `tx ${module} ${subcommand}`,\n },\n );\n}\n"],"mappings":";;;;AAYA,MAAM,qBAAqB;;;;;;AAO3B,SAAS,aACP,MACA,OACA,WACM;AACN,KAAI,CAAC,QAAQ,CAAC,mBAAmB,KAAK,KAAK,CACzC,OAAM,IAAI,iBACR,WACA,WAAW,MAAM,KAAK,KAAK,wEAC5B;;;;;;;;AAUL,eAAsB,YACpB,eACA,QACA,YACA,OAAiB,EAAE,EACS;AAC5B,cAAa,QAAQ,UAAU,qBAAqB,kBAAkB;AACtE,cACE,YACA,cACA,qBAAqB,kBACtB;CAGD,MAAM,UAAU,gBAAgB,OAAO;AAEvC,QAAO,UACL,YAAY;AAEV,QAAM,cAAc,kBAAkB;EAEtC,MAAM,cAAc,MAAM,cAAc,gBAAgB;AAExD,MAAI;AAGF,UAAO;IACL;IACA;IACA,QALa,MAAM,QAAQ,aAAa,YAAY,KAAK;IAM1D;WACM,OAAO;AACd,OAAI,iBAAiB,iBACnB,OAAM;AAER,SAAM,IAAI,iBACR,qBAAqB,cACrB,SAAS,OAAO,GAAG,WAAW,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAChG;;IAGL;EACE,QAAQ,cAAc,WAAW,CAAC;EAClC,eAAe,SAAS,OAAO,GAAG;EACnC,CACF;;;;;;;;;;;AAYH,eAAsB,SACpB,eACA,QACA,YACA,OAAiB,EAAE,EACnB,sBAA+B,OACN;AACzB,cAAa,QAAQ,UAAU,qBAAqB,eAAe;AACnE,cAAa,YAAY,cAAc,qBAAqB,eAAe;CAG3E,MAAM,UAAU,aAAa,OAAO;AAEpC,QAAO,UACL,YAAY;AAEV,QAAM,cAAc,kBAAkB;EAEtC,MAAM,gBAAgB,MAAM,cAAc,kBAAkB;EAC5D,MAAM,gBAAgB,MAAM,cAAc,YAAY;AAEtD,MAAI;AACF,UAAO,MAAM,QACX,eACA,eACA,YACA,MACA,oBACD;WACM,OAAO;AACd,OAAI,iBAAiB,kBAAkB;AAErC,QAAI,CAAC,MAAM,SAAS,OAClB,OAAM,IAAI,iBAAiB,MAAM,MAAM,MAAM,SAAS;KACpD,GAAG,MAAM;KACT;KACA;KACA;KACD,CAAC;AAEJ,UAAM;;AAER,SAAM,IAAI,iBACR,qBAAqB,WACrB,MAAM,OAAO,GAAG,WAAW,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC5F;IAAE;IAAQ;IAAY;IAAM,CAC7B;;IAGL;EACE,QAAQ,cAAc,WAAW,CAAC;EAClC,eAAe,MAAM,OAAO,GAAG;EAChC,CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AccountInfo, AccountInfoResult, AddressBytesToStringResult, AddressStringToBytesResult, Any, AuthAccountResult, AuthAccountsResult, AuthParams, AuthParamsResult, AvailableModules, BalanceResult, BalancesResult, BankMetadata, BankParams, BankParamsResult, BaseAccount, Bech32PrefixResult, BillingParams, BillingParamsResult, Coin, CommissionResult, CommunityPoolResult, CosmosQueryResult, CosmosTxResult, CreditAccount, CreditAccountResult, CreditAccountsResult, CreditAddressResult, CreditEstimateResult, DecCoin, DelegationDelegatorReward, DelegationResponse, DelegationResult, DelegationsResult, DelegatorValidatorsResult, DelegatorWithdrawAddressResult, DenomMetadataResult, DenomsMetadataResult, DepositParams, DepositResult, DepositsResult, DistributionParams, DistributionParamsResult, GovDeposit, GovParams, GovParamsResult, GovProposal, GovTallyResult, GovVote, GroupInfo, GroupInfoResult, GroupMember, GroupMembersResult, GroupPoliciesResult, GroupPolicyInfo, GroupPolicyInfoResult, GroupProposal, GroupProposalResult, GroupProposalsResult, GroupTallyQueryResult, GroupTallyResult, GroupVote, GroupVoteResult, GroupVotesResult, GroupsResult, HistoricalInfo, HistoricalInfoResult, Lease, LeaseItemInput, LeaseResult, LeasesResult, ManifestMCPConfig, ManifestMCPError, ManifestMCPErrorCode, ModuleAccount, ModuleAccountsResult, ModuleInfo, PaginatedResult, PaginationResponse, ProposalResult, ProposalsResult, Provider, ProviderResult, ProviderWithdrawableResult, ProvidersResult, QueryCreditEstimateResponse, QueryResult, RateLimitConfig, RedelegationResponse, RedelegationsResult, RetryConfig, RewardsResult, SKU, SendEnabled, SendEnabledResult, SignArbitraryResult, SkuParams, SkuParamsResult, SkuResult, SkusResult, SlashesResult, StakingParams, StakingParamsResult, StakingPool, StakingPoolResult, SupplyOfResult, TallyParams, TallyResult, TotalSupplyResult, UnbondingDelegation, UnbondingDelegationResult, UnbondingDelegationsResult, Validator, ValidatorAccumulatedCommission, ValidatorOutstandingRewards, ValidatorOutstandingRewardsResult, ValidatorResult, ValidatorSlashEvent, ValidatorsResult, VoteResult, VotesResult, VotingParams, WalletProvider, WithdrawableAmountResult } from "./types.js";
|
|
2
|
+
import { CosmosClientManager, ManifestQueryClient } from "./client.js";
|
|
3
|
+
import { DEFAULT_RETRY_CONFIG, RetryOptions, calculateBackoff, isRetryableError, withRetry } from "./retry.js";
|
|
4
|
+
import { ValidationResult, createConfig, createValidatedConfig, validateConfig } from "./config.js";
|
|
5
|
+
import { cosmosQuery, cosmosTx } from "./cosmos.js";
|
|
6
|
+
import { createLCDQueryClient } from "./lcd-adapter.js";
|
|
7
|
+
import { LogLevel, logger } from "./logger.js";
|
|
8
|
+
import { getAvailableModules, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isSubcommandSupported } from "./modules.js";
|
|
9
|
+
import { MAX_PAGE_LIMIT, createPagination } from "./queries/utils.js";
|
|
10
|
+
import { INFRASTRUCTURE_ERROR_CODES, ManifestMCPServerOptions, MnemonicServerConfig, SENSITIVE_FIELDS, bigIntReplacer, createMnemonicServer, jsonResponse, sanitizeForLogging, withErrorHandling } from "./server-utils.js";
|
|
11
|
+
import { fundCredits } from "./tools/fundCredits.js";
|
|
12
|
+
import { getBalance } from "./tools/getBalance.js";
|
|
13
|
+
import { StopAppResult, stopApp } from "./tools/stopApp.js";
|
|
14
|
+
import { DNS_LABEL_RE, optionalBoolean, parseArgs, requireString, requireStringEnum, requireUuid } from "./validation.js";
|
|
15
|
+
import { VERSION } from "./version.js";
|
|
16
|
+
import { MnemonicWalletProvider } from "./wallet/mnemonic.js";
|
|
17
|
+
import { signArbitraryWithAmino } from "./wallet/sign-arbitrary.js";
|
|
18
|
+
import { LeaseState, leaseStateFromJSON, leaseStateToJSON } from "@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js";
|
|
19
|
+
export { AccountInfo, AccountInfoResult, AddressBytesToStringResult, AddressStringToBytesResult, Any, AuthAccountResult, AuthAccountsResult, AuthParams, AuthParamsResult, AvailableModules, BalanceResult, BalancesResult, BankMetadata, BankParams, BankParamsResult, BaseAccount, Bech32PrefixResult, BillingParams, BillingParamsResult, Coin, CommissionResult, CommunityPoolResult, CosmosClientManager, CosmosQueryResult, CosmosTxResult, CreditAccount, CreditAccountResult, CreditAccountsResult, CreditAddressResult, CreditEstimateResult, DEFAULT_RETRY_CONFIG, DNS_LABEL_RE, DecCoin, DelegationDelegatorReward, DelegationResponse, DelegationResult, DelegationsResult, DelegatorValidatorsResult, DelegatorWithdrawAddressResult, DenomMetadataResult, DenomsMetadataResult, DepositParams, DepositResult, DepositsResult, DistributionParams, DistributionParamsResult, GovDeposit, GovParams, GovParamsResult, GovProposal, GovTallyResult, GovVote, GroupInfo, GroupInfoResult, GroupMember, GroupMembersResult, GroupPoliciesResult, GroupPolicyInfo, GroupPolicyInfoResult, GroupProposal, GroupProposalResult, GroupProposalsResult, GroupTallyQueryResult, GroupTallyResult, GroupVote, GroupVoteResult, GroupVotesResult, GroupsResult, HistoricalInfo, HistoricalInfoResult, INFRASTRUCTURE_ERROR_CODES, Lease, LeaseItemInput, LeaseResult, LeaseState, LeasesResult, type LogLevel, MAX_PAGE_LIMIT, ManifestMCPConfig, ManifestMCPError, ManifestMCPErrorCode, type ManifestMCPServerOptions, type ManifestQueryClient, type MnemonicServerConfig, MnemonicWalletProvider, ModuleAccount, ModuleAccountsResult, ModuleInfo, PaginatedResult, PaginationResponse, ProposalResult, ProposalsResult, Provider, ProviderResult, ProviderWithdrawableResult, ProvidersResult, QueryCreditEstimateResponse, QueryResult, RateLimitConfig, RedelegationResponse, RedelegationsResult, RetryConfig, type RetryOptions, RewardsResult, SENSITIVE_FIELDS, SKU, SendEnabled, SendEnabledResult, SignArbitraryResult, SkuParams, SkuParamsResult, SkuResult, SkusResult, SlashesResult, StakingParams, StakingParamsResult, StakingPool, StakingPoolResult, type StopAppResult, SupplyOfResult, TallyParams, TallyResult, TotalSupplyResult, UnbondingDelegation, UnbondingDelegationResult, UnbondingDelegationsResult, VERSION, type ValidationResult, Validator, ValidatorAccumulatedCommission, ValidatorOutstandingRewards, ValidatorOutstandingRewardsResult, ValidatorResult, ValidatorSlashEvent, ValidatorsResult, VoteResult, VotesResult, VotingParams, WalletProvider, WithdrawableAmountResult, bigIntReplacer, calculateBackoff, cosmosQuery, cosmosTx, createConfig, createLCDQueryClient, createMnemonicServer, createPagination, createValidatedConfig, fundCredits, getAvailableModules, getBalance, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isRetryableError, isSubcommandSupported, jsonResponse, leaseStateFromJSON, leaseStateToJSON, logger, optionalBoolean, parseArgs, requireString, requireStringEnum, requireUuid, sanitizeForLogging, signArbitraryWithAmino, stopApp, validateConfig, withErrorHandling, withRetry };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
import { DEFAULT_RETRY_CONFIG, calculateBackoff, isRetryableError, withRetry } from "./retry.js";
|
|
3
|
+
import { createConfig, createValidatedConfig, validateConfig } from "./config.js";
|
|
4
|
+
import { createLCDQueryClient } from "./lcd-adapter.js";
|
|
5
|
+
import { CosmosClientManager } from "./client.js";
|
|
6
|
+
import { DNS_LABEL_RE, optionalBoolean, parseArgs, requireString, requireStringEnum, requireUuid } from "./validation.js";
|
|
7
|
+
import { MAX_PAGE_LIMIT, createPagination } from "./queries/utils.js";
|
|
8
|
+
import { getAvailableModules, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isSubcommandSupported } from "./modules.js";
|
|
9
|
+
import { cosmosQuery, cosmosTx } from "./cosmos.js";
|
|
10
|
+
import { logger } from "./logger.js";
|
|
11
|
+
import { signArbitraryWithAmino } from "./wallet/sign-arbitrary.js";
|
|
12
|
+
import { MnemonicWalletProvider } from "./wallet/mnemonic.js";
|
|
13
|
+
import "./wallet/index.js";
|
|
14
|
+
import { INFRASTRUCTURE_ERROR_CODES, SENSITIVE_FIELDS, bigIntReplacer, createMnemonicServer, jsonResponse, sanitizeForLogging, withErrorHandling } from "./server-utils.js";
|
|
15
|
+
import { fundCredits } from "./tools/fundCredits.js";
|
|
16
|
+
import { getBalance } from "./tools/getBalance.js";
|
|
17
|
+
import { stopApp } from "./tools/stopApp.js";
|
|
18
|
+
import { VERSION } from "./version.js";
|
|
19
|
+
import { LeaseState, leaseStateFromJSON, leaseStateToJSON } from "@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js";
|
|
20
|
+
export { CosmosClientManager, DEFAULT_RETRY_CONFIG, DNS_LABEL_RE, INFRASTRUCTURE_ERROR_CODES, LeaseState, MAX_PAGE_LIMIT, ManifestMCPError, ManifestMCPErrorCode, MnemonicWalletProvider, SENSITIVE_FIELDS, VERSION, bigIntReplacer, calculateBackoff, cosmosQuery, cosmosTx, createConfig, createLCDQueryClient, createMnemonicServer, createPagination, createValidatedConfig, fundCredits, getAvailableModules, getBalance, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isRetryableError, isSubcommandSupported, jsonResponse, leaseStateFromJSON, leaseStateToJSON, logger, optionalBoolean, parseArgs, requireString, requireStringEnum, requireUuid, sanitizeForLogging, signArbitraryWithAmino, stopApp, validateConfig, withErrorHandling, withRetry };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ManifestQueryClient } from "./client.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lcd-adapter.d.ts
|
|
4
|
+
declare function snakeToCamelDeep(obj: unknown): unknown;
|
|
5
|
+
interface Converter {
|
|
6
|
+
fromJSON(object: unknown): unknown;
|
|
7
|
+
}
|
|
8
|
+
declare function findConverter(namespace: Record<string, unknown>, methodName: string): Converter;
|
|
9
|
+
type AsyncFn = (...args: unknown[]) => Promise<unknown>;
|
|
10
|
+
declare function adaptModule(lcdMod: unknown, converterNs: unknown): Record<string, AsyncFn>;
|
|
11
|
+
declare function unsupportedModule(modulePath: string): unknown;
|
|
12
|
+
declare function createLCDQueryClient(restEndpoint: string): Promise<ManifestQueryClient>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { adaptModule as _adaptModule, findConverter as _findConverter, snakeToCamelDeep as _snakeToCamelDeep, unsupportedModule as _unsupportedModule, createLCDQueryClient };
|
|
15
|
+
//# sourceMappingURL=lcd-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lcd-adapter.d.ts","names":[],"sources":["../src/lcd-adapter.ts"],"mappings":";;;iBAQS,gBAAA,CAAiB,GAAA;AAAA,UAwBhB,SAAA;EACR,QAAA,CAAS,MAAA;AAAA;AAAA,iBAGF,aAAA,CACP,SAAA,EAAW,MAAA,mBACX,UAAA,WACC,SAAA;AAAA,KAiBE,OAAA,OAAc,IAAA,gBAAoB,OAAA;AAAA,iBAE9B,WAAA,CACP,MAAA,WACA,WAAA,YACC,MAAA,SAAe,OAAA;AAAA,iBAqCT,iBAAA,CAAkB,UAAA;AAAA,iBAiBL,oBAAA,CACpB,YAAA,WACC,OAAA,CAAQ,mBAAA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
import { cosmos, liftedinit } from "@manifest-network/manifestjs";
|
|
3
|
+
//#region src/lcd-adapter.ts
|
|
4
|
+
function snakeToCamel(s) {
|
|
5
|
+
return s.replace(/_(.)/g, (_, c) => c.toUpperCase());
|
|
6
|
+
}
|
|
7
|
+
function snakeToCamelDeep(obj) {
|
|
8
|
+
if (Array.isArray(obj)) return obj.map(snakeToCamelDeep);
|
|
9
|
+
if (obj !== null && typeof obj === "object" && !(obj instanceof Date) && !(obj instanceof Uint8Array)) return Object.fromEntries(Object.entries(obj).map(([k, v]) => [snakeToCamel(k), snakeToCamelDeep(v)]));
|
|
10
|
+
return obj;
|
|
11
|
+
}
|
|
12
|
+
function ucFirst(s) {
|
|
13
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
14
|
+
}
|
|
15
|
+
function findConverter(namespace, methodName) {
|
|
16
|
+
const uc = ucFirst(methodName);
|
|
17
|
+
const queryName = `Query${uc}Response`;
|
|
18
|
+
const plainName = `${uc}Response`;
|
|
19
|
+
const converter = namespace[queryName] ?? namespace[plainName];
|
|
20
|
+
if (!converter?.fromJSON) throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, `No response converter found for method "${methodName}" (tried "${queryName}" and "${plainName}")`);
|
|
21
|
+
return converter;
|
|
22
|
+
}
|
|
23
|
+
function adaptModule(lcdMod, converterNs) {
|
|
24
|
+
const lcdModule = lcdMod;
|
|
25
|
+
const converterNamespace = converterNs;
|
|
26
|
+
const adapted = {};
|
|
27
|
+
for (const key of Object.keys(lcdModule)) {
|
|
28
|
+
if (key === "req" || typeof lcdModule[key] !== "function") continue;
|
|
29
|
+
const originalFn = lcdModule[key];
|
|
30
|
+
const converter = findConverter(converterNamespace, key);
|
|
31
|
+
adapted[key] = async (...args) => {
|
|
32
|
+
let sdkResult;
|
|
33
|
+
try {
|
|
34
|
+
sdkResult = await originalFn.call(lcdModule, ...args);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (error instanceof ManifestMCPError) throw error;
|
|
37
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, `LCD query "${key}" failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
}
|
|
39
|
+
const camelCased = snakeToCamelDeep(sdkResult);
|
|
40
|
+
try {
|
|
41
|
+
return converter.fromJSON(camelCased);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.QUERY_FAILED, `Failed to convert LCD response for "${key}": ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return adapted;
|
|
48
|
+
}
|
|
49
|
+
function unsupportedModule(modulePath) {
|
|
50
|
+
return new Proxy({}, { get(_target, prop) {
|
|
51
|
+
if (typeof prop === "string") throw new ManifestMCPError(ManifestMCPErrorCode.UNSUPPORTED_QUERY, `Module "${modulePath}" is not available via LCD/REST. Use an RPC endpoint instead.`);
|
|
52
|
+
} });
|
|
53
|
+
}
|
|
54
|
+
async function createLCDQueryClient(restEndpoint) {
|
|
55
|
+
let lcd;
|
|
56
|
+
try {
|
|
57
|
+
lcd = await liftedinit.ClientFactory.createLCDClient({ restEndpoint });
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.RPC_CONNECTION_FAILED, `Failed to create LCD client for ${restEndpoint}: ${error instanceof Error ? error.message : String(error)}`);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
return {
|
|
63
|
+
cosmos: {
|
|
64
|
+
auth: { v1beta1: adaptModule(lcd.cosmos.auth.v1beta1, cosmos.auth.v1beta1) },
|
|
65
|
+
authz: { v1beta1: adaptModule(lcd.cosmos.authz.v1beta1, cosmos.authz.v1beta1) },
|
|
66
|
+
bank: { v1beta1: adaptModule(lcd.cosmos.bank.v1beta1, cosmos.bank.v1beta1) },
|
|
67
|
+
base: { node: { v1beta1: adaptModule(lcd.cosmos.base.node.v1beta1, cosmos.base.node.v1beta1) } },
|
|
68
|
+
circuit: { v1: adaptModule(lcd.cosmos.circuit.v1, cosmos.circuit.v1) },
|
|
69
|
+
consensus: { v1: adaptModule(lcd.cosmos.consensus.v1, cosmos.consensus.v1) },
|
|
70
|
+
distribution: { v1beta1: adaptModule(lcd.cosmos.distribution.v1beta1, cosmos.distribution.v1beta1) },
|
|
71
|
+
feegrant: { v1beta1: adaptModule(lcd.cosmos.feegrant.v1beta1, cosmos.feegrant.v1beta1) },
|
|
72
|
+
gov: {
|
|
73
|
+
v1: adaptModule(lcd.cosmos.gov.v1, cosmos.gov.v1),
|
|
74
|
+
v1beta1: adaptModule(lcd.cosmos.gov.v1beta1, cosmos.gov.v1beta1)
|
|
75
|
+
},
|
|
76
|
+
group: { v1: adaptModule(lcd.cosmos.group.v1, cosmos.group.v1) },
|
|
77
|
+
mint: { v1beta1: adaptModule(lcd.cosmos.mint.v1beta1, cosmos.mint.v1beta1) },
|
|
78
|
+
orm: { query: { v1alpha1: unsupportedModule("cosmos.orm.query.v1alpha1") } },
|
|
79
|
+
params: { v1beta1: adaptModule(lcd.cosmos.params.v1beta1, cosmos.params.v1beta1) },
|
|
80
|
+
staking: { v1beta1: adaptModule(lcd.cosmos.staking.v1beta1, cosmos.staking.v1beta1) },
|
|
81
|
+
tx: { v1beta1: adaptModule(lcd.cosmos.tx.v1beta1, cosmos.tx.v1beta1) },
|
|
82
|
+
upgrade: { v1beta1: adaptModule(lcd.cosmos.upgrade.v1beta1, cosmos.upgrade.v1beta1) }
|
|
83
|
+
},
|
|
84
|
+
liftedinit: {
|
|
85
|
+
billing: { v1: adaptModule(lcd.liftedinit.billing.v1, liftedinit.billing.v1) },
|
|
86
|
+
manifest: { v1: unsupportedModule("liftedinit.manifest.v1") },
|
|
87
|
+
sku: { v1: adaptModule(lcd.liftedinit.sku.v1, liftedinit.sku.v1) }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (error instanceof ManifestMCPError) throw error;
|
|
92
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.RPC_CONNECTION_FAILED, `Failed to adapt LCD modules: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { adaptModule as _adaptModule, findConverter as _findConverter, snakeToCamelDeep as _snakeToCamelDeep, unsupportedModule as _unsupportedModule, createLCDQueryClient };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=lcd-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lcd-adapter.js","names":[],"sources":["../src/lcd-adapter.ts"],"sourcesContent":["import { cosmos, liftedinit } from '@manifest-network/manifestjs';\nimport type { ManifestQueryClient } from './client.js';\nimport { ManifestMCPError, ManifestMCPErrorCode } from './types.js';\n\nfunction snakeToCamel(s: string): string {\n return s.replace(/_(.)/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction snakeToCamelDeep(obj: unknown): unknown {\n if (Array.isArray(obj)) {\n return obj.map(snakeToCamelDeep);\n }\n if (\n obj !== null &&\n typeof obj === 'object' &&\n !(obj instanceof Date) &&\n !(obj instanceof Uint8Array)\n ) {\n return Object.fromEntries(\n Object.entries(obj as Record<string, unknown>).map(([k, v]) => [\n snakeToCamel(k),\n snakeToCamelDeep(v),\n ]),\n );\n }\n return obj;\n}\n\nfunction ucFirst(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\ninterface Converter {\n fromJSON(object: unknown): unknown;\n}\n\nfunction findConverter(\n namespace: Record<string, unknown>,\n methodName: string,\n): Converter {\n const uc = ucFirst(methodName);\n const queryName = `Query${uc}Response`;\n const plainName = `${uc}Response`;\n\n const converter = (namespace[queryName] ?? namespace[plainName]) as\n | Converter\n | undefined;\n if (!converter?.fromJSON) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `No response converter found for method \"${methodName}\" (tried \"${queryName}\" and \"${plainName}\")`,\n );\n }\n return converter;\n}\n\ntype AsyncFn = (...args: unknown[]) => Promise<unknown>;\n\nfunction adaptModule(\n lcdMod: unknown,\n converterNs: unknown,\n): Record<string, AsyncFn> {\n const lcdModule = lcdMod as Record<string, unknown>;\n const converterNamespace = converterNs as Record<string, unknown>;\n const adapted: Record<string, AsyncFn> = {};\n\n for (const key of Object.keys(lcdModule)) {\n if (key === 'req' || typeof lcdModule[key] !== 'function') continue;\n\n const originalFn = lcdModule[key] as AsyncFn;\n const converter = findConverter(converterNamespace, key);\n\n adapted[key] = async (...args: unknown[]) => {\n let sdkResult: unknown;\n try {\n sdkResult = await originalFn.call(lcdModule, ...args);\n } catch (error) {\n if (error instanceof ManifestMCPError) throw error;\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `LCD query \"${key}\" failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n const camelCased = snakeToCamelDeep(sdkResult);\n try {\n return converter.fromJSON(camelCased);\n } catch (error) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `Failed to convert LCD response for \"${key}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n };\n }\n\n return adapted;\n}\n\nfunction unsupportedModule(modulePath: string): unknown {\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (typeof prop === 'string') {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.UNSUPPORTED_QUERY,\n `Module \"${modulePath}\" is not available via LCD/REST. Use an RPC endpoint instead.`,\n );\n }\n return undefined;\n },\n },\n );\n}\n\nexport async function createLCDQueryClient(\n restEndpoint: string,\n): Promise<ManifestQueryClient> {\n let lcd: Awaited<ReturnType<typeof liftedinit.ClientFactory.createLCDClient>>;\n try {\n lcd = await liftedinit.ClientFactory.createLCDClient({ restEndpoint });\n } catch (error) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.RPC_CONNECTION_FAILED,\n `Failed to create LCD client for ${restEndpoint}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n try {\n return {\n cosmos: {\n auth: {\n v1beta1: adaptModule(lcd.cosmos.auth.v1beta1, cosmos.auth.v1beta1),\n },\n authz: {\n v1beta1: adaptModule(lcd.cosmos.authz.v1beta1, cosmos.authz.v1beta1),\n },\n bank: {\n v1beta1: adaptModule(lcd.cosmos.bank.v1beta1, cosmos.bank.v1beta1),\n },\n base: {\n node: {\n v1beta1: adaptModule(\n lcd.cosmos.base.node.v1beta1,\n cosmos.base.node.v1beta1,\n ),\n },\n },\n circuit: { v1: adaptModule(lcd.cosmos.circuit.v1, cosmos.circuit.v1) },\n consensus: {\n v1: adaptModule(lcd.cosmos.consensus.v1, cosmos.consensus.v1),\n },\n distribution: {\n v1beta1: adaptModule(\n lcd.cosmos.distribution.v1beta1,\n cosmos.distribution.v1beta1,\n ),\n },\n feegrant: {\n v1beta1: adaptModule(\n lcd.cosmos.feegrant.v1beta1,\n cosmos.feegrant.v1beta1,\n ),\n },\n gov: {\n v1: adaptModule(lcd.cosmos.gov.v1, cosmos.gov.v1),\n v1beta1: adaptModule(lcd.cosmos.gov.v1beta1, cosmos.gov.v1beta1),\n },\n group: { v1: adaptModule(lcd.cosmos.group.v1, cosmos.group.v1) },\n mint: {\n v1beta1: adaptModule(lcd.cosmos.mint.v1beta1, cosmos.mint.v1beta1),\n },\n orm: {\n query: { v1alpha1: unsupportedModule('cosmos.orm.query.v1alpha1') },\n },\n params: {\n v1beta1: adaptModule(\n lcd.cosmos.params.v1beta1,\n cosmos.params.v1beta1,\n ),\n },\n staking: {\n v1beta1: adaptModule(\n lcd.cosmos.staking.v1beta1,\n cosmos.staking.v1beta1,\n ),\n },\n tx: { v1beta1: adaptModule(lcd.cosmos.tx.v1beta1, cosmos.tx.v1beta1) },\n upgrade: {\n v1beta1: adaptModule(\n lcd.cosmos.upgrade.v1beta1,\n cosmos.upgrade.v1beta1,\n ),\n },\n },\n liftedinit: {\n billing: {\n v1: adaptModule(lcd.liftedinit.billing.v1, liftedinit.billing.v1),\n },\n manifest: { v1: unsupportedModule('liftedinit.manifest.v1') },\n sku: { v1: adaptModule(lcd.liftedinit.sku.v1, liftedinit.sku.v1) },\n },\n } as ManifestQueryClient;\n } catch (error) {\n if (error instanceof ManifestMCPError) throw error;\n throw new ManifestMCPError(\n ManifestMCPErrorCode.RPC_CONNECTION_FAILED,\n `Failed to adapt LCD modules: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\n// Re-export for testing\nexport {\n adaptModule as _adaptModule,\n findConverter as _findConverter,\n snakeToCamelDeep as _snakeToCamelDeep,\n unsupportedModule as _unsupportedModule,\n};\n"],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/logger.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Leveled logger for MCP server processes.
|
|
4
|
+
*
|
|
5
|
+
* All output goes to stderr because stdout is reserved for MCP protocol messages.
|
|
6
|
+
* The level is resolved from `process.env.LOG_LEVEL` at import time and can be
|
|
7
|
+
* overridden at runtime via `logger.setLevel()`.
|
|
8
|
+
*/
|
|
9
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
10
|
+
declare const logger: {
|
|
11
|
+
debug(...args: unknown[]): void;
|
|
12
|
+
info(...args: unknown[]): void;
|
|
13
|
+
warn(...args: unknown[]): void;
|
|
14
|
+
error(...args: unknown[]): void;
|
|
15
|
+
setLevel(level: LogLevel): void;
|
|
16
|
+
getLevel(): LogLevel;
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { LogLevel, logger };
|
|
20
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","names":[],"sources":["../src/logger.ts"],"mappings":";;AAQA;;;;;AA4BA;KA5BY,QAAA;AAAA,cA4BC,MAAA;;;;;kBAaK,QAAA;cAGJ,QAAA;AAAA"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/logger.ts
|
|
2
|
+
const LOG_LEVEL_ORDER = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3,
|
|
7
|
+
silent: 4
|
|
8
|
+
};
|
|
9
|
+
function resolveLevel() {
|
|
10
|
+
const env = typeof process !== "undefined" ? process.env.LOG_LEVEL : void 0;
|
|
11
|
+
if (!env) return "warn";
|
|
12
|
+
if (new Set(Object.keys(LOG_LEVEL_ORDER)).has(env)) return env;
|
|
13
|
+
console.error(`[WARN] Invalid LOG_LEVEL "${env}". Valid values: debug, info, warn, error, silent. Defaulting to "warn".`);
|
|
14
|
+
return "warn";
|
|
15
|
+
}
|
|
16
|
+
let currentLevel = resolveLevel();
|
|
17
|
+
function shouldLog(level) {
|
|
18
|
+
return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[currentLevel];
|
|
19
|
+
}
|
|
20
|
+
const logger = {
|
|
21
|
+
debug(...args) {
|
|
22
|
+
if (shouldLog("debug")) console.error("[DEBUG]", ...args);
|
|
23
|
+
},
|
|
24
|
+
info(...args) {
|
|
25
|
+
if (shouldLog("info")) console.error("[INFO]", ...args);
|
|
26
|
+
},
|
|
27
|
+
warn(...args) {
|
|
28
|
+
if (shouldLog("warn")) console.error("[WARN]", ...args);
|
|
29
|
+
},
|
|
30
|
+
error(...args) {
|
|
31
|
+
if (shouldLog("error")) console.error("[ERROR]", ...args);
|
|
32
|
+
},
|
|
33
|
+
setLevel(level) {
|
|
34
|
+
currentLevel = level;
|
|
35
|
+
},
|
|
36
|
+
getLevel() {
|
|
37
|
+
return currentLevel;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { logger };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["/**\n * Leveled logger for MCP server processes.\n *\n * All output goes to stderr because stdout is reserved for MCP protocol messages.\n * The level is resolved from `process.env.LOG_LEVEL` at import time and can be\n * overridden at runtime via `logger.setLevel()`.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nconst LOG_LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nfunction resolveLevel(): LogLevel {\n const env =\n typeof process !== 'undefined' ? process.env.LOG_LEVEL : undefined;\n if (!env) return 'warn';\n const validLevels = new Set<string>(Object.keys(LOG_LEVEL_ORDER));\n if (validLevels.has(env)) return env as LogLevel;\n console.error(\n `[WARN] Invalid LOG_LEVEL \"${env}\". Valid values: debug, info, warn, error, silent. Defaulting to \"warn\".`,\n );\n return 'warn';\n}\n\nlet currentLevel: LogLevel = resolveLevel();\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[currentLevel];\n}\n\nexport const logger = {\n debug(...args: unknown[]) {\n if (shouldLog('debug')) console.error('[DEBUG]', ...args);\n },\n info(...args: unknown[]) {\n if (shouldLog('info')) console.error('[INFO]', ...args);\n },\n warn(...args: unknown[]) {\n if (shouldLog('warn')) console.error('[WARN]', ...args);\n },\n error(...args: unknown[]) {\n if (shouldLog('error')) console.error('[ERROR]', ...args);\n },\n setLevel(level: LogLevel) {\n currentLevel = level;\n },\n getLevel(): LogLevel {\n return currentLevel;\n },\n};\n"],"mappings":";AAUA,MAAM,kBAA4C;CAChD,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACP,QAAQ;CACT;AAED,SAAS,eAAyB;CAChC,MAAM,MACJ,OAAO,YAAY,cAAc,QAAQ,IAAI,YAAY,KAAA;AAC3D,KAAI,CAAC,IAAK,QAAO;AAEjB,KADoB,IAAI,IAAY,OAAO,KAAK,gBAAgB,CAAC,CACjD,IAAI,IAAI,CAAE,QAAO;AACjC,SAAQ,MACN,6BAA6B,IAAI,0EAClC;AACD,QAAO;;AAGT,IAAI,eAAyB,cAAc;AAE3C,SAAS,UAAU,OAA0B;AAC3C,QAAO,gBAAgB,UAAU,gBAAgB;;AAGnD,MAAa,SAAS;CACpB,MAAM,GAAG,MAAiB;AACxB,MAAI,UAAU,QAAQ,CAAE,SAAQ,MAAM,WAAW,GAAG,KAAK;;CAE3D,KAAK,GAAG,MAAiB;AACvB,MAAI,UAAU,OAAO,CAAE,SAAQ,MAAM,UAAU,GAAG,KAAK;;CAEzD,KAAK,GAAG,MAAiB;AACvB,MAAI,UAAU,OAAO,CAAE,SAAQ,MAAM,UAAU,GAAG,KAAK;;CAEzD,MAAM,GAAG,MAAiB;AACxB,MAAI,UAAU,QAAQ,CAAE,SAAQ,MAAM,WAAW,GAAG,KAAK;;CAE3D,SAAS,OAAiB;AACxB,iBAAe;;CAEjB,WAAqB;AACnB,SAAO;;CAEV"}
|