@manifest-network/manifest-mcp-browser 0.1.0 → 0.1.5
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/.github/workflows/publish.yml +4 -2
- package/CLAUDE.md +9 -3
- package/README.md +6 -1
- package/dist/client.d.ts +13 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +105 -9
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -7
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +128 -0
- package/dist/config.test.js.map +1 -1
- package/dist/cosmos.d.ts.map +1 -1
- package/dist/cosmos.js +11 -57
- package/dist/cosmos.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -25
- package/dist/index.js.map +1 -1
- package/dist/modules.d.ts +30 -1
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +67 -3
- package/dist/modules.js.map +1 -1
- package/dist/modules.test.js +58 -1
- package/dist/modules.test.js.map +1 -1
- package/dist/queries/auth.d.ts +7 -1
- package/dist/queries/auth.d.ts.map +1 -1
- package/dist/queries/auth.js +18 -45
- package/dist/queries/auth.js.map +1 -1
- package/dist/queries/bank.d.ts +7 -1
- package/dist/queries/bank.d.ts.map +1 -1
- package/dist/queries/bank.js +24 -38
- package/dist/queries/bank.js.map +1 -1
- package/dist/queries/billing.d.ts +7 -1
- package/dist/queries/billing.d.ts.map +1 -1
- package/dist/queries/billing.js +28 -54
- package/dist/queries/billing.js.map +1 -1
- package/dist/queries/distribution.d.ts +7 -1
- package/dist/queries/distribution.d.ts.map +1 -1
- package/dist/queries/distribution.js +18 -36
- package/dist/queries/distribution.js.map +1 -1
- package/dist/queries/gov.d.ts +7 -1
- package/dist/queries/gov.d.ts.map +1 -1
- package/dist/queries/gov.js +24 -41
- package/dist/queries/gov.js.map +1 -1
- package/dist/queries/index.d.ts +2 -1
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +1 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/staking.d.ts +7 -1
- package/dist/queries/staking.d.ts.map +1 -1
- package/dist/queries/staking.js +36 -59
- package/dist/queries/staking.js.map +1 -1
- package/dist/queries/utils.d.ts +42 -10
- package/dist/queries/utils.d.ts.map +1 -1
- package/dist/queries/utils.js +64 -12
- package/dist/queries/utils.js.map +1 -1
- package/dist/queries/utils.test.js +68 -8
- package/dist/queries/utils.test.js.map +1 -1
- package/dist/transactions/bank.d.ts +2 -2
- package/dist/transactions/bank.d.ts.map +1 -1
- package/dist/transactions/bank.js +9 -18
- package/dist/transactions/bank.js.map +1 -1
- package/dist/transactions/billing.d.ts +2 -2
- package/dist/transactions/billing.d.ts.map +1 -1
- package/dist/transactions/billing.js +52 -34
- package/dist/transactions/billing.js.map +1 -1
- package/dist/transactions/distribution.d.ts +2 -2
- package/dist/transactions/distribution.d.ts.map +1 -1
- package/dist/transactions/distribution.js +7 -13
- package/dist/transactions/distribution.js.map +1 -1
- package/dist/transactions/gov.d.ts +2 -2
- package/dist/transactions/gov.d.ts.map +1 -1
- package/dist/transactions/gov.js +32 -17
- package/dist/transactions/gov.js.map +1 -1
- package/dist/transactions/index.d.ts +1 -1
- package/dist/transactions/index.d.ts.map +1 -1
- package/dist/transactions/index.js +1 -1
- package/dist/transactions/index.js.map +1 -1
- package/dist/transactions/manifest.d.ts +2 -2
- package/dist/transactions/manifest.d.ts.map +1 -1
- package/dist/transactions/manifest.js +7 -14
- package/dist/transactions/manifest.js.map +1 -1
- package/dist/transactions/staking.d.ts +2 -2
- package/dist/transactions/staking.d.ts.map +1 -1
- package/dist/transactions/staking.js +7 -13
- package/dist/transactions/staking.js.map +1 -1
- package/dist/transactions/utils.d.ts +63 -1
- package/dist/transactions/utils.d.ts.map +1 -1
- package/dist/transactions/utils.js +121 -2
- package/dist/transactions/utils.js.map +1 -1
- package/dist/transactions/utils.test.js +351 -1
- package/dist/transactions/utils.test.js.map +1 -1
- package/dist/types.d.ts +212 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wallet/mnemonic.d.ts +1 -0
- package/dist/wallet/mnemonic.d.ts.map +1 -1
- package/dist/wallet/mnemonic.js +34 -13
- package/dist/wallet/mnemonic.js.map +1 -1
- package/package.json +11 -6
- package/src/client.ts +119 -9
- package/src/config.test.ts +156 -0
- package/src/config.ts +59 -7
- package/src/cosmos.ts +19 -109
- package/src/index.ts +17 -23
- package/src/modules.test.ts +60 -0
- package/src/modules.ts +124 -7
- package/src/queries/auth.ts +35 -74
- package/src/queries/bank.ts +40 -58
- package/src/queries/billing.ts +46 -86
- package/src/queries/distribution.ts +35 -59
- package/src/queries/gov.ts +40 -64
- package/src/queries/index.ts +10 -1
- package/src/queries/staking.ts +55 -91
- package/src/queries/utils.test.ts +103 -8
- package/src/queries/utils.ts +92 -12
- package/src/transactions/bank.ts +9 -33
- package/src/transactions/billing.ts +64 -59
- package/src/transactions/distribution.ts +7 -29
- package/src/transactions/gov.ts +40 -34
- package/src/transactions/index.ts +1 -1
- package/src/transactions/manifest.ts +7 -29
- package/src/transactions/staking.ts +7 -29
- package/src/transactions/utils.test.ts +390 -1
- package/src/transactions/utils.ts +191 -2
- package/src/types.ts +328 -9
- package/src/wallet/mnemonic.ts +41 -17
- package/.claude/settings.local.json +0 -17
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.js.map +0 -1
- package/dist/queries/manifest.d.ts +0 -10
- package/dist/queries/manifest.d.ts.map +0 -1
- package/dist/queries/manifest.js +0 -14
- package/dist/queries/manifest.js.map +0 -1
- package/dist/wallet/keplr.d.ts.map +0 -1
- package/dist/wallet/keplr.js.map +0 -1
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,wCAAwC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAiFA;;GAEG;AACH,MAAM,CAAN,IAAY,oBAkCX;AAlCD,WAAY,oBAAoB;IAC9B,uBAAuB;IACvB,yDAAiC,CAAA;IACjC,yDAAiC,CAAA;IAEjC,gBAAgB;IAChB,qEAA6C,CAAA;IAC7C,6EAAqD,CAAA;IACrD,mEAA2C,CAAA;IAC3C,6DAAqC,CAAA;IAErC,gBAAgB;IAChB,yEAAiD,CAAA;IACjD,uEAA+C,CAAA;IAE/C,eAAe;IACf,qDAA6B,CAAA;IAC7B,+DAAuC,CAAA;IACvC,2DAAmC,CAAA;IAEnC,qBAAqB;IACrB,+CAAuB,CAAA;IACvB,qEAA6C,CAAA;IAC7C,mEAA2C,CAAA;IAC3C,2EAAmD,CAAA;IACnD,yDAAiC,CAAA;IACjC,iEAAyC,CAAA;IAEzC,gBAAgB;IAChB,yDAAiC,CAAA;IACjC,iEAAyC,CAAA;IAEzC,iBAAiB;IACjB,uDAA+B,CAAA;AACjC,CAAC,EAlCW,oBAAoB,KAApB,oBAAoB,QAkC/B;AAED;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAIzC,YACE,IAA0B,EAC1B,OAAe,EACf,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,sDAAsD;QACtD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -12,6 +12,7 @@ export declare class MnemonicWalletProvider implements WalletProvider {
|
|
|
12
12
|
private wallet;
|
|
13
13
|
private address;
|
|
14
14
|
private disconnected;
|
|
15
|
+
private initPromise;
|
|
15
16
|
constructor(config: ManifestMCPConfig, mnemonic: string);
|
|
16
17
|
/**
|
|
17
18
|
* Initialize the wallet from the mnemonic
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mnemonic.d.ts","sourceRoot":"","sources":["../../src/wallet/mnemonic.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAA0C,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExG;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,YAAY,CAAkB;
|
|
1
|
+
{"version":3,"file":"mnemonic.d.ts","sourceRoot":"","sources":["../../src/wallet/mnemonic.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAA0C,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExG;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,YAAY,CAAkB;IAGtC,OAAO,CAAC,WAAW,CAA8B;gBAErC,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM;IAKvD;;OAEG;YACW,UAAU;IA+DxB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAanC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;CAY1C"}
|
package/dist/wallet/mnemonic.js
CHANGED
|
@@ -11,6 +11,8 @@ export class MnemonicWalletProvider {
|
|
|
11
11
|
this.wallet = null;
|
|
12
12
|
this.address = null;
|
|
13
13
|
this.disconnected = false;
|
|
14
|
+
// Promise to prevent concurrent wallet initialization (lazy init race condition)
|
|
15
|
+
this.initPromise = null;
|
|
14
16
|
this.config = config;
|
|
15
17
|
this.mnemonic = mnemonic;
|
|
16
18
|
}
|
|
@@ -21,26 +23,44 @@ export class MnemonicWalletProvider {
|
|
|
21
23
|
if (this.disconnected) {
|
|
22
24
|
throw new ManifestMCPError(ManifestMCPErrorCode.WALLET_NOT_CONNECTED, 'Wallet has been disconnected and cannot be reconnected. Create a new MnemonicWalletProvider instance.');
|
|
23
25
|
}
|
|
26
|
+
// Return if already initialized
|
|
24
27
|
if (this.wallet) {
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
30
|
+
// If initialization is already in progress, wait for it
|
|
31
|
+
if (this.initPromise) {
|
|
32
|
+
return this.initPromise;
|
|
33
|
+
}
|
|
27
34
|
if (!this.mnemonic) {
|
|
28
35
|
throw new ManifestMCPError(ManifestMCPErrorCode.WALLET_NOT_CONNECTED, 'Mnemonic has been cleared. Create a new MnemonicWalletProvider instance.');
|
|
29
36
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
// Start initialization and cache the promise to prevent concurrent init
|
|
38
|
+
this.initPromise = (async () => {
|
|
39
|
+
const prefix = this.config.addressPrefix ?? 'manifest';
|
|
40
|
+
try {
|
|
41
|
+
this.wallet = await DirectSecp256k1HdWallet.fromMnemonic(this.mnemonic, {
|
|
42
|
+
prefix,
|
|
43
|
+
});
|
|
44
|
+
const accounts = await this.wallet.getAccounts();
|
|
45
|
+
if (accounts.length === 0) {
|
|
46
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_MNEMONIC, 'No accounts derived from mnemonic');
|
|
47
|
+
}
|
|
48
|
+
this.address = accounts[0].address;
|
|
49
|
+
// Clear promise after successful init - wallet check will short-circuit future calls
|
|
50
|
+
this.initPromise = null;
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
catch (error) {
|
|
53
|
+
// Clear state on failure so retry is possible
|
|
54
|
+
this.initPromise = null;
|
|
55
|
+
this.wallet = null;
|
|
56
|
+
this.address = null;
|
|
57
|
+
if (error instanceof ManifestMCPError) {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
throw new ManifestMCPError(ManifestMCPErrorCode.INVALID_MNEMONIC, `Failed to create wallet from mnemonic: ${error instanceof Error ? error.message : String(error)}`);
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
return this.initPromise;
|
|
44
64
|
}
|
|
45
65
|
/**
|
|
46
66
|
* Connect (initialize) the wallet
|
|
@@ -61,6 +81,7 @@ export class MnemonicWalletProvider {
|
|
|
61
81
|
this.mnemonic = null;
|
|
62
82
|
this.wallet = null;
|
|
63
83
|
this.address = null;
|
|
84
|
+
this.initPromise = null;
|
|
64
85
|
this.disconnected = true;
|
|
65
86
|
}
|
|
66
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mnemonic.js","sourceRoot":"","sources":["../../src/wallet/mnemonic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAiB,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAkB,gBAAgB,EAAE,oBAAoB,EAAqB,MAAM,aAAa,CAAC;AAExG;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;
|
|
1
|
+
{"version":3,"file":"mnemonic.js","sourceRoot":"","sources":["../../src/wallet/mnemonic.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manifest-network/manifest-mcp-browser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Browser-compatible MCP server for Cosmos SDK blockchain interactions with Manifest Network using CosmJS",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,15 +26,20 @@
|
|
|
26
26
|
"manifest",
|
|
27
27
|
"browser"
|
|
28
28
|
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/manifest-network/manifest-mcp-browser"
|
|
32
|
+
},
|
|
29
33
|
"author": "Felix C. Morency",
|
|
30
34
|
"license": "MIT",
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@manifest-network/manifestjs": "2.2.0-billing-v2.
|
|
33
|
-
"@modelcontextprotocol/sdk": "
|
|
36
|
+
"@manifest-network/manifestjs": "2.2.0-billing-v2.1",
|
|
37
|
+
"@modelcontextprotocol/sdk": "1.25.3",
|
|
38
|
+
"limiter": "3.0.0"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
|
-
"@types/node": "
|
|
37
|
-
"typescript": "
|
|
38
|
-
"vitest": "
|
|
41
|
+
"@types/node": "20.19.30",
|
|
42
|
+
"typescript": "5.9.3",
|
|
43
|
+
"vitest": "4.0.18"
|
|
39
44
|
}
|
|
40
45
|
}
|
package/src/client.ts
CHANGED
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
} from '@manifest-network/manifestjs';
|
|
13
13
|
import { Registry } from '@cosmjs/proto-signing';
|
|
14
14
|
import { AminoTypes } from '@cosmjs/stargate';
|
|
15
|
+
import { RateLimiter } from 'limiter';
|
|
15
16
|
import { ManifestMCPConfig, WalletProvider, ManifestMCPError, ManifestMCPErrorCode } from './types.js';
|
|
17
|
+
import { DEFAULT_REQUESTS_PER_SECOND } from './config.js';
|
|
16
18
|
|
|
17
19
|
// Type for the RPC query client from manifestjs liftedinit bundle
|
|
18
20
|
// This includes cosmos modules + liftedinit-specific modules (billing, manifest, sku)
|
|
@@ -55,14 +57,30 @@ export class CosmosClientManager {
|
|
|
55
57
|
private walletProvider: WalletProvider;
|
|
56
58
|
private queryClient: ManifestQueryClient | null = null;
|
|
57
59
|
private signingClient: SigningStargateClient | null = null;
|
|
60
|
+
private rateLimiter: RateLimiter;
|
|
61
|
+
|
|
62
|
+
// Promises to prevent concurrent client initialization (lazy init race condition)
|
|
63
|
+
private queryClientPromise: Promise<ManifestQueryClient> | null = null;
|
|
64
|
+
private signingClientPromise: Promise<SigningStargateClient> | null = null;
|
|
58
65
|
|
|
59
66
|
private constructor(config: ManifestMCPConfig, walletProvider: WalletProvider) {
|
|
60
67
|
this.config = config;
|
|
61
68
|
this.walletProvider = walletProvider;
|
|
69
|
+
|
|
70
|
+
// Initialize rate limiter with configured or default requests per second
|
|
71
|
+
const requestsPerSecond = config.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND;
|
|
72
|
+
this.rateLimiter = new RateLimiter({
|
|
73
|
+
tokensPerInterval: requestsPerSecond,
|
|
74
|
+
interval: 'second',
|
|
75
|
+
});
|
|
62
76
|
}
|
|
63
77
|
|
|
64
78
|
/**
|
|
65
|
-
* Get or create a singleton instance for the given config
|
|
79
|
+
* Get or create a singleton instance for the given config.
|
|
80
|
+
* Instances are keyed by chainId:rpcUrl. For existing instances:
|
|
81
|
+
* - Config and walletProvider references are always updated
|
|
82
|
+
* - Signing client is disconnected/recreated if gasPrice or walletProvider changed
|
|
83
|
+
* - Rate limiter is updated if requestsPerSecond changed (without affecting signing client)
|
|
66
84
|
*/
|
|
67
85
|
static getInstance(
|
|
68
86
|
config: ManifestMCPConfig,
|
|
@@ -74,6 +92,37 @@ export class CosmosClientManager {
|
|
|
74
92
|
if (!instance) {
|
|
75
93
|
instance = new CosmosClientManager(config, walletProvider);
|
|
76
94
|
CosmosClientManager.instances.set(key, instance);
|
|
95
|
+
} else {
|
|
96
|
+
// Check what changed to determine what needs updating
|
|
97
|
+
const signingClientAffected =
|
|
98
|
+
instance.config.gasPrice !== config.gasPrice ||
|
|
99
|
+
instance.walletProvider !== walletProvider;
|
|
100
|
+
|
|
101
|
+
const rateLimitChanged =
|
|
102
|
+
instance.config.rateLimit?.requestsPerSecond !== config.rateLimit?.requestsPerSecond;
|
|
103
|
+
|
|
104
|
+
// Always update config reference
|
|
105
|
+
instance.config = config;
|
|
106
|
+
instance.walletProvider = walletProvider;
|
|
107
|
+
|
|
108
|
+
// Only invalidate signing client if fields it depends on changed
|
|
109
|
+
if (signingClientAffected) {
|
|
110
|
+
if (instance.signingClient) {
|
|
111
|
+
instance.signingClient.disconnect();
|
|
112
|
+
instance.signingClient = null;
|
|
113
|
+
}
|
|
114
|
+
// Also clear the promise to allow re-initialization with new config
|
|
115
|
+
instance.signingClientPromise = null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Update rate limiter independently (doesn't affect signing client)
|
|
119
|
+
if (rateLimitChanged) {
|
|
120
|
+
const newRps = config.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND;
|
|
121
|
+
instance.rateLimiter = new RateLimiter({
|
|
122
|
+
tokensPerInterval: newRps,
|
|
123
|
+
interval: 'second',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
77
126
|
}
|
|
78
127
|
|
|
79
128
|
return instance;
|
|
@@ -90,28 +139,65 @@ export class CosmosClientManager {
|
|
|
90
139
|
* Get the manifestjs RPC query client with all module extensions
|
|
91
140
|
*/
|
|
92
141
|
async getQueryClient(): Promise<ManifestQueryClient> {
|
|
93
|
-
if
|
|
142
|
+
// Return cached client if available
|
|
143
|
+
if (this.queryClient) {
|
|
144
|
+
return this.queryClient;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// If initialization is already in progress, wait for it
|
|
148
|
+
if (this.queryClientPromise) {
|
|
149
|
+
return this.queryClientPromise;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Start initialization and cache the promise to prevent concurrent init
|
|
153
|
+
this.queryClientPromise = (async () => {
|
|
154
|
+
// Capture reference to detect if superseded by disconnect/config change
|
|
155
|
+
const thisInitPromise = this.queryClientPromise;
|
|
94
156
|
try {
|
|
95
157
|
// Use liftedinit ClientFactory which includes cosmos + liftedinit modules
|
|
96
|
-
|
|
158
|
+
const client = await liftedinit.ClientFactory.createRPCQueryClient({
|
|
97
159
|
rpcEndpoint: this.config.rpcUrl,
|
|
98
160
|
});
|
|
161
|
+
// Only store if this is still the active promise
|
|
162
|
+
if (this.queryClientPromise === thisInitPromise) {
|
|
163
|
+
this.queryClient = client;
|
|
164
|
+
this.queryClientPromise = null;
|
|
165
|
+
}
|
|
166
|
+
return client;
|
|
99
167
|
} catch (error) {
|
|
168
|
+
// Clear promise on failure so retry is possible (only if still active)
|
|
169
|
+
if (this.queryClientPromise === thisInitPromise) {
|
|
170
|
+
this.queryClientPromise = null;
|
|
171
|
+
}
|
|
100
172
|
throw new ManifestMCPError(
|
|
101
173
|
ManifestMCPErrorCode.RPC_CONNECTION_FAILED,
|
|
102
174
|
`Failed to connect to RPC endpoint: ${error instanceof Error ? error.message : String(error)}`,
|
|
103
175
|
{ rpcUrl: this.config.rpcUrl }
|
|
104
176
|
);
|
|
105
177
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
178
|
+
})();
|
|
179
|
+
|
|
180
|
+
return this.queryClientPromise;
|
|
108
181
|
}
|
|
109
182
|
|
|
110
183
|
/**
|
|
111
184
|
* Get a signing client with all Manifest registries (for transactions)
|
|
112
185
|
*/
|
|
113
186
|
async getSigningClient(): Promise<SigningStargateClient> {
|
|
114
|
-
if
|
|
187
|
+
// Return cached client if available
|
|
188
|
+
if (this.signingClient) {
|
|
189
|
+
return this.signingClient;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// If initialization is already in progress, wait for it
|
|
193
|
+
if (this.signingClientPromise) {
|
|
194
|
+
return this.signingClientPromise;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Start initialization and cache the promise to prevent concurrent init
|
|
198
|
+
this.signingClientPromise = (async () => {
|
|
199
|
+
// Capture reference to detect if superseded by disconnect/config change
|
|
200
|
+
const thisInitPromise = this.signingClientPromise;
|
|
115
201
|
try {
|
|
116
202
|
const signer = await this.walletProvider.getSigner();
|
|
117
203
|
const gasPrice = GasPrice.fromString(this.config.gasPrice);
|
|
@@ -126,7 +212,7 @@ export class CosmosClientManager {
|
|
|
126
212
|
// Note: Registry type from @cosmjs/proto-signing doesn't perfectly match
|
|
127
213
|
// SigningStargateClientOptions due to telescope-generated proto types.
|
|
128
214
|
// This is a known limitation with custom cosmos-sdk module registries.
|
|
129
|
-
|
|
215
|
+
const client = await SigningStargateClient.connectWithSigner(
|
|
130
216
|
endpoint,
|
|
131
217
|
signer,
|
|
132
218
|
{
|
|
@@ -137,7 +223,20 @@ export class CosmosClientManager {
|
|
|
137
223
|
broadcastPollIntervalMs: DEFAULT_BROADCAST_POLL_INTERVAL_MS,
|
|
138
224
|
}
|
|
139
225
|
);
|
|
226
|
+
// Only store if this is still the active promise
|
|
227
|
+
if (this.signingClientPromise === thisInitPromise) {
|
|
228
|
+
this.signingClient = client;
|
|
229
|
+
this.signingClientPromise = null;
|
|
230
|
+
} else {
|
|
231
|
+
// Promise was superseded, clean up the client we just created
|
|
232
|
+
client.disconnect();
|
|
233
|
+
}
|
|
234
|
+
return client;
|
|
140
235
|
} catch (error) {
|
|
236
|
+
// Clear promise on failure so retry is possible (only if still active)
|
|
237
|
+
if (this.signingClientPromise === thisInitPromise) {
|
|
238
|
+
this.signingClientPromise = null;
|
|
239
|
+
}
|
|
141
240
|
if (error instanceof ManifestMCPError) {
|
|
142
241
|
throw error;
|
|
143
242
|
}
|
|
@@ -147,8 +246,9 @@ export class CosmosClientManager {
|
|
|
147
246
|
{ rpcUrl: this.config.rpcUrl }
|
|
148
247
|
);
|
|
149
248
|
}
|
|
150
|
-
}
|
|
151
|
-
|
|
249
|
+
})();
|
|
250
|
+
|
|
251
|
+
return this.signingClientPromise;
|
|
152
252
|
}
|
|
153
253
|
|
|
154
254
|
/**
|
|
@@ -165,6 +265,14 @@ export class CosmosClientManager {
|
|
|
165
265
|
return this.config;
|
|
166
266
|
}
|
|
167
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Acquire a rate limit token before making an RPC request.
|
|
270
|
+
* This will wait if the rate limit has been exceeded.
|
|
271
|
+
*/
|
|
272
|
+
async acquireRateLimit(): Promise<void> {
|
|
273
|
+
await this.rateLimiter.removeTokens(1);
|
|
274
|
+
}
|
|
275
|
+
|
|
168
276
|
/**
|
|
169
277
|
* Disconnect all clients
|
|
170
278
|
*/
|
|
@@ -173,6 +281,8 @@ export class CosmosClientManager {
|
|
|
173
281
|
this.signingClient.disconnect();
|
|
174
282
|
this.signingClient = null;
|
|
175
283
|
}
|
|
284
|
+
this.signingClientPromise = null;
|
|
176
285
|
this.queryClient = null;
|
|
286
|
+
this.queryClientPromise = null;
|
|
177
287
|
}
|
|
178
288
|
}
|
package/src/config.test.ts
CHANGED
|
@@ -29,6 +29,28 @@ describe('createConfig', () => {
|
|
|
29
29
|
expect(config.gasAdjustment).toBe(2.0);
|
|
30
30
|
expect(config.addressPrefix).toBe('custom');
|
|
31
31
|
});
|
|
32
|
+
|
|
33
|
+
it('should apply default rateLimit', () => {
|
|
34
|
+
const config = createConfig({
|
|
35
|
+
chainId: 'test-chain',
|
|
36
|
+
rpcUrl: 'https://example.com',
|
|
37
|
+
gasPrice: '1.0umfx',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(config.rateLimit).toBeDefined();
|
|
41
|
+
expect(config.rateLimit?.requestsPerSecond).toBe(10);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should preserve provided rateLimit', () => {
|
|
45
|
+
const config = createConfig({
|
|
46
|
+
chainId: 'test-chain',
|
|
47
|
+
rpcUrl: 'https://example.com',
|
|
48
|
+
gasPrice: '1.0umfx',
|
|
49
|
+
rateLimit: { requestsPerSecond: 20 },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(config.rateLimit?.requestsPerSecond).toBe(20);
|
|
53
|
+
});
|
|
32
54
|
});
|
|
33
55
|
|
|
34
56
|
describe('validateConfig', () => {
|
|
@@ -108,6 +130,140 @@ describe('validateConfig', () => {
|
|
|
108
130
|
expect(result.valid).toBe(false);
|
|
109
131
|
expect(result.errors.some(e => e.includes('addressPrefix'))).toBe(true);
|
|
110
132
|
});
|
|
133
|
+
|
|
134
|
+
it('should accept HTTPS URLs', () => {
|
|
135
|
+
const result = validateConfig({
|
|
136
|
+
chainId: 'test',
|
|
137
|
+
rpcUrl: 'https://rpc.example.com',
|
|
138
|
+
gasPrice: '1.0umfx',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
expect(result.valid).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should accept HTTP URLs for localhost', () => {
|
|
145
|
+
const result = validateConfig({
|
|
146
|
+
chainId: 'test',
|
|
147
|
+
rpcUrl: 'http://localhost:26657',
|
|
148
|
+
gasPrice: '1.0umfx',
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(result.valid).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should accept HTTP URLs for 127.0.0.1', () => {
|
|
155
|
+
const result = validateConfig({
|
|
156
|
+
chainId: 'test',
|
|
157
|
+
rpcUrl: 'http://127.0.0.1:26657',
|
|
158
|
+
gasPrice: '1.0umfx',
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(result.valid).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should accept HTTP URLs for IPv6 localhost', () => {
|
|
165
|
+
const result = validateConfig({
|
|
166
|
+
chainId: 'test',
|
|
167
|
+
rpcUrl: 'http://[::1]:26657',
|
|
168
|
+
gasPrice: '1.0umfx',
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(result.valid).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should reject HTTP URLs for non-localhost', () => {
|
|
175
|
+
const result = validateConfig({
|
|
176
|
+
chainId: 'test',
|
|
177
|
+
rpcUrl: 'http://rpc.example.com',
|
|
178
|
+
gasPrice: '1.0umfx',
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(result.valid).toBe(false);
|
|
182
|
+
expect(result.errors.some(e => e.includes('HTTPS'))).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should accept valid rateLimit config', () => {
|
|
186
|
+
const result = validateConfig({
|
|
187
|
+
chainId: 'test',
|
|
188
|
+
rpcUrl: 'https://example.com',
|
|
189
|
+
gasPrice: '1.0umfx',
|
|
190
|
+
rateLimit: { requestsPerSecond: 5 },
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(result.valid).toBe(true);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should reject non-integer rateLimit.requestsPerSecond', () => {
|
|
197
|
+
const result = validateConfig({
|
|
198
|
+
chainId: 'test',
|
|
199
|
+
rpcUrl: 'https://example.com',
|
|
200
|
+
gasPrice: '1.0umfx',
|
|
201
|
+
rateLimit: { requestsPerSecond: 5.5 },
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(result.valid).toBe(false);
|
|
205
|
+
expect(result.errors.some(e => e.includes('requestsPerSecond'))).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should reject negative rateLimit.requestsPerSecond', () => {
|
|
209
|
+
const result = validateConfig({
|
|
210
|
+
chainId: 'test',
|
|
211
|
+
rpcUrl: 'https://example.com',
|
|
212
|
+
gasPrice: '1.0umfx',
|
|
213
|
+
rateLimit: { requestsPerSecond: -1 },
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(result.valid).toBe(false);
|
|
217
|
+
expect(result.errors.some(e => e.includes('requestsPerSecond'))).toBe(true);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should reject zero rateLimit.requestsPerSecond', () => {
|
|
221
|
+
const result = validateConfig({
|
|
222
|
+
chainId: 'test',
|
|
223
|
+
rpcUrl: 'https://example.com',
|
|
224
|
+
gasPrice: '1.0umfx',
|
|
225
|
+
rateLimit: { requestsPerSecond: 0 },
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
expect(result.valid).toBe(false);
|
|
229
|
+
expect(result.errors.some(e => e.includes('requestsPerSecond'))).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should reject null rateLimit', () => {
|
|
233
|
+
const result = validateConfig({
|
|
234
|
+
chainId: 'test',
|
|
235
|
+
rpcUrl: 'https://example.com',
|
|
236
|
+
gasPrice: '1.0umfx',
|
|
237
|
+
rateLimit: null as unknown as { requestsPerSecond?: number },
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
expect(result.valid).toBe(false);
|
|
241
|
+
expect(result.errors.some(e => e.includes('rateLimit must be a plain object'))).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('should reject non-object rateLimit', () => {
|
|
245
|
+
const result = validateConfig({
|
|
246
|
+
chainId: 'test',
|
|
247
|
+
rpcUrl: 'https://example.com',
|
|
248
|
+
gasPrice: '1.0umfx',
|
|
249
|
+
rateLimit: 'invalid' as unknown as { requestsPerSecond?: number },
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
expect(result.valid).toBe(false);
|
|
253
|
+
expect(result.errors.some(e => e.includes('rateLimit must be a plain object'))).toBe(true);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should reject array rateLimit', () => {
|
|
257
|
+
const result = validateConfig({
|
|
258
|
+
chainId: 'test',
|
|
259
|
+
rpcUrl: 'https://example.com',
|
|
260
|
+
gasPrice: '1.0umfx',
|
|
261
|
+
rateLimit: [] as unknown as { requestsPerSecond?: number },
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
expect(result.valid).toBe(false);
|
|
265
|
+
expect(result.errors.some(e => e.includes('rateLimit must be a plain object'))).toBe(true);
|
|
266
|
+
});
|
|
111
267
|
});
|
|
112
268
|
|
|
113
269
|
describe('createValidatedConfig', () => {
|
package/src/config.ts
CHANGED
|
@@ -11,15 +11,47 @@ const DEFAULT_GAS_ADJUSTMENT = 1.3;
|
|
|
11
11
|
const DEFAULT_ADDRESS_PREFIX = 'manifest';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Default requests per second for rate limiting
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export const DEFAULT_REQUESTS_PER_SECOND = 10;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Check if a hostname is localhost (IPv4, IPv6, or hostname)
|
|
20
|
+
* Handles both bracketed and unbracketed IPv6 formats
|
|
21
|
+
*/
|
|
22
|
+
function isLocalhostHostname(hostname: string): boolean {
|
|
23
|
+
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
|
19
24
|
return true;
|
|
25
|
+
}
|
|
26
|
+
// Handle IPv6 localhost - hostname may be '::1' or '[::1]' depending on environment
|
|
27
|
+
const normalizedHostname = hostname.replace(/^\[|\]$/g, '');
|
|
28
|
+
return normalizedHostname === '::1';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validate URL format and check if it uses HTTPS or is localhost (HTTP allowed for local dev)
|
|
33
|
+
* Returns validation result with error reason if invalid
|
|
34
|
+
*/
|
|
35
|
+
function validateRpcUrl(url: string): { valid: boolean; reason?: string } {
|
|
36
|
+
let parsed: URL;
|
|
37
|
+
try {
|
|
38
|
+
parsed = new URL(url);
|
|
20
39
|
} catch {
|
|
21
|
-
return false;
|
|
40
|
+
return { valid: false, reason: 'rpcUrl must be a valid URL' };
|
|
22
41
|
}
|
|
42
|
+
|
|
43
|
+
if (parsed.protocol === 'https:') {
|
|
44
|
+
return { valid: true };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (parsed.protocol === 'http:' && isLocalhostHostname(parsed.hostname)) {
|
|
48
|
+
return { valid: true }; // HTTP allowed for localhost
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
valid: false,
|
|
53
|
+
reason: `RPC URL must use HTTPS (got ${parsed.protocol}//). HTTP is only allowed for local development (localhost, 127.0.0.1, ::1).`,
|
|
54
|
+
};
|
|
23
55
|
}
|
|
24
56
|
|
|
25
57
|
/**
|
|
@@ -48,6 +80,9 @@ export function createConfig(input: ManifestMCPConfig): ManifestMCPConfig {
|
|
|
48
80
|
gasPrice: input.gasPrice,
|
|
49
81
|
gasAdjustment: input.gasAdjustment ?? DEFAULT_GAS_ADJUSTMENT,
|
|
50
82
|
addressPrefix: input.addressPrefix ?? DEFAULT_ADDRESS_PREFIX,
|
|
83
|
+
rateLimit: {
|
|
84
|
+
requestsPerSecond: input.rateLimit?.requestsPerSecond ?? DEFAULT_REQUESTS_PER_SECOND,
|
|
85
|
+
},
|
|
51
86
|
};
|
|
52
87
|
}
|
|
53
88
|
|
|
@@ -74,8 +109,11 @@ export function validateConfig(config: Partial<ManifestMCPConfig>): ValidationRe
|
|
|
74
109
|
|
|
75
110
|
if (!config.rpcUrl) {
|
|
76
111
|
errors.push('rpcUrl is required');
|
|
77
|
-
} else
|
|
78
|
-
|
|
112
|
+
} else {
|
|
113
|
+
const urlCheck = validateRpcUrl(config.rpcUrl);
|
|
114
|
+
if (!urlCheck.valid) {
|
|
115
|
+
errors.push(urlCheck.reason!);
|
|
116
|
+
}
|
|
79
117
|
}
|
|
80
118
|
|
|
81
119
|
if (!config.gasPrice) {
|
|
@@ -97,6 +135,20 @@ export function validateConfig(config: Partial<ManifestMCPConfig>): ValidationRe
|
|
|
97
135
|
}
|
|
98
136
|
}
|
|
99
137
|
|
|
138
|
+
if (config.rateLimit !== undefined) {
|
|
139
|
+
if (typeof config.rateLimit !== 'object' || config.rateLimit === null || Array.isArray(config.rateLimit)) {
|
|
140
|
+
errors.push('rateLimit must be a plain object');
|
|
141
|
+
} else if (config.rateLimit.requestsPerSecond !== undefined) {
|
|
142
|
+
if (
|
|
143
|
+
typeof config.rateLimit.requestsPerSecond !== 'number' ||
|
|
144
|
+
config.rateLimit.requestsPerSecond <= 0 ||
|
|
145
|
+
!Number.isInteger(config.rateLimit.requestsPerSecond)
|
|
146
|
+
) {
|
|
147
|
+
errors.push('rateLimit.requestsPerSecond must be a positive integer');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
100
152
|
return {
|
|
101
153
|
valid: errors.length === 0,
|
|
102
154
|
errors,
|