@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 +1 @@
1
- {"version":3,"file":"staking.js","sourceRoot":"","sources":["../../src/transactions/staking.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"staking.js","sourceRoot":"","sources":["../../src/transactions/staking.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,60 @@ import { SigningStargateClient } from '@cosmjs/stargate';
2
2
  import { ManifestMCPErrorCode, CosmosTxResult } from '../types.js';
3
3
  /** Maximum number of arguments allowed */
4
4
  export declare const MAX_ARGS = 100;
5
+ /** Maximum meta hash length in bytes (64 bytes for SHA-512) */
6
+ export declare const MAX_META_HASH_BYTES = 64;
7
+ /**
8
+ * Result from extracting a flag from args
9
+ */
10
+ export interface ExtractedFlag {
11
+ /** The flag value, or undefined if flag not present */
12
+ value: string | undefined;
13
+ /** Indices consumed by the flag and its value (for filtering) */
14
+ consumedIndices: number[];
15
+ }
16
+ /**
17
+ * Extract a flag value from args array.
18
+ * Returns { value, consumedIndices } or { value: undefined, consumedIndices: [] } if flag not present.
19
+ * Throws if flag is present but value is missing or looks like another flag.
20
+ *
21
+ * @param args - The arguments array to search
22
+ * @param flagName - The flag to look for (e.g., '--memo')
23
+ * @param context - Description for error messages (e.g., 'bank send')
24
+ */
25
+ export declare function extractFlag(args: string[], flagName: string, context: string): ExtractedFlag;
26
+ /**
27
+ * Filter args to remove consumed flag indices
28
+ */
29
+ export declare function filterConsumedArgs(args: string[], consumedIndices: number[]): string[];
5
30
  /** Maximum memo length (Cosmos SDK default) */
6
31
  export declare const MAX_MEMO_LENGTH = 256;
7
32
  /**
8
- * Validate args array length
33
+ * Parse a colon-separated pair (e.g., "address:amount", "sku:quantity").
34
+ * Throws with helpful error if format is invalid.
35
+ *
36
+ * @param input - The string to parse (e.g., "manifest1abc:1000umfx")
37
+ * @param leftName - Name of the left value for error messages (e.g., "address")
38
+ * @param rightName - Name of the right value for error messages (e.g., "amount")
39
+ * @param context - Context for error messages (e.g., "multi-send pair")
40
+ * @returns Tuple of [left, right] values
41
+ */
42
+ export declare function parseColonPair(input: string, leftName: string, rightName: string, context: string): [string, string];
43
+ /**
44
+ * Validate args array length (max limit)
9
45
  */
10
46
  export declare function validateArgsLength(args: string[], context: string): void;
47
+ /**
48
+ * Validate that required arguments are present.
49
+ * Provides helpful error messages with received vs expected args.
50
+ *
51
+ * @param args - The arguments array to validate
52
+ * @param minCount - Minimum number of required arguments
53
+ * @param expectedNames - Names of expected arguments for error messages
54
+ * @param context - Context for error messages (e.g., 'bank send', 'staking delegate')
55
+ * @param errorCode - Error code to use (defaults to TX_FAILED)
56
+ * @throws ManifestMCPError if args.length < minCount
57
+ */
58
+ export declare function requireArgs(args: string[], minCount: number, expectedNames: string[], context: string, errorCode?: ManifestMCPErrorCode): void;
11
59
  /**
12
60
  * Validate a bech32 address using @cosmjs/encoding
13
61
  */
@@ -16,6 +64,22 @@ export declare function validateAddress(address: string, fieldName: string, expe
16
64
  * Validate memo length
17
65
  */
18
66
  export declare function validateMemo(memo: string): void;
67
+ /**
68
+ * Parse and validate a hex string into Uint8Array.
69
+ * Uses @cosmjs/encoding for browser compatibility.
70
+ *
71
+ * @param hexString - The hex string to parse
72
+ * @param fieldName - Name of the field for error messages
73
+ * @param maxBytes - Maximum allowed byte length
74
+ * @param errorCode - Error code to use (defaults to TX_FAILED)
75
+ * @returns Uint8Array of the parsed bytes
76
+ */
77
+ export declare function parseHexBytes(hexString: string, fieldName: string, maxBytes: number, errorCode?: ManifestMCPErrorCode): Uint8Array;
78
+ /**
79
+ * Convert Uint8Array to hex string.
80
+ * Uses @cosmjs/encoding for browser compatibility.
81
+ */
82
+ export declare function bytesToHex(bytes: Uint8Array): string;
19
83
  /**
20
84
  * Safely parse a string to BigInt with proper error handling and configurable error code.
21
85
  * This is the base implementation used by both transaction and query utilities.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/transactions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAoB,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,+CAA+C;AAC/C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAOxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAyBjG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAO/C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,oBAAoB,GAC9B,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAyBhF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC,CAAC,EACtE,mBAAmB,EAAE,OAAO,GAC3B,cAAc,CAkBhB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/transactions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAoB,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErF,0CAA0C;AAC1C,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iEAAiE;IACjE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,aAAa,CAef;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAMtF;AAED,+CAA+C;AAC/C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBlB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAOxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,oBAAqD,GAC/D,IAAI,CAoBN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAyBjG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAO/C;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,oBAAqD,GAC/D,UAAU,CAmCZ;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,oBAAoB,GAC9B,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAyBhF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC,CAAC,EACtE,mBAAmB,EAAE,OAAO,GAC3B,cAAc,CAmBhB"}
@@ -1,17 +1,98 @@
1
- import { fromBech32 } from '@cosmjs/encoding';
1
+ import { fromBech32, fromHex, toHex } from '@cosmjs/encoding';
2
2
  import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
3
3
  /** Maximum number of arguments allowed */
4
4
  export const MAX_ARGS = 100;
5
+ /** Maximum meta hash length in bytes (64 bytes for SHA-512) */
6
+ export const MAX_META_HASH_BYTES = 64;
7
+ /**
8
+ * Extract a flag value from args array.
9
+ * Returns { value, consumedIndices } or { value: undefined, consumedIndices: [] } if flag not present.
10
+ * Throws if flag is present but value is missing or looks like another flag.
11
+ *
12
+ * @param args - The arguments array to search
13
+ * @param flagName - The flag to look for (e.g., '--memo')
14
+ * @param context - Description for error messages (e.g., 'bank send')
15
+ */
16
+ export function extractFlag(args, flagName, context) {
17
+ const flagIndex = args.indexOf(flagName);
18
+ if (flagIndex === -1) {
19
+ return { value: undefined, consumedIndices: [] };
20
+ }
21
+ const value = args[flagIndex + 1];
22
+ if (!value || value.startsWith('--')) {
23
+ throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `${flagName} flag requires a value in ${context}`);
24
+ }
25
+ return { value, consumedIndices: [flagIndex, flagIndex + 1] };
26
+ }
27
+ /**
28
+ * Filter args to remove consumed flag indices
29
+ */
30
+ export function filterConsumedArgs(args, consumedIndices) {
31
+ if (consumedIndices.length === 0) {
32
+ return args;
33
+ }
34
+ const consumedSet = new Set(consumedIndices);
35
+ return args.filter((_, index) => !consumedSet.has(index));
36
+ }
5
37
  /** Maximum memo length (Cosmos SDK default) */
6
38
  export const MAX_MEMO_LENGTH = 256;
7
39
  /**
8
- * Validate args array length
40
+ * Parse a colon-separated pair (e.g., "address:amount", "sku:quantity").
41
+ * Throws with helpful error if format is invalid.
42
+ *
43
+ * @param input - The string to parse (e.g., "manifest1abc:1000umfx")
44
+ * @param leftName - Name of the left value for error messages (e.g., "address")
45
+ * @param rightName - Name of the right value for error messages (e.g., "amount")
46
+ * @param context - Context for error messages (e.g., "multi-send pair")
47
+ * @returns Tuple of [left, right] values
48
+ */
49
+ export function parseColonPair(input, leftName, rightName, context) {
50
+ const colonIndex = input.indexOf(':');
51
+ if (colonIndex === -1) {
52
+ throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Invalid ${context} format: "${input}". Missing colon separator. Expected format: ${leftName}:${rightName}`);
53
+ }
54
+ if (colonIndex === 0) {
55
+ throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Invalid ${context} format: "${input}". Missing ${leftName}. Expected format: ${leftName}:${rightName}`);
56
+ }
57
+ if (colonIndex === input.length - 1) {
58
+ throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Invalid ${context} format: "${input}". Missing ${rightName}. Expected format: ${leftName}:${rightName}`);
59
+ }
60
+ return [input.slice(0, colonIndex), input.slice(colonIndex + 1)];
61
+ }
62
+ /**
63
+ * Validate args array length (max limit)
9
64
  */
10
65
  export function validateArgsLength(args, context) {
11
66
  if (args.length > MAX_ARGS) {
12
67
  throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Too many arguments for ${context}: ${args.length}. Maximum allowed: ${MAX_ARGS}`);
13
68
  }
14
69
  }
70
+ /**
71
+ * Validate that required arguments are present.
72
+ * Provides helpful error messages with received vs expected args.
73
+ *
74
+ * @param args - The arguments array to validate
75
+ * @param minCount - Minimum number of required arguments
76
+ * @param expectedNames - Names of expected arguments for error messages
77
+ * @param context - Context for error messages (e.g., 'bank send', 'staking delegate')
78
+ * @param errorCode - Error code to use (defaults to TX_FAILED)
79
+ * @throws ManifestMCPError if args.length < minCount
80
+ */
81
+ export function requireArgs(args, minCount, expectedNames, context, errorCode = ManifestMCPErrorCode.TX_FAILED) {
82
+ if (args.length >= minCount) {
83
+ return;
84
+ }
85
+ const expectedList = expectedNames.slice(0, minCount).join(', ');
86
+ const receivedList = args.length === 0
87
+ ? 'none'
88
+ : args.map(a => `"${a}"`).join(', ');
89
+ throw new ManifestMCPError(errorCode, `${context} requires ${minCount} argument(s): ${expectedList}. Received ${args.length}: ${receivedList}`, {
90
+ expectedArgs: expectedNames.slice(0, minCount),
91
+ receivedArgs: args,
92
+ receivedCount: args.length,
93
+ requiredCount: minCount,
94
+ });
95
+ }
15
96
  /**
16
97
  * Validate a bech32 address using @cosmjs/encoding
17
98
  */
@@ -40,6 +121,45 @@ export function validateMemo(memo) {
40
121
  throw new ManifestMCPError(ManifestMCPErrorCode.TX_FAILED, `Memo too long: ${memo.length} characters. Maximum allowed: ${MAX_MEMO_LENGTH}`);
41
122
  }
42
123
  }
124
+ /**
125
+ * Parse and validate a hex string into Uint8Array.
126
+ * Uses @cosmjs/encoding for browser compatibility.
127
+ *
128
+ * @param hexString - The hex string to parse
129
+ * @param fieldName - Name of the field for error messages
130
+ * @param maxBytes - Maximum allowed byte length
131
+ * @param errorCode - Error code to use (defaults to TX_FAILED)
132
+ * @returns Uint8Array of the parsed bytes
133
+ */
134
+ export function parseHexBytes(hexString, fieldName, maxBytes, errorCode = ManifestMCPErrorCode.TX_FAILED) {
135
+ // Check for empty string
136
+ if (!hexString || hexString.trim() === '') {
137
+ throw new ManifestMCPError(errorCode, `Invalid ${fieldName}: empty value. Expected a hex string.`);
138
+ }
139
+ // Check even length (each byte is 2 hex chars)
140
+ if (hexString.length % 2 !== 0) {
141
+ throw new ManifestMCPError(errorCode, `Invalid ${fieldName}: hex string must have even length. Got ${hexString.length} characters.`);
142
+ }
143
+ // Check max length
144
+ const byteLength = hexString.length / 2;
145
+ if (byteLength > maxBytes) {
146
+ throw new ManifestMCPError(errorCode, `Invalid ${fieldName}: exceeds maximum ${maxBytes} bytes. Got ${byteLength} bytes (${hexString.length} hex chars).`);
147
+ }
148
+ // Use @cosmjs/encoding for browser-compatible hex parsing
149
+ try {
150
+ return fromHex(hexString);
151
+ }
152
+ catch (error) {
153
+ throw new ManifestMCPError(errorCode, `Invalid ${fieldName}: "${hexString}". Must contain only hexadecimal characters (0-9, a-f, A-F).`);
154
+ }
155
+ }
156
+ /**
157
+ * Convert Uint8Array to hex string.
158
+ * Uses @cosmjs/encoding for browser compatibility.
159
+ */
160
+ export function bytesToHex(bytes) {
161
+ return toHex(bytes);
162
+ }
43
163
  /**
44
164
  * Safely parse a string to BigInt with proper error handling and configurable error code.
45
165
  * This is the base implementation used by both transaction and query utilities.
@@ -104,6 +224,7 @@ export function buildTxResult(module, subcommand, result, waitForConfirmation) {
104
224
  rawLog: result.rawLog || undefined,
105
225
  gasUsed: String(result.gasUsed),
106
226
  gasWanted: String(result.gasWanted),
227
+ events: result.events,
107
228
  };
108
229
  if (waitForConfirmation) {
109
230
  txResult.confirmed = result.code === 0;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/transactions/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/transactions/utils.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { parseAmount, parseBigInt } from './utils.js';
2
+ import { toBech32 } from '@cosmjs/encoding';
3
+ import { parseAmount, parseBigInt, extractFlag, filterConsumedArgs, parseColonPair, validateAddress, validateMemo, validateArgsLength, requireArgs, parseHexBytes, bytesToHex } from './utils.js';
3
4
  import { ManifestMCPError, ManifestMCPErrorCode } from '../types.js';
4
5
  describe('parseAmount', () => {
5
6
  it('should parse valid amount strings', () => {
@@ -118,4 +119,353 @@ describe('parseBigInt', () => {
118
119
  }
119
120
  });
120
121
  });
122
+ describe('extractFlag', () => {
123
+ it('should extract flag value when present', () => {
124
+ const result = extractFlag(['--memo', 'hello'], '--memo', 'test');
125
+ expect(result.value).toBe('hello');
126
+ expect(result.consumedIndices).toEqual([0, 1]);
127
+ });
128
+ it('should return undefined when flag not present', () => {
129
+ const result = extractFlag(['arg1', 'arg2'], '--memo', 'test');
130
+ expect(result.value).toBeUndefined();
131
+ expect(result.consumedIndices).toEqual([]);
132
+ });
133
+ it('should handle flag in middle of args', () => {
134
+ const result = extractFlag(['arg1', '--memo', 'hello', 'arg2'], '--memo', 'test');
135
+ expect(result.value).toBe('hello');
136
+ expect(result.consumedIndices).toEqual([1, 2]);
137
+ });
138
+ it('should throw when flag has no value', () => {
139
+ expect(() => extractFlag(['--memo'], '--memo', 'test')).toThrow(ManifestMCPError);
140
+ });
141
+ it('should throw when flag value looks like another flag', () => {
142
+ expect(() => extractFlag(['--memo', '--other'], '--memo', 'test')).toThrow(ManifestMCPError);
143
+ });
144
+ it('should include context in error message', () => {
145
+ try {
146
+ extractFlag(['--memo'], '--memo', 'bank send');
147
+ }
148
+ catch (error) {
149
+ expect(error.message).toContain('bank send');
150
+ expect(error.message).toContain('--memo');
151
+ }
152
+ });
153
+ });
154
+ describe('filterConsumedArgs', () => {
155
+ it('should filter out consumed indices', () => {
156
+ const result = filterConsumedArgs(['a', 'b', 'c', 'd'], [1, 2]);
157
+ expect(result).toEqual(['a', 'd']);
158
+ });
159
+ it('should return original array when no indices consumed', () => {
160
+ const result = filterConsumedArgs(['a', 'b', 'c'], []);
161
+ expect(result).toEqual(['a', 'b', 'c']);
162
+ });
163
+ it('should handle all indices consumed', () => {
164
+ const result = filterConsumedArgs(['a', 'b'], [0, 1]);
165
+ expect(result).toEqual([]);
166
+ });
167
+ it('should handle non-contiguous indices', () => {
168
+ const result = filterConsumedArgs(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
169
+ expect(result).toEqual(['b', 'd']);
170
+ });
171
+ });
172
+ describe('parseColonPair', () => {
173
+ it('should parse valid colon-separated pairs', () => {
174
+ expect(parseColonPair('address:amount', 'address', 'amount', 'test')).toEqual(['address', 'amount']);
175
+ expect(parseColonPair('key:value', 'key', 'value', 'test')).toEqual(['key', 'value']);
176
+ });
177
+ it('should handle values with colons (takes first colon as separator)', () => {
178
+ const result = parseColonPair('address:100:extra', 'address', 'amount', 'test');
179
+ expect(result).toEqual(['address', '100:extra']);
180
+ });
181
+ it('should throw for missing colon', () => {
182
+ expect(() => parseColonPair('nodelimiter', 'left', 'right', 'test')).toThrow(ManifestMCPError);
183
+ });
184
+ it('should throw for empty left side', () => {
185
+ expect(() => parseColonPair(':value', 'left', 'right', 'test')).toThrow(ManifestMCPError);
186
+ });
187
+ it('should throw for empty right side', () => {
188
+ expect(() => parseColonPair('key:', 'left', 'right', 'test')).toThrow(ManifestMCPError);
189
+ });
190
+ it('should include context and field names in error messages', () => {
191
+ try {
192
+ parseColonPair('invalid', 'address', 'amount', 'multi-send');
193
+ }
194
+ catch (error) {
195
+ const message = error.message;
196
+ expect(message).toContain('multi-send');
197
+ expect(message).toContain('address');
198
+ expect(message).toContain('amount');
199
+ }
200
+ });
201
+ it('should provide specific error for missing left value', () => {
202
+ try {
203
+ parseColonPair(':value', 'address', 'amount', 'test');
204
+ }
205
+ catch (error) {
206
+ expect(error.message).toContain('Missing address');
207
+ }
208
+ });
209
+ it('should provide specific error for missing right value', () => {
210
+ try {
211
+ parseColonPair('key:', 'address', 'amount', 'test');
212
+ }
213
+ catch (error) {
214
+ expect(error.message).toContain('Missing amount');
215
+ }
216
+ });
217
+ });
218
+ describe('validateAddress', () => {
219
+ // Generate valid bech32 addresses programmatically using @cosmjs/encoding
220
+ // 20 bytes is the standard Cosmos address length
221
+ const validManifestAddress = toBech32('manifest', new Uint8Array(20));
222
+ const validCosmosAddress = toBech32('cosmos', new Uint8Array(20));
223
+ it('should accept valid bech32 addresses', () => {
224
+ expect(() => validateAddress(validManifestAddress, 'test')).not.toThrow();
225
+ expect(() => validateAddress(validCosmosAddress, 'test')).not.toThrow();
226
+ });
227
+ it('should throw for empty address', () => {
228
+ expect(() => validateAddress('', 'recipient')).toThrow(ManifestMCPError);
229
+ expect(() => validateAddress(' ', 'recipient')).toThrow(ManifestMCPError);
230
+ });
231
+ it('should throw for invalid bech32 address', () => {
232
+ expect(() => validateAddress('notanaddress', 'recipient')).toThrow(ManifestMCPError);
233
+ expect(() => validateAddress('manifest1invalid', 'recipient')).toThrow(ManifestMCPError);
234
+ });
235
+ it('should use INVALID_ADDRESS error code', () => {
236
+ try {
237
+ validateAddress('invalid', 'recipient');
238
+ }
239
+ catch (error) {
240
+ expect(error.code).toBe(ManifestMCPErrorCode.INVALID_ADDRESS);
241
+ }
242
+ });
243
+ it('should include field name in error message', () => {
244
+ try {
245
+ validateAddress('invalid', 'validator address');
246
+ }
247
+ catch (error) {
248
+ expect(error.message).toContain('validator address');
249
+ }
250
+ });
251
+ it('should validate expected prefix when provided', () => {
252
+ // Should pass when prefix matches
253
+ expect(() => validateAddress(validManifestAddress, 'test', 'manifest')).not.toThrow();
254
+ // Should fail when prefix doesn't match
255
+ expect(() => validateAddress(validManifestAddress, 'test', 'cosmos')).toThrow(ManifestMCPError);
256
+ });
257
+ it('should include expected prefix in error message', () => {
258
+ try {
259
+ validateAddress(validManifestAddress, 'recipient', 'cosmos');
260
+ }
261
+ catch (error) {
262
+ const message = error.message;
263
+ expect(message).toContain('cosmos');
264
+ expect(message).toContain('manifest');
265
+ }
266
+ });
267
+ });
268
+ describe('validateMemo', () => {
269
+ it('should accept memo within limit', () => {
270
+ expect(() => validateMemo('')).not.toThrow();
271
+ expect(() => validateMemo('short memo')).not.toThrow();
272
+ expect(() => validateMemo('a'.repeat(256))).not.toThrow();
273
+ });
274
+ it('should throw for memo exceeding 256 characters', () => {
275
+ expect(() => validateMemo('a'.repeat(257))).toThrow(ManifestMCPError);
276
+ expect(() => validateMemo('a'.repeat(500))).toThrow(ManifestMCPError);
277
+ });
278
+ it('should use TX_FAILED error code', () => {
279
+ try {
280
+ validateMemo('a'.repeat(300));
281
+ }
282
+ catch (error) {
283
+ expect(error.code).toBe(ManifestMCPErrorCode.TX_FAILED);
284
+ }
285
+ });
286
+ it('should include length info in error message', () => {
287
+ try {
288
+ validateMemo('a'.repeat(300));
289
+ }
290
+ catch (error) {
291
+ const message = error.message;
292
+ expect(message).toContain('300');
293
+ expect(message).toContain('256');
294
+ }
295
+ });
296
+ });
297
+ describe('validateArgsLength', () => {
298
+ it('should accept args within limit', () => {
299
+ expect(() => validateArgsLength([], 'test')).not.toThrow();
300
+ expect(() => validateArgsLength(['a', 'b', 'c'], 'test')).not.toThrow();
301
+ expect(() => validateArgsLength(new Array(100).fill('arg'), 'test')).not.toThrow();
302
+ });
303
+ it('should throw for args exceeding 100 items', () => {
304
+ expect(() => validateArgsLength(new Array(101).fill('arg'), 'test')).toThrow(ManifestMCPError);
305
+ expect(() => validateArgsLength(new Array(200).fill('arg'), 'test')).toThrow(ManifestMCPError);
306
+ });
307
+ it('should use TX_FAILED error code', () => {
308
+ try {
309
+ validateArgsLength(new Array(150).fill('arg'), 'test');
310
+ }
311
+ catch (error) {
312
+ expect(error.code).toBe(ManifestMCPErrorCode.TX_FAILED);
313
+ }
314
+ });
315
+ it('should include context and count in error message', () => {
316
+ try {
317
+ validateArgsLength(new Array(150).fill('arg'), 'bank send');
318
+ }
319
+ catch (error) {
320
+ const message = error.message;
321
+ expect(message).toContain('bank send');
322
+ expect(message).toContain('150');
323
+ expect(message).toContain('100');
324
+ }
325
+ });
326
+ });
327
+ describe('requireArgs', () => {
328
+ it('should pass when args meet minimum count', () => {
329
+ expect(() => requireArgs(['a', 'b'], 2, ['arg1', 'arg2'], 'test')).not.toThrow();
330
+ expect(() => requireArgs(['a', 'b', 'c'], 2, ['arg1', 'arg2'], 'test')).not.toThrow();
331
+ });
332
+ it('should pass when zero args required', () => {
333
+ expect(() => requireArgs([], 0, [], 'test')).not.toThrow();
334
+ });
335
+ it('should throw when args below minimum count', () => {
336
+ expect(() => requireArgs(['a'], 2, ['arg1', 'arg2'], 'test')).toThrow(ManifestMCPError);
337
+ expect(() => requireArgs([], 1, ['arg1'], 'test')).toThrow(ManifestMCPError);
338
+ });
339
+ it('should use TX_FAILED error code by default', () => {
340
+ try {
341
+ requireArgs([], 1, ['arg1'], 'test');
342
+ }
343
+ catch (error) {
344
+ expect(error.code).toBe(ManifestMCPErrorCode.TX_FAILED);
345
+ }
346
+ });
347
+ it('should include context in error message', () => {
348
+ try {
349
+ requireArgs(['a'], 2, ['recipient', 'amount'], 'bank send');
350
+ }
351
+ catch (error) {
352
+ const message = error.message;
353
+ expect(message).toContain('bank send');
354
+ expect(message).toContain('recipient');
355
+ expect(message).toContain('amount');
356
+ }
357
+ });
358
+ it('should include received args in error message', () => {
359
+ try {
360
+ requireArgs(['value1'], 2, ['arg1', 'arg2'], 'test');
361
+ }
362
+ catch (error) {
363
+ const message = error.message;
364
+ expect(message).toContain('"value1"');
365
+ expect(message).toContain('Received 1');
366
+ }
367
+ });
368
+ it('should show "none" when no args received', () => {
369
+ try {
370
+ requireArgs([], 1, ['arg1'], 'test');
371
+ }
372
+ catch (error) {
373
+ const message = error.message;
374
+ expect(message).toContain('none');
375
+ }
376
+ });
377
+ it('should include details with expected and received args', () => {
378
+ try {
379
+ requireArgs(['a'], 2, ['arg1', 'arg2'], 'test');
380
+ }
381
+ catch (error) {
382
+ const details = error.details;
383
+ expect(details?.expectedArgs).toEqual(['arg1', 'arg2']);
384
+ expect(details?.receivedArgs).toEqual(['a']);
385
+ expect(details?.receivedCount).toBe(1);
386
+ expect(details?.requiredCount).toBe(2);
387
+ }
388
+ });
389
+ it('should accept custom error code', () => {
390
+ try {
391
+ requireArgs([], 1, ['arg1'], 'test', ManifestMCPErrorCode.QUERY_FAILED);
392
+ }
393
+ catch (error) {
394
+ expect(error.code).toBe(ManifestMCPErrorCode.QUERY_FAILED);
395
+ }
396
+ });
397
+ });
398
+ describe('parseHexBytes', () => {
399
+ it('should parse valid hex strings', () => {
400
+ expect(parseHexBytes('deadbeef', 'test', 100)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
401
+ expect(parseHexBytes('00', 'test', 100)).toEqual(new Uint8Array([0x00]));
402
+ expect(parseHexBytes('ff', 'test', 100)).toEqual(new Uint8Array([0xff]));
403
+ expect(parseHexBytes('0123456789abcdef', 'test', 100)).toEqual(new Uint8Array([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]));
404
+ });
405
+ it('should be case-insensitive', () => {
406
+ expect(parseHexBytes('DEADBEEF', 'test', 100)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
407
+ expect(parseHexBytes('DeAdBeEf', 'test', 100)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
408
+ });
409
+ it('should throw for empty string', () => {
410
+ expect(() => parseHexBytes('', 'field', 100)).toThrow(ManifestMCPError);
411
+ expect(() => parseHexBytes(' ', 'field', 100)).toThrow(ManifestMCPError);
412
+ });
413
+ it('should throw for odd-length hex strings', () => {
414
+ expect(() => parseHexBytes('abc', 'field', 100)).toThrow(ManifestMCPError);
415
+ expect(() => parseHexBytes('1', 'field', 100)).toThrow(ManifestMCPError);
416
+ expect(() => parseHexBytes('12345', 'field', 100)).toThrow(ManifestMCPError);
417
+ });
418
+ it('should throw for exceeding max bytes', () => {
419
+ expect(() => parseHexBytes('deadbeef', 'field', 2)).toThrow(ManifestMCPError);
420
+ expect(() => parseHexBytes('0102030405', 'field', 2)).toThrow(ManifestMCPError);
421
+ });
422
+ it('should accept exactly max bytes', () => {
423
+ expect(parseHexBytes('deadbeef', 'test', 4)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
424
+ });
425
+ it('should throw for invalid hex characters', () => {
426
+ expect(() => parseHexBytes('ghij', 'field', 100)).toThrow(ManifestMCPError);
427
+ expect(() => parseHexBytes('12gg', 'field', 100)).toThrow(ManifestMCPError);
428
+ expect(() => parseHexBytes('xy00', 'field', 100)).toThrow(ManifestMCPError);
429
+ });
430
+ it('should use TX_FAILED error code by default', () => {
431
+ try {
432
+ parseHexBytes('', 'field', 100);
433
+ }
434
+ catch (error) {
435
+ expect(error.code).toBe(ManifestMCPErrorCode.TX_FAILED);
436
+ }
437
+ });
438
+ it('should accept custom error code', () => {
439
+ try {
440
+ parseHexBytes('', 'field', 100, ManifestMCPErrorCode.QUERY_FAILED);
441
+ }
442
+ catch (error) {
443
+ expect(error.code).toBe(ManifestMCPErrorCode.QUERY_FAILED);
444
+ }
445
+ });
446
+ it('should include field name in error message', () => {
447
+ try {
448
+ parseHexBytes('', 'my-custom-field', 100);
449
+ }
450
+ catch (error) {
451
+ expect(error.message).toContain('my-custom-field');
452
+ }
453
+ });
454
+ });
455
+ describe('bytesToHex', () => {
456
+ it('should convert bytes to hex string', () => {
457
+ expect(bytesToHex(new Uint8Array([0xde, 0xad, 0xbe, 0xef]))).toBe('deadbeef');
458
+ expect(bytesToHex(new Uint8Array([0x00]))).toBe('00');
459
+ expect(bytesToHex(new Uint8Array([0xff]))).toBe('ff');
460
+ expect(bytesToHex(new Uint8Array([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]))).toBe('0123456789abcdef');
461
+ });
462
+ it('should handle empty array', () => {
463
+ expect(bytesToHex(new Uint8Array([]))).toBe('');
464
+ });
465
+ it('should round-trip with parseHexBytes', () => {
466
+ const original = 'deadbeefcafe1234';
467
+ const bytes = parseHexBytes(original, 'test', 100);
468
+ expect(bytesToHex(bytes)).toBe(original);
469
+ });
470
+ });
121
471
  //# sourceMappingURL=utils.test.js.map