@manifest-network/manifest-mcp-core 0.11.0 → 0.13.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.map +1 -1
- package/dist/__test-utils__/callTool.js.map +1 -1
- package/dist/__test-utils__/callToolWithElicitation.d.ts.map +1 -1
- package/dist/__test-utils__/callToolWithElicitation.js.map +1 -1
- package/dist/__test-utils__/mocks.d.ts +6 -8
- package/dist/__test-utils__/mocks.d.ts.map +1 -1
- package/dist/__test-utils__/mocks.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/cosmos.d.ts.map +1 -1
- package/dist/cosmos.js.map +1 -1
- package/dist/env-utils.d.ts.map +1 -1
- package/dist/env-utils.js.map +1 -1
- package/dist/guarded-fetch.d.ts +2 -0
- package/dist/guarded-fetch.js +2 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/internals/guarded-fetch.d.ts.map +1 -1
- package/dist/internals/guarded-fetch.js.map +1 -1
- package/dist/lcd-adapter.d.ts.map +1 -1
- package/dist/lcd-adapter.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js.map +1 -1
- package/dist/queries/auth.js.map +1 -1
- package/dist/queries/authz.js.map +1 -1
- package/dist/queries/bank.js.map +1 -1
- package/dist/queries/billing.js.map +1 -1
- package/dist/queries/distribution.js.map +1 -1
- package/dist/queries/feegrant.d.ts.map +1 -1
- package/dist/queries/feegrant.js.map +1 -1
- package/dist/queries/gov.js.map +1 -1
- package/dist/queries/group.js.map +1 -1
- package/dist/queries/ibc-transfer.js.map +1 -1
- package/dist/queries/mint.js.map +1 -1
- package/dist/queries/poa.js.map +1 -1
- package/dist/queries/sku.js.map +1 -1
- package/dist/queries/staking.js.map +1 -1
- package/dist/queries/tokenfactory.js.map +1 -1
- package/dist/queries/utils.d.ts.map +1 -1
- package/dist/queries/utils.js.map +1 -1
- package/dist/queries/wasm.js.map +1 -1
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js.map +1 -1
- package/dist/server-utils.d.ts.map +1 -1
- package/dist/server-utils.js.map +1 -1
- package/dist/tool-metadata.d.ts.map +1 -1
- package/dist/tool-metadata.js.map +1 -1
- package/dist/tools/fundCredits.d.ts.map +1 -1
- package/dist/tools/fundCredits.js.map +1 -1
- package/dist/tools/getBalance.js.map +1 -1
- package/dist/tools/setItemCustomDomain.d.ts.map +1 -1
- package/dist/tools/setItemCustomDomain.js.map +1 -1
- package/dist/tools/stopApp.js.map +1 -1
- package/dist/transactions/authz.d.ts.map +1 -1
- package/dist/transactions/authz.js.map +1 -1
- package/dist/transactions/bank.d.ts.map +1 -1
- package/dist/transactions/bank.js.map +1 -1
- package/dist/transactions/billing.d.ts.map +1 -1
- package/dist/transactions/billing.js.map +1 -1
- package/dist/transactions/distribution.d.ts.map +1 -1
- package/dist/transactions/distribution.js.map +1 -1
- package/dist/transactions/feegrant.d.ts.map +1 -1
- package/dist/transactions/feegrant.js.map +1 -1
- package/dist/transactions/gov.d.ts.map +1 -1
- package/dist/transactions/gov.js.map +1 -1
- package/dist/transactions/group.d.ts.map +1 -1
- package/dist/transactions/group.js.map +1 -1
- package/dist/transactions/ibc-transfer.d.ts.map +1 -1
- package/dist/transactions/ibc-transfer.js.map +1 -1
- package/dist/transactions/json-schemas.d.ts.map +1 -1
- package/dist/transactions/json-schemas.js.map +1 -1
- package/dist/transactions/manifest.d.ts.map +1 -1
- package/dist/transactions/manifest.js.map +1 -1
- package/dist/transactions/poa.d.ts.map +1 -1
- package/dist/transactions/poa.js.map +1 -1
- package/dist/transactions/sku.d.ts.map +1 -1
- package/dist/transactions/sku.js.map +1 -1
- package/dist/transactions/staking.d.ts.map +1 -1
- package/dist/transactions/staking.js.map +1 -1
- package/dist/transactions/tokenfactory.d.ts.map +1 -1
- package/dist/transactions/tokenfactory.js.map +1 -1
- package/dist/transactions/utils.d.ts.map +1 -1
- package/dist/transactions/utils.js.map +1 -1
- package/dist/transactions/wasm.d.ts.map +1 -1
- package/dist/transactions/wasm.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/wallet/mnemonic.d.ts.map +1 -1
- package/dist/wallet/mnemonic.js.map +1 -1
- package/dist/wallet/sign-arbitrary.js.map +1 -1
- package/package.json +10 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callTool.d.ts","names":[],"sources":["../../src/__test-utils__/callTool.ts"],"mappings":";;;;UAIiB,UAAA;EACf,OAAA,EAAS,KAAA;IAAQ,IAAA;IAAc,IAAA;EAAA;EAC/B,OAAA;EACA,iBAAA,GAAoB,
|
|
1
|
+
{"version":3,"file":"callTool.d.ts","names":[],"sources":["../../src/__test-utils__/callTool.ts"],"mappings":";;;;UAIiB,UAAA;EACf,OAAA,EAAS,KAAA;IAAQ,IAAA;IAAc,IAAA;EAAA;EAC/B,OAAA;EACA,iBAAA,GAAoB,MAAM;AAAA;;;;;;;AAAA;AAiB5B;;;;;;;iBAAsB,QAAA,CACpB,MAAA,EAAQ,MAAA,EACR,QAAA,UACA,SAAA,GAAW,MAAA,mBACX,gBAAA,GAAkB,iBAAA,KACjB,OAAA,CAAQ,UAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callTool.js","names":[],"sources":["../../src/__test-utils__/callTool.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\n\nexport interface ToolResult {\n content: Array<{ type: string; text: string }>;\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n}\n\n/**\n * Shared test helper: connects an MCP client to a server via in-memory\n * transport, calls the given tool, then cleans up both transports.\n *\n * Cleanup always runs via the `finally` block: client and both transports\n * are closed, then removed from `activeTransports` to prevent double-close\n * in the caller's `afterEach`.\n *\n * @param server - The MCP `Server` instance (from `getServer()`)\n * @param toolName - Name of the tool to invoke\n * @param toolInput - Optional tool arguments\n * @param activeTransports - Optional mutable array; transports are added\n * before the call and removed after cleanup completes.\n */\nexport async function callTool(\n server: Server,\n toolName: string,\n toolInput: Record<string, unknown> = {},\n activeTransports: InMemoryTransport[] = [],\n): Promise<ToolResult> {\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n activeTransports.push(clientTransport, serverTransport);\n\n const client = new Client({ name: 'test-client', version: '1.0.0' });\n\n try {\n await server.connect(serverTransport);\n await client.connect(clientTransport);\n\n return (await client.callTool({\n name: toolName,\n arguments: toolInput,\n })) as ToolResult;\n } finally {\n await client.close().catch(() => {});\n await clientTransport.close().catch(() => {});\n await serverTransport.close().catch(() => {});\n\n // Remove by identity so afterEach won't double-close\n for (const t of [clientTransport, serverTransport]) {\n const idx = activeTransports.indexOf(t);\n if (idx !== -1) activeTransports.splice(idx, 1);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,eAAsB,SACpB,QACA,UACA,YAAqC,
|
|
1
|
+
{"version":3,"file":"callTool.js","names":[],"sources":["../../src/__test-utils__/callTool.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\n\nexport interface ToolResult {\n content: Array<{ type: string; text: string }>;\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n}\n\n/**\n * Shared test helper: connects an MCP client to a server via in-memory\n * transport, calls the given tool, then cleans up both transports.\n *\n * Cleanup always runs via the `finally` block: client and both transports\n * are closed, then removed from `activeTransports` to prevent double-close\n * in the caller's `afterEach`.\n *\n * @param server - The MCP `Server` instance (from `getServer()`)\n * @param toolName - Name of the tool to invoke\n * @param toolInput - Optional tool arguments\n * @param activeTransports - Optional mutable array; transports are added\n * before the call and removed after cleanup completes.\n */\nexport async function callTool(\n server: Server,\n toolName: string,\n toolInput: Record<string, unknown> = {},\n activeTransports: InMemoryTransport[] = [],\n): Promise<ToolResult> {\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n activeTransports.push(clientTransport, serverTransport);\n\n const client = new Client({ name: 'test-client', version: '1.0.0' });\n\n try {\n await server.connect(serverTransport);\n await client.connect(clientTransport);\n\n return (await client.callTool({\n name: toolName,\n arguments: toolInput,\n })) as ToolResult;\n } finally {\n await client.close().catch(() => {});\n await clientTransport.close().catch(() => {});\n await serverTransport.close().catch(() => {});\n\n // Remove by identity so afterEach won't double-close\n for (const t of [clientTransport, serverTransport]) {\n const idx = activeTransports.indexOf(t);\n if (idx !== -1) activeTransports.splice(idx, 1);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,eAAsB,SACpB,QACA,UACA,YAAqC,CAAC,GACtC,mBAAwC,CAAC,GACpB;CACrB,MAAM,CAAC,iBAAiB,mBACtB,kBAAkB,iBAAiB;CACrC,iBAAiB,KAAK,iBAAiB,eAAe;CAEtD,MAAM,SAAS,IAAI,OAAO;EAAE,MAAM;EAAe,SAAS;CAAQ,CAAC;CAEnE,IAAI;EACF,MAAM,OAAO,QAAQ,eAAe;EACpC,MAAM,OAAO,QAAQ,eAAe;EAEpC,OAAQ,MAAM,OAAO,SAAS;GAC5B,MAAM;GACN,WAAW;EACb,CAAC;CACH,UAAU;EACR,MAAM,OAAO,MAAM,EAAE,YAAY,CAAC,CAAC;EACnC,MAAM,gBAAgB,MAAM,EAAE,YAAY,CAAC,CAAC;EAC5C,MAAM,gBAAgB,MAAM,EAAE,YAAY,CAAC,CAAC;EAG5C,KAAK,MAAM,KAAK,CAAC,iBAAiB,eAAe,GAAG;GAClD,MAAM,MAAM,iBAAiB,QAAQ,CAAC;GACtC,IAAI,QAAQ,IAAI,iBAAiB,OAAO,KAAK,CAAC;EAChD;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callToolWithElicitation.d.ts","names":[],"sources":["../../src/__test-utils__/callToolWithElicitation.ts"],"mappings":";;;;;;;;AAkBA;;;;;;UAAiB,iBAAA;EACf,OAAA,GAAU,GAAA,EAAK,aAAA,KAAkB,YAAA,GAAe,OAAA,CAAQ,YAAA;AAAA
|
|
1
|
+
{"version":3,"file":"callToolWithElicitation.d.ts","names":[],"sources":["../../src/__test-utils__/callToolWithElicitation.ts"],"mappings":";;;;;;;;AAkBA;;;;;;UAAiB,iBAAA;EACf,OAAA,GAAU,GAAA,EAAK,aAAA,KAAkB,YAAA,GAAe,OAAA,CAAQ,YAAA;AAAA;;;;;;;;AAAY;AAyBtE;;;;;;;;;;;;;;iBAAsB,uBAAA,CACpB,MAAA,EAAQ,MAAA,EACR,QAAA,UACA,SAAA,EAAW,MAAA,mBACX,MAAA,EAAQ,iBAAA,EACR,gBAAA,GAAkB,iBAAA,IAClB,4BAAA,aACC,OAAA,CAAQ,UAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callToolWithElicitation.js","names":[],"sources":["../../src/__test-utils__/callToolWithElicitation.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n type ElicitRequest,\n ElicitRequestSchema,\n type ElicitResult,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolResult } from './callTool.js';\n\n/**\n * Scripted responder for incoming `elicitation/create` requests on the\n * test-side MCP `Client`. The test author owns the mapping from request\n * shape → result — the helper just wires it up.\n *\n * `respond` may be sync or async. It must return a valid `ElicitResult`\n * (`{ action: 'accept' | 'decline' | 'cancel', content?: ... }`).\n */\nexport interface ElicitationScript {\n respond: (req: ElicitRequest) => ElicitResult | Promise<ElicitResult>;\n}\n\n/**\n * Mirror of `callTool` for tools that mid-execution call\n * `server.elicitInput(...)`. Connects an MCP client (advertising the\n * `elicitation` capability by default) to the server over an in-memory\n * transport, registers a request handler that delegates each incoming\n * elicitation to `script.respond`, then invokes the named tool.\n *\n * Cleanup always runs via the `finally` block: client and both transports\n * are closed, then removed from `activeTransports` to prevent double-close\n * in the caller's `afterEach`.\n *\n * @param server - The MCP `Server` instance (from `getServer()`)\n * @param toolName - Name of the tool to invoke\n * @param toolInput - Tool arguments\n * @param script - Scripted responder for `elicitation/create` requests\n * @param activeTransports - Optional mutable array; transports are added\n * before the call and removed after cleanup completes.\n * @param declareElicitationCapability - When `true` (default) the test\n * `Client` advertises `capabilities: { elicitation: {} }`. Set to\n * `false` to exercise the wrapper's capability-guard path (the tool\n * should reject with `INVALID_CONFIG` before any elicitation happens).\n */\nexport async function callToolWithElicitation(\n server: Server,\n toolName: string,\n toolInput: Record<string, unknown>,\n script: ElicitationScript,\n activeTransports: InMemoryTransport[] = [],\n declareElicitationCapability = true,\n): Promise<ToolResult> {\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n activeTransports.push(clientTransport, serverTransport);\n\n const client = new Client(\n { name: 'test-client', version: '1.0.0' },\n declareElicitationCapability\n ? { capabilities: { elicitation: {} } }\n : { capabilities: {} },\n );\n\n // Register BEFORE connect so the handler is in place by the time the\n // server issues its first `elicitation/create` request mid-tool.\n //\n // Skip registration when the client did NOT advertise the elicitation\n // capability — the SDK's `setRequestHandler` enforces that the client\n // must have declared the capability for the request type, and would\n // throw before the tool call ever ran. The capability-guard test path\n // (`declareElicitationCapability: false`) exercises the wrapper's\n // `assertElicitationCapability` throw — no elicitation will arrive,\n // so no handler is needed.\n if (declareElicitationCapability) {\n client.setRequestHandler(ElicitRequestSchema, async (request) => {\n return await script.respond(request);\n });\n }\n\n try {\n await server.connect(serverTransport);\n await client.connect(clientTransport);\n\n return (await client.callTool({\n name: toolName,\n arguments: toolInput,\n })) as ToolResult;\n } finally {\n await client.close().catch(() => {});\n await clientTransport.close().catch(() => {});\n await serverTransport.close().catch(() => {});\n\n // Remove by identity so afterEach won't double-close\n for (const t of [clientTransport, serverTransport]) {\n const idx = activeTransports.indexOf(t);\n if (idx !== -1) activeTransports.splice(idx, 1);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,eAAsB,wBACpB,QACA,UACA,WACA,QACA,mBAAwC,
|
|
1
|
+
{"version":3,"file":"callToolWithElicitation.js","names":[],"sources":["../../src/__test-utils__/callToolWithElicitation.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n type ElicitRequest,\n ElicitRequestSchema,\n type ElicitResult,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolResult } from './callTool.js';\n\n/**\n * Scripted responder for incoming `elicitation/create` requests on the\n * test-side MCP `Client`. The test author owns the mapping from request\n * shape → result — the helper just wires it up.\n *\n * `respond` may be sync or async. It must return a valid `ElicitResult`\n * (`{ action: 'accept' | 'decline' | 'cancel', content?: ... }`).\n */\nexport interface ElicitationScript {\n respond: (req: ElicitRequest) => ElicitResult | Promise<ElicitResult>;\n}\n\n/**\n * Mirror of `callTool` for tools that mid-execution call\n * `server.elicitInput(...)`. Connects an MCP client (advertising the\n * `elicitation` capability by default) to the server over an in-memory\n * transport, registers a request handler that delegates each incoming\n * elicitation to `script.respond`, then invokes the named tool.\n *\n * Cleanup always runs via the `finally` block: client and both transports\n * are closed, then removed from `activeTransports` to prevent double-close\n * in the caller's `afterEach`.\n *\n * @param server - The MCP `Server` instance (from `getServer()`)\n * @param toolName - Name of the tool to invoke\n * @param toolInput - Tool arguments\n * @param script - Scripted responder for `elicitation/create` requests\n * @param activeTransports - Optional mutable array; transports are added\n * before the call and removed after cleanup completes.\n * @param declareElicitationCapability - When `true` (default) the test\n * `Client` advertises `capabilities: { elicitation: {} }`. Set to\n * `false` to exercise the wrapper's capability-guard path (the tool\n * should reject with `INVALID_CONFIG` before any elicitation happens).\n */\nexport async function callToolWithElicitation(\n server: Server,\n toolName: string,\n toolInput: Record<string, unknown>,\n script: ElicitationScript,\n activeTransports: InMemoryTransport[] = [],\n declareElicitationCapability = true,\n): Promise<ToolResult> {\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n activeTransports.push(clientTransport, serverTransport);\n\n const client = new Client(\n { name: 'test-client', version: '1.0.0' },\n declareElicitationCapability\n ? { capabilities: { elicitation: {} } }\n : { capabilities: {} },\n );\n\n // Register BEFORE connect so the handler is in place by the time the\n // server issues its first `elicitation/create` request mid-tool.\n //\n // Skip registration when the client did NOT advertise the elicitation\n // capability — the SDK's `setRequestHandler` enforces that the client\n // must have declared the capability for the request type, and would\n // throw before the tool call ever ran. The capability-guard test path\n // (`declareElicitationCapability: false`) exercises the wrapper's\n // `assertElicitationCapability` throw — no elicitation will arrive,\n // so no handler is needed.\n if (declareElicitationCapability) {\n client.setRequestHandler(ElicitRequestSchema, async (request) => {\n return await script.respond(request);\n });\n }\n\n try {\n await server.connect(serverTransport);\n await client.connect(clientTransport);\n\n return (await client.callTool({\n name: toolName,\n arguments: toolInput,\n })) as ToolResult;\n } finally {\n await client.close().catch(() => {});\n await clientTransport.close().catch(() => {});\n await serverTransport.close().catch(() => {});\n\n // Remove by identity so afterEach won't double-close\n for (const t of [clientTransport, serverTransport]) {\n const idx = activeTransports.indexOf(t);\n if (idx !== -1) activeTransports.splice(idx, 1);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,eAAsB,wBACpB,QACA,UACA,WACA,QACA,mBAAwC,CAAC,GACzC,+BAA+B,MACV;CACrB,MAAM,CAAC,iBAAiB,mBACtB,kBAAkB,iBAAiB;CACrC,iBAAiB,KAAK,iBAAiB,eAAe;CAEtD,MAAM,SAAS,IAAI,OACjB;EAAE,MAAM;EAAe,SAAS;CAAQ,GACxC,+BACI,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,EAAE,IACpC,EAAE,cAAc,CAAC,EAAE,CACzB;CAYA,IAAI,8BACF,OAAO,kBAAkB,qBAAqB,OAAO,YAAY;EAC/D,OAAO,MAAM,OAAO,QAAQ,OAAO;CACrC,CAAC;CAGH,IAAI;EACF,MAAM,OAAO,QAAQ,eAAe;EACpC,MAAM,OAAO,QAAQ,eAAe;EAEpC,OAAQ,MAAM,OAAO,SAAS;GAC5B,MAAM;GACN,WAAW;EACb,CAAC;CACH,UAAU;EACR,MAAM,OAAO,MAAM,EAAE,YAAY,CAAC,CAAC;EACnC,MAAM,gBAAgB,MAAM,EAAE,YAAY,CAAC,CAAC;EAC5C,MAAM,gBAAgB,MAAM,EAAE,YAAY,CAAC,CAAC;EAG5C,KAAK,MAAM,KAAK,CAAC,iBAAiB,eAAe,GAAG;GAClD,MAAM,MAAM,iBAAiB,QAAQ,CAAC;GACtC,IAAI,QAAQ,IAAI,iBAAiB,OAAO,KAAK,CAAC;EAChD;CACF;AACF"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { ManifestMCPConfig, WalletProvider } from "../types.js";
|
|
2
2
|
import { ManifestQueryClient } from "../client.js";
|
|
3
3
|
import { LeaseState } from "@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js";
|
|
4
|
-
import * as _$vitest from "vitest";
|
|
5
|
-
import * as _$_vitest_spy0 from "@vitest/spy";
|
|
6
4
|
|
|
7
5
|
//#region src/__test-utils__/mocks.d.ts
|
|
8
6
|
/**
|
|
@@ -122,12 +120,12 @@ declare function makeMockClientManager(overrides?: {
|
|
|
122
120
|
address?: string;
|
|
123
121
|
config?: ManifestMCPConfig;
|
|
124
122
|
}): {
|
|
125
|
-
getQueryClient:
|
|
126
|
-
getSigningClient:
|
|
127
|
-
getAddress:
|
|
128
|
-
getConfig:
|
|
129
|
-
acquireRateLimit:
|
|
130
|
-
disconnect:
|
|
123
|
+
getQueryClient: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
124
|
+
getSigningClient: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
125
|
+
getAddress: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
126
|
+
getConfig: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
127
|
+
acquireRateLimit: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
128
|
+
disconnect: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
131
129
|
};
|
|
132
130
|
//#endregion
|
|
133
131
|
export { makeMockClientManager, makeMockConfig, makeMockQueryClient, makeMockWallet };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mocks.d.ts","names":[],"sources":["../../src/__test-utils__/mocks.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"mocks.d.ts","names":[],"sources":["../../src/__test-utils__/mocks.ts"],"mappings":";;;;;;;AAYA;iBAAgB,cAAA,CACd,SAAA,GAAY,OAAA,CAAQ,iBAAA,IACnB,iBAAA;;;;;iBAca,cAAA,CAAe,IAAA;EAC7B,aAAA;AAAA,IACE,cAAc;;;;UAiBR,gBAAA;EACR,QAAA;IAAa,KAAA;IAAe,MAAA;EAAA;EAC5B,aAAA;IACE,gBAAA;IACA,iBAAA;IACA,eAAA;MAAmB,KAAA;MAAe,MAAA;IAAA;EAAA;EAEpC,qBAAA;IAA0B,KAAA;IAAe,MAAA;EAAA;EACzC,8BAAA;IAAmC,KAAA;IAAe,MAAA;EAAA;EAClD,cAAA;IACE,cAAA;MAAkB,KAAA;MAAe,MAAA;IAAA;IACjC,kBAAA;MAAsB,KAAA;MAAe,MAAA;IAAA;IACrC,wBAAA;IACA,gBAAA;EAAA;EAEF,KAAA;IACE,IAAA;IACA,KAAA,EAAO,UAAA;IACP,YAAA;IACA,SAAA,GAAY,IAAA;IACZ,QAAA,GAAW,IAAA;EAAA;EAEb,YAAA;IAAiB,IAAA;IAAc,YAAA;IAAsB,SAAA,GAAY,IAAA;EAAA;EACjE,aAAA;IAAkB,IAAA;IAAc,YAAA;IAAsB,SAAA,GAAY,IAAA;EAAA;EAClE,YAAA;IAAiB,IAAA;IAAc,YAAA;IAAsB,SAAA,GAAY,IAAA;EAAA;EACjE,cAAA;IAAmB,IAAA;IAAc,YAAA;IAAsB,SAAA,GAAY,IAAA;EAAA;EACnE,aAAA;IAAkB,IAAA;IAAc,YAAA;IAAsB,SAAA,GAAY,IAAA;EAAA;AAAA;AAAA,UAG1D,YAAA;EACR,SAAA;IACE,IAAA;IACA,OAAA;IACA,MAAA;IACA,MAAA;EAAA;EAEF,IAAA;IACE,IAAA;IACA,IAAA;IACA,YAAA;IACA,SAAA;MAAc,MAAA;MAAgB,KAAA;IAAA;EAAA;EAEhC,cAAA,GAAiB,MAAM;IAAW,QAAA;MAAY,MAAA;IAAA;EAAA;AAAA;;;;iBAMhC,mBAAA,CAAoB,SAAA;EAClC,OAAA,GAAU,gBAAA;EACV,GAAA,GAAM,YAAA;AAAA,IA4KU,mBAAA;;;;iBAMF,qBAAA,CAAsB,SAAA;EACpC,WAAA,GAAc,mBAAA;EACd,OAAA;EACA,MAAA,GAAS,iBAAiB;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mocks.js","names":[],"sources":["../../src/__test-utils__/mocks.ts"],"sourcesContent":["import { LeaseState } from '@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js';\nimport { vi } from 'vitest';\nimport type { ManifestQueryClient } from '../client.js';\nimport type {\n ManifestMCPConfig,\n SignArbitraryResult,\n WalletProvider,\n} from '../types.js';\n\n/**\n * Create a mock ManifestMCPConfig with sensible defaults.\n */\nexport function makeMockConfig(\n overrides?: Partial<ManifestMCPConfig>,\n): ManifestMCPConfig {\n return {\n chainId: 'test-chain',\n rpcUrl: 'https://rpc.example.com',\n gasPrice: '1.0umfx',\n addressPrefix: 'manifest',\n ...overrides,\n };\n}\n\n/**\n * Create a mock WalletProvider.\n * Pass `signArbitrary: true` to include a signArbitrary stub.\n */\nexport function makeMockWallet(opts?: {\n signArbitrary?: boolean;\n}): WalletProvider {\n const wallet: WalletProvider = {\n getAddress: vi.fn().mockResolvedValue('manifest1abc'),\n getSigner: vi.fn().mockResolvedValue({}),\n };\n if (opts?.signArbitrary) {\n wallet.signArbitrary = vi.fn().mockResolvedValue({\n pub_key: { type: 'tendermint/PubKeySecp256k1', value: 'mockPubKey' },\n signature: 'mockSignature',\n } satisfies SignArbitraryResult);\n }\n return wallet;\n}\n\n/**\n * Billing mock data defaults\n */\ninterface BillingOverrides {\n balances?: { denom: string; amount: string }[];\n creditAccount?: {\n activeLeaseCount: bigint;\n pendingLeaseCount: bigint;\n reservedAmounts: { denom: string; amount: string }[];\n } | null;\n creditAccountBalances?: { denom: string; amount: string }[];\n creditAccountAvailableBalances?: { denom: string; amount: string }[];\n creditEstimate?: {\n currentBalance: { denom: string; amount: string }[];\n totalRatePerSecond: { denom: string; amount: string }[];\n estimatedDurationSeconds: bigint;\n activeLeaseCount: bigint;\n } | null;\n lease?: {\n uuid: string;\n state: LeaseState;\n providerUuid: string;\n createdAt?: Date;\n closedAt?: Date;\n } | null;\n activeLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n pendingLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n closedLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n rejectedLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n expiredLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n}\n\ninterface SkuOverrides {\n providers?: {\n uuid: string;\n address: string;\n apiUrl: string;\n active: boolean;\n }[];\n skus?: {\n uuid?: string;\n name: string;\n providerUuid: string;\n basePrice?: { amount: string; denom: string };\n }[];\n providerLookup?: Record<string, { provider: { apiUrl: string } }>;\n}\n\n/**\n * Create a mock ManifestQueryClient with configurable billing, bank, and SKU data.\n */\nexport function makeMockQueryClient(overrides?: {\n billing?: BillingOverrides;\n sku?: SkuOverrides;\n}) {\n const billing = overrides?.billing ?? {};\n const sku = overrides?.sku ?? {};\n\n const balances = billing.balances ?? [{ denom: 'umfx', amount: '1000000' }];\n const creditAccount = billing.creditAccount ?? null;\n const creditAccountBalances = billing.creditAccountBalances ?? [];\n const creditAccountAvailableBalances =\n billing.creditAccountAvailableBalances ?? [];\n const creditEstimate = billing.creditEstimate ?? null;\n const lease = billing.lease ?? null;\n const activeLeases = billing.activeLeases ?? [];\n const pendingLeases = billing.pendingLeases ?? [];\n const closedLeases = billing.closedLeases ?? [];\n const rejectedLeases = billing.rejectedLeases ?? [];\n const expiredLeases = billing.expiredLeases ?? [];\n\n const providers = sku.providers ?? [];\n const skus = sku.skus ?? [];\n const providerLookup = sku.providerLookup ?? {};\n\n return {\n cosmos: {\n bank: {\n v1beta1: {\n allBalances: vi.fn().mockResolvedValue({ balances }),\n },\n },\n },\n cosmwasm: {\n wasm: {\n v1: {\n contractInfo: vi.fn().mockResolvedValue({}),\n contractHistory: vi\n .fn()\n .mockResolvedValue({ entries: [], pagination: null }),\n contractsByCode: vi\n .fn()\n .mockResolvedValue({ contracts: [], pagination: null }),\n allContractState: vi\n .fn()\n .mockResolvedValue({ models: [], pagination: null }),\n rawContractState: vi\n .fn()\n .mockResolvedValue({ data: new Uint8Array() }),\n smartContractState: vi\n .fn()\n .mockResolvedValue({ data: new Uint8Array() }),\n code: vi\n .fn()\n .mockResolvedValue({ codeInfo: null, data: new Uint8Array() }),\n codes: vi.fn().mockResolvedValue({ codeInfos: [], pagination: null }),\n codeInfo: vi.fn().mockResolvedValue({\n codeId: BigInt(0),\n creator: '',\n checksum: new Uint8Array(),\n instantiatePermission: { permission: 0, addresses: [] },\n }),\n pinnedCodes: vi\n .fn()\n .mockResolvedValue({ codeIds: [], pagination: null }),\n params: vi.fn().mockResolvedValue({ params: null }),\n contractsByCreator: vi\n .fn()\n .mockResolvedValue({ contractAddresses: [], pagination: null }),\n wasmLimitsConfig: vi.fn().mockResolvedValue({ config: '{}' }),\n buildAddress: vi.fn().mockResolvedValue({ address: '' }),\n },\n },\n },\n liftedinit: {\n billing: {\n v1: {\n creditAccount: vi.fn().mockImplementation(async () => {\n if (creditAccount === null) throw new Error('key not found');\n return {\n creditAccount,\n balances: creditAccountBalances,\n availableBalances: creditAccountAvailableBalances,\n };\n }),\n creditEstimate: vi.fn().mockImplementation(async () => {\n if (creditEstimate === null) throw new Error('credit not found');\n return creditEstimate;\n }),\n lease: vi.fn().mockImplementation(async () => {\n return { lease };\n }),\n leasesByTenant: vi\n .fn()\n .mockImplementation(\n async ({ stateFilter }: { stateFilter: LeaseState }) => {\n if (stateFilter === LeaseState.LEASE_STATE_UNSPECIFIED) {\n return {\n leases: [\n ...activeLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_ACTIVE,\n ...l,\n })),\n ...pendingLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_PENDING,\n ...l,\n })),\n ...closedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_CLOSED,\n ...l,\n })),\n ...rejectedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_REJECTED,\n ...l,\n })),\n ...expiredLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_EXPIRED,\n ...l,\n })),\n ],\n };\n }\n if (stateFilter === LeaseState.LEASE_STATE_ACTIVE)\n return {\n leases: activeLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_ACTIVE,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_PENDING)\n return {\n leases: pendingLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_PENDING,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_CLOSED)\n return {\n leases: closedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_CLOSED,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_REJECTED)\n return {\n leases: rejectedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_REJECTED,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_EXPIRED)\n return {\n leases: expiredLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_EXPIRED,\n ...l,\n })),\n };\n return { leases: [] };\n },\n ),\n },\n },\n sku: {\n v1: {\n providers: vi.fn().mockResolvedValue({ providers }),\n sKUs: vi.fn().mockResolvedValue({ skus }),\n provider: vi\n .fn()\n .mockImplementation(async ({ uuid }: { uuid: string }) => {\n if (providerLookup[uuid]) return providerLookup[uuid];\n throw new Error(`provider ${uuid} not found`);\n }),\n },\n },\n },\n } as unknown as ManifestQueryClient;\n}\n\n/**\n * Create a mock CosmosClientManager.\n */\nexport function makeMockClientManager(overrides?: {\n queryClient?: ManifestQueryClient;\n address?: string;\n config?: ManifestMCPConfig;\n}) {\n const queryClient = overrides?.queryClient ?? makeMockQueryClient();\n const address = overrides?.address ?? 'manifest1abc';\n const config = overrides?.config ?? makeMockConfig();\n\n return {\n getQueryClient: vi.fn().mockResolvedValue(queryClient),\n getSigningClient: vi.fn().mockResolvedValue({}),\n getAddress: vi.fn().mockResolvedValue(address),\n getConfig: vi.fn().mockReturnValue(config),\n acquireRateLimit: vi.fn().mockResolvedValue(undefined),\n disconnect: vi.fn(),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mocks.js","names":[],"sources":["../../src/__test-utils__/mocks.ts"],"sourcesContent":["import { LeaseState } from '@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js';\nimport { vi } from 'vitest';\nimport type { ManifestQueryClient } from '../client.js';\nimport type {\n ManifestMCPConfig,\n SignArbitraryResult,\n WalletProvider,\n} from '../types.js';\n\n/**\n * Create a mock ManifestMCPConfig with sensible defaults.\n */\nexport function makeMockConfig(\n overrides?: Partial<ManifestMCPConfig>,\n): ManifestMCPConfig {\n return {\n chainId: 'test-chain',\n rpcUrl: 'https://rpc.example.com',\n gasPrice: '1.0umfx',\n addressPrefix: 'manifest',\n ...overrides,\n };\n}\n\n/**\n * Create a mock WalletProvider.\n * Pass `signArbitrary: true` to include a signArbitrary stub.\n */\nexport function makeMockWallet(opts?: {\n signArbitrary?: boolean;\n}): WalletProvider {\n const wallet: WalletProvider = {\n getAddress: vi.fn().mockResolvedValue('manifest1abc'),\n getSigner: vi.fn().mockResolvedValue({}),\n };\n if (opts?.signArbitrary) {\n wallet.signArbitrary = vi.fn().mockResolvedValue({\n pub_key: { type: 'tendermint/PubKeySecp256k1', value: 'mockPubKey' },\n signature: 'mockSignature',\n } satisfies SignArbitraryResult);\n }\n return wallet;\n}\n\n/**\n * Billing mock data defaults\n */\ninterface BillingOverrides {\n balances?: { denom: string; amount: string }[];\n creditAccount?: {\n activeLeaseCount: bigint;\n pendingLeaseCount: bigint;\n reservedAmounts: { denom: string; amount: string }[];\n } | null;\n creditAccountBalances?: { denom: string; amount: string }[];\n creditAccountAvailableBalances?: { denom: string; amount: string }[];\n creditEstimate?: {\n currentBalance: { denom: string; amount: string }[];\n totalRatePerSecond: { denom: string; amount: string }[];\n estimatedDurationSeconds: bigint;\n activeLeaseCount: bigint;\n } | null;\n lease?: {\n uuid: string;\n state: LeaseState;\n providerUuid: string;\n createdAt?: Date;\n closedAt?: Date;\n } | null;\n activeLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n pendingLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n closedLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n rejectedLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n expiredLeases?: { uuid: string; providerUuid: string; createdAt?: Date }[];\n}\n\ninterface SkuOverrides {\n providers?: {\n uuid: string;\n address: string;\n apiUrl: string;\n active: boolean;\n }[];\n skus?: {\n uuid?: string;\n name: string;\n providerUuid: string;\n basePrice?: { amount: string; denom: string };\n }[];\n providerLookup?: Record<string, { provider: { apiUrl: string } }>;\n}\n\n/**\n * Create a mock ManifestQueryClient with configurable billing, bank, and SKU data.\n */\nexport function makeMockQueryClient(overrides?: {\n billing?: BillingOverrides;\n sku?: SkuOverrides;\n}) {\n const billing = overrides?.billing ?? {};\n const sku = overrides?.sku ?? {};\n\n const balances = billing.balances ?? [{ denom: 'umfx', amount: '1000000' }];\n const creditAccount = billing.creditAccount ?? null;\n const creditAccountBalances = billing.creditAccountBalances ?? [];\n const creditAccountAvailableBalances =\n billing.creditAccountAvailableBalances ?? [];\n const creditEstimate = billing.creditEstimate ?? null;\n const lease = billing.lease ?? null;\n const activeLeases = billing.activeLeases ?? [];\n const pendingLeases = billing.pendingLeases ?? [];\n const closedLeases = billing.closedLeases ?? [];\n const rejectedLeases = billing.rejectedLeases ?? [];\n const expiredLeases = billing.expiredLeases ?? [];\n\n const providers = sku.providers ?? [];\n const skus = sku.skus ?? [];\n const providerLookup = sku.providerLookup ?? {};\n\n return {\n cosmos: {\n bank: {\n v1beta1: {\n allBalances: vi.fn().mockResolvedValue({ balances }),\n },\n },\n },\n cosmwasm: {\n wasm: {\n v1: {\n contractInfo: vi.fn().mockResolvedValue({}),\n contractHistory: vi\n .fn()\n .mockResolvedValue({ entries: [], pagination: null }),\n contractsByCode: vi\n .fn()\n .mockResolvedValue({ contracts: [], pagination: null }),\n allContractState: vi\n .fn()\n .mockResolvedValue({ models: [], pagination: null }),\n rawContractState: vi\n .fn()\n .mockResolvedValue({ data: new Uint8Array() }),\n smartContractState: vi\n .fn()\n .mockResolvedValue({ data: new Uint8Array() }),\n code: vi\n .fn()\n .mockResolvedValue({ codeInfo: null, data: new Uint8Array() }),\n codes: vi.fn().mockResolvedValue({ codeInfos: [], pagination: null }),\n codeInfo: vi.fn().mockResolvedValue({\n codeId: BigInt(0),\n creator: '',\n checksum: new Uint8Array(),\n instantiatePermission: { permission: 0, addresses: [] },\n }),\n pinnedCodes: vi\n .fn()\n .mockResolvedValue({ codeIds: [], pagination: null }),\n params: vi.fn().mockResolvedValue({ params: null }),\n contractsByCreator: vi\n .fn()\n .mockResolvedValue({ contractAddresses: [], pagination: null }),\n wasmLimitsConfig: vi.fn().mockResolvedValue({ config: '{}' }),\n buildAddress: vi.fn().mockResolvedValue({ address: '' }),\n },\n },\n },\n liftedinit: {\n billing: {\n v1: {\n creditAccount: vi.fn().mockImplementation(async () => {\n if (creditAccount === null) throw new Error('key not found');\n return {\n creditAccount,\n balances: creditAccountBalances,\n availableBalances: creditAccountAvailableBalances,\n };\n }),\n creditEstimate: vi.fn().mockImplementation(async () => {\n if (creditEstimate === null) throw new Error('credit not found');\n return creditEstimate;\n }),\n lease: vi.fn().mockImplementation(async () => {\n return { lease };\n }),\n leasesByTenant: vi\n .fn()\n .mockImplementation(\n async ({ stateFilter }: { stateFilter: LeaseState }) => {\n if (stateFilter === LeaseState.LEASE_STATE_UNSPECIFIED) {\n return {\n leases: [\n ...activeLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_ACTIVE,\n ...l,\n })),\n ...pendingLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_PENDING,\n ...l,\n })),\n ...closedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_CLOSED,\n ...l,\n })),\n ...rejectedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_REJECTED,\n ...l,\n })),\n ...expiredLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_EXPIRED,\n ...l,\n })),\n ],\n };\n }\n if (stateFilter === LeaseState.LEASE_STATE_ACTIVE)\n return {\n leases: activeLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_ACTIVE,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_PENDING)\n return {\n leases: pendingLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_PENDING,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_CLOSED)\n return {\n leases: closedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_CLOSED,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_REJECTED)\n return {\n leases: rejectedLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_REJECTED,\n ...l,\n })),\n };\n if (stateFilter === LeaseState.LEASE_STATE_EXPIRED)\n return {\n leases: expiredLeases.map((l) => ({\n state: LeaseState.LEASE_STATE_EXPIRED,\n ...l,\n })),\n };\n return { leases: [] };\n },\n ),\n },\n },\n sku: {\n v1: {\n providers: vi.fn().mockResolvedValue({ providers }),\n sKUs: vi.fn().mockResolvedValue({ skus }),\n provider: vi\n .fn()\n .mockImplementation(async ({ uuid }: { uuid: string }) => {\n if (providerLookup[uuid]) return providerLookup[uuid];\n throw new Error(`provider ${uuid} not found`);\n }),\n },\n },\n },\n } as unknown as ManifestQueryClient;\n}\n\n/**\n * Create a mock CosmosClientManager.\n */\nexport function makeMockClientManager(overrides?: {\n queryClient?: ManifestQueryClient;\n address?: string;\n config?: ManifestMCPConfig;\n}) {\n const queryClient = overrides?.queryClient ?? makeMockQueryClient();\n const address = overrides?.address ?? 'manifest1abc';\n const config = overrides?.config ?? makeMockConfig();\n\n return {\n getQueryClient: vi.fn().mockResolvedValue(queryClient),\n getSigningClient: vi.fn().mockResolvedValue({}),\n getAddress: vi.fn().mockResolvedValue(address),\n getConfig: vi.fn().mockReturnValue(config),\n acquireRateLimit: vi.fn().mockResolvedValue(undefined),\n disconnect: vi.fn(),\n };\n}\n"],"mappings":"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"}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KA4CK,qBAAA,GAAwB,OAAA,CAC3B,UAAA,QAAkB,UAAA,CAAW,aAAA,CAAc,oBAAA;AAAA,KAExC,mBAAA,GAAsB,OAAA,CACzB,UAAA,QAAkB,QAAA,CAAW,aAAA,CAAc,oBAAA;AAAA,KAExC,8BAAA,GAAiC,OAAA,CACpC,UAAA,QAAkB,oBAAA,CAAsB,aAAA,CAAc,oBAAA;AAAA,KAEnD,kBAAA,GAAqB,OAAA,CACxB,UAAA,QAAkB,OAAA,CAAU,aAAA,CAAc,oBAAA;AAAA,KAEvC,cAAA,GAAiB,OAAA,CACpB,UAAA,QAAkB,GAAA,CAAM,aAAA,CAAc,oBAAA;AAAA,KAE5B,mBAAA,GAAsB,qBAAA,GAChC,IAAA,CAAK,mBAAA,gBACL,IAAA,CAAK,8BAAA,4BACL,IAAA,CAAK,kBAAA,eACL,IAAA,CAAK,cAAA;;;;cAiDM,mBAAA;EAAA,eACI,SAAA;EAAA,QAEP,MAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;EAAA,QACA,aAAA;EAAA,QACA,WAAA;EAAA,QAMA,QAAA;EAAA,QAGA,kBAAA;EAAA,QACA,oBAAA;EAAA,QAED,WAAA
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;KA4CK,qBAAA,GAAwB,OAAA,CAC3B,UAAA,QAAkB,UAAA,CAAW,aAAA,CAAc,oBAAA;AAAA,KAExC,mBAAA,GAAsB,OAAA,CACzB,UAAA,QAAkB,QAAA,CAAW,aAAA,CAAc,oBAAA;AAAA,KAExC,8BAAA,GAAiC,OAAA,CACpC,UAAA,QAAkB,oBAAA,CAAsB,aAAA,CAAc,oBAAA;AAAA,KAEnD,kBAAA,GAAqB,OAAA,CACxB,UAAA,QAAkB,OAAA,CAAU,aAAA,CAAc,oBAAA;AAAA,KAEvC,cAAA,GAAiB,OAAA,CACpB,UAAA,QAAkB,GAAA,CAAM,aAAA,CAAc,oBAAA;AAAA,KAE5B,mBAAA,GAAsB,qBAAA,GAChC,IAAA,CAAK,mBAAA,gBACL,IAAA,CAAK,8BAAA,4BACL,IAAA,CAAK,kBAAA,eACL,IAAA,CAAK,cAAA;;;;cAiDM,mBAAA;EAAA,eACI,SAAA;EAAA,QAEP,MAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;EAAA,QACA,aAAA;EAAA,QACA,WAAA;EAAA,QAMA,QAAA;EAAA,QAGA,kBAAA;EAAA,QACA,oBAAA;EAAA,QAED,WAAA;EAnFW;;;;;;;;;;;AAA6C;AAAA;;;;;;;;EAA7C,OAuHX,WAAA,CACL,MAAA,EAAQ,iBAAA,EACR,cAAA,EAAgB,cAAA,GACf,mBAAA;EAvHH;;;;;AAA0E;AAAA;EAA1E,OA+KO,cAAA;;;;;;EAeD,cAAA,IAAkB,OAAA,CAAQ,mBAAA;EA5LR;;;;;EAmSlB,gBAAA,IAAoB,OAAA,CAAQ,qBAAA;EAlS4B;AAAA;;EAyYxD,UAAA,IAAc,OAAA;EAtYF;;;EA6YlB,SAAA,IAAa,iBAAA;EA9Yc;;;;EAsZrB,gBAAA,IAAoB,OAAA;EArZY;;AAAoB;AAE5D;;;;;EA+ZE,UAAA;EA7ZK;;;;;EAAA,QAuaG,QAAA;AAAA"}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["cosmwasmNs","strangeloveVenturesNs","osmosisNs","ibcNs"],"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 cosmwasmAminoConverters,\n cosmwasm as cosmwasmNs,\n cosmwasmProtoRegistry,\n ibcAminoConverters,\n ibc as ibcNs,\n ibcProtoRegistry,\n liftedinit,\n liftedinitAminoConverters,\n liftedinitProtoRegistry,\n osmosisAminoConverters,\n osmosis as osmosisNs,\n osmosisProtoRegistry,\n strangeloveVenturesAminoConverters,\n strangelove_ventures as strangeloveVenturesNs,\n strangeloveVenturesProtoRegistry,\n} from '@manifest-network/manifestjs';\nimport { RateLimiter } from 'limiter';\nimport {\n DEFAULT_GAS_MULTIPLIER,\n DEFAULT_REQUESTS_PER_SECOND,\n} from './config.js';\nimport { createLCDQueryClient } from './lcd-adapter.js';\nimport { logger } from './logger.js';\nimport { withRetry } from './retry.js';\nimport {\n type ManifestMCPConfig,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type WalletProvider,\n} from './types.js';\n\n// Combined query client type: liftedinit modules (cosmos + billing/manifest/sku) + cosmwasm\n// + strangelove_ventures (poa) + osmosis (tokenfactory) + ibc (transfer, channel, client, connection).\n// Uses Pick to extract only each factory's unique namespace, avoiding conflicts with overlapping cosmos types.\ntype LiftedinitQueryClient = Awaited<\n ReturnType<typeof liftedinit.ClientFactory.createRPCQueryClient>\n>;\ntype CosmwasmQueryClient = Awaited<\n ReturnType<typeof cosmwasmNs.ClientFactory.createRPCQueryClient>\n>;\ntype StrangeloveVenturesQueryClient = Awaited<\n ReturnType<typeof strangeloveVenturesNs.ClientFactory.createRPCQueryClient>\n>;\ntype OsmosisQueryClient = Awaited<\n ReturnType<typeof osmosisNs.ClientFactory.createRPCQueryClient>\n>;\ntype IbcQueryClient = Awaited<\n ReturnType<typeof ibcNs.ClientFactory.createRPCQueryClient>\n>;\nexport type ManifestQueryClient = LiftedinitQueryClient &\n Pick<CosmwasmQueryClient, 'cosmwasm'> &\n Pick<StrangeloveVenturesQueryClient, 'strangelove_ventures'> &\n Pick<OsmosisQueryClient, 'osmosis'> &\n Pick<IbcQueryClient, 'ibc'>;\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 ...cosmwasmProtoRegistry,\n ...ibcProtoRegistry,\n ]);\n\n const aminoTypes = new AminoTypes({\n ...cosmosAminoConverters,\n ...liftedinitAminoConverters,\n ...strangeloveVenturesAminoConverters,\n ...osmosisAminoConverters,\n ...cosmwasmAminoConverters,\n ...ibcAminoConverters,\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 // Number of live holders (servers) sharing this instance. Each getInstance\n // acquisition increments it; each disconnect() decrements it. The underlying\n // clients are only torn down once the count reaches zero (the last holder\n // disconnects), so one server's shutdown can't sever another's shared client.\n private refCount = 0;\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, gasMultiplier, or walletProvider changed\n * - Rate limiter is updated if requestsPerSecond changed (without affecting signing client)\n *\n * Every call acquires a reference (increments refCount). Each caller must\n * balance it with exactly one disconnect() so the shared clients are torn\n * down only once the last holder releases (see disconnect()).\n *\n * Reference accounting counts calls, not distinct callers: a call that only\n * updates config on an existing key (changed gasPrice/gasMultiplier/\n * walletProvider/rate limit) still acquires a reference. A holder that\n * re-invokes getInstance to reconfigure a key it already holds therefore\n * takes an ADDITIONAL reference and must balance it with an additional\n * disconnect(), or refCount never reaches zero and the clients leak. Today\n * every server acquires once at construction and releases once at shutdown,\n * so this caveat only applies to callers that reconfigure a live key in place.\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.config.gasMultiplier !== config.gasMultiplier ||\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 instance.refCount += 1;\n return instance;\n }\n\n /**\n * Clear all cached instances (useful for testing or reconnection).\n * Force-tears-down each instance regardless of its refCount — clearing the\n * registry is an unconditional reset, so it ignores outstanding holders,\n * disconnects signing clients, releases query client references, and resets\n * refCount to zero before clearing.\n */\n static clearInstances(): void {\n for (const instance of CosmosClientManager.instances.values()) {\n // Force teardown regardless of refCount — clearing the registry is an\n // unconditional reset (used by tests/reconnection), so drop all holders.\n instance.teardown();\n instance.refCount = 0;\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: merge liftedinit + cosmwasm + strangelove_ventures + osmosis + ibc namespaces\n client = await withRetry(\n async () => {\n const [\n liftedinitClient,\n cosmwasmClient,\n strangeloveClient,\n osmosisClient,\n ibcClient,\n ] = await Promise.all([\n liftedinit.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n cosmwasmNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n strangeloveVenturesNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n osmosisNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n ibcNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n ]);\n return {\n ...liftedinitClient,\n cosmwasm: cosmwasmClient.cosmwasm,\n strangelove_ventures: strangeloveClient.strangelove_ventures,\n osmosis: osmosisClient.osmosis,\n ibc: ibcClient.ibc,\n } as ManifestQueryClient;\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 async () => {\n const c = await SigningStargateClient.connectWithSigner(\n endpoint,\n signer,\n {\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 // The property is private readonly with no constructor option,\n // so we must bypass TypeScript's access control to override it.\n const record = c as unknown as Record<string, unknown>;\n if (typeof record.defaultGasMultiplier === 'number') {\n record.defaultGasMultiplier =\n this.config.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER;\n } else {\n const effective =\n this.config.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER;\n logger.warn(\n `gasMultiplier ${effective} could not be applied: ` +\n `signing client defaultGasMultiplier is ${typeof record.defaultGasMultiplier}, expected number. ` +\n `Transactions will use the CosmJS built-in gas multiplier instead.`,\n );\n }\n return c;\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 * Release this holder's reference to the shared instance. The underlying\n * clients are only torn down once the last holder disconnects (refCount\n * reaches zero), so one server's shutdown cannot sever a client still in\n * use by another server sharing the same config key. Calling disconnect()\n * more times than getInstance() was called is safe and never drives the\n * count negative.\n */\n disconnect(): void {\n if (this.refCount > 0) this.refCount -= 1;\n if (this.refCount === 0) this.teardown();\n }\n\n /**\n * Tear down 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 private teardown(): 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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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["cosmwasmNs","strangeloveVenturesNs","osmosisNs","ibcNs"],"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 cosmwasmAminoConverters,\n cosmwasm as cosmwasmNs,\n cosmwasmProtoRegistry,\n ibcAminoConverters,\n ibc as ibcNs,\n ibcProtoRegistry,\n liftedinit,\n liftedinitAminoConverters,\n liftedinitProtoRegistry,\n osmosisAminoConverters,\n osmosis as osmosisNs,\n osmosisProtoRegistry,\n strangeloveVenturesAminoConverters,\n strangelove_ventures as strangeloveVenturesNs,\n strangeloveVenturesProtoRegistry,\n} from '@manifest-network/manifestjs';\nimport { RateLimiter } from 'limiter';\nimport {\n DEFAULT_GAS_MULTIPLIER,\n DEFAULT_REQUESTS_PER_SECOND,\n} from './config.js';\nimport { createLCDQueryClient } from './lcd-adapter.js';\nimport { logger } from './logger.js';\nimport { withRetry } from './retry.js';\nimport {\n type ManifestMCPConfig,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type WalletProvider,\n} from './types.js';\n\n// Combined query client type: liftedinit modules (cosmos + billing/manifest/sku) + cosmwasm\n// + strangelove_ventures (poa) + osmosis (tokenfactory) + ibc (transfer, channel, client, connection).\n// Uses Pick to extract only each factory's unique namespace, avoiding conflicts with overlapping cosmos types.\ntype LiftedinitQueryClient = Awaited<\n ReturnType<typeof liftedinit.ClientFactory.createRPCQueryClient>\n>;\ntype CosmwasmQueryClient = Awaited<\n ReturnType<typeof cosmwasmNs.ClientFactory.createRPCQueryClient>\n>;\ntype StrangeloveVenturesQueryClient = Awaited<\n ReturnType<typeof strangeloveVenturesNs.ClientFactory.createRPCQueryClient>\n>;\ntype OsmosisQueryClient = Awaited<\n ReturnType<typeof osmosisNs.ClientFactory.createRPCQueryClient>\n>;\ntype IbcQueryClient = Awaited<\n ReturnType<typeof ibcNs.ClientFactory.createRPCQueryClient>\n>;\nexport type ManifestQueryClient = LiftedinitQueryClient &\n Pick<CosmwasmQueryClient, 'cosmwasm'> &\n Pick<StrangeloveVenturesQueryClient, 'strangelove_ventures'> &\n Pick<OsmosisQueryClient, 'osmosis'> &\n Pick<IbcQueryClient, 'ibc'>;\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 ...cosmwasmProtoRegistry,\n ...ibcProtoRegistry,\n ]);\n\n const aminoTypes = new AminoTypes({\n ...cosmosAminoConverters,\n ...liftedinitAminoConverters,\n ...strangeloveVenturesAminoConverters,\n ...osmosisAminoConverters,\n ...cosmwasmAminoConverters,\n ...ibcAminoConverters,\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 // Number of live holders (servers) sharing this instance. Each getInstance\n // acquisition increments it; each disconnect() decrements it. The underlying\n // clients are only torn down once the count reaches zero (the last holder\n // disconnects), so one server's shutdown can't sever another's shared client.\n private refCount = 0;\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, gasMultiplier, or walletProvider changed\n * - Rate limiter is updated if requestsPerSecond changed (without affecting signing client)\n *\n * Every call acquires a reference (increments refCount). Each caller must\n * balance it with exactly one disconnect() so the shared clients are torn\n * down only once the last holder releases (see disconnect()).\n *\n * Reference accounting counts calls, not distinct callers: a call that only\n * updates config on an existing key (changed gasPrice/gasMultiplier/\n * walletProvider/rate limit) still acquires a reference. A holder that\n * re-invokes getInstance to reconfigure a key it already holds therefore\n * takes an ADDITIONAL reference and must balance it with an additional\n * disconnect(), or refCount never reaches zero and the clients leak. Today\n * every server acquires once at construction and releases once at shutdown,\n * so this caveat only applies to callers that reconfigure a live key in place.\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.config.gasMultiplier !== config.gasMultiplier ||\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 instance.refCount += 1;\n return instance;\n }\n\n /**\n * Clear all cached instances (useful for testing or reconnection).\n * Force-tears-down each instance regardless of its refCount — clearing the\n * registry is an unconditional reset, so it ignores outstanding holders,\n * disconnects signing clients, releases query client references, and resets\n * refCount to zero before clearing.\n */\n static clearInstances(): void {\n for (const instance of CosmosClientManager.instances.values()) {\n // Force teardown regardless of refCount — clearing the registry is an\n // unconditional reset (used by tests/reconnection), so drop all holders.\n instance.teardown();\n instance.refCount = 0;\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: merge liftedinit + cosmwasm + strangelove_ventures + osmosis + ibc namespaces\n client = await withRetry(\n async () => {\n const [\n liftedinitClient,\n cosmwasmClient,\n strangeloveClient,\n osmosisClient,\n ibcClient,\n ] = await Promise.all([\n liftedinit.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n cosmwasmNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n strangeloveVenturesNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n osmosisNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n ibcNs.ClientFactory.createRPCQueryClient({\n rpcEndpoint: this.config.rpcUrl!,\n }),\n ]);\n return {\n ...liftedinitClient,\n cosmwasm: cosmwasmClient.cosmwasm,\n strangelove_ventures: strangeloveClient.strangelove_ventures,\n osmosis: osmosisClient.osmosis,\n ibc: ibcClient.ibc,\n } as ManifestQueryClient;\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 async () => {\n const c = await SigningStargateClient.connectWithSigner(\n endpoint,\n signer,\n {\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 // The property is private readonly with no constructor option,\n // so we must bypass TypeScript's access control to override it.\n const record = c as unknown as Record<string, unknown>;\n if (typeof record.defaultGasMultiplier === 'number') {\n record.defaultGasMultiplier =\n this.config.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER;\n } else {\n const effective =\n this.config.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER;\n logger.warn(\n `gasMultiplier ${effective} could not be applied: ` +\n `signing client defaultGasMultiplier is ${typeof record.defaultGasMultiplier}, expected number. ` +\n `Transactions will use the CosmJS built-in gas multiplier instead.`,\n );\n }\n return c;\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 * Release this holder's reference to the shared instance. The underlying\n * clients are only torn down once the last holder disconnects (refCount\n * reaches zero), so one server's shutdown cannot sever a client still in\n * use by another server sharing the same config key. Calling disconnect()\n * more times than getInstance() was called is safe and never drives the\n * count negative.\n */\n disconnect(): void {\n if (this.refCount > 0) this.refCount -= 1;\n if (this.refCount === 0) this.teardown();\n }\n\n /**\n * Tear down 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 private teardown(): 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.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;;;;AAeA;cAAa,2BAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;;;;AAeA;cAAa,2BAAA;;;AAA2B;AAOxC;;cAAa,sBAAA;AAAsB;AAsBnC;;;AAtBmC,iBAsBnB,mBAAA,CACd,GAAA,UACA,KAAA;EACG,KAAA;AAAA;EAAkB,KAAA;EAAc,MAAA;AAAA;;AAAM;AAqD3C;iBAAgB,YAAA,CAAa,KAAA,EAAO,iBAAA,GAAoB,iBAAiB;;;;UAuBxD,gBAAA;EACf,KAAA;EACA,MAAM;AAAA;AAFR;;;AAAA,iBAQgB,cAAA,CACd,MAAA,EAAQ,OAAA,CAAQ,iBAAA,IACf,gBAAA;AARK;AAMR;;AANQ,iBA4IQ,qBAAA,CACd,KAAA,EAAO,iBAAA,GACN,iBAAiB"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +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/**\n * Default gas simulation multiplier. CosmJS defaults to 1.4 but billing module\n * transactions (close-lease in particular) can exceed that. 1.5 matches\n * the --gas-adjustment value used in this project's E2E scripts (e2e/scripts/init_billing.sh).\n */\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\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 */\nexport function 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 // Denoms can be simple (umfx), IBC (ibc/ABC123...), or factory\n // (factory/manifest1.../utoken). Denoms are made of non-empty segments\n // separated by '/', with the first segment starting with a letter.\n // Each segment may contain letters, digits, dots, colons, underscores,\n // and hyphens. Denom length must be 3-128 chars per the Cosmos SDK spec.\n const match = gasPrice.match(\n /^(\\d+(?:\\.\\d+)?)([a-zA-Z][a-zA-Z0-9.:_-]*(?:\\/[a-zA-Z0-9.:_-]+)*)$/,\n );\n if (!match) {\n return false;\n }\n const denom = match[2];\n return denom.length >= 3 && denom.length <= 128;\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 gasMultiplier: input.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER,\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\", \"0.5factory/addr/udenom\", or \"0.25ibc/ABC123\")',\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 if (config.gasMultiplier !== undefined) {\n if (\n typeof config.gasMultiplier !== 'number' ||\n !Number.isFinite(config.gasMultiplier) ||\n config.gasMultiplier < 1\n ) {\n errors.push('gasMultiplier must be a finite number >= 1');\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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"}
|
|
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/**\n * Default gas simulation multiplier. CosmJS defaults to 1.4 but billing module\n * transactions (close-lease in particular) can exceed that. 1.5 matches\n * the --gas-adjustment value used in this project's E2E scripts (e2e/scripts/init_billing.sh).\n */\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\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 */\nexport function 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 // Denoms can be simple (umfx), IBC (ibc/ABC123...), or factory\n // (factory/manifest1.../utoken). Denoms are made of non-empty segments\n // separated by '/', with the first segment starting with a letter.\n // Each segment may contain letters, digits, dots, colons, underscores,\n // and hyphens. Denom length must be 3-128 chars per the Cosmos SDK spec.\n const match = gasPrice.match(\n /^(\\d+(?:\\.\\d+)?)([a-zA-Z][a-zA-Z0-9.:_-]*(?:\\/[a-zA-Z0-9.:_-]+)*)$/,\n );\n if (!match) {\n return false;\n }\n const denom = match[2];\n return denom.length >= 3 && denom.length <= 128;\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 gasMultiplier: input.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER,\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\", \"0.5factory/addr/udenom\", or \"0.25ibc/ABC123\")',\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 if (config.gasMultiplier !== undefined) {\n if (\n typeof config.gasMultiplier !== 'number' ||\n !Number.isFinite(config.gasMultiplier) ||\n config.gasMultiplier < 1\n ) {\n errors.push('gasMultiplier must be a finite number >= 1');\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.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmos.d.ts","names":[],"sources":["../src/cosmos.ts"],"mappings":";;;;;;AAqGA;;;;iBAAsB,WAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,cACC,OAAA,CAAQ,iBAAA;;;;;;;;;;iBA+DW,QAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,aACA,mBAAA,YACA,SAAA,GAAY,WAAA,GACX,OAAA,CAAQ,cAAA
|
|
1
|
+
{"version":3,"file":"cosmos.d.ts","names":[],"sources":["../src/cosmos.ts"],"mappings":";;;;;;AAqGA;;;;iBAAsB,WAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,cACC,OAAA,CAAQ,iBAAA;;;;;;;;;;iBA+DW,QAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,aACA,mBAAA,YACA,SAAA,GAAY,WAAA,GACX,OAAA,CAAQ,cAAA;;AAtEiB;AA+D5B;;;;;;;;;iBA4GsB,iBAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,UACA,UAAA,UACA,IAAA,aACA,SAAA,GAAY,WAAA,GACX,OAAA,CAAQ,iBAAA"}
|
package/dist/cosmos.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmos.js","names":[],"sources":["../src/cosmos.ts"],"sourcesContent":["import { calculateFee } from '@cosmjs/stargate';\nimport type { CosmosClientManager } from './client.js';\nimport { DEFAULT_GAS_MULTIPLIER } from './config.js';\nimport {\n getQueryHandler,\n getTxContextLoader,\n getTxHandler,\n getTxMsgBuilder,\n} from './modules.js';\nimport { withRetry } from './retry.js';\nimport {\n type CosmosQueryResult,\n type CosmosTxResult,\n type FeeEstimateResult,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type TxBuildContext,\n type TxOptions,\n type TxOverrides,\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 * Resolve and run the `TxBuildContext` loader registered for `(module,\n * subcommand)` in `TX_MODULES`. Returns `undefined` when no loader is\n * registered (the common case) so the caller can short-circuit and skip the\n * chain read.\n *\n * Acquires a rate-limit token before the loader runs so each extra RPC is\n * counted against the same budget every other RPC respects, and wraps any\n * non-`ManifestMCPError` failure as `QUERY_FAILED` with `{module, subcommand}`\n * details for symmetric error classification on both broadcast and estimate\n * paths.\n */\nasync function loadBuildContext(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n): Promise<TxBuildContext | undefined> {\n const loader = getTxContextLoader(module, subcommand);\n if (!loader) return undefined;\n\n // The full loader call sequence — rate-limit acquire, query-client\n // construction, loader invocation — runs inside the try/catch so every\n // failure mode gets the {module, subcommand} attribution callers expect\n // from a structured error. Without the wrap, an INVALID_CONFIG from\n // `getQueryClient` (or a connection failure that escapes the inner\n // withRetry) would propagate without telling the caller which tx was\n // being prepared.\n try {\n await clientManager.acquireRateLimit();\n const queryClient = await clientManager.getQueryClient();\n return await loader(queryClient);\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n if (!error.details?.module) {\n throw new ManifestMCPError(error.code, error.message, {\n ...error.details,\n module,\n subcommand,\n });\n }\n throw error;\n }\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `Failed to load build context for ${module} ${subcommand}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { module, subcommand },\n );\n }\n}\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 // The rate-limit + query-client acquisition runs inside the try/catch\n // so a failure during either step is wrapped with {module, subcommand}\n // attribution, matching the handler-leg semantics. Otherwise an\n // INVALID_CONFIG from `getQueryClient` (or a connection failure that\n // escapes the inner withRetry) would propagate without telling the\n // caller which query was being routed.\n try {\n await clientManager.acquireRateLimit();\n const queryClient = await clientManager.getQueryClient();\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 if (!error.details?.module) {\n throw new ManifestMCPError(error.code, error.message, {\n ...error.details,\n module,\n subcommand,\n });\n }\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 { module, subcommand },\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 overrides?: TxOverrides,\n): Promise<CosmosTxResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_TX);\n validateName(subcommand, 'subcommand', ManifestMCPErrorCode.UNSUPPORTED_TX);\n\n // Build fully-resolved gas options from caller overrides + server config\n let txOptions: TxOptions | undefined;\n if (overrides?.gasMultiplier !== undefined) {\n if (\n !Number.isFinite(overrides.gasMultiplier) ||\n overrides.gasMultiplier < 1\n ) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `gasMultiplier must be a finite number >= 1, got ${overrides.gasMultiplier}`,\n );\n }\n const gasPrice = clientManager.getConfig().gasPrice;\n if (!gasPrice) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'gasMultiplier override requires gasPrice configuration',\n );\n }\n txOptions = { gasMultiplier: overrides.gasMultiplier, gasPrice };\n }\n\n // Get handler from registry (throws if module not found) - do this before retry loop\n const handler = getTxHandler(module);\n // Fetch chain context once before the broadcast retry loop: every broadcast\n // attempt uses the same snapshot and we don't consume extra rate-limit\n // tokens per broadcast retry. The loader is independently wrapped in its\n // own withRetry so transient LCD failures during the chain read still get\n // retried (parity with cosmosQuery's params reads).\n const buildContext = await withRetry(\n () => loadBuildContext(clientManager, module, subcommand),\n {\n config: clientManager.getConfig().retry,\n operationName: `load-context ${module} ${subcommand}`,\n },\n );\n\n return withRetry(\n async () => {\n // The rate-limit + signing-client + address acquisition runs inside\n // the try/catch so a failure during any of those steps is wrapped\n // with {module, subcommand, args} attribution, matching the\n // handler-leg semantics. Otherwise an INVALID_CONFIG / wallet error\n // from these calls would propagate without telling the caller which\n // tx was being prepared.\n try {\n await clientManager.acquireRateLimit();\n const signingClient = await clientManager.getSigningClient();\n const senderAddress = await clientManager.getAddress();\n\n return await handler(\n signingClient,\n senderAddress,\n subcommand,\n args,\n waitForConfirmation,\n txOptions,\n buildContext,\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\n/**\n * Estimate the fee for a Cosmos transaction without broadcasting it.\n *\n * Looks up the message builder for the given module, builds the messages,\n * and calls `client.simulate()` to get a gas estimate. Multiplies by the\n * configured (or overridden) gas multiplier and computes the fee.\n *\n * Automatically retries on transient failures via `withRetry`.\n *\n * @returns FeeEstimateResult with raw gas estimate and computed fee\n */\nexport async function cosmosEstimateFee(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n args: string[] = [],\n overrides?: TxOverrides,\n): Promise<FeeEstimateResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_TX);\n validateName(subcommand, 'subcommand', ManifestMCPErrorCode.UNSUPPORTED_TX);\n\n // Always need gasPrice for fee calculation (unlike cosmosTx which can use 'auto')\n const config = clientManager.getConfig();\n const gasPrice = config.gasPrice;\n if (!gasPrice) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'Fee estimation requires gasPrice configuration',\n );\n }\n\n // Validate the override eagerly (the resolved fallback values are always valid).\n if (overrides?.gasMultiplier !== undefined) {\n if (\n !Number.isFinite(overrides.gasMultiplier) ||\n overrides.gasMultiplier < 1\n ) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `gasMultiplier must be a finite number >= 1, got ${overrides.gasMultiplier}`,\n );\n }\n }\n\n // Get builder from registry (throws if module not found) - do this before retry loop\n const builder = getTxMsgBuilder(module);\n // Fetch chain context once before the simulate retry loop: every simulate\n // attempt uses the same snapshot and we don't consume extra rate-limit\n // tokens per simulate retry. The loader is independently wrapped in its\n // own withRetry so transient LCD failures during the chain read still get\n // retried (parity with cosmosQuery's params reads).\n const buildContext = await withRetry(\n () => loadBuildContext(clientManager, module, subcommand),\n {\n config: config.retry,\n operationName: `load-context ${module} ${subcommand}`,\n },\n );\n\n return withRetry(\n async () => {\n // The rate-limit + signing-client + address acquisition runs inside\n // the try/catch so a failure during any of those steps is wrapped\n // with {module, subcommand, args} attribution, matching the\n // handler-leg semantics. Otherwise an INVALID_CONFIG / wallet error\n // from these calls would propagate without telling the caller which\n // estimate was being computed.\n try {\n await clientManager.acquireRateLimit();\n const signingClient = await clientManager.getSigningClient();\n const senderAddress = await clientManager.getAddress();\n\n // Resolve gasMultiplier from the signing client when no override is provided.\n // This guarantees parity with cosmosTx's 'auto' path: client.ts patches the\n // signing client's defaultGasMultiplier to config.gasMultiplier; if that\n // patch fails (rare — only when CosmJS internals change), the client\n // falls back to CosmJS's built-in default. Reading from the client uses\n // the same value cosmosTx would.\n const clientMultiplier = (\n signingClient as unknown as { defaultGasMultiplier?: unknown }\n ).defaultGasMultiplier;\n const gasMultiplier =\n overrides?.gasMultiplier ??\n (typeof clientMultiplier === 'number'\n ? clientMultiplier\n : DEFAULT_GAS_MULTIPLIER);\n\n const built = builder(senderAddress, subcommand, args, buildContext);\n const gasEstimate = await signingClient.simulate(\n senderAddress,\n built.messages,\n built.memo,\n );\n const gasLimit = Math.ceil(gasEstimate * gasMultiplier);\n const fee = calculateFee(gasLimit, gasPrice);\n\n return {\n module,\n subcommand: built.canonicalSubcommand ?? subcommand,\n gasEstimate: String(gasEstimate),\n fee: { amount: fee.amount, gas: fee.gas },\n };\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n // Re-throw with enriched context if not already present (mirrors cosmosTx)\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 // SIMULATION_FAILED is NOT in NON_RETRYABLE_ERROR_CODES, so withRetry\n // will fall through to isTransientErrorMessage for message-based\n // classification. Transient errors (network/5xx) get retried; real\n // simulation failures (insufficient funds, etc) fail fast.\n throw new ManifestMCPError(\n ManifestMCPErrorCode.SIMULATION_FAILED,\n `Fee estimation for ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`,\n { module, subcommand, args },\n );\n }\n },\n {\n config: config.retry,\n operationName: `estimate ${module} ${subcommand}`,\n },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cosmos.js","names":[],"sources":["../src/cosmos.ts"],"sourcesContent":["import { calculateFee } from '@cosmjs/stargate';\nimport type { CosmosClientManager } from './client.js';\nimport { DEFAULT_GAS_MULTIPLIER } from './config.js';\nimport {\n getQueryHandler,\n getTxContextLoader,\n getTxHandler,\n getTxMsgBuilder,\n} from './modules.js';\nimport { withRetry } from './retry.js';\nimport {\n type CosmosQueryResult,\n type CosmosTxResult,\n type FeeEstimateResult,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type TxBuildContext,\n type TxOptions,\n type TxOverrides,\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 * Resolve and run the `TxBuildContext` loader registered for `(module,\n * subcommand)` in `TX_MODULES`. Returns `undefined` when no loader is\n * registered (the common case) so the caller can short-circuit and skip the\n * chain read.\n *\n * Acquires a rate-limit token before the loader runs so each extra RPC is\n * counted against the same budget every other RPC respects, and wraps any\n * non-`ManifestMCPError` failure as `QUERY_FAILED` with `{module, subcommand}`\n * details for symmetric error classification on both broadcast and estimate\n * paths.\n */\nasync function loadBuildContext(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n): Promise<TxBuildContext | undefined> {\n const loader = getTxContextLoader(module, subcommand);\n if (!loader) return undefined;\n\n // The full loader call sequence — rate-limit acquire, query-client\n // construction, loader invocation — runs inside the try/catch so every\n // failure mode gets the {module, subcommand} attribution callers expect\n // from a structured error. Without the wrap, an INVALID_CONFIG from\n // `getQueryClient` (or a connection failure that escapes the inner\n // withRetry) would propagate without telling the caller which tx was\n // being prepared.\n try {\n await clientManager.acquireRateLimit();\n const queryClient = await clientManager.getQueryClient();\n return await loader(queryClient);\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n if (!error.details?.module) {\n throw new ManifestMCPError(error.code, error.message, {\n ...error.details,\n module,\n subcommand,\n });\n }\n throw error;\n }\n throw new ManifestMCPError(\n ManifestMCPErrorCode.QUERY_FAILED,\n `Failed to load build context for ${module} ${subcommand}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { module, subcommand },\n );\n }\n}\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 // The rate-limit + query-client acquisition runs inside the try/catch\n // so a failure during either step is wrapped with {module, subcommand}\n // attribution, matching the handler-leg semantics. Otherwise an\n // INVALID_CONFIG from `getQueryClient` (or a connection failure that\n // escapes the inner withRetry) would propagate without telling the\n // caller which query was being routed.\n try {\n await clientManager.acquireRateLimit();\n const queryClient = await clientManager.getQueryClient();\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 if (!error.details?.module) {\n throw new ManifestMCPError(error.code, error.message, {\n ...error.details,\n module,\n subcommand,\n });\n }\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 { module, subcommand },\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 overrides?: TxOverrides,\n): Promise<CosmosTxResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_TX);\n validateName(subcommand, 'subcommand', ManifestMCPErrorCode.UNSUPPORTED_TX);\n\n // Build fully-resolved gas options from caller overrides + server config\n let txOptions: TxOptions | undefined;\n if (overrides?.gasMultiplier !== undefined) {\n if (\n !Number.isFinite(overrides.gasMultiplier) ||\n overrides.gasMultiplier < 1\n ) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `gasMultiplier must be a finite number >= 1, got ${overrides.gasMultiplier}`,\n );\n }\n const gasPrice = clientManager.getConfig().gasPrice;\n if (!gasPrice) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'gasMultiplier override requires gasPrice configuration',\n );\n }\n txOptions = { gasMultiplier: overrides.gasMultiplier, gasPrice };\n }\n\n // Get handler from registry (throws if module not found) - do this before retry loop\n const handler = getTxHandler(module);\n // Fetch chain context once before the broadcast retry loop: every broadcast\n // attempt uses the same snapshot and we don't consume extra rate-limit\n // tokens per broadcast retry. The loader is independently wrapped in its\n // own withRetry so transient LCD failures during the chain read still get\n // retried (parity with cosmosQuery's params reads).\n const buildContext = await withRetry(\n () => loadBuildContext(clientManager, module, subcommand),\n {\n config: clientManager.getConfig().retry,\n operationName: `load-context ${module} ${subcommand}`,\n },\n );\n\n return withRetry(\n async () => {\n // The rate-limit + signing-client + address acquisition runs inside\n // the try/catch so a failure during any of those steps is wrapped\n // with {module, subcommand, args} attribution, matching the\n // handler-leg semantics. Otherwise an INVALID_CONFIG / wallet error\n // from these calls would propagate without telling the caller which\n // tx was being prepared.\n try {\n await clientManager.acquireRateLimit();\n const signingClient = await clientManager.getSigningClient();\n const senderAddress = await clientManager.getAddress();\n\n return await handler(\n signingClient,\n senderAddress,\n subcommand,\n args,\n waitForConfirmation,\n txOptions,\n buildContext,\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\n/**\n * Estimate the fee for a Cosmos transaction without broadcasting it.\n *\n * Looks up the message builder for the given module, builds the messages,\n * and calls `client.simulate()` to get a gas estimate. Multiplies by the\n * configured (or overridden) gas multiplier and computes the fee.\n *\n * Automatically retries on transient failures via `withRetry`.\n *\n * @returns FeeEstimateResult with raw gas estimate and computed fee\n */\nexport async function cosmosEstimateFee(\n clientManager: CosmosClientManager,\n module: string,\n subcommand: string,\n args: string[] = [],\n overrides?: TxOverrides,\n): Promise<FeeEstimateResult> {\n validateName(module, 'module', ManifestMCPErrorCode.UNSUPPORTED_TX);\n validateName(subcommand, 'subcommand', ManifestMCPErrorCode.UNSUPPORTED_TX);\n\n // Always need gasPrice for fee calculation (unlike cosmosTx which can use 'auto')\n const config = clientManager.getConfig();\n const gasPrice = config.gasPrice;\n if (!gasPrice) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n 'Fee estimation requires gasPrice configuration',\n );\n }\n\n // Validate the override eagerly (the resolved fallback values are always valid).\n if (overrides?.gasMultiplier !== undefined) {\n if (\n !Number.isFinite(overrides.gasMultiplier) ||\n overrides.gasMultiplier < 1\n ) {\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `gasMultiplier must be a finite number >= 1, got ${overrides.gasMultiplier}`,\n );\n }\n }\n\n // Get builder from registry (throws if module not found) - do this before retry loop\n const builder = getTxMsgBuilder(module);\n // Fetch chain context once before the simulate retry loop: every simulate\n // attempt uses the same snapshot and we don't consume extra rate-limit\n // tokens per simulate retry. The loader is independently wrapped in its\n // own withRetry so transient LCD failures during the chain read still get\n // retried (parity with cosmosQuery's params reads).\n const buildContext = await withRetry(\n () => loadBuildContext(clientManager, module, subcommand),\n {\n config: config.retry,\n operationName: `load-context ${module} ${subcommand}`,\n },\n );\n\n return withRetry(\n async () => {\n // The rate-limit + signing-client + address acquisition runs inside\n // the try/catch so a failure during any of those steps is wrapped\n // with {module, subcommand, args} attribution, matching the\n // handler-leg semantics. Otherwise an INVALID_CONFIG / wallet error\n // from these calls would propagate without telling the caller which\n // estimate was being computed.\n try {\n await clientManager.acquireRateLimit();\n const signingClient = await clientManager.getSigningClient();\n const senderAddress = await clientManager.getAddress();\n\n // Resolve gasMultiplier from the signing client when no override is provided.\n // This guarantees parity with cosmosTx's 'auto' path: client.ts patches the\n // signing client's defaultGasMultiplier to config.gasMultiplier; if that\n // patch fails (rare — only when CosmJS internals change), the client\n // falls back to CosmJS's built-in default. Reading from the client uses\n // the same value cosmosTx would.\n const clientMultiplier = (\n signingClient as unknown as { defaultGasMultiplier?: unknown }\n ).defaultGasMultiplier;\n const gasMultiplier =\n overrides?.gasMultiplier ??\n (typeof clientMultiplier === 'number'\n ? clientMultiplier\n : DEFAULT_GAS_MULTIPLIER);\n\n const built = builder(senderAddress, subcommand, args, buildContext);\n const gasEstimate = await signingClient.simulate(\n senderAddress,\n built.messages,\n built.memo,\n );\n const gasLimit = Math.ceil(gasEstimate * gasMultiplier);\n const fee = calculateFee(gasLimit, gasPrice);\n\n return {\n module,\n subcommand: built.canonicalSubcommand ?? subcommand,\n gasEstimate: String(gasEstimate),\n fee: { amount: fee.amount, gas: fee.gas },\n };\n } catch (error) {\n if (error instanceof ManifestMCPError) {\n // Re-throw with enriched context if not already present (mirrors cosmosTx)\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 // SIMULATION_FAILED is NOT in NON_RETRYABLE_ERROR_CODES, so withRetry\n // will fall through to isTransientErrorMessage for message-based\n // classification. Transient errors (network/5xx) get retried; real\n // simulation failures (insufficient funds, etc) fail fast.\n throw new ManifestMCPError(\n ManifestMCPErrorCode.SIMULATION_FAILED,\n `Fee estimation for ${module} ${subcommand} failed: ${error instanceof Error ? error.message : String(error)}`,\n { module, subcommand, args },\n );\n }\n },\n {\n config: config.retry,\n operationName: `estimate ${module} ${subcommand}`,\n },\n );\n}\n"],"mappings":"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"}
|
package/dist/env-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-utils.d.ts","names":[],"sources":["../src/env-utils.ts"],"mappings":";;AAgCA
|
|
1
|
+
{"version":3,"file":"env-utils.d.ts","names":[],"sources":["../src/env-utils.ts"],"mappings":";;AAgCA;;;;;;;;AAGiB;;;;;;;;;;;;;;;;;iBAHD,eAAA,CACd,KAAA,sBACA,YAAA,WACA,OAAA"}
|
package/dist/env-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-utils.js","names":[],"sources":["../src/env-utils.ts"],"sourcesContent":["/**\n * Boolean-flavored env-var parsing, shared across packages.\n *\n * Promoted from `packages/agent` to `core` in ENG-268 once a second\n * consumer (`packages/fred`'s SSRF-guard gate) needed it — `packages/agent`\n * now re-exports this. Keeping one implementation avoids drift between the\n * two servers' `*_FETCH_GUARDED` parsing.\n */\n\nimport { ManifestMCPError, ManifestMCPErrorCode } from './types.js';\n\nconst TRUTHY = new Set(['1', 'true', 'yes', 'on']);\nconst FALSY = new Set(['0', 'false', 'no', 'off']);\n\n/**\n * Parse a boolean-flavored env var. Returns `defaultValue` when the env\n * var is unset, empty, or whitespace-only. Otherwise compares the\n * trimmed, lower-cased value against the canonical truthy / falsy sets:\n *\n * truthy: '1', 'true', 'yes', 'on'\n * falsy: '0', 'false', 'no', 'off'\n *\n * An unrecognized non-empty value throws `ManifestMCPError(INVALID_CONFIG)`\n * naming `envName` — silently falling back to the default would defeat\n * the helper's purpose (e.g. `MANIFEST_FRED_FETCH_GUARDED=ture` would\n * silently no-op the SSRF guard the operator clearly intended to keep on).\n *\n * @param value - Raw env-var value (typically `process.env[envName]`).\n * @param defaultValue - Returned when `value` is `undefined`/empty/whitespace.\n * @param envName - Env var name; embedded in the diagnostic message\n * when the value is unrecognized.\n */\nexport function parseBooleanEnv(\n value: string | undefined,\n defaultValue: boolean,\n envName: string,\n): boolean {\n if (value === undefined) return defaultValue;\n const trimmed = value.trim();\n if (trimmed.length === 0) return defaultValue;\n const normalised = trimmed.toLowerCase();\n if (TRUTHY.has(normalised)) return true;\n if (FALSY.has(normalised)) return false;\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `${envName}: unrecognized boolean value \"${value}\". ` +\n \"Accepted truthy: '1', 'true', 'yes', 'on'. \" +\n \"Accepted falsy: '0', 'false', 'no', 'off'. \" +\n 'Case-insensitive; leading / trailing whitespace ignored.',\n );\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,SAAS,IAAI,IAAI;CAAC;CAAK;CAAQ;CAAO;
|
|
1
|
+
{"version":3,"file":"env-utils.js","names":[],"sources":["../src/env-utils.ts"],"sourcesContent":["/**\n * Boolean-flavored env-var parsing, shared across packages.\n *\n * Promoted from `packages/agent` to `core` in ENG-268 once a second\n * consumer (`packages/fred`'s SSRF-guard gate) needed it — `packages/agent`\n * now re-exports this. Keeping one implementation avoids drift between the\n * two servers' `*_FETCH_GUARDED` parsing.\n */\n\nimport { ManifestMCPError, ManifestMCPErrorCode } from './types.js';\n\nconst TRUTHY = new Set(['1', 'true', 'yes', 'on']);\nconst FALSY = new Set(['0', 'false', 'no', 'off']);\n\n/**\n * Parse a boolean-flavored env var. Returns `defaultValue` when the env\n * var is unset, empty, or whitespace-only. Otherwise compares the\n * trimmed, lower-cased value against the canonical truthy / falsy sets:\n *\n * truthy: '1', 'true', 'yes', 'on'\n * falsy: '0', 'false', 'no', 'off'\n *\n * An unrecognized non-empty value throws `ManifestMCPError(INVALID_CONFIG)`\n * naming `envName` — silently falling back to the default would defeat\n * the helper's purpose (e.g. `MANIFEST_FRED_FETCH_GUARDED=ture` would\n * silently no-op the SSRF guard the operator clearly intended to keep on).\n *\n * @param value - Raw env-var value (typically `process.env[envName]`).\n * @param defaultValue - Returned when `value` is `undefined`/empty/whitespace.\n * @param envName - Env var name; embedded in the diagnostic message\n * when the value is unrecognized.\n */\nexport function parseBooleanEnv(\n value: string | undefined,\n defaultValue: boolean,\n envName: string,\n): boolean {\n if (value === undefined) return defaultValue;\n const trimmed = value.trim();\n if (trimmed.length === 0) return defaultValue;\n const normalised = trimmed.toLowerCase();\n if (TRUTHY.has(normalised)) return true;\n if (FALSY.has(normalised)) return false;\n throw new ManifestMCPError(\n ManifestMCPErrorCode.INVALID_CONFIG,\n `${envName}: unrecognized boolean value \"${value}\". ` +\n \"Accepted truthy: '1', 'true', 'yes', 'on'. \" +\n \"Accepted falsy: '0', 'false', 'no', 'off'. \" +\n 'Case-insensitive; leading / trailing whitespace ignored.',\n );\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,SAAS,IAAI,IAAI;CAAC;CAAK;CAAQ;CAAO;AAAI,CAAC;AACjD,MAAM,QAAQ,IAAI,IAAI;CAAC;CAAK;CAAS;CAAM;AAAK,CAAC;;;;;;;;;;;;;;;;;;;AAoBjD,SAAgB,gBACd,OACA,cACA,SACS;CACT,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,QAAQ,WAAW,GAAG,OAAO;CACjC,MAAM,aAAa,QAAQ,YAAY;CACvC,IAAI,OAAO,IAAI,UAAU,GAAG,OAAO;CACnC,IAAI,MAAM,IAAI,UAAU,GAAG,OAAO;CAClC,MAAM,IAAI,iBAAA,kBAER,GAAG,QAAQ,gCAAgC,MAAM,kJAInD;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { DEFAULT_RETRY_CONFIG, RetryOptions, calculateBackoff, isRetryableError,
|
|
|
4
4
|
import { ValidationResult, createConfig, createValidatedConfig, validateConfig, validateEndpointUrl } from "./config.js";
|
|
5
5
|
import { cosmosEstimateFee, cosmosQuery, cosmosTx } from "./cosmos.js";
|
|
6
6
|
import { parseBooleanEnv } from "./env-utils.js";
|
|
7
|
-
import { BLOCKED_RANGES_IPV4, BLOCKED_RANGES_IPV6, GuardedFetch, createGuardedFetch, isBlocked } from "./internals/guarded-fetch.js";
|
|
8
7
|
import { createLCDQueryClient } from "./lcd-adapter.js";
|
|
9
8
|
import { LogLevel, logger, parseLogLevel } from "./logger.js";
|
|
10
9
|
import { getAvailableModules, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isSubcommandSupported } from "./modules.js";
|
|
@@ -21,4 +20,4 @@ import { VERSION } from "./version.js";
|
|
|
21
20
|
import { MnemonicWalletProvider } from "./wallet/mnemonic.js";
|
|
22
21
|
import { signArbitraryWithAmino } from "./wallet/sign-arbitrary.js";
|
|
23
22
|
import { LeaseState, leaseStateFromJSON, leaseStateToJSON } from "@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js";
|
|
24
|
-
export { AccountInfo, AccountInfoResult, AddressBytesToStringResult, AddressStringToBytesResult, Any, AuthAccountResult, AuthAccountsResult, AuthParams, AuthParamsResult, AuthzGrant, AuthzGrantAuthorization, AuthzGranteeGrantsResult, AuthzGranterGrantsResult, AuthzGrantsResult, AvailableModules,
|
|
23
|
+
export { AccountInfo, AccountInfoResult, AddressBytesToStringResult, AddressStringToBytesResult, type Any, AuthAccountResult, AuthAccountsResult, type AuthParams, AuthParamsResult, type AuthzGrant, type AuthzGrantAuthorization, AuthzGranteeGrantsResult, AuthzGranterGrantsResult, AuthzGrantsResult, AvailableModules, BalanceResult, BalancesResult, type BankMetadata, type BankParams, BankParamsResult, type BaseAccount, Bech32PrefixResult, type BillingParams, BillingParamsResult, BuiltMessages, type CodeInfoResponse, Coin, CommissionResult, CommunityPoolResult, type ContractCodeHistoryEntry, type ContractInfo, CosmosClientManager, CosmosQueryResult, CosmosTxResult, type CreditAccount, CreditAccountResult, CreditAccountsResult, CreditAddressResult, CreditEstimateResult, DEFAULT_RETRY_CONFIG, DNS_LABEL_RE, DecCoin, type DelegationDelegatorReward, type DelegationResponse, DelegationResult, DelegationsResult, DelegatorValidatorsResult, DelegatorWithdrawAddressResult, type DenomAuthorityMetadata, DenomAuthorityMetadataResult, DenomMetadataResult, type DenomTrace, DenomsFromAdminResult, DenomsFromCreatorResult, DenomsMetadataResult, type DepositParams, DepositResult, DepositsResult, type DistributionParams, DistributionParamsResult, FeeEstimateResult, FeegrantAllowanceResult, FeegrantAllowancesResult, type FeegrantGrant, type FundCreditsResult, type GovDeposit, type GovParams, GovParamsResult, type GovProposal, type GovTallyResult, type GovVote, type GroupInfo, GroupInfoResult, type GroupMember, GroupMembersResult, GroupPoliciesResult, type GroupPolicyInfo, GroupPolicyInfoResult, type GroupProposal, GroupProposalResult, GroupProposalsResult, GroupTallyQueryResult, type GroupTallyResult, type GroupVote, GroupVoteResult, GroupVotesResult, GroupsResult, type HistoricalInfo, HistoricalInfoResult, INFRASTRUCTURE_ERROR_CODES, IbcDenomTraceResult, IbcDenomTracesResult, type IbcTransferParams, IbcTransferParamsResult, type Lease, LeaseByCustomDomainResult, type LeaseItemInput, LeaseResult, LeaseState, LeasesResult, type LogLevel, MANIFEST_TOOL_META_VERSION, MAX_PAGE_LIMIT, ManifestMCPConfig, ManifestMCPError, ManifestMCPErrorCode, type ManifestMCPServerOptions, type ManifestQueryClient, type ManifestToolMeta, type ManifestToolMetaContainer, type ManifestToolMetaVersion, MintAnnualProvisionsResult, MintInflationResult, type MintParams, MintParamsResult, type MnemonicServerConfig, MnemonicWalletProvider, type Model, type ModuleAccount, ModuleAccountsResult, ModuleInfo, PaginatedResult, PaginationResponse, PoAAuthorityResult, PoAConsensusPowerResult, PoAPendingValidatorsResult, type PoAStakingParams, type PoAValidator, ProposalResult, ProposalsResult, type Provider, ProviderResult, ProviderWithdrawableResult, ProvidersResult, type QueryCreditEstimateResponse, QueryResult, RateLimitConfig, type RedelegationResponse, RedelegationsResult, RetryConfig, type RetryOptions, RewardsResult, SENSITIVE_FIELDS, type SKU, type SendEnabled, SendEnabledResult, type SetItemCustomDomainOptions, type SetItemCustomDomainResult, SignArbitraryResult, type SkuParams, SkuParamsResult, SkuResult, SkusResult, SlashesResult, type StakingParams, StakingParamsResult, type StakingPool, StakingPoolResult, type StopAppResult, SupplyOfResult, type TallyParams, TallyResult, type TokenfactoryParams, TokenfactoryParamsResult, TotalSupplyResult, TxBuildContext, TxOptions, TxOverrides, type UnbondingDelegation, UnbondingDelegationResult, UnbondingDelegationsResult, VERSION, type ValidationResult, type Validator, type ValidatorAccumulatedCommission, type ValidatorOutstandingRewards, ValidatorOutstandingRewardsResult, ValidatorResult, type ValidatorSlashEvent, ValidatorsResult, VoteResult, VotesResult, type VotingParams, WalletProvider, WasmAllContractStateResult, WasmBuildAddressResult, WasmCodeInfo, WasmCodeInfoResult, WasmCodeResult, WasmCodesResult, WasmContractHistoryResult, WasmContractInfoResult, WasmContractsByCodeResult, WasmContractsByCreatorResult, WasmLimitsConfigResult, type WasmParams, WasmParamsResult, WasmPinnedCodesResult, WasmRawContractStateResult, WasmSmartContractStateResult, WithdrawableAmountResult, bigIntReplacer, calculateBackoff, cosmosEstimateFee, cosmosQuery, cosmosTx, createConfig, createLCDQueryClient, createMnemonicServer, createPagination, createValidatedConfig, fundCredits, getAvailableModules, getBalance, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isRetryableError, isSubcommandSupported, jsonResponse, leaseStateFromJSON, leaseStateToJSON, logger, manifestMeta, mutatingAnnotations, optionalBoolean, parseArgs, parseBooleanEnv, parseLogLevel, readOnlyAnnotations, requireString, requireStringEnum, requireUuid, sanitizeForLogging, setItemCustomDomain, signArbitraryWithAmino, stopApp, structuredResponse, validateAddress, validateConfig, validateEndpointUrl, withErrorHandling, withRetry };
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import { MAX_PAGE_LIMIT, createPagination } from "./queries/utils.js";
|
|
|
10
10
|
import { getAvailableModules, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isSubcommandSupported } from "./modules.js";
|
|
11
11
|
import { cosmosEstimateFee, cosmosQuery, cosmosTx } from "./cosmos.js";
|
|
12
12
|
import { parseBooleanEnv } from "./env-utils.js";
|
|
13
|
-
import { BLOCKED_RANGES_IPV4, BLOCKED_RANGES_IPV6, createGuardedFetch, isBlocked } from "./internals/guarded-fetch.js";
|
|
14
13
|
import { signArbitraryWithAmino } from "./wallet/sign-arbitrary.js";
|
|
15
14
|
import { MnemonicWalletProvider } from "./wallet/mnemonic.js";
|
|
16
15
|
import "./wallet/index.js";
|
|
@@ -22,4 +21,4 @@ import { setItemCustomDomain } from "./tools/setItemCustomDomain.js";
|
|
|
22
21
|
import { stopApp } from "./tools/stopApp.js";
|
|
23
22
|
import { VERSION } from "./version.js";
|
|
24
23
|
import { LeaseState, leaseStateFromJSON, leaseStateToJSON } from "@manifest-network/manifestjs/dist/codegen/liftedinit/billing/v1/types.js";
|
|
25
|
-
export {
|
|
24
|
+
export { CosmosClientManager, DEFAULT_RETRY_CONFIG, DNS_LABEL_RE, INFRASTRUCTURE_ERROR_CODES, LeaseState, MANIFEST_TOOL_META_VERSION, MAX_PAGE_LIMIT, ManifestMCPError, ManifestMCPErrorCode, MnemonicWalletProvider, SENSITIVE_FIELDS, VERSION, bigIntReplacer, calculateBackoff, cosmosEstimateFee, cosmosQuery, cosmosTx, createConfig, createLCDQueryClient, createMnemonicServer, createPagination, createValidatedConfig, fundCredits, getAvailableModules, getBalance, getModuleSubcommands, getSubcommandUsage, getSupportedModules, isRetryableError, isSubcommandSupported, jsonResponse, leaseStateFromJSON, leaseStateToJSON, logger, manifestMeta, mutatingAnnotations, optionalBoolean, parseArgs, parseBooleanEnv, parseLogLevel, readOnlyAnnotations, requireString, requireStringEnum, requireUuid, sanitizeForLogging, setItemCustomDomain, signArbitraryWithAmino, stopApp, structuredResponse, validateAddress, validateConfig, validateEndpointUrl, withErrorHandling, withRetry };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guarded-fetch.d.ts","names":[],"sources":["../../src/internals/guarded-fetch.ts"],"mappings":";;AAyDA
|
|
1
|
+
{"version":3,"file":"guarded-fetch.d.ts","names":[],"sources":["../../src/internals/guarded-fetch.ts"],"mappings":";;AAyDA;;;;AAAuC;AAUvC;;;;;;;;AAEc;AA6Bd;;;;;;;;AAEc;AAyCd;;;;;;;;AAEK;AAmEL;;;;AAAkD;;;;;;;;;;;;;;;;;KAzJtC,YAAA,UAAsB,KAAK;;;;;;;;;cAU1B,mBAAA,EAAqB,aAAa;EAAA,SACpC,KAAA;EAAA,SACA,GAAA;AAAA;;;;;;;;;cA6BE,mBAAA,EAAqB,aAAa;EAAA,SACpC,KAAA;EAAA,SACA,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyCK,SAAA,CAAU,QAAA;EACxB,KAAA;EACA,GAAA;AAAA;;;;;;;;;;;;;;;;;;;;iBAmEc,kBAAA,IAAsB,YAAY"}
|