@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/src/queries/gov.ts
CHANGED
|
@@ -1,46 +1,54 @@
|
|
|
1
1
|
import { ManifestQueryClient } from '../client.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
ProposalResult, ProposalsResult, VoteResult, VotesResult,
|
|
4
|
+
DepositResult, DepositsResult, TallyResult, GovParamsResult
|
|
5
|
+
} from '../types.js';
|
|
6
|
+
import { parseBigInt, parseInteger, requireArgs, extractPaginationArgs } from './utils.js';
|
|
7
|
+
import { throwUnsupportedSubcommand } from '../modules.js';
|
|
8
|
+
|
|
9
|
+
/** Gov query result union type */
|
|
10
|
+
type GovQueryResult =
|
|
11
|
+
| ProposalResult
|
|
12
|
+
| ProposalsResult
|
|
13
|
+
| VoteResult
|
|
14
|
+
| VotesResult
|
|
15
|
+
| DepositResult
|
|
16
|
+
| DepositsResult
|
|
17
|
+
| TallyResult
|
|
18
|
+
| GovParamsResult;
|
|
4
19
|
|
|
5
20
|
/**
|
|
6
21
|
* Route gov query to manifestjs query client
|
|
22
|
+
*
|
|
23
|
+
* Paginated queries support --limit flag (default: 100, max: 1000)
|
|
7
24
|
*/
|
|
8
25
|
export async function routeGovQuery(
|
|
9
26
|
queryClient: ManifestQueryClient,
|
|
10
27
|
subcommand: string,
|
|
11
28
|
args: string[]
|
|
12
|
-
): Promise<
|
|
29
|
+
): Promise<GovQueryResult> {
|
|
13
30
|
const gov = queryClient.cosmos.gov.v1;
|
|
14
31
|
|
|
15
32
|
switch (subcommand) {
|
|
16
33
|
case 'proposal': {
|
|
17
|
-
|
|
18
|
-
throw new ManifestMCPError(
|
|
19
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
20
|
-
'proposal requires proposal-id argument'
|
|
21
|
-
);
|
|
22
|
-
}
|
|
34
|
+
requireArgs(args, 1, ['proposal-id'], 'gov proposal');
|
|
23
35
|
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
24
36
|
const result = await gov.proposal({ proposalId });
|
|
25
37
|
return { proposal: result.proposal };
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
case 'proposals': {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
41
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'gov proposals');
|
|
42
|
+
// All optional: status filter, voter, depositor
|
|
43
|
+
const proposalStatus = remainingArgs[0] ? parseInteger(remainingArgs[0], 'status') : 0;
|
|
44
|
+
const voter = remainingArgs[1] || '';
|
|
45
|
+
const depositor = remainingArgs[2] || '';
|
|
46
|
+
const result = await gov.proposals({ proposalStatus, voter, depositor, pagination });
|
|
34
47
|
return { proposals: result.proposals, pagination: result.pagination };
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
case 'vote': {
|
|
38
|
-
|
|
39
|
-
throw new ManifestMCPError(
|
|
40
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
41
|
-
'vote requires proposal-id and voter-address arguments'
|
|
42
|
-
);
|
|
43
|
-
}
|
|
51
|
+
requireArgs(args, 2, ['proposal-id', 'voter-address'], 'gov vote');
|
|
44
52
|
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
45
53
|
const voter = args[1];
|
|
46
54
|
const result = await gov.vote({ proposalId, voter });
|
|
@@ -48,24 +56,15 @@ export async function routeGovQuery(
|
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
case 'votes': {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
58
|
-
const result = await gov.votes({ proposalId, pagination: defaultPagination });
|
|
59
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'gov votes');
|
|
60
|
+
requireArgs(remainingArgs, 1, ['proposal-id'], 'gov votes');
|
|
61
|
+
const proposalId = parseBigInt(remainingArgs[0], 'proposal-id');
|
|
62
|
+
const result = await gov.votes({ proposalId, pagination });
|
|
59
63
|
return { votes: result.votes, pagination: result.pagination };
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
case 'deposit': {
|
|
63
|
-
|
|
64
|
-
throw new ManifestMCPError(
|
|
65
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
66
|
-
'deposit requires proposal-id and depositor-address arguments'
|
|
67
|
-
);
|
|
68
|
-
}
|
|
67
|
+
requireArgs(args, 2, ['proposal-id', 'depositor-address'], 'gov deposit');
|
|
69
68
|
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
70
69
|
const depositor = args[1];
|
|
71
70
|
const result = await gov.deposit({ proposalId, depositor });
|
|
@@ -73,30 +72,22 @@ export async function routeGovQuery(
|
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
case 'deposits': {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
83
|
-
const result = await gov.deposits({ proposalId, pagination: defaultPagination });
|
|
75
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'gov deposits');
|
|
76
|
+
requireArgs(remainingArgs, 1, ['proposal-id'], 'gov deposits');
|
|
77
|
+
const proposalId = parseBigInt(remainingArgs[0], 'proposal-id');
|
|
78
|
+
const result = await gov.deposits({ proposalId, pagination });
|
|
84
79
|
return { deposits: result.deposits, pagination: result.pagination };
|
|
85
80
|
}
|
|
86
81
|
|
|
87
82
|
case 'tally': {
|
|
88
|
-
|
|
89
|
-
throw new ManifestMCPError(
|
|
90
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
91
|
-
'tally requires proposal-id argument'
|
|
92
|
-
);
|
|
93
|
-
}
|
|
83
|
+
requireArgs(args, 1, ['proposal-id'], 'gov tally');
|
|
94
84
|
const proposalId = parseBigInt(args[0], 'proposal-id');
|
|
95
85
|
const result = await gov.tallyResult({ proposalId });
|
|
96
86
|
return { tally: result.tally };
|
|
97
87
|
}
|
|
98
88
|
|
|
99
89
|
case 'params': {
|
|
90
|
+
// Optional: params type (defaults to 'tallying')
|
|
100
91
|
const paramsType = args[0] || 'tallying';
|
|
101
92
|
const result = await gov.params({ paramsType });
|
|
102
93
|
return {
|
|
@@ -108,21 +99,6 @@ export async function routeGovQuery(
|
|
|
108
99
|
}
|
|
109
100
|
|
|
110
101
|
default:
|
|
111
|
-
|
|
112
|
-
ManifestMCPErrorCode.UNSUPPORTED_QUERY,
|
|
113
|
-
`Unsupported gov query subcommand: ${subcommand}`,
|
|
114
|
-
{
|
|
115
|
-
availableSubcommands: [
|
|
116
|
-
'proposal',
|
|
117
|
-
'proposals',
|
|
118
|
-
'vote',
|
|
119
|
-
'votes',
|
|
120
|
-
'deposit',
|
|
121
|
-
'deposits',
|
|
122
|
-
'tally',
|
|
123
|
-
'params',
|
|
124
|
-
],
|
|
125
|
-
}
|
|
126
|
-
);
|
|
102
|
+
throwUnsupportedSubcommand('query', 'gov', subcommand);
|
|
127
103
|
}
|
|
128
104
|
}
|
package/src/queries/index.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
parseBigInt,
|
|
3
|
+
parseInteger,
|
|
4
|
+
createPagination,
|
|
5
|
+
extractPaginationArgs,
|
|
6
|
+
DEFAULT_PAGE_LIMIT,
|
|
7
|
+
MAX_PAGE_LIMIT,
|
|
8
|
+
defaultPagination,
|
|
9
|
+
} from './utils.js';
|
|
10
|
+
export type { PaginationConfig } from './utils.js';
|
|
2
11
|
export { routeBankQuery } from './bank.js';
|
|
3
12
|
export { routeStakingQuery } from './staking.js';
|
|
4
13
|
export { routeDistributionQuery } from './distribution.js';
|
package/src/queries/staking.ts
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
import { ManifestQueryClient } from '../client.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
DelegationResult, DelegationsResult, UnbondingDelegationResult, UnbondingDelegationsResult,
|
|
4
|
+
RedelegationsResult, ValidatorResult, ValidatorsResult, StakingPoolResult,
|
|
5
|
+
StakingParamsResult, HistoricalInfoResult
|
|
6
|
+
} from '../types.js';
|
|
7
|
+
import { parseBigInt, requireArgs, extractPaginationArgs } from './utils.js';
|
|
8
|
+
import { throwUnsupportedSubcommand } from '../modules.js';
|
|
9
|
+
|
|
10
|
+
/** Staking query result union type */
|
|
11
|
+
type StakingQueryResult =
|
|
12
|
+
| DelegationResult
|
|
13
|
+
| DelegationsResult
|
|
14
|
+
| UnbondingDelegationResult
|
|
15
|
+
| UnbondingDelegationsResult
|
|
16
|
+
| RedelegationsResult
|
|
17
|
+
| ValidatorResult
|
|
18
|
+
| ValidatorsResult
|
|
19
|
+
| StakingPoolResult
|
|
20
|
+
| StakingParamsResult
|
|
21
|
+
| HistoricalInfoResult;
|
|
4
22
|
|
|
5
23
|
/**
|
|
6
24
|
* Route staking query to manifestjs query client
|
|
25
|
+
*
|
|
26
|
+
* Paginated queries support --limit flag (default: 100, max: 1000)
|
|
7
27
|
*/
|
|
8
28
|
export async function routeStakingQuery(
|
|
9
29
|
queryClient: ManifestQueryClient,
|
|
10
30
|
subcommand: string,
|
|
11
31
|
args: string[]
|
|
12
|
-
): Promise<
|
|
32
|
+
): Promise<StakingQueryResult> {
|
|
13
33
|
const staking = queryClient.cosmos.staking.v1beta1;
|
|
14
34
|
|
|
15
35
|
switch (subcommand) {
|
|
16
36
|
case 'delegation': {
|
|
17
|
-
|
|
18
|
-
throw new ManifestMCPError(
|
|
19
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
20
|
-
'delegation requires delegator-address and validator-address arguments'
|
|
21
|
-
);
|
|
22
|
-
}
|
|
37
|
+
requireArgs(args, 2, ['delegator-address', 'validator-address'], 'staking delegation');
|
|
23
38
|
const [delegatorAddr, validatorAddr] = args;
|
|
24
39
|
const result = await staking.delegation({
|
|
25
40
|
delegatorAddr,
|
|
@@ -29,14 +44,10 @@ export async function routeStakingQuery(
|
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
case 'delegations': {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
const [delegatorAddr] = args;
|
|
39
|
-
const result = await staking.delegatorDelegations({ delegatorAddr, pagination: defaultPagination });
|
|
47
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking delegations');
|
|
48
|
+
requireArgs(remainingArgs, 1, ['delegator-address'], 'staking delegations');
|
|
49
|
+
const [delegatorAddr] = remainingArgs;
|
|
50
|
+
const result = await staking.delegatorDelegations({ delegatorAddr, pagination });
|
|
40
51
|
return {
|
|
41
52
|
delegationResponses: result.delegationResponses,
|
|
42
53
|
pagination: result.pagination,
|
|
@@ -44,12 +55,7 @@ export async function routeStakingQuery(
|
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
case 'unbonding-delegation': {
|
|
47
|
-
|
|
48
|
-
throw new ManifestMCPError(
|
|
49
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
50
|
-
'unbonding-delegation requires delegator-address and validator-address arguments'
|
|
51
|
-
);
|
|
52
|
-
}
|
|
58
|
+
requireArgs(args, 2, ['delegator-address', 'validator-address'], 'staking unbonding-delegation');
|
|
53
59
|
const [delegatorAddr, validatorAddr] = args;
|
|
54
60
|
const result = await staking.unbondingDelegation({
|
|
55
61
|
delegatorAddr,
|
|
@@ -59,14 +65,10 @@ export async function routeStakingQuery(
|
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
case 'unbonding-delegations': {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
const [delegatorAddr] = args;
|
|
69
|
-
const result = await staking.delegatorUnbondingDelegations({ delegatorAddr, pagination: defaultPagination });
|
|
68
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking unbonding-delegations');
|
|
69
|
+
requireArgs(remainingArgs, 1, ['delegator-address'], 'staking unbonding-delegations');
|
|
70
|
+
const [delegatorAddr] = remainingArgs;
|
|
71
|
+
const result = await staking.delegatorUnbondingDelegations({ delegatorAddr, pagination });
|
|
70
72
|
return {
|
|
71
73
|
unbondingResponses: result.unbondingResponses,
|
|
72
74
|
pagination: result.pagination,
|
|
@@ -74,20 +76,17 @@ export async function routeStakingQuery(
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
case 'redelegations': {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const [delegatorAddr] = args;
|
|
84
|
-
const srcValidatorAddr = args[1] || '';
|
|
85
|
-
const dstValidatorAddr = args[2] || '';
|
|
79
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking redelegations');
|
|
80
|
+
requireArgs(remainingArgs, 1, ['delegator-address'], 'staking redelegations');
|
|
81
|
+
const [delegatorAddr] = remainingArgs;
|
|
82
|
+
// Optional: src and dst validator addresses for filtering
|
|
83
|
+
const srcValidatorAddr = remainingArgs[1] || '';
|
|
84
|
+
const dstValidatorAddr = remainingArgs[2] || '';
|
|
86
85
|
const result = await staking.redelegations({
|
|
87
86
|
delegatorAddr,
|
|
88
87
|
srcValidatorAddr,
|
|
89
88
|
dstValidatorAddr,
|
|
90
|
-
pagination
|
|
89
|
+
pagination,
|
|
91
90
|
});
|
|
92
91
|
return {
|
|
93
92
|
redelegationResponses: result.redelegationResponses,
|
|
@@ -96,32 +95,25 @@ export async function routeStakingQuery(
|
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
case 'validator': {
|
|
99
|
-
|
|
100
|
-
throw new ManifestMCPError(
|
|
101
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
102
|
-
'validator requires validator-address argument'
|
|
103
|
-
);
|
|
104
|
-
}
|
|
98
|
+
requireArgs(args, 1, ['validator-address'], 'staking validator');
|
|
105
99
|
const [validatorAddr] = args;
|
|
106
100
|
const result = await staking.validator({ validatorAddr });
|
|
107
101
|
return { validator: result.validator };
|
|
108
102
|
}
|
|
109
103
|
|
|
110
104
|
case 'validators': {
|
|
111
|
-
const
|
|
112
|
-
|
|
105
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking validators');
|
|
106
|
+
// Optional: status filter
|
|
107
|
+
const status = remainingArgs[0] || '';
|
|
108
|
+
const result = await staking.validators({ status, pagination });
|
|
113
109
|
return { validators: result.validators, pagination: result.pagination };
|
|
114
110
|
}
|
|
115
111
|
|
|
116
112
|
case 'validator-delegations': {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
const [validatorAddr] = args;
|
|
124
|
-
const result = await staking.validatorDelegations({ validatorAddr, pagination: defaultPagination });
|
|
113
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking validator-delegations');
|
|
114
|
+
requireArgs(remainingArgs, 1, ['validator-address'], 'staking validator-delegations');
|
|
115
|
+
const [validatorAddr] = remainingArgs;
|
|
116
|
+
const result = await staking.validatorDelegations({ validatorAddr, pagination });
|
|
125
117
|
return {
|
|
126
118
|
delegationResponses: result.delegationResponses,
|
|
127
119
|
pagination: result.pagination,
|
|
@@ -129,14 +121,10 @@ export async function routeStakingQuery(
|
|
|
129
121
|
}
|
|
130
122
|
|
|
131
123
|
case 'validator-unbonding-delegations': {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
const [validatorAddr] = args;
|
|
139
|
-
const result = await staking.validatorUnbondingDelegations({ validatorAddr, pagination: defaultPagination });
|
|
124
|
+
const { pagination, remainingArgs } = extractPaginationArgs(args, 'staking validator-unbonding-delegations');
|
|
125
|
+
requireArgs(remainingArgs, 1, ['validator-address'], 'staking validator-unbonding-delegations');
|
|
126
|
+
const [validatorAddr] = remainingArgs;
|
|
127
|
+
const result = await staking.validatorUnbondingDelegations({ validatorAddr, pagination });
|
|
140
128
|
return {
|
|
141
129
|
unbondingResponses: result.unbondingResponses,
|
|
142
130
|
pagination: result.pagination,
|
|
@@ -154,37 +142,13 @@ export async function routeStakingQuery(
|
|
|
154
142
|
}
|
|
155
143
|
|
|
156
144
|
case 'historical-info': {
|
|
157
|
-
|
|
158
|
-
throw new ManifestMCPError(
|
|
159
|
-
ManifestMCPErrorCode.QUERY_FAILED,
|
|
160
|
-
'historical-info requires height argument'
|
|
161
|
-
);
|
|
162
|
-
}
|
|
145
|
+
requireArgs(args, 1, ['height'], 'staking historical-info');
|
|
163
146
|
const height = parseBigInt(args[0], 'height');
|
|
164
147
|
const result = await staking.historicalInfo({ height });
|
|
165
148
|
return { hist: result.hist };
|
|
166
149
|
}
|
|
167
150
|
|
|
168
151
|
default:
|
|
169
|
-
|
|
170
|
-
ManifestMCPErrorCode.UNSUPPORTED_QUERY,
|
|
171
|
-
`Unsupported staking query subcommand: ${subcommand}`,
|
|
172
|
-
{
|
|
173
|
-
availableSubcommands: [
|
|
174
|
-
'delegation',
|
|
175
|
-
'delegations',
|
|
176
|
-
'unbonding-delegation',
|
|
177
|
-
'unbonding-delegations',
|
|
178
|
-
'redelegations',
|
|
179
|
-
'validator',
|
|
180
|
-
'validators',
|
|
181
|
-
'validator-delegations',
|
|
182
|
-
'validator-unbonding-delegations',
|
|
183
|
-
'pool',
|
|
184
|
-
'params',
|
|
185
|
-
'historical-info',
|
|
186
|
-
],
|
|
187
|
-
}
|
|
188
|
-
);
|
|
152
|
+
throwUnsupportedSubcommand('query', 'staking', subcommand);
|
|
189
153
|
}
|
|
190
154
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
parseBigInt,
|
|
4
|
+
parseInteger,
|
|
5
|
+
createPagination,
|
|
6
|
+
extractPaginationArgs,
|
|
7
|
+
DEFAULT_PAGE_LIMIT,
|
|
8
|
+
MAX_PAGE_LIMIT,
|
|
9
|
+
} from './utils.js';
|
|
3
10
|
import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
|
|
4
11
|
|
|
5
12
|
describe('parseBigInt', () => {
|
|
@@ -38,24 +45,112 @@ describe('parseBigInt', () => {
|
|
|
38
45
|
});
|
|
39
46
|
});
|
|
40
47
|
|
|
41
|
-
describe('
|
|
48
|
+
describe('parseInteger', () => {
|
|
42
49
|
it('should parse valid integer strings', () => {
|
|
43
|
-
expect(
|
|
44
|
-
expect(
|
|
45
|
-
expect(
|
|
50
|
+
expect(parseInteger('0', 'status')).toBe(0);
|
|
51
|
+
expect(parseInteger('123', 'status')).toBe(123);
|
|
52
|
+
expect(parseInteger('-5', 'status')).toBe(-5);
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
it('should throw ManifestMCPError for invalid integers', () => {
|
|
49
|
-
expect(() =>
|
|
50
|
-
expect(() =>
|
|
56
|
+
expect(() => parseInteger('', 'status')).toThrow(ManifestMCPError);
|
|
57
|
+
expect(() => parseInteger('abc', 'status')).toThrow(ManifestMCPError);
|
|
51
58
|
});
|
|
52
59
|
|
|
53
60
|
it('should have correct error code', () => {
|
|
54
61
|
try {
|
|
55
|
-
|
|
62
|
+
parseInteger('invalid', 'status');
|
|
56
63
|
} catch (error) {
|
|
57
64
|
expect(error).toBeInstanceOf(ManifestMCPError);
|
|
58
65
|
expect((error as ManifestMCPError).code).toBe(ManifestMCPErrorCode.QUERY_FAILED);
|
|
59
66
|
}
|
|
60
67
|
});
|
|
61
68
|
});
|
|
69
|
+
|
|
70
|
+
describe('createPagination', () => {
|
|
71
|
+
it('should use default limit when none provided', () => {
|
|
72
|
+
const pagination = createPagination();
|
|
73
|
+
expect(pagination.limit).toBe(DEFAULT_PAGE_LIMIT);
|
|
74
|
+
expect(pagination.offset).toBe(BigInt(0));
|
|
75
|
+
expect(pagination.countTotal).toBe(false);
|
|
76
|
+
expect(pagination.reverse).toBe(false);
|
|
77
|
+
expect(pagination.key).toEqual(new Uint8Array());
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should use provided limit', () => {
|
|
81
|
+
const pagination = createPagination(BigInt(50));
|
|
82
|
+
expect(pagination.limit).toBe(BigInt(50));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should clamp limit to minimum of 1', () => {
|
|
86
|
+
const pagination = createPagination(BigInt(0));
|
|
87
|
+
expect(pagination.limit).toBe(BigInt(1));
|
|
88
|
+
|
|
89
|
+
const paginationNegative = createPagination(BigInt(-10));
|
|
90
|
+
expect(paginationNegative.limit).toBe(BigInt(1));
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should clamp limit to maximum', () => {
|
|
94
|
+
const pagination = createPagination(BigInt(9999));
|
|
95
|
+
expect(pagination.limit).toBe(MAX_PAGE_LIMIT);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('extractPaginationArgs', () => {
|
|
100
|
+
it('should return default pagination when no --limit flag', () => {
|
|
101
|
+
const { pagination, remainingArgs } = extractPaginationArgs(['arg1', 'arg2'], 'test');
|
|
102
|
+
expect(pagination.limit).toBe(DEFAULT_PAGE_LIMIT);
|
|
103
|
+
expect(remainingArgs).toEqual(['arg1', 'arg2']);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should extract --limit flag and value', () => {
|
|
107
|
+
const { pagination, remainingArgs } = extractPaginationArgs(
|
|
108
|
+
['arg1', '--limit', '50', 'arg2'],
|
|
109
|
+
'test'
|
|
110
|
+
);
|
|
111
|
+
expect(pagination.limit).toBe(BigInt(50));
|
|
112
|
+
expect(remainingArgs).toEqual(['arg1', 'arg2']);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should handle --limit at end of args', () => {
|
|
116
|
+
const { pagination, remainingArgs } = extractPaginationArgs(
|
|
117
|
+
['arg1', '--limit', '25'],
|
|
118
|
+
'test'
|
|
119
|
+
);
|
|
120
|
+
expect(pagination.limit).toBe(BigInt(25));
|
|
121
|
+
expect(remainingArgs).toEqual(['arg1']);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should handle --limit at start of args', () => {
|
|
125
|
+
const { pagination, remainingArgs } = extractPaginationArgs(
|
|
126
|
+
['--limit', '75', 'arg1'],
|
|
127
|
+
'test'
|
|
128
|
+
);
|
|
129
|
+
expect(pagination.limit).toBe(BigInt(75));
|
|
130
|
+
expect(remainingArgs).toEqual(['arg1']);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should throw for invalid limit value', () => {
|
|
134
|
+
expect(() =>
|
|
135
|
+
extractPaginationArgs(['--limit', 'abc'], 'test')
|
|
136
|
+
).toThrow(ManifestMCPError);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should throw for limit below minimum', () => {
|
|
140
|
+
expect(() =>
|
|
141
|
+
extractPaginationArgs(['--limit', '0'], 'test')
|
|
142
|
+
).toThrow(ManifestMCPError);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should throw for limit above maximum', () => {
|
|
146
|
+
expect(() =>
|
|
147
|
+
extractPaginationArgs(['--limit', '9999'], 'test')
|
|
148
|
+
).toThrow(ManifestMCPError);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should handle empty args array', () => {
|
|
152
|
+
const { pagination, remainingArgs } = extractPaginationArgs([], 'test');
|
|
153
|
+
expect(pagination.limit).toBe(DEFAULT_PAGE_LIMIT);
|
|
154
|
+
expect(remainingArgs).toEqual([]);
|
|
155
|
+
});
|
|
156
|
+
});
|
package/src/queries/utils.ts
CHANGED
|
@@ -1,20 +1,86 @@
|
|
|
1
1
|
import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
|
|
2
|
-
import { parseBigIntWithCode } from '../transactions/utils.js';
|
|
2
|
+
import { parseBigIntWithCode, requireArgs as requireArgsBase, extractFlag, filterConsumedArgs } from '../transactions/utils.js';
|
|
3
3
|
|
|
4
4
|
/** Default page size limit for paginated queries to prevent resource exhaustion */
|
|
5
5
|
export const DEFAULT_PAGE_LIMIT = BigInt(100);
|
|
6
6
|
|
|
7
|
+
/** Maximum page size limit to prevent DoS */
|
|
8
|
+
export const MAX_PAGE_LIMIT = BigInt(1000);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Cosmos SDK pagination configuration
|
|
12
|
+
*/
|
|
13
|
+
export interface PaginationConfig {
|
|
14
|
+
readonly key: Uint8Array;
|
|
15
|
+
readonly offset: bigint;
|
|
16
|
+
readonly limit: bigint;
|
|
17
|
+
readonly countTotal: boolean;
|
|
18
|
+
readonly reverse: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create pagination configuration with optional custom limit.
|
|
23
|
+
* Validates that limit is within acceptable bounds.
|
|
24
|
+
*
|
|
25
|
+
* @param limit - Optional custom limit (defaults to DEFAULT_PAGE_LIMIT)
|
|
26
|
+
* @returns Cosmos SDK pagination object
|
|
27
|
+
*/
|
|
28
|
+
export function createPagination(limit?: bigint): PaginationConfig {
|
|
29
|
+
let effectiveLimit = limit ?? DEFAULT_PAGE_LIMIT;
|
|
30
|
+
|
|
31
|
+
// Clamp to valid range
|
|
32
|
+
if (effectiveLimit < BigInt(1)) {
|
|
33
|
+
effectiveLimit = BigInt(1);
|
|
34
|
+
} else if (effectiveLimit > MAX_PAGE_LIMIT) {
|
|
35
|
+
effectiveLimit = MAX_PAGE_LIMIT;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
key: new Uint8Array(),
|
|
40
|
+
offset: BigInt(0),
|
|
41
|
+
limit: effectiveLimit,
|
|
42
|
+
countTotal: false,
|
|
43
|
+
reverse: false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
7
47
|
/**
|
|
8
|
-
* Default pagination configuration for queries
|
|
9
|
-
*
|
|
48
|
+
* Default pagination configuration for queries (for backwards compatibility)
|
|
49
|
+
* @deprecated Use createPagination() instead for configurable limits
|
|
10
50
|
*/
|
|
11
|
-
export const defaultPagination =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
51
|
+
export const defaultPagination = createPagination();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract --limit flag from args and return pagination config with remaining args.
|
|
55
|
+
* Use this helper for paginated queries.
|
|
56
|
+
*
|
|
57
|
+
* @param args - The arguments array
|
|
58
|
+
* @param context - Context for error messages
|
|
59
|
+
* @returns Object with pagination config and filtered args
|
|
60
|
+
*/
|
|
61
|
+
export function extractPaginationArgs(
|
|
62
|
+
args: string[],
|
|
63
|
+
context: string
|
|
64
|
+
): { pagination: PaginationConfig; remainingArgs: string[] } {
|
|
65
|
+
const { value: limitStr, consumedIndices } = extractFlag(args, '--limit', context);
|
|
66
|
+
const remainingArgs = filterConsumedArgs(args, consumedIndices);
|
|
67
|
+
|
|
68
|
+
let pagination: PaginationConfig;
|
|
69
|
+
if (limitStr) {
|
|
70
|
+
const limit = parseBigInt(limitStr, 'limit');
|
|
71
|
+
if (limit < BigInt(1) || limit > MAX_PAGE_LIMIT) {
|
|
72
|
+
throw new ManifestMCPError(
|
|
73
|
+
ManifestMCPErrorCode.QUERY_FAILED,
|
|
74
|
+
`Invalid limit: ${limit}. Must be between 1 and ${MAX_PAGE_LIMIT}.`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
pagination = createPagination(limit);
|
|
78
|
+
} else {
|
|
79
|
+
pagination = createPagination();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { pagination, remainingArgs };
|
|
83
|
+
}
|
|
18
84
|
|
|
19
85
|
/**
|
|
20
86
|
* Safely parse a string to BigInt with proper error handling (for queries)
|
|
@@ -24,9 +90,10 @@ export function parseBigInt(value: string, fieldName: string): bigint {
|
|
|
24
90
|
}
|
|
25
91
|
|
|
26
92
|
/**
|
|
27
|
-
* Safely parse a string to integer with proper error handling
|
|
93
|
+
* Safely parse a string to integer with proper error handling.
|
|
94
|
+
* Named parseInteger to avoid shadowing global parseInt.
|
|
28
95
|
*/
|
|
29
|
-
export function
|
|
96
|
+
export function parseInteger(value: string, fieldName: string): number {
|
|
30
97
|
const parsed = Number.parseInt(value, 10);
|
|
31
98
|
if (Number.isNaN(parsed)) {
|
|
32
99
|
throw new ManifestMCPError(
|
|
@@ -36,3 +103,16 @@ export function parseInt(value: string, fieldName: string): number {
|
|
|
36
103
|
}
|
|
37
104
|
return parsed;
|
|
38
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Validate that required arguments are present (for queries).
|
|
109
|
+
* Uses QUERY_FAILED error code by default.
|
|
110
|
+
*/
|
|
111
|
+
export function requireArgs(
|
|
112
|
+
args: string[],
|
|
113
|
+
minCount: number,
|
|
114
|
+
expectedNames: string[],
|
|
115
|
+
context: string
|
|
116
|
+
): void {
|
|
117
|
+
requireArgsBase(args, minCount, expectedNames, context, ManifestMCPErrorCode.QUERY_FAILED);
|
|
118
|
+
}
|