@manifest-network/manifest-mcp-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__test-utils__/callTool.d.ts +29 -0
- package/dist/__test-utils__/callTool.d.ts.map +1 -0
- package/dist/__test-utils__/callTool.js +45 -0
- package/dist/__test-utils__/callTool.js.map +1 -0
- package/dist/__test-utils__/mocks.d.ts +125 -0
- package/dist/__test-utils__/mocks.d.ts.map +1 -0
- package/dist/__test-utils__/mocks.js +146 -0
- package/dist/__test-utils__/mocks.js.map +1 -0
- package/dist/client.d.ts +67 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +209 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +127 -0
- package/dist/config.js.map +1 -0
- package/dist/cosmos.d.ts +24 -0
- package/dist/cosmos.d.ts.map +1 -0
- package/dist/cosmos.js +85 -0
- package/dist/cosmos.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +20 -0
- package/dist/lcd-adapter.d.ts +15 -0
- package/dist/lcd-adapter.d.ts.map +1 -0
- package/dist/lcd-adapter.js +98 -0
- package/dist/lcd-adapter.js.map +1 -0
- package/dist/logger.d.ts +20 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +43 -0
- package/dist/logger.js.map +1 -0
- package/dist/modules.d.ts +63 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +759 -0
- package/dist/modules.js.map +1 -0
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +78 -0
- package/dist/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js.map +1 -0
- package/dist/node_modules/@vitest/expect/dist/index.d.ts +802 -0
- package/dist/node_modules/@vitest/expect/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/expect/dist/index.js +1457 -0
- package/dist/node_modules/@vitest/expect/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.d.ts +95 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.js +877 -0
- package/dist/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/chunk-tasks.js +91 -0
- package/dist/node_modules/@vitest/runner/dist/chunk-tasks.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/index.js +1381 -0
- package/dist/node_modules/@vitest/runner/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/tasks.d-D2GKpdwQ.d.ts +540 -0
- package/dist/node_modules/@vitest/runner/dist/tasks.d-D2GKpdwQ.d.ts.map +1 -0
- package/dist/node_modules/@vitest/runner/dist/utils.js +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/environment.d-DOJxxZV9.d.ts +16 -0
- package/dist/node_modules/@vitest/snapshot/dist/environment.d-DOJxxZV9.d.ts.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.d.ts +89 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.js +649 -0
- package/dist/node_modules/@vitest/snapshot/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/snapshot/dist/rawSnapshot.d-U2kJUxDr.d.ts +40 -0
- package/dist/node_modules/@vitest/snapshot/dist/rawSnapshot.d-U2kJUxDr.d.ts.map +1 -0
- package/dist/node_modules/@vitest/spy/dist/index.d.ts +343 -0
- package/dist/node_modules/@vitest/spy/dist/index.d.ts.map +1 -0
- package/dist/node_modules/@vitest/spy/dist/index.js +386 -0
- package/dist/node_modules/@vitest/spy/dist/index.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +82 -0
- package/dist/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/diff.d.ts +14 -0
- package/dist/node_modules/@vitest/utils/dist/diff.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/diff.js +1297 -0
- package/dist/node_modules/@vitest/utils/dist/diff.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/display.d.ts +15 -0
- package/dist/node_modules/@vitest/utils/dist/display.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/display.js +558 -0
- package/dist/node_modules/@vitest/utils/dist/display.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/error.js +30 -0
- package/dist/node_modules/@vitest/utils/dist/error.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/helpers.js +181 -0
- package/dist/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/offset.js +27 -0
- package/dist/node_modules/@vitest/utils/dist/offset.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/serialize.js +77 -0
- package/dist/node_modules/@vitest/utils/dist/serialize.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/source-map.js +367 -0
- package/dist/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/timers.js +37 -0
- package/dist/node_modules/@vitest/utils/dist/timers.js.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts +38 -0
- package/dist/node_modules/@vitest/utils/dist/types.d-BCElaP-c.d.ts.map +1 -0
- package/dist/node_modules/@vitest/utils/dist/types.d.ts +25 -0
- package/dist/node_modules/@vitest/utils/dist/types.d.ts.map +1 -0
- package/dist/node_modules/chai/index.js +2875 -0
- package/dist/node_modules/chai/index.js.map +1 -0
- package/dist/node_modules/magic-string/dist/magic-string.es.js +939 -0
- package/dist/node_modules/magic-string/dist/magic-string.es.js.map +1 -0
- package/dist/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +85 -0
- package/dist/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js.map +1 -0
- package/dist/node_modules/tinybench/dist/index.d.ts +91 -0
- package/dist/node_modules/tinybench/dist/index.d.ts.map +1 -0
- package/dist/node_modules/tinyrainbow/dist/index.d.ts +9 -0
- package/dist/node_modules/tinyrainbow/dist/index.d.ts.map +1 -0
- package/dist/node_modules/tinyrainbow/dist/index.js +86 -0
- package/dist/node_modules/tinyrainbow/dist/index.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -0
- package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.D0SlKNbZ.js +41 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.D0SlKNbZ.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.d.DAaHLpsq.d.ts +12 -0
- package/dist/node_modules/vitest/dist/chunks/benchmark.d.DAaHLpsq.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/global.d.x-ILCfAE.d.ts +100 -0
- package/dist/node_modules/vitest/dist/chunks/global.d.x-ILCfAE.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +57 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.d.BFMWpdph.d.ts +13 -0
- package/dist/node_modules/vitest/dist/chunks/rpc.d.BFMWpdph.d.ts.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/test.CTcmp4Su.js +2791 -0
- package/dist/node_modules/vitest/dist/chunks/test.CTcmp4Su.js.map +1 -0
- package/dist/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +44 -0
- package/dist/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js.map +1 -0
- package/dist/node_modules/vitest/dist/index.d.ts +9 -0
- package/dist/queries/auth.d.ts +15 -0
- package/dist/queries/auth.d.ts.map +1 -0
- package/dist/queries/auth.js +58 -0
- package/dist/queries/auth.js.map +1 -0
- package/dist/queries/bank.d.ts +15 -0
- package/dist/queries/bank.d.ts.map +1 -0
- package/dist/queries/bank.js +93 -0
- package/dist/queries/bank.js.map +1 -0
- package/dist/queries/billing.d.ts +15 -0
- package/dist/queries/billing.d.ts.map +1 -0
- package/dist/queries/billing.js +114 -0
- package/dist/queries/billing.js.map +1 -0
- package/dist/queries/distribution.d.ts +15 -0
- package/dist/queries/distribution.d.ts.map +1 -0
- package/dist/queries/distribution.js +73 -0
- package/dist/queries/distribution.js.map +1 -0
- package/dist/queries/gov.d.ts +15 -0
- package/dist/queries/gov.d.ts.map +1 -0
- package/dist/queries/gov.js +98 -0
- package/dist/queries/gov.js.map +1 -0
- package/dist/queries/group.d.ts +15 -0
- package/dist/queries/group.d.ts.map +1 -0
- package/dist/queries/group.js +159 -0
- package/dist/queries/group.js.map +1 -0
- package/dist/queries/index.d.ts +10 -0
- package/dist/queries/index.js +10 -0
- package/dist/queries/sku.d.ts +16 -0
- package/dist/queries/sku.d.ts.map +1 -0
- package/dist/queries/sku.js +85 -0
- package/dist/queries/sku.js.map +1 -0
- package/dist/queries/staking.d.ts +15 -0
- package/dist/queries/staking.d.ts.map +1 -0
- package/dist/queries/staking.js +127 -0
- package/dist/queries/staking.js.map +1 -0
- package/dist/queries/utils.d.ts +54 -0
- package/dist/queries/utils.d.ts.map +1 -0
- package/dist/queries/utils.js +74 -0
- package/dist/queries/utils.js.map +1 -0
- package/dist/retry.d.ts +48 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +106 -0
- package/dist/retry.js.map +1 -0
- package/dist/server-utils.d.ts +61 -0
- package/dist/server-utils.d.ts.map +1 -0
- package/dist/server-utils.js +156 -0
- package/dist/server-utils.js.map +1 -0
- package/dist/tools/fundCredits.d.ts +8 -0
- package/dist/tools/fundCredits.d.ts.map +1 -0
- package/dist/tools/fundCredits.js +9 -0
- package/dist/tools/fundCredits.js.map +1 -0
- package/dist/tools/getBalance.d.ts +26 -0
- package/dist/tools/getBalance.d.ts.map +1 -0
- package/dist/tools/getBalance.js +59 -0
- package/dist/tools/getBalance.js.map +1 -0
- package/dist/tools/stopApp.d.ts +13 -0
- package/dist/tools/stopApp.d.ts.map +1 -0
- package/dist/tools/stopApp.js +15 -0
- package/dist/tools/stopApp.js.map +1 -0
- package/dist/transactions/bank.d.ts +11 -0
- package/dist/transactions/bank.d.ts.map +1 -0
- package/dist/transactions/bank.js +75 -0
- package/dist/transactions/bank.js.map +1 -0
- package/dist/transactions/billing.d.ts +11 -0
- package/dist/transactions/billing.d.ts.map +1 -0
- package/dist/transactions/billing.js +189 -0
- package/dist/transactions/billing.js.map +1 -0
- package/dist/transactions/distribution.d.ts +11 -0
- package/dist/transactions/distribution.d.ts.map +1 -0
- package/dist/transactions/distribution.js +60 -0
- package/dist/transactions/distribution.js.map +1 -0
- package/dist/transactions/gov.d.ts +11 -0
- package/dist/transactions/gov.d.ts.map +1 -0
- package/dist/transactions/gov.js +108 -0
- package/dist/transactions/gov.js.map +1 -0
- package/dist/transactions/group.d.ts +11 -0
- package/dist/transactions/group.d.ts.map +1 -0
- package/dist/transactions/group.js +347 -0
- package/dist/transactions/group.js.map +1 -0
- package/dist/transactions/index.d.ts +10 -0
- package/dist/transactions/index.js +10 -0
- package/dist/transactions/manifest.d.ts +11 -0
- package/dist/transactions/manifest.d.ts.map +1 -0
- package/dist/transactions/manifest.js +59 -0
- package/dist/transactions/manifest.js.map +1 -0
- package/dist/transactions/sku.d.ts +11 -0
- package/dist/transactions/sku.d.ts.map +1 -0
- package/dist/transactions/sku.js +191 -0
- package/dist/transactions/sku.js.map +1 -0
- package/dist/transactions/staking.d.ts +11 -0
- package/dist/transactions/staking.d.ts.map +1 -0
- package/dist/transactions/staking.js +79 -0
- package/dist/transactions/staking.js.map +1 -0
- package/dist/transactions/utils.d.ts +161 -0
- package/dist/transactions/utils.d.ts.map +1 -0
- package/dist/transactions/utils.js +272 -0
- package/dist/transactions/utils.js.map +1 -0
- package/dist/types.d.ts +390 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +30 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +53 -0
- package/dist/validation.js.map +1 -0
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/dist/wallet/index.d.ts +4 -0
- package/dist/wallet/index.js +3 -0
- package/dist/wallet/mnemonic.d.ts +47 -0
- package/dist/wallet/mnemonic.d.ts.map +1 -0
- package/dist/wallet/mnemonic.js +97 -0
- package/dist/wallet/mnemonic.js.map +1 -0
- package/dist/wallet/sign-arbitrary.d.ts +12 -0
- package/dist/wallet/sign-arbitrary.d.ts.map +1 -0
- package/dist/wallet/sign-arbitrary.js +36 -0
- package/dist/wallet/sign-arbitrary.js.map +1 -0
- package/package.json +72 -0
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { RetryConfig } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/retry.d.ts
|
|
4
|
+
/** Default retry configuration */
|
|
5
|
+
declare const DEFAULT_RETRY_CONFIG: Required<RetryConfig>;
|
|
6
|
+
/**
|
|
7
|
+
* Determine if an error is retryable
|
|
8
|
+
*/
|
|
9
|
+
declare function isRetryableError(error: unknown): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate delay with exponential backoff and jitter
|
|
12
|
+
* @param attempt - Current attempt number (0-indexed)
|
|
13
|
+
* @param baseDelayMs - Base delay in milliseconds
|
|
14
|
+
* @param maxDelayMs - Maximum delay cap
|
|
15
|
+
* @returns Delay in milliseconds
|
|
16
|
+
*/
|
|
17
|
+
declare function calculateBackoff(attempt: number, baseDelayMs: number, maxDelayMs: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* Options for the retry wrapper
|
|
20
|
+
*/
|
|
21
|
+
interface RetryOptions {
|
|
22
|
+
/** Retry configuration */
|
|
23
|
+
config?: RetryConfig;
|
|
24
|
+
/** Operation name for error messages */
|
|
25
|
+
operationName?: string;
|
|
26
|
+
/** Callback invoked before each retry attempt */
|
|
27
|
+
onRetry?: (error: unknown, attempt: number, delayMs: number) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Execute an async operation with retry logic for transient failures
|
|
31
|
+
*
|
|
32
|
+
* @param operation - Async function to execute
|
|
33
|
+
* @param options - Retry options
|
|
34
|
+
* @returns Result of the operation
|
|
35
|
+
* @throws The last error if all retries are exhausted
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = await withRetry(
|
|
40
|
+
* () => fetchData(),
|
|
41
|
+
* { config: { maxRetries: 3 }, operationName: 'fetchData' }
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { DEFAULT_RETRY_CONFIG, RetryOptions, calculateBackoff, isRetryableError, withRetry };
|
|
48
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","names":[],"sources":["../src/retry.ts"],"mappings":";;;;cAOa,oBAAA,EAAsB,QAAA,CAAS,WAAA;AAA5C;;;AAAA,iBAqFgB,gBAAA,CAAiB,KAAA;;AAAjC;;;;;AA0BA;iBAAgB,gBAAA,CACd,OAAA,UACA,WAAA,UACA,UAAA;;;;UAwBe,YAAA;EAxBf;EA0BA,MAAA,GAAS,WAAA;EA1BS;EA4BlB,aAAA;EAJ2B;EAM3B,OAAA,IAAW,KAAA,WAAgB,OAAA,UAAiB,OAAA;AAAA;;;;;;;;;;AAmB9C;;;;;;;iBAAsB,SAAA,GAAA,CACpB,SAAA,QAAiB,OAAA,CAAQ,CAAA,GACzB,OAAA,GAAS,YAAA,GACR,OAAA,CAAQ,CAAA"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
//#region src/retry.ts
|
|
3
|
+
/** Default retry configuration */
|
|
4
|
+
const DEFAULT_RETRY_CONFIG = {
|
|
5
|
+
maxRetries: 3,
|
|
6
|
+
baseDelayMs: 1e3,
|
|
7
|
+
maxDelayMs: 1e4
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Error codes that should NOT be retried (permanent failures)
|
|
11
|
+
*/
|
|
12
|
+
const NON_RETRYABLE_ERROR_CODES = [
|
|
13
|
+
ManifestMCPErrorCode.INVALID_CONFIG,
|
|
14
|
+
ManifestMCPErrorCode.MISSING_CONFIG,
|
|
15
|
+
ManifestMCPErrorCode.WALLET_NOT_CONNECTED,
|
|
16
|
+
ManifestMCPErrorCode.WALLET_CONNECTION_FAILED,
|
|
17
|
+
ManifestMCPErrorCode.INVALID_MNEMONIC,
|
|
18
|
+
ManifestMCPErrorCode.INVALID_ADDRESS,
|
|
19
|
+
ManifestMCPErrorCode.UNSUPPORTED_TX,
|
|
20
|
+
ManifestMCPErrorCode.UNSUPPORTED_QUERY,
|
|
21
|
+
ManifestMCPErrorCode.UNKNOWN_MODULE,
|
|
22
|
+
ManifestMCPErrorCode.TX_FAILED,
|
|
23
|
+
ManifestMCPErrorCode.TX_BROADCAST_FAILED,
|
|
24
|
+
ManifestMCPErrorCode.INSUFFICIENT_FUNDS
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Check if an error message indicates a transient failure that should be retried.
|
|
28
|
+
*
|
|
29
|
+
* Uses specific patterns to avoid false positives (e.g. "proposal 500" matching
|
|
30
|
+
* bare "500", or "connection to validator not authorized" matching "connection").
|
|
31
|
+
*/
|
|
32
|
+
function isTransientErrorMessage(message) {
|
|
33
|
+
const lowerMessage = message.toLowerCase();
|
|
34
|
+
if (lowerMessage.includes("econnrefused") || lowerMessage.includes("econnreset") || lowerMessage.includes("etimedout") || lowerMessage.includes("enotfound") || lowerMessage.includes("epipe") || lowerMessage.includes("socket hang up") || lowerMessage.includes("timed out") || lowerMessage.includes("network request failed") || lowerMessage.includes("fetch failed")) return true;
|
|
35
|
+
if (/\b(?:http|status)\s*5\d{2}\b/.test(lowerMessage)) return true;
|
|
36
|
+
if (lowerMessage.includes("internal server error") || lowerMessage.includes("bad gateway") || lowerMessage.includes("service unavailable") || lowerMessage.includes("gateway timeout")) return true;
|
|
37
|
+
if (/\b429\b/.test(lowerMessage) || lowerMessage.includes("too many requests")) return true;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Determine if an error is retryable
|
|
42
|
+
*/
|
|
43
|
+
function isRetryableError(error) {
|
|
44
|
+
if (error instanceof ManifestMCPError) {
|
|
45
|
+
if (NON_RETRYABLE_ERROR_CODES.includes(error.code)) return false;
|
|
46
|
+
return isTransientErrorMessage(error.message);
|
|
47
|
+
}
|
|
48
|
+
if (error instanceof Error) return isTransientErrorMessage(error.message);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Calculate delay with exponential backoff and jitter
|
|
53
|
+
* @param attempt - Current attempt number (0-indexed)
|
|
54
|
+
* @param baseDelayMs - Base delay in milliseconds
|
|
55
|
+
* @param maxDelayMs - Maximum delay cap
|
|
56
|
+
* @returns Delay in milliseconds
|
|
57
|
+
*/
|
|
58
|
+
function calculateBackoff(attempt, baseDelayMs, maxDelayMs) {
|
|
59
|
+
const exponentialDelay = baseDelayMs * 2 ** attempt;
|
|
60
|
+
const cappedDelay = Math.min(exponentialDelay, maxDelayMs);
|
|
61
|
+
const jitter = cappedDelay * .25 * (Math.random() * 2 - 1);
|
|
62
|
+
return Math.floor(cappedDelay + jitter);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Sleep for a given number of milliseconds
|
|
66
|
+
*/
|
|
67
|
+
function sleep(ms) {
|
|
68
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Execute an async operation with retry logic for transient failures
|
|
72
|
+
*
|
|
73
|
+
* @param operation - Async function to execute
|
|
74
|
+
* @param options - Retry options
|
|
75
|
+
* @returns Result of the operation
|
|
76
|
+
* @throws The last error if all retries are exhausted
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await withRetry(
|
|
81
|
+
* () => fetchData(),
|
|
82
|
+
* { config: { maxRetries: 3 }, operationName: 'fetchData' }
|
|
83
|
+
* );
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
async function withRetry(operation, options = {}) {
|
|
87
|
+
const config = {
|
|
88
|
+
...DEFAULT_RETRY_CONFIG,
|
|
89
|
+
...options.config
|
|
90
|
+
};
|
|
91
|
+
let lastError;
|
|
92
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) try {
|
|
93
|
+
return await operation();
|
|
94
|
+
} catch (error) {
|
|
95
|
+
lastError = error;
|
|
96
|
+
if (!(!(attempt === config.maxRetries) && isRetryableError(error))) throw error;
|
|
97
|
+
const delayMs = calculateBackoff(attempt, config.baseDelayMs, config.maxDelayMs);
|
|
98
|
+
if (options.onRetry) options.onRetry(error, attempt + 1, delayMs);
|
|
99
|
+
await sleep(delayMs);
|
|
100
|
+
}
|
|
101
|
+
throw lastError;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { DEFAULT_RETRY_CONFIG, calculateBackoff, isRetryableError, withRetry };
|
|
105
|
+
|
|
106
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","names":[],"sources":["../src/retry.ts"],"sourcesContent":["import {\n ManifestMCPError,\n ManifestMCPErrorCode,\n type RetryConfig,\n} from './types.js';\n\n/** Default retry configuration */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n};\n\n/**\n * Error codes that should NOT be retried (permanent failures)\n */\nconst NON_RETRYABLE_ERROR_CODES: ManifestMCPErrorCode[] = [\n // Configuration errors - won't change on retry\n ManifestMCPErrorCode.INVALID_CONFIG,\n ManifestMCPErrorCode.MISSING_CONFIG,\n\n // Wallet errors - require user action\n ManifestMCPErrorCode.WALLET_NOT_CONNECTED,\n ManifestMCPErrorCode.WALLET_CONNECTION_FAILED,\n ManifestMCPErrorCode.INVALID_MNEMONIC,\n\n // Validation errors - input is invalid\n ManifestMCPErrorCode.INVALID_ADDRESS,\n ManifestMCPErrorCode.UNSUPPORTED_TX,\n ManifestMCPErrorCode.UNSUPPORTED_QUERY,\n ManifestMCPErrorCode.UNKNOWN_MODULE,\n\n // Transaction failures - on-chain rejection or broadcast failure\n // Retrying could cause double-spend for non-idempotent operations\n ManifestMCPErrorCode.TX_FAILED,\n ManifestMCPErrorCode.TX_BROADCAST_FAILED,\n ManifestMCPErrorCode.INSUFFICIENT_FUNDS,\n];\n\n/**\n * Check if an error message indicates a transient failure that should be retried.\n *\n * Uses specific patterns to avoid false positives (e.g. \"proposal 500\" matching\n * bare \"500\", or \"connection to validator not authorized\" matching \"connection\").\n */\nfunction isTransientErrorMessage(message: string): boolean {\n const lowerMessage = message.toLowerCase();\n\n // Node.js / system error codes (specific, no false positives)\n if (\n lowerMessage.includes('econnrefused') ||\n lowerMessage.includes('econnreset') ||\n lowerMessage.includes('etimedout') ||\n lowerMessage.includes('enotfound') ||\n lowerMessage.includes('epipe') ||\n lowerMessage.includes('socket hang up') ||\n lowerMessage.includes('timed out') ||\n lowerMessage.includes('network request failed') ||\n lowerMessage.includes('fetch failed')\n ) {\n return true;\n }\n\n // HTTP 5xx errors — match \"HTTP 5xx\" or \"status 5xx\" patterns, not bare numbers\n if (/\\b(?:http|status)\\s*5\\d{2}\\b/.test(lowerMessage)) {\n return true;\n }\n\n // HTTP 5xx descriptive strings\n if (\n lowerMessage.includes('internal server error') ||\n lowerMessage.includes('bad gateway') ||\n lowerMessage.includes('service unavailable') ||\n lowerMessage.includes('gateway timeout')\n ) {\n return true;\n }\n\n // Rate limiting\n if (\n /\\b429\\b/.test(lowerMessage) ||\n lowerMessage.includes('too many requests')\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Determine if an error is retryable\n */\nexport function isRetryableError(error: unknown): boolean {\n // ManifestMCPError with non-retryable code\n if (error instanceof ManifestMCPError) {\n if (NON_RETRYABLE_ERROR_CODES.includes(error.code)) {\n return false;\n }\n // Check message for transient indicators\n return isTransientErrorMessage(error.message);\n }\n\n // Standard Error - check message\n if (error instanceof Error) {\n return isTransientErrorMessage(error.message);\n }\n\n // Unknown error type - don't retry\n return false;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter\n * @param attempt - Current attempt number (0-indexed)\n * @param baseDelayMs - Base delay in milliseconds\n * @param maxDelayMs - Maximum delay cap\n * @returns Delay in milliseconds\n */\nexport function calculateBackoff(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n // Exponential backoff: baseDelay * 2^attempt\n const exponentialDelay = baseDelayMs * 2 ** attempt;\n\n // Cap at max delay\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\n\n // Add jitter (±25% randomization to prevent thundering herd)\n const jitter = cappedDelay * 0.25 * (Math.random() * 2 - 1);\n\n return Math.floor(cappedDelay + jitter);\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Options for the retry wrapper\n */\nexport interface RetryOptions {\n /** Retry configuration */\n config?: RetryConfig;\n /** Operation name for error messages */\n operationName?: string;\n /** Callback invoked before each retry attempt */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n}\n\n/**\n * Execute an async operation with retry logic for transient failures\n *\n * @param operation - Async function to execute\n * @param options - Retry options\n * @returns Result of the operation\n * @throws The last error if all retries are exhausted\n *\n * @example\n * ```typescript\n * const result = await withRetry(\n * () => fetchData(),\n * { config: { maxRetries: 3 }, operationName: 'fetchData' }\n * );\n * ```\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const config = {\n ...DEFAULT_RETRY_CONFIG,\n ...options.config,\n };\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error;\n\n // Check if we should retry\n const isLastAttempt = attempt === config.maxRetries;\n const shouldRetry = !isLastAttempt && isRetryableError(error);\n\n if (!shouldRetry) {\n throw error;\n }\n\n // Calculate backoff delay\n const delayMs = calculateBackoff(\n attempt,\n config.baseDelayMs,\n config.maxDelayMs,\n );\n\n // Notify callback if provided\n if (options.onRetry) {\n options.onRetry(error, attempt + 1, delayMs);\n }\n\n // Wait before retrying\n await sleep(delayMs);\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError;\n}\n"],"mappings":";;;AAOA,MAAa,uBAA8C;CACzD,YAAY;CACZ,aAAa;CACb,YAAY;CACb;;;;AAKD,MAAM,4BAAoD;CAExD,qBAAqB;CACrB,qBAAqB;CAGrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CAGrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CAIrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACtB;;;;;;;AAQD,SAAS,wBAAwB,SAA0B;CACzD,MAAM,eAAe,QAAQ,aAAa;AAG1C,KACE,aAAa,SAAS,eAAe,IACrC,aAAa,SAAS,aAAa,IACnC,aAAa,SAAS,YAAY,IAClC,aAAa,SAAS,YAAY,IAClC,aAAa,SAAS,QAAQ,IAC9B,aAAa,SAAS,iBAAiB,IACvC,aAAa,SAAS,YAAY,IAClC,aAAa,SAAS,yBAAyB,IAC/C,aAAa,SAAS,eAAe,CAErC,QAAO;AAIT,KAAI,+BAA+B,KAAK,aAAa,CACnD,QAAO;AAIT,KACE,aAAa,SAAS,wBAAwB,IAC9C,aAAa,SAAS,cAAc,IACpC,aAAa,SAAS,sBAAsB,IAC5C,aAAa,SAAS,kBAAkB,CAExC,QAAO;AAIT,KACE,UAAU,KAAK,aAAa,IAC5B,aAAa,SAAS,oBAAoB,CAE1C,QAAO;AAGT,QAAO;;;;;AAMT,SAAgB,iBAAiB,OAAyB;AAExD,KAAI,iBAAiB,kBAAkB;AACrC,MAAI,0BAA0B,SAAS,MAAM,KAAK,CAChD,QAAO;AAGT,SAAO,wBAAwB,MAAM,QAAQ;;AAI/C,KAAI,iBAAiB,MACnB,QAAO,wBAAwB,MAAM,QAAQ;AAI/C,QAAO;;;;;;;;;AAUT,SAAgB,iBACd,SACA,aACA,YACQ;CAER,MAAM,mBAAmB,cAAc,KAAK;CAG5C,MAAM,cAAc,KAAK,IAAI,kBAAkB,WAAW;CAG1D,MAAM,SAAS,cAAc,OAAQ,KAAK,QAAQ,GAAG,IAAI;AAEzD,QAAO,KAAK,MAAM,cAAc,OAAO;;;;;AAMzC,SAAS,MAAM,IAA2B;AACxC,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;;;;;;;AA+B1D,eAAsB,UACpB,WACA,UAAwB,EAAE,EACd;CACZ,MAAM,SAAS;EACb,GAAG;EACH,GAAG,QAAQ;EACZ;CAED,IAAI;AAEJ,MAAK,IAAI,UAAU,GAAG,WAAW,OAAO,YAAY,UAClD,KAAI;AACF,SAAO,MAAM,WAAW;UACjB,OAAO;AACd,cAAY;AAMZ,MAAI,EAFgB,EADE,YAAY,OAAO,eACH,iBAAiB,MAAM,EAG3D,OAAM;EAIR,MAAM,UAAU,iBACd,SACA,OAAO,aACP,OAAO,WACR;AAGD,MAAI,QAAQ,QACV,SAAQ,QAAQ,OAAO,UAAU,GAAG,QAAQ;AAI9C,QAAM,MAAM,QAAQ;;AAKxB,OAAM"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ManifestMCPConfig, ManifestMCPErrorCode, WalletProvider } from "./types.js";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/server-utils.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Error codes that indicate infrastructure-level failures (wallet, RPC, config).
|
|
7
|
+
* Used by tool implementations to distinguish infrastructure errors from
|
|
8
|
+
* provider/application errors so that infrastructure errors are always re-thrown.
|
|
9
|
+
*/
|
|
10
|
+
declare const INFRASTRUCTURE_ERROR_CODES: ReadonlySet<ManifestMCPErrorCode>;
|
|
11
|
+
/**
|
|
12
|
+
* Sensitive field names that should be redacted from error responses
|
|
13
|
+
*/
|
|
14
|
+
declare const SENSITIVE_FIELDS: ReadonlySet<string>;
|
|
15
|
+
/**
|
|
16
|
+
* JSON replacer that converts BigInt values to strings
|
|
17
|
+
*/
|
|
18
|
+
declare function bigIntReplacer(_key: string, value: unknown): unknown;
|
|
19
|
+
/**
|
|
20
|
+
* Recursively sanitize an object by redacting sensitive fields
|
|
21
|
+
*/
|
|
22
|
+
declare function sanitizeForLogging(obj: unknown, depth?: number): unknown;
|
|
23
|
+
/**
|
|
24
|
+
* Options for creating a chain, lease, or fred MCP server
|
|
25
|
+
*/
|
|
26
|
+
interface ManifestMCPServerOptions {
|
|
27
|
+
config: ManifestMCPConfig;
|
|
28
|
+
walletProvider: WalletProvider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wrap a tool handler with error handling that preserves the existing error format.
|
|
32
|
+
*
|
|
33
|
+
* Generic over the callback type so that Zod-inferred argument types from
|
|
34
|
+
* McpServer.registerTool flow through without requiring manual casts.
|
|
35
|
+
*/
|
|
36
|
+
declare function withErrorHandling<T extends (...args: any[]) => Promise<CallToolResult>>(toolName: string, fn: T): T;
|
|
37
|
+
/**
|
|
38
|
+
* Helper to build a successful JSON text response
|
|
39
|
+
*/
|
|
40
|
+
declare function jsonResponse(data: unknown, replacer?: (key: string, value: any) => any): CallToolResult;
|
|
41
|
+
/**
|
|
42
|
+
* Config shape accepted by createMnemonicServer.
|
|
43
|
+
*/
|
|
44
|
+
interface MnemonicServerConfig {
|
|
45
|
+
chainId: string;
|
|
46
|
+
rpcUrl?: string;
|
|
47
|
+
gasPrice?: string;
|
|
48
|
+
restUrl?: string;
|
|
49
|
+
addressPrefix?: string;
|
|
50
|
+
mnemonic: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generic factory that creates any MCP server class with a mnemonic wallet.
|
|
54
|
+
*
|
|
55
|
+
* Eliminates duplicated createMnemonic*Server patterns -- callers pass the
|
|
56
|
+
* server constructor instead.
|
|
57
|
+
*/
|
|
58
|
+
declare function createMnemonicServer<T>(config: MnemonicServerConfig, ServerClass: new (opts: ManifestMCPServerOptions) => T): Promise<T>;
|
|
59
|
+
//#endregion
|
|
60
|
+
export { INFRASTRUCTURE_ERROR_CODES, ManifestMCPServerOptions, MnemonicServerConfig, SENSITIVE_FIELDS, bigIntReplacer, createMnemonicServer, jsonResponse, sanitizeForLogging, withErrorHandling };
|
|
61
|
+
//# sourceMappingURL=server-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-utils.d.ts","names":[],"sources":["../src/server-utils.ts"],"mappings":";;;;;;AAgBA;;;cAAa,0BAAA,EAA4B,WAAA,CAAY,oBAAA;;AAYrD;;cAAa,gBAAA,EAAkB,WAAA;;;AAwB/B;iBAAgB,cAAA,CAAe,IAAA,UAAc,KAAA;;;;iBAO7B,kBAAA,CAAmB,GAAA,WAAc,KAAA;;;;UAgDhC,wBAAA;EACf,MAAA,EAAQ,iBAAA;EACR,cAAA,EAAgB,cAAA;AAAA;;;;;;;iBAUF,iBAAA,eACA,IAAA,YAAgB,OAAA,CAAQ,cAAA,EAAA,CACtC,QAAA,UAAkB,EAAA,EAAI,CAAA,GAAI,CAAA;AAF5B;;;AAAA,iBAoFgB,YAAA,CACd,IAAA,WACA,QAAA,IAAY,GAAA,UAAa,KAAA,gBACxB,cAAA;;;;UAcc,oBAAA;EACf,OAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA;EACA,aAAA;EACA,QAAA;AAAA;;;;;AAvBF;;iBAgCsB,oBAAA,GAAA,CACpB,MAAA,EAAQ,oBAAA,EACR,WAAA,OAAkB,IAAA,EAAM,wBAAA,KAA6B,CAAA,GACpD,OAAA,CAAQ,CAAA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { ManifestMCPError, ManifestMCPErrorCode } from "./types.js";
|
|
2
|
+
import { createValidatedConfig } from "./config.js";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
import { MnemonicWalletProvider } from "./wallet/mnemonic.js";
|
|
5
|
+
import "./wallet/index.js";
|
|
6
|
+
//#region src/server-utils.ts
|
|
7
|
+
/**
|
|
8
|
+
* Error codes that indicate infrastructure-level failures (wallet, RPC, config).
|
|
9
|
+
* Used by tool implementations to distinguish infrastructure errors from
|
|
10
|
+
* provider/application errors so that infrastructure errors are always re-thrown.
|
|
11
|
+
*/
|
|
12
|
+
const INFRASTRUCTURE_ERROR_CODES = new Set([
|
|
13
|
+
ManifestMCPErrorCode.WALLET_NOT_CONNECTED,
|
|
14
|
+
ManifestMCPErrorCode.WALLET_CONNECTION_FAILED,
|
|
15
|
+
ManifestMCPErrorCode.RPC_CONNECTION_FAILED,
|
|
16
|
+
ManifestMCPErrorCode.INVALID_MNEMONIC,
|
|
17
|
+
ManifestMCPErrorCode.INVALID_CONFIG
|
|
18
|
+
]);
|
|
19
|
+
/**
|
|
20
|
+
* Sensitive field names that should be redacted from error responses
|
|
21
|
+
*/
|
|
22
|
+
const SENSITIVE_FIELDS = new Set([
|
|
23
|
+
"mnemonic",
|
|
24
|
+
"privatekey",
|
|
25
|
+
"private_key",
|
|
26
|
+
"secret",
|
|
27
|
+
"password",
|
|
28
|
+
"seed",
|
|
29
|
+
"secret_key",
|
|
30
|
+
"signing_key",
|
|
31
|
+
"apikey",
|
|
32
|
+
"api_key",
|
|
33
|
+
"auth_token",
|
|
34
|
+
"bearer_token",
|
|
35
|
+
"access_token",
|
|
36
|
+
"refresh_token"
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* JSON replacer that converts BigInt values to strings
|
|
40
|
+
*/
|
|
41
|
+
function bigIntReplacer(_key, value) {
|
|
42
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Recursively sanitize an object by redacting sensitive fields
|
|
46
|
+
*/
|
|
47
|
+
function sanitizeForLogging(obj, depth = 0) {
|
|
48
|
+
if (depth > 10) return "[max depth exceeded]";
|
|
49
|
+
if (obj === null || obj === void 0) return obj;
|
|
50
|
+
if (typeof obj === "string") {
|
|
51
|
+
const words = obj.trim().split(/\s+/);
|
|
52
|
+
const wordCount = words.length;
|
|
53
|
+
if (wordCount >= 12 && wordCount <= 24 && wordCount % 3 === 0) {
|
|
54
|
+
if (words.every((w) => /^[a-z]+$/.test(w))) return "[REDACTED - possible mnemonic]";
|
|
55
|
+
}
|
|
56
|
+
return obj;
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(obj)) return obj.map((item) => sanitizeForLogging(item, depth + 1));
|
|
59
|
+
if (typeof obj === "object") {
|
|
60
|
+
const sanitized = {};
|
|
61
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
62
|
+
const lowerKey = key.toLowerCase();
|
|
63
|
+
if (SENSITIVE_FIELDS.has(lowerKey)) sanitized[key] = "[REDACTED]";
|
|
64
|
+
else sanitized[key] = sanitizeForLogging(value, depth + 1);
|
|
65
|
+
}
|
|
66
|
+
return sanitized;
|
|
67
|
+
}
|
|
68
|
+
return obj;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wrap a tool handler with error handling that preserves the existing error format.
|
|
72
|
+
*
|
|
73
|
+
* Generic over the callback type so that Zod-inferred argument types from
|
|
74
|
+
* McpServer.registerTool flow through without requiring manual casts.
|
|
75
|
+
*/
|
|
76
|
+
function withErrorHandling(toolName, fn) {
|
|
77
|
+
const wrapped = async (...cbArgs) => {
|
|
78
|
+
const hasArgs = cbArgs.length >= 2;
|
|
79
|
+
const args = hasArgs ? cbArgs[0] ?? {} : {};
|
|
80
|
+
try {
|
|
81
|
+
return hasArgs ? await fn(args, cbArgs[1]) : await fn(cbArgs[0]);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
84
|
+
const errorCode = error instanceof ManifestMCPError ? error.code : "UNKNOWN";
|
|
85
|
+
if (error instanceof ManifestMCPError) logger.error(`[${toolName}] Tool error [${errorCode}]: ${errorMessage}`);
|
|
86
|
+
else {
|
|
87
|
+
const stack = error instanceof Error && error.stack ? `\n${error.stack}` : "";
|
|
88
|
+
logger.error(`[${toolName}] Tool error [${errorCode}]: ${errorMessage}${stack}`);
|
|
89
|
+
}
|
|
90
|
+
const safeMessage = sanitizeForLogging(errorMessage);
|
|
91
|
+
let errorResponse = {
|
|
92
|
+
error: true,
|
|
93
|
+
tool: toolName,
|
|
94
|
+
input: sanitizeForLogging(args)
|
|
95
|
+
};
|
|
96
|
+
if (error instanceof ManifestMCPError) errorResponse = {
|
|
97
|
+
...errorResponse,
|
|
98
|
+
code: error.code,
|
|
99
|
+
message: sanitizeForLogging(error.message),
|
|
100
|
+
details: sanitizeForLogging(error.details)
|
|
101
|
+
};
|
|
102
|
+
else errorResponse = {
|
|
103
|
+
...errorResponse,
|
|
104
|
+
message: safeMessage
|
|
105
|
+
};
|
|
106
|
+
let responseText;
|
|
107
|
+
try {
|
|
108
|
+
responseText = JSON.stringify(errorResponse, bigIntReplacer, 2);
|
|
109
|
+
} catch (stringifyError) {
|
|
110
|
+
logger.error(`[${toolName}] Failed to serialize error response: ${stringifyError instanceof Error ? stringifyError.message : String(stringifyError)}`);
|
|
111
|
+
responseText = JSON.stringify({
|
|
112
|
+
error: true,
|
|
113
|
+
tool: toolName,
|
|
114
|
+
message: safeMessage
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
content: [{
|
|
119
|
+
type: "text",
|
|
120
|
+
text: responseText
|
|
121
|
+
}],
|
|
122
|
+
isError: true
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
return wrapped;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Helper to build a successful JSON text response
|
|
130
|
+
*/
|
|
131
|
+
function jsonResponse(data, replacer) {
|
|
132
|
+
return { content: [{
|
|
133
|
+
type: "text",
|
|
134
|
+
text: JSON.stringify(data, replacer, 2)
|
|
135
|
+
}] };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generic factory that creates any MCP server class with a mnemonic wallet.
|
|
139
|
+
*
|
|
140
|
+
* Eliminates duplicated createMnemonic*Server patterns -- callers pass the
|
|
141
|
+
* server constructor instead.
|
|
142
|
+
*/
|
|
143
|
+
async function createMnemonicServer(config, ServerClass) {
|
|
144
|
+
const { mnemonic, ...mcpConfig } = config;
|
|
145
|
+
const validatedConfig = createValidatedConfig(mcpConfig);
|
|
146
|
+
const walletProvider = new MnemonicWalletProvider(validatedConfig, mnemonic);
|
|
147
|
+
await walletProvider.connect();
|
|
148
|
+
return new ServerClass({
|
|
149
|
+
config: validatedConfig,
|
|
150
|
+
walletProvider
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { INFRASTRUCTURE_ERROR_CODES, SENSITIVE_FIELDS, bigIntReplacer, createMnemonicServer, jsonResponse, sanitizeForLogging, withErrorHandling };
|
|
155
|
+
|
|
156
|
+
//# sourceMappingURL=server-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-utils.js","names":[],"sources":["../src/server-utils.ts"],"sourcesContent":["import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { createValidatedConfig } from './config.js';\nimport { logger } from './logger.js';\nimport {\n type ManifestMCPConfig,\n ManifestMCPError,\n ManifestMCPErrorCode,\n type WalletProvider,\n} from './types.js';\nimport { MnemonicWalletProvider } from './wallet/index.js';\n\n/**\n * Error codes that indicate infrastructure-level failures (wallet, RPC, config).\n * Used by tool implementations to distinguish infrastructure errors from\n * provider/application errors so that infrastructure errors are always re-thrown.\n */\nexport const INFRASTRUCTURE_ERROR_CODES: ReadonlySet<ManifestMCPErrorCode> =\n new Set([\n ManifestMCPErrorCode.WALLET_NOT_CONNECTED,\n ManifestMCPErrorCode.WALLET_CONNECTION_FAILED,\n ManifestMCPErrorCode.RPC_CONNECTION_FAILED,\n ManifestMCPErrorCode.INVALID_MNEMONIC,\n ManifestMCPErrorCode.INVALID_CONFIG,\n ]);\n\n/**\n * Sensitive field names that should be redacted from error responses\n */\nexport const SENSITIVE_FIELDS: ReadonlySet<string> = new Set([\n 'mnemonic',\n 'privatekey',\n 'private_key',\n 'secret',\n 'password',\n 'seed',\n 'secret_key',\n 'signing_key',\n 'apikey',\n 'api_key',\n 'auth_token',\n 'bearer_token',\n 'access_token',\n 'refresh_token',\n]);\n\n// Note: standalone \"key\" and \"token\" are intentionally excluded from SENSITIVE_FIELDS\n// because they are too generic — they would match pagination keys, map keys, and\n// non-sensitive token identifiers. Use compound names (api_key, auth_token, etc.) instead.\n\n/**\n * JSON replacer that converts BigInt values to strings\n */\nexport function bigIntReplacer(_key: string, value: unknown): unknown {\n return typeof value === 'bigint' ? value.toString() : value;\n}\n\n/**\n * Recursively sanitize an object by redacting sensitive fields\n */\nexport function sanitizeForLogging(obj: unknown, depth = 0): unknown {\n // Prevent infinite recursion\n if (depth > 10) {\n return '[max depth exceeded]';\n }\n\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (typeof obj === 'string') {\n // Redact strings that look like BIP-39 mnemonics (12/15/18/21/24 words).\n // BIP-39 words are all lowercase alphabetic, so require that to avoid\n // false positives on error messages that happen to be 12/24 words.\n const words = obj.trim().split(/\\s+/);\n const wordCount = words.length;\n if (wordCount >= 12 && wordCount <= 24 && wordCount % 3 === 0) {\n const allLowercaseAlpha = words.every((w) => /^[a-z]+$/.test(w));\n if (allLowercaseAlpha) {\n return '[REDACTED - possible mnemonic]';\n }\n }\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sanitizeForLogging(item, depth + 1));\n }\n\n if (typeof obj === 'object') {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const lowerKey = key.toLowerCase();\n if (SENSITIVE_FIELDS.has(lowerKey)) {\n sanitized[key] = '[REDACTED]';\n } else {\n sanitized[key] = sanitizeForLogging(value, depth + 1);\n }\n }\n return sanitized;\n }\n\n return obj;\n}\n\n/**\n * Options for creating a chain, lease, or fred MCP server\n */\nexport interface ManifestMCPServerOptions {\n config: ManifestMCPConfig;\n walletProvider: WalletProvider;\n}\n\n/**\n * Wrap a tool handler with error handling that preserves the existing error format.\n *\n * Generic over the callback type so that Zod-inferred argument types from\n * McpServer.registerTool flow through without requiring manual casts.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- preserves ToolCallback<Args> signature from McpServer\nexport function withErrorHandling<\n T extends (...args: any[]) => Promise<CallToolResult>,\n>(toolName: string, fn: T): T {\n // For tools with no inputSchema, McpServer calls cb(extra) with one arg.\n // For tools with inputSchema, McpServer calls cb(parsedArgs, extra).\n // We infer from cbArgs.length at call time (not fn.length) so default parameters are safe.\n const wrapped = async (...cbArgs: any[]) => {\n const hasArgs = cbArgs.length >= 2;\n const args = hasArgs ? (cbArgs[0] ?? {}) : {};\n try {\n return hasArgs ? await fn(args, cbArgs[1]) : await fn(cbArgs[0]);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorCode =\n error instanceof ManifestMCPError ? error.code : 'UNKNOWN';\n if (error instanceof ManifestMCPError) {\n logger.error(\n `[${toolName}] Tool error [${errorCode}]: ${errorMessage}`,\n );\n } else {\n const stack =\n error instanceof Error && error.stack ? `\\n${error.stack}` : '';\n logger.error(\n `[${toolName}] Tool error [${errorCode}]: ${errorMessage}${stack}`,\n );\n }\n\n // Sanitize error messages before including in the MCP response.\n // This catches mnemonic-like strings in error messages and redacts them.\n const safeMessage = sanitizeForLogging(errorMessage) as string;\n\n let errorResponse: Record<string, unknown> = {\n error: true,\n tool: toolName,\n input: sanitizeForLogging(args),\n };\n\n if (error instanceof ManifestMCPError) {\n errorResponse = {\n ...errorResponse,\n code: error.code,\n message: sanitizeForLogging(error.message) as string,\n details: sanitizeForLogging(error.details),\n };\n } else {\n errorResponse = {\n ...errorResponse,\n message: safeMessage,\n };\n }\n\n let responseText: string;\n try {\n responseText = JSON.stringify(errorResponse, bigIntReplacer, 2);\n } catch (stringifyError) {\n logger.error(\n `[${toolName}] Failed to serialize error response: ${stringifyError instanceof Error ? stringifyError.message : String(stringifyError)}`,\n );\n responseText = JSON.stringify({\n error: true,\n tool: toolName,\n message: safeMessage,\n });\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: responseText,\n },\n ],\n isError: true,\n };\n }\n };\n return wrapped as T;\n}\n\n/**\n * Helper to build a successful JSON text response\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches JSON.stringify's replacer signature\nexport function jsonResponse(\n data: unknown,\n replacer?: (key: string, value: any) => any,\n): CallToolResult {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, replacer, 2),\n },\n ],\n };\n}\n\n/**\n * Config shape accepted by createMnemonicServer.\n */\nexport interface MnemonicServerConfig {\n chainId: string;\n rpcUrl?: string;\n gasPrice?: string;\n restUrl?: string;\n addressPrefix?: string;\n mnemonic: string;\n}\n\n/**\n * Generic factory that creates any MCP server class with a mnemonic wallet.\n *\n * Eliminates duplicated createMnemonic*Server patterns -- callers pass the\n * server constructor instead.\n */\nexport async function createMnemonicServer<T>(\n config: MnemonicServerConfig,\n ServerClass: new (opts: ManifestMCPServerOptions) => T,\n): Promise<T> {\n const { mnemonic, ...mcpConfig } = config;\n const validatedConfig = createValidatedConfig(mcpConfig);\n const walletProvider = new MnemonicWalletProvider(validatedConfig, mnemonic);\n await walletProvider.connect();\n\n return new ServerClass({\n config: validatedConfig,\n walletProvider,\n });\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,6BACX,IAAI,IAAI;CACN,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACtB,CAAC;;;;AAKJ,MAAa,mBAAwC,IAAI,IAAI;CAC3D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AASF,SAAgB,eAAe,MAAc,OAAyB;AACpE,QAAO,OAAO,UAAU,WAAW,MAAM,UAAU,GAAG;;;;;AAMxD,SAAgB,mBAAmB,KAAc,QAAQ,GAAY;AAEnE,KAAI,QAAQ,GACV,QAAO;AAGT,KAAI,QAAQ,QAAQ,QAAQ,KAAA,EAC1B,QAAO;AAGT,KAAI,OAAO,QAAQ,UAAU;EAI3B,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,MAAM;EACrC,MAAM,YAAY,MAAM;AACxB,MAAI,aAAa,MAAM,aAAa,MAAM,YAAY,MAAM;OAChC,MAAM,OAAO,MAAM,WAAW,KAAK,EAAE,CAAC,CAE9D,QAAO;;AAGX,SAAO;;AAGT,KAAI,MAAM,QAAQ,IAAI,CACpB,QAAO,IAAI,KAAK,SAAS,mBAAmB,MAAM,QAAQ,EAAE,CAAC;AAG/D,KAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,YAAqC,EAAE;AAC7C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;GAC9C,MAAM,WAAW,IAAI,aAAa;AAClC,OAAI,iBAAiB,IAAI,SAAS,CAChC,WAAU,OAAO;OAEjB,WAAU,OAAO,mBAAmB,OAAO,QAAQ,EAAE;;AAGzD,SAAO;;AAGT,QAAO;;;;;;;;AAkBT,SAAgB,kBAEd,UAAkB,IAAU;CAI5B,MAAM,UAAU,OAAO,GAAG,WAAkB;EAC1C,MAAM,UAAU,OAAO,UAAU;EACjC,MAAM,OAAO,UAAW,OAAO,MAAM,EAAE,GAAI,EAAE;AAC7C,MAAI;AACF,UAAO,UAAU,MAAM,GAAG,MAAM,OAAO,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG;WACzD,OAAO;GACd,MAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACxD,MAAM,YACJ,iBAAiB,mBAAmB,MAAM,OAAO;AACnD,OAAI,iBAAiB,iBACnB,QAAO,MACL,IAAI,SAAS,gBAAgB,UAAU,KAAK,eAC7C;QACI;IACL,MAAM,QACJ,iBAAiB,SAAS,MAAM,QAAQ,KAAK,MAAM,UAAU;AAC/D,WAAO,MACL,IAAI,SAAS,gBAAgB,UAAU,KAAK,eAAe,QAC5D;;GAKH,MAAM,cAAc,mBAAmB,aAAa;GAEpD,IAAI,gBAAyC;IAC3C,OAAO;IACP,MAAM;IACN,OAAO,mBAAmB,KAAK;IAChC;AAED,OAAI,iBAAiB,iBACnB,iBAAgB;IACd,GAAG;IACH,MAAM,MAAM;IACZ,SAAS,mBAAmB,MAAM,QAAQ;IAC1C,SAAS,mBAAmB,MAAM,QAAQ;IAC3C;OAED,iBAAgB;IACd,GAAG;IACH,SAAS;IACV;GAGH,IAAI;AACJ,OAAI;AACF,mBAAe,KAAK,UAAU,eAAe,gBAAgB,EAAE;YACxD,gBAAgB;AACvB,WAAO,MACL,IAAI,SAAS,wCAAwC,0BAA0B,QAAQ,eAAe,UAAU,OAAO,eAAe,GACvI;AACD,mBAAe,KAAK,UAAU;KAC5B,OAAO;KACP,MAAM;KACN,SAAS;KACV,CAAC;;AAGJ,UAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM;KACP,CACF;IACD,SAAS;IACV;;;AAGL,QAAO;;;;;AAOT,SAAgB,aACd,MACA,UACgB;AAChB,QAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,MAAM,UAAU,EAAE;EACxC,CACF,EACF;;;;;;;;AAqBH,eAAsB,qBACpB,QACA,aACY;CACZ,MAAM,EAAE,UAAU,GAAG,cAAc;CACnC,MAAM,kBAAkB,sBAAsB,UAAU;CACxD,MAAM,iBAAiB,IAAI,uBAAuB,iBAAiB,SAAS;AAC5E,OAAM,eAAe,SAAS;AAE9B,QAAO,IAAI,YAAY;EACrB,QAAQ;EACR;EACD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CosmosTxResult } from "../types.js";
|
|
2
|
+
import { CosmosClientManager } from "../client.js";
|
|
3
|
+
|
|
4
|
+
//#region src/tools/fundCredits.d.ts
|
|
5
|
+
declare function fundCredits(clientManager: CosmosClientManager, amount: string): Promise<CosmosTxResult>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { fundCredits };
|
|
8
|
+
//# sourceMappingURL=fundCredits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fundCredits.d.ts","names":[],"sources":["../../src/tools/fundCredits.ts"],"mappings":";;;;iBAIsB,WAAA,CACpB,aAAA,EAAe,mBAAA,EACf,MAAA,WACC,OAAA,CAAQ,cAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { cosmosTx } from "../cosmos.js";
|
|
2
|
+
//#region src/tools/fundCredits.ts
|
|
3
|
+
async function fundCredits(clientManager, amount) {
|
|
4
|
+
return cosmosTx(clientManager, "billing", "fund-credit", [await clientManager.getAddress(), amount], true);
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { fundCredits };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=fundCredits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fundCredits.js","names":[],"sources":["../../src/tools/fundCredits.ts"],"sourcesContent":["import type { CosmosClientManager } from '../client.js';\nimport { cosmosTx } from '../cosmos.js';\nimport type { CosmosTxResult } from '../types.js';\n\nexport async function fundCredits(\n clientManager: CosmosClientManager,\n amount: string,\n): Promise<CosmosTxResult> {\n const address = await clientManager.getAddress();\n return cosmosTx(\n clientManager,\n 'billing',\n 'fund-credit',\n [address, amount],\n true,\n );\n}\n"],"mappings":";;AAIA,eAAsB,YACpB,eACA,QACyB;AAEzB,QAAO,SACL,eACA,WACA,eACA,CALc,MAAM,cAAc,YAAY,EAKpC,OAAO,EACjB,KACD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ManifestQueryClient } from "../client.js";
|
|
2
|
+
|
|
3
|
+
//#region src/tools/getBalance.d.ts
|
|
4
|
+
declare function getBalance(queryClient: ManifestQueryClient, address: string): Promise<{
|
|
5
|
+
balances: {
|
|
6
|
+
denom: string;
|
|
7
|
+
amount: string;
|
|
8
|
+
}[];
|
|
9
|
+
spending_per_hour?: {
|
|
10
|
+
denom: string;
|
|
11
|
+
amount: string;
|
|
12
|
+
}[] | undefined;
|
|
13
|
+
hours_remaining?: string | undefined;
|
|
14
|
+
running_apps?: string | undefined;
|
|
15
|
+
credits: {
|
|
16
|
+
active_leases: string;
|
|
17
|
+
pending_leases: string;
|
|
18
|
+
reserved_amounts: {
|
|
19
|
+
denom: string;
|
|
20
|
+
amount: string;
|
|
21
|
+
}[];
|
|
22
|
+
} | null;
|
|
23
|
+
}>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { getBalance };
|
|
26
|
+
//# sourceMappingURL=getBalance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBalance.d.ts","names":[],"sources":["../../src/tools/getBalance.ts"],"mappings":";;;iBAqBsB,UAAA,CACpB,WAAA,EAAa,mBAAA,EACb,OAAA,WAAe,OAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ManifestMCPError } from "../types.js";
|
|
2
|
+
//#region src/tools/getBalance.ts
|
|
3
|
+
function catchNotFound(promise) {
|
|
4
|
+
return promise.catch((err) => {
|
|
5
|
+
if (err instanceof ManifestMCPError) throw err;
|
|
6
|
+
if (!(err instanceof Error)) throw err;
|
|
7
|
+
const msg = err.message;
|
|
8
|
+
if (/key not found/i.test(msg) || /account.*not found/i.test(msg) || /credit.*not found/i.test(msg)) return null;
|
|
9
|
+
throw err;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
async function getBalance(queryClient, address) {
|
|
13
|
+
const bank = queryClient.cosmos.bank.v1beta1;
|
|
14
|
+
const billing = queryClient.liftedinit.billing.v1;
|
|
15
|
+
const [balancesResult, creditResult, estimateResult] = await Promise.all([
|
|
16
|
+
bank.allBalances({
|
|
17
|
+
address,
|
|
18
|
+
resolveDenom: false
|
|
19
|
+
}),
|
|
20
|
+
catchNotFound(billing.creditAccount({ tenant: address })),
|
|
21
|
+
catchNotFound(billing.creditEstimate({ tenant: address }))
|
|
22
|
+
]);
|
|
23
|
+
const credits = creditResult?.creditAccount ? {
|
|
24
|
+
active_leases: creditResult.creditAccount.activeLeaseCount.toString(),
|
|
25
|
+
pending_leases: creditResult.creditAccount.pendingLeaseCount.toString(),
|
|
26
|
+
reserved_amounts: creditResult.creditAccount.reservedAmounts.map((c) => ({
|
|
27
|
+
denom: c.denom,
|
|
28
|
+
amount: c.amount
|
|
29
|
+
}))
|
|
30
|
+
} : null;
|
|
31
|
+
const estimate = estimateResult ? {
|
|
32
|
+
current_balance: estimateResult.currentBalance.map((c) => ({
|
|
33
|
+
denom: c.denom,
|
|
34
|
+
amount: c.amount
|
|
35
|
+
})),
|
|
36
|
+
spending_per_hour: estimateResult.totalRatePerSecond.map((c) => ({
|
|
37
|
+
denom: c.denom,
|
|
38
|
+
amount: (BigInt(c.amount) * 3600n).toString()
|
|
39
|
+
})),
|
|
40
|
+
hours_remaining: estimateResult.estimatedDurationSeconds > 0n ? (Number(estimateResult.estimatedDurationSeconds) / 3600).toFixed(1) : "0",
|
|
41
|
+
running_apps: estimateResult.activeLeaseCount.toString()
|
|
42
|
+
} : null;
|
|
43
|
+
return {
|
|
44
|
+
credits,
|
|
45
|
+
...estimate && {
|
|
46
|
+
spending_per_hour: estimate.spending_per_hour,
|
|
47
|
+
hours_remaining: estimate.hours_remaining,
|
|
48
|
+
running_apps: estimate.running_apps
|
|
49
|
+
},
|
|
50
|
+
balances: balancesResult.balances.map((c) => ({
|
|
51
|
+
denom: c.denom,
|
|
52
|
+
amount: c.amount
|
|
53
|
+
}))
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { getBalance };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=getBalance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBalance.js","names":[],"sources":["../../src/tools/getBalance.ts"],"sourcesContent":["import type { ManifestQueryClient } from '../client.js';\nimport { ManifestMCPError } from '../types.js';\n\nfunction catchNotFound<T>(promise: Promise<T>): Promise<T | null> {\n return promise.catch((err: unknown) => {\n // Never suppress structured infrastructure errors\n if (err instanceof ManifestMCPError) throw err;\n if (!(err instanceof Error)) throw err;\n const msg = err.message;\n // Match Cosmos SDK / gRPC NOT_FOUND patterns (key not found, account not found, etc.)\n if (\n /key not found/i.test(msg) ||\n /account.*not found/i.test(msg) ||\n /credit.*not found/i.test(msg)\n ) {\n return null;\n }\n throw err;\n });\n}\n\nexport async function getBalance(\n queryClient: ManifestQueryClient,\n address: string,\n) {\n const bank = queryClient.cosmos.bank.v1beta1;\n const billing = queryClient.liftedinit.billing.v1;\n\n const [balancesResult, creditResult, estimateResult] = await Promise.all([\n bank.allBalances({ address, resolveDenom: false }),\n catchNotFound(billing.creditAccount({ tenant: address })),\n catchNotFound(billing.creditEstimate({ tenant: address })),\n ]);\n\n const credits = creditResult?.creditAccount\n ? {\n active_leases: creditResult.creditAccount.activeLeaseCount.toString(),\n pending_leases: creditResult.creditAccount.pendingLeaseCount.toString(),\n reserved_amounts: creditResult.creditAccount.reservedAmounts.map(\n (c) => ({\n denom: c.denom,\n amount: c.amount,\n }),\n ),\n }\n : null;\n\n const estimate = estimateResult\n ? {\n current_balance: estimateResult.currentBalance.map((c) => ({\n denom: c.denom,\n amount: c.amount,\n })),\n spending_per_hour: estimateResult.totalRatePerSecond.map((c) => ({\n denom: c.denom,\n amount: (BigInt(c.amount) * 3600n).toString(),\n })),\n hours_remaining:\n estimateResult.estimatedDurationSeconds > 0n\n ? (Number(estimateResult.estimatedDurationSeconds) / 3600).toFixed(\n 1,\n )\n : '0',\n running_apps: estimateResult.activeLeaseCount.toString(),\n }\n : null;\n\n return {\n credits,\n ...(estimate && {\n spending_per_hour: estimate.spending_per_hour,\n hours_remaining: estimate.hours_remaining,\n running_apps: estimate.running_apps,\n }),\n balances: balancesResult.balances.map((c) => ({\n denom: c.denom,\n amount: c.amount,\n })),\n };\n}\n"],"mappings":";;AAGA,SAAS,cAAiB,SAAwC;AAChE,QAAO,QAAQ,OAAO,QAAiB;AAErC,MAAI,eAAe,iBAAkB,OAAM;AAC3C,MAAI,EAAE,eAAe,OAAQ,OAAM;EACnC,MAAM,MAAM,IAAI;AAEhB,MACE,iBAAiB,KAAK,IAAI,IAC1B,sBAAsB,KAAK,IAAI,IAC/B,qBAAqB,KAAK,IAAI,CAE9B,QAAO;AAET,QAAM;GACN;;AAGJ,eAAsB,WACpB,aACA,SACA;CACA,MAAM,OAAO,YAAY,OAAO,KAAK;CACrC,MAAM,UAAU,YAAY,WAAW,QAAQ;CAE/C,MAAM,CAAC,gBAAgB,cAAc,kBAAkB,MAAM,QAAQ,IAAI;EACvE,KAAK,YAAY;GAAE;GAAS,cAAc;GAAO,CAAC;EAClD,cAAc,QAAQ,cAAc,EAAE,QAAQ,SAAS,CAAC,CAAC;EACzD,cAAc,QAAQ,eAAe,EAAE,QAAQ,SAAS,CAAC,CAAC;EAC3D,CAAC;CAEF,MAAM,UAAU,cAAc,gBAC1B;EACE,eAAe,aAAa,cAAc,iBAAiB,UAAU;EACrE,gBAAgB,aAAa,cAAc,kBAAkB,UAAU;EACvE,kBAAkB,aAAa,cAAc,gBAAgB,KAC1D,OAAO;GACN,OAAO,EAAE;GACT,QAAQ,EAAE;GACX,EACF;EACF,GACD;CAEJ,MAAM,WAAW,iBACb;EACE,iBAAiB,eAAe,eAAe,KAAK,OAAO;GACzD,OAAO,EAAE;GACT,QAAQ,EAAE;GACX,EAAE;EACH,mBAAmB,eAAe,mBAAmB,KAAK,OAAO;GAC/D,OAAO,EAAE;GACT,SAAS,OAAO,EAAE,OAAO,GAAG,OAAO,UAAU;GAC9C,EAAE;EACH,iBACE,eAAe,2BAA2B,MACrC,OAAO,eAAe,yBAAyB,GAAG,MAAM,QACvD,EACD,GACD;EACN,cAAc,eAAe,iBAAiB,UAAU;EACzD,GACD;AAEJ,QAAO;EACL;EACA,GAAI,YAAY;GACd,mBAAmB,SAAS;GAC5B,iBAAiB,SAAS;GAC1B,cAAc,SAAS;GACxB;EACD,UAAU,eAAe,SAAS,KAAK,OAAO;GAC5C,OAAO,EAAE;GACT,QAAQ,EAAE;GACX,EAAE;EACJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CosmosClientManager } from "../client.js";
|
|
2
|
+
|
|
3
|
+
//#region src/tools/stopApp.d.ts
|
|
4
|
+
interface StopAppResult {
|
|
5
|
+
readonly lease_uuid: string;
|
|
6
|
+
readonly status: 'stopped';
|
|
7
|
+
readonly transactionHash: string;
|
|
8
|
+
readonly code: number;
|
|
9
|
+
}
|
|
10
|
+
declare function stopApp(clientManager: CosmosClientManager, leaseUuid: string): Promise<StopAppResult>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { StopAppResult, stopApp };
|
|
13
|
+
//# sourceMappingURL=stopApp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stopApp.d.ts","names":[],"sources":["../../src/tools/stopApp.ts"],"mappings":";;;UAGiB,aAAA;EAAA,SACN,UAAA;EAAA,SACA,MAAA;EAAA,SACA,eAAA;EAAA,SACA,IAAA;AAAA;AAAA,iBAGW,OAAA,CACpB,aAAA,EAAe,mBAAA,EACf,SAAA,WACC,OAAA,CAAQ,aAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cosmosTx } from "../cosmos.js";
|
|
2
|
+
//#region src/tools/stopApp.ts
|
|
3
|
+
async function stopApp(clientManager, leaseUuid) {
|
|
4
|
+
const result = await cosmosTx(clientManager, "billing", "close-lease", [leaseUuid], true);
|
|
5
|
+
return {
|
|
6
|
+
lease_uuid: leaseUuid,
|
|
7
|
+
status: "stopped",
|
|
8
|
+
transactionHash: result.transactionHash,
|
|
9
|
+
code: result.code
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { stopApp };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=stopApp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stopApp.js","names":[],"sources":["../../src/tools/stopApp.ts"],"sourcesContent":["import type { CosmosClientManager } from '../client.js';\nimport { cosmosTx } from '../cosmos.js';\n\nexport interface StopAppResult {\n readonly lease_uuid: string;\n readonly status: 'stopped';\n readonly transactionHash: string;\n readonly code: number;\n}\n\nexport async function stopApp(\n clientManager: CosmosClientManager,\n leaseUuid: string,\n): Promise<StopAppResult> {\n const result = await cosmosTx(\n clientManager,\n 'billing',\n 'close-lease',\n [leaseUuid],\n true,\n );\n\n return {\n lease_uuid: leaseUuid,\n status: 'stopped',\n transactionHash: result.transactionHash,\n code: result.code,\n };\n}\n"],"mappings":";;AAUA,eAAsB,QACpB,eACA,WACwB;CACxB,MAAM,SAAS,MAAM,SACnB,eACA,WACA,eACA,CAAC,UAAU,EACX,KACD;AAED,QAAO;EACL,YAAY;EACZ,QAAQ;EACR,iBAAiB,OAAO;EACxB,MAAM,OAAO;EACd"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CosmosTxResult } from "../types.js";
|
|
2
|
+
import { SigningStargateClient } from "@cosmjs/stargate";
|
|
3
|
+
|
|
4
|
+
//#region src/transactions/bank.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Route bank transaction to appropriate handler
|
|
7
|
+
*/
|
|
8
|
+
declare function routeBankTransaction(client: SigningStargateClient, senderAddress: string, subcommand: string, args: string[], waitForConfirmation: boolean): Promise<CosmosTxResult>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { routeBankTransaction };
|
|
11
|
+
//# sourceMappingURL=bank.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bank.d.ts","names":[],"sources":["../../src/transactions/bank.ts"],"mappings":";;;;;;AAqBA;iBAAsB,oBAAA,CACpB,MAAA,EAAQ,qBAAA,EACR,aAAA,UACA,UAAA,UACA,IAAA,YACA,mBAAA,YACC,OAAA,CAAQ,cAAA"}
|