@manifest-network/manifest-mcp-browser 0.1.1 → 0.1.6

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.
Files changed (131) hide show
  1. package/.github/workflows/publish.yml +4 -2
  2. package/CLAUDE.md +11 -6
  3. package/README.md +1 -1
  4. package/dist/client.d.ts +6 -1
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +77 -21
  7. package/dist/client.js.map +1 -1
  8. package/dist/cosmos.d.ts.map +1 -1
  9. package/dist/cosmos.js +7 -57
  10. package/dist/cosmos.js.map +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +16 -25
  13. package/dist/index.js.map +1 -1
  14. package/dist/modules.d.ts +30 -1
  15. package/dist/modules.d.ts.map +1 -1
  16. package/dist/modules.js +98 -1
  17. package/dist/modules.js.map +1 -1
  18. package/dist/modules.test.js +60 -1
  19. package/dist/modules.test.js.map +1 -1
  20. package/dist/queries/auth.d.ts +7 -1
  21. package/dist/queries/auth.d.ts.map +1 -1
  22. package/dist/queries/auth.js +18 -45
  23. package/dist/queries/auth.js.map +1 -1
  24. package/dist/queries/bank.d.ts +7 -1
  25. package/dist/queries/bank.d.ts.map +1 -1
  26. package/dist/queries/bank.js +24 -38
  27. package/dist/queries/bank.js.map +1 -1
  28. package/dist/queries/billing.d.ts +7 -1
  29. package/dist/queries/billing.d.ts.map +1 -1
  30. package/dist/queries/billing.js +28 -54
  31. package/dist/queries/billing.js.map +1 -1
  32. package/dist/queries/distribution.d.ts +7 -1
  33. package/dist/queries/distribution.d.ts.map +1 -1
  34. package/dist/queries/distribution.js +18 -36
  35. package/dist/queries/distribution.js.map +1 -1
  36. package/dist/queries/gov.d.ts +7 -1
  37. package/dist/queries/gov.d.ts.map +1 -1
  38. package/dist/queries/gov.js +24 -41
  39. package/dist/queries/gov.js.map +1 -1
  40. package/dist/queries/index.d.ts +2 -1
  41. package/dist/queries/index.d.ts.map +1 -1
  42. package/dist/queries/index.js +1 -1
  43. package/dist/queries/index.js.map +1 -1
  44. package/dist/queries/sku.d.ts +13 -0
  45. package/dist/queries/sku.d.ts.map +1 -0
  46. package/dist/queries/sku.js +60 -0
  47. package/dist/queries/sku.js.map +1 -0
  48. package/dist/queries/staking.d.ts +7 -1
  49. package/dist/queries/staking.d.ts.map +1 -1
  50. package/dist/queries/staking.js +36 -59
  51. package/dist/queries/staking.js.map +1 -1
  52. package/dist/queries/utils.d.ts +60 -10
  53. package/dist/queries/utils.d.ts.map +1 -1
  54. package/dist/queries/utils.js +80 -12
  55. package/dist/queries/utils.js.map +1 -1
  56. package/dist/queries/utils.test.js +68 -8
  57. package/dist/queries/utils.test.js.map +1 -1
  58. package/dist/transactions/bank.d.ts +2 -2
  59. package/dist/transactions/bank.d.ts.map +1 -1
  60. package/dist/transactions/bank.js +9 -18
  61. package/dist/transactions/bank.js.map +1 -1
  62. package/dist/transactions/billing.d.ts +2 -2
  63. package/dist/transactions/billing.d.ts.map +1 -1
  64. package/dist/transactions/billing.js +125 -89
  65. package/dist/transactions/billing.js.map +1 -1
  66. package/dist/transactions/distribution.d.ts +2 -2
  67. package/dist/transactions/distribution.d.ts.map +1 -1
  68. package/dist/transactions/distribution.js +7 -13
  69. package/dist/transactions/distribution.js.map +1 -1
  70. package/dist/transactions/gov.d.ts +2 -2
  71. package/dist/transactions/gov.d.ts.map +1 -1
  72. package/dist/transactions/gov.js +29 -20
  73. package/dist/transactions/gov.js.map +1 -1
  74. package/dist/transactions/index.d.ts +1 -1
  75. package/dist/transactions/index.d.ts.map +1 -1
  76. package/dist/transactions/index.js +1 -1
  77. package/dist/transactions/index.js.map +1 -1
  78. package/dist/transactions/manifest.d.ts +2 -2
  79. package/dist/transactions/manifest.d.ts.map +1 -1
  80. package/dist/transactions/manifest.js +7 -14
  81. package/dist/transactions/manifest.js.map +1 -1
  82. package/dist/transactions/sku.d.ts +7 -0
  83. package/dist/transactions/sku.d.ts.map +1 -0
  84. package/dist/transactions/sku.js +184 -0
  85. package/dist/transactions/sku.js.map +1 -0
  86. package/dist/transactions/staking.d.ts +2 -2
  87. package/dist/transactions/staking.d.ts.map +1 -1
  88. package/dist/transactions/staking.js +7 -13
  89. package/dist/transactions/staking.js.map +1 -1
  90. package/dist/transactions/utils.d.ts +65 -1
  91. package/dist/transactions/utils.d.ts.map +1 -1
  92. package/dist/transactions/utils.js +123 -2
  93. package/dist/transactions/utils.js.map +1 -1
  94. package/dist/transactions/utils.test.js +351 -1
  95. package/dist/transactions/utils.test.js.map +1 -1
  96. package/dist/types.d.ts +218 -8
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/types.js.map +1 -1
  99. package/dist/wallet/mnemonic.d.ts +1 -0
  100. package/dist/wallet/mnemonic.d.ts.map +1 -1
  101. package/dist/wallet/mnemonic.js +34 -13
  102. package/dist/wallet/mnemonic.js.map +1 -1
  103. package/package.json +5 -1
  104. package/src/client.ts +84 -21
  105. package/src/cosmos.ts +13 -109
  106. package/src/index.ts +17 -23
  107. package/src/modules.test.ts +62 -0
  108. package/src/modules.ts +155 -5
  109. package/src/queries/auth.ts +35 -74
  110. package/src/queries/bank.ts +40 -58
  111. package/src/queries/billing.ts +46 -86
  112. package/src/queries/distribution.ts +35 -59
  113. package/src/queries/gov.ts +40 -64
  114. package/src/queries/index.ts +10 -1
  115. package/src/queries/sku.ts +85 -0
  116. package/src/queries/staking.ts +55 -91
  117. package/src/queries/utils.test.ts +103 -8
  118. package/src/queries/utils.ts +119 -12
  119. package/src/transactions/bank.ts +9 -33
  120. package/src/transactions/billing.ts +155 -141
  121. package/src/transactions/distribution.ts +7 -29
  122. package/src/transactions/gov.ts +33 -37
  123. package/src/transactions/index.ts +1 -1
  124. package/src/transactions/manifest.ts +7 -29
  125. package/src/transactions/sku.ts +232 -0
  126. package/src/transactions/staking.ts +7 -29
  127. package/src/transactions/utils.test.ts +390 -1
  128. package/src/transactions/utils.ts +194 -2
  129. package/src/types.ts +344 -9
  130. package/src/wallet/mnemonic.ts +41 -17
  131. package/.claude/settings.local.json +0 -20
@@ -1,46 +1,54 @@
1
1
  import { ManifestQueryClient } from '../client.js';
2
- import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
3
- import { parseBigInt, parseInt, defaultPagination } from './utils.js';
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<Record<string, unknown>> {
29
+ ): Promise<GovQueryResult> {
13
30
  const gov = queryClient.cosmos.gov.v1;
14
31
 
15
32
  switch (subcommand) {
16
33
  case 'proposal': {
17
- if (args.length < 1) {
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
- // Parse optional status filter
30
- const proposalStatus = args[0] ? parseInt(args[0], 'status') : 0;
31
- const voter = args[1] || '';
32
- const depositor = args[2] || '';
33
- const result = await gov.proposals({ proposalStatus, voter, depositor, pagination: defaultPagination });
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
- if (args.length < 2) {
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
- if (args.length < 1) {
52
- throw new ManifestMCPError(
53
- ManifestMCPErrorCode.QUERY_FAILED,
54
- 'votes requires proposal-id argument'
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
- if (args.length < 2) {
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
- if (args.length < 1) {
77
- throw new ManifestMCPError(
78
- ManifestMCPErrorCode.QUERY_FAILED,
79
- 'deposits requires proposal-id argument'
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
- if (args.length < 1) {
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
- throw new ManifestMCPError(
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
  }
@@ -1,4 +1,13 @@
1
- export { parseBigInt, parseInt, defaultPagination, DEFAULT_PAGE_LIMIT } from './utils.js';
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';
@@ -0,0 +1,85 @@
1
+ import { ManifestQueryClient } from '../client.js';
2
+ import {
3
+ SkuParamsResult, ProviderResult, ProvidersResult,
4
+ SkuResult, SkusResult
5
+ } from '../types.js';
6
+ import { requireArgs, extractPaginationArgs, extractBooleanFlag } from './utils.js';
7
+ import { throwUnsupportedSubcommand } from '../modules.js';
8
+
9
+ /** SKU query result union type */
10
+ type SkuQueryResult =
11
+ | SkuParamsResult
12
+ | ProviderResult
13
+ | ProvidersResult
14
+ | SkuResult
15
+ | SkusResult;
16
+
17
+ /**
18
+ * Route SKU module query to manifestjs query client
19
+ *
20
+ * Paginated queries support --limit flag (default: 100, max: 1000)
21
+ * Filterable queries support --active-only flag
22
+ */
23
+ export async function routeSkuQuery(
24
+ queryClient: ManifestQueryClient,
25
+ subcommand: string,
26
+ args: string[]
27
+ ): Promise<SkuQueryResult> {
28
+ const sku = queryClient.liftedinit.sku.v1;
29
+
30
+ switch (subcommand) {
31
+ case 'params': {
32
+ const result = await sku.params({});
33
+ return { params: result.params };
34
+ }
35
+
36
+ case 'provider': {
37
+ requireArgs(args, 1, ['provider-uuid'], 'sku provider');
38
+ const [uuid] = args;
39
+ const result = await sku.provider({ uuid });
40
+ return { provider: result.provider };
41
+ }
42
+
43
+ case 'providers': {
44
+ const { value: activeOnly, remainingArgs: afterBool } = extractBooleanFlag(args, '--active-only');
45
+ const { pagination } = extractPaginationArgs(afterBool, 'sku providers');
46
+ const result = await sku.providers({ pagination, activeOnly });
47
+ return { providers: result.providers, pagination: result.pagination };
48
+ }
49
+
50
+ case 'sku': {
51
+ requireArgs(args, 1, ['sku-uuid'], 'sku sku');
52
+ const [uuid] = args;
53
+ const result = await sku.sKU({ uuid });
54
+ return { sku: result.sku };
55
+ }
56
+
57
+ case 'skus': {
58
+ const { value: activeOnly, remainingArgs: afterBool } = extractBooleanFlag(args, '--active-only');
59
+ const { pagination } = extractPaginationArgs(afterBool, 'sku skus');
60
+ const result = await sku.sKUs({ pagination, activeOnly });
61
+ return { skus: result.skus, pagination: result.pagination };
62
+ }
63
+
64
+ case 'skus-by-provider': {
65
+ const { value: activeOnly, remainingArgs: afterBool } = extractBooleanFlag(args, '--active-only');
66
+ const { pagination, remainingArgs } = extractPaginationArgs(afterBool, 'sku skus-by-provider');
67
+ requireArgs(remainingArgs, 1, ['provider-uuid'], 'sku skus-by-provider');
68
+ const [providerUuid] = remainingArgs;
69
+ const result = await sku.sKUsByProvider({ providerUuid, pagination, activeOnly });
70
+ return { skus: result.skus, pagination: result.pagination };
71
+ }
72
+
73
+ case 'provider-by-address': {
74
+ const { value: activeOnly, remainingArgs: afterBool } = extractBooleanFlag(args, '--active-only');
75
+ const { pagination, remainingArgs } = extractPaginationArgs(afterBool, 'sku provider-by-address');
76
+ requireArgs(remainingArgs, 1, ['address'], 'sku provider-by-address');
77
+ const [address] = remainingArgs;
78
+ const result = await sku.providerByAddress({ address, pagination, activeOnly });
79
+ return { providers: result.providers, pagination: result.pagination };
80
+ }
81
+
82
+ default:
83
+ throwUnsupportedSubcommand('query', 'sku', subcommand);
84
+ }
85
+ }
@@ -1,25 +1,40 @@
1
1
  import { ManifestQueryClient } from '../client.js';
2
- import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
3
- import { parseBigInt, defaultPagination } from './utils.js';
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<Record<string, unknown>> {
32
+ ): Promise<StakingQueryResult> {
13
33
  const staking = queryClient.cosmos.staking.v1beta1;
14
34
 
15
35
  switch (subcommand) {
16
36
  case 'delegation': {
17
- if (args.length < 2) {
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
- if (args.length < 1) {
33
- throw new ManifestMCPError(
34
- ManifestMCPErrorCode.QUERY_FAILED,
35
- 'delegations requires delegator-address argument'
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
- if (args.length < 2) {
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
- if (args.length < 1) {
63
- throw new ManifestMCPError(
64
- ManifestMCPErrorCode.QUERY_FAILED,
65
- 'unbonding-delegations requires delegator-address argument'
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
- if (args.length < 1) {
78
- throw new ManifestMCPError(
79
- ManifestMCPErrorCode.QUERY_FAILED,
80
- 'redelegations requires delegator-address argument'
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: defaultPagination,
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
- if (args.length < 1) {
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 status = args[0] || '';
112
- const result = await staking.validators({ status, pagination: defaultPagination });
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
- if (args.length < 1) {
118
- throw new ManifestMCPError(
119
- ManifestMCPErrorCode.QUERY_FAILED,
120
- 'validator-delegations requires validator-address argument'
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
- if (args.length < 1) {
133
- throw new ManifestMCPError(
134
- ManifestMCPErrorCode.QUERY_FAILED,
135
- 'validator-unbonding-delegations requires validator-address argument'
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
- if (args.length < 1) {
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
- throw new ManifestMCPError(
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 { parseBigInt, parseInt } from './utils.js';
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('parseInt', () => {
48
+ describe('parseInteger', () => {
42
49
  it('should parse valid integer strings', () => {
43
- expect(parseInt('0', 'status')).toBe(0);
44
- expect(parseInt('123', 'status')).toBe(123);
45
- expect(parseInt('-5', 'status')).toBe(-5);
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(() => parseInt('', 'status')).toThrow(ManifestMCPError);
50
- expect(() => parseInt('abc', 'status')).toThrow(ManifestMCPError);
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
- parseInt('invalid', 'status');
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
+ });