@hashgraphonline/standards-sdk 0.1.184 → 0.1.185

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 (262) hide show
  1. package/dist/browser/hcs-25/identifiers.d.ts +24 -0
  2. package/dist/browser/hcs-25/identifiers.d.ts.map +1 -0
  3. package/dist/browser/hcs-25/index.d.ts +4 -0
  4. package/dist/browser/hcs-25/index.d.ts.map +1 -0
  5. package/dist/browser/hcs-25/scoring.d.ts +32 -0
  6. package/dist/browser/hcs-25/scoring.d.ts.map +1 -0
  7. package/dist/browser/hcs-25/types.d.ts +363 -0
  8. package/dist/browser/hcs-25/types.d.ts.map +1 -0
  9. package/dist/browser/index.d.ts +1 -0
  10. package/dist/browser/index.d.ts.map +1 -1
  11. package/dist/browser-root/hcs-25/identifiers.d.ts +24 -0
  12. package/dist/browser-root/hcs-25/identifiers.d.ts.map +1 -0
  13. package/dist/browser-root/hcs-25/index.d.ts +4 -0
  14. package/dist/browser-root/hcs-25/index.d.ts.map +1 -0
  15. package/dist/browser-root/hcs-25/scoring.d.ts +32 -0
  16. package/dist/browser-root/hcs-25/scoring.d.ts.map +1 -0
  17. package/dist/browser-root/hcs-25/types.d.ts +363 -0
  18. package/dist/browser-root/hcs-25/types.d.ts.map +1 -0
  19. package/dist/browser-root/index.d.ts +1 -0
  20. package/dist/browser-root/index.d.ts.map +1 -1
  21. package/dist/cjs/hcs-25/identifiers.d.ts +24 -0
  22. package/dist/cjs/hcs-25/identifiers.d.ts.map +1 -0
  23. package/dist/cjs/hcs-25/index.d.ts +4 -0
  24. package/dist/cjs/hcs-25/index.d.ts.map +1 -0
  25. package/dist/cjs/hcs-25/scoring.d.ts +32 -0
  26. package/dist/cjs/hcs-25/scoring.d.ts.map +1 -0
  27. package/dist/cjs/hcs-25/types.d.ts +363 -0
  28. package/dist/cjs/hcs-25/types.d.ts.map +1 -0
  29. package/dist/cjs/index.d.ts +1 -0
  30. package/dist/cjs/index.d.ts.map +1 -1
  31. package/dist/cjs/standards-sdk.cjs +1 -1
  32. package/dist/cjs/standards-sdk.cjs.map +1 -1
  33. package/dist/es/hcs-25/identifiers.d.ts +24 -0
  34. package/dist/es/hcs-25/identifiers.d.ts.map +1 -0
  35. package/dist/es/hcs-25/index.d.ts +4 -0
  36. package/dist/es/hcs-25/index.d.ts.map +1 -0
  37. package/dist/es/hcs-25/scoring.d.ts +32 -0
  38. package/dist/es/hcs-25/scoring.d.ts.map +1 -0
  39. package/dist/es/hcs-25/types.d.ts +363 -0
  40. package/dist/es/hcs-25/types.d.ts.map +1 -0
  41. package/dist/es/index.d.ts +1 -0
  42. package/dist/es/index.d.ts.map +1 -1
  43. package/dist/es/standards-sdk.es.js +62 -40
  44. package/dist/es/standards-sdk.es.js.map +1 -1
  45. package/dist/es/standards-sdk.es101.js +2 -2
  46. package/dist/es/standards-sdk.es103.js +2 -2
  47. package/dist/es/standards-sdk.es104.js +1 -1
  48. package/dist/es/standards-sdk.es106.js +1 -1
  49. package/dist/es/standards-sdk.es108.js +2 -2
  50. package/dist/es/standards-sdk.es11.js +1 -1
  51. package/dist/es/standards-sdk.es110.js +1 -1
  52. package/dist/es/standards-sdk.es111.js +2 -2
  53. package/dist/es/standards-sdk.es115.js +3 -3
  54. package/dist/es/standards-sdk.es116.js +4 -4
  55. package/dist/es/standards-sdk.es117.js +19 -251
  56. package/dist/es/standards-sdk.es117.js.map +1 -1
  57. package/dist/es/standards-sdk.es118.js +60 -475
  58. package/dist/es/standards-sdk.es118.js.map +1 -1
  59. package/dist/es/standards-sdk.es119.js +217 -86
  60. package/dist/es/standards-sdk.es119.js.map +1 -1
  61. package/dist/es/standards-sdk.es12.js +1 -1
  62. package/dist/es/standards-sdk.es120.js +242 -150
  63. package/dist/es/standards-sdk.es120.js.map +1 -1
  64. package/dist/es/standards-sdk.es121.js +470 -26
  65. package/dist/es/standards-sdk.es121.js.map +1 -1
  66. package/dist/es/standards-sdk.es122.js +103 -10
  67. package/dist/es/standards-sdk.es122.js.map +1 -1
  68. package/dist/es/standards-sdk.es123.js +145 -167
  69. package/dist/es/standards-sdk.es123.js.map +1 -1
  70. package/dist/es/standards-sdk.es124.js +30 -25
  71. package/dist/es/standards-sdk.es124.js.map +1 -1
  72. package/dist/es/standards-sdk.es125.js +10 -20
  73. package/dist/es/standards-sdk.es125.js.map +1 -1
  74. package/dist/es/standards-sdk.es126.js +159 -137
  75. package/dist/es/standards-sdk.es126.js.map +1 -1
  76. package/dist/es/standards-sdk.es127.js +27 -199
  77. package/dist/es/standards-sdk.es127.js.map +1 -1
  78. package/dist/es/standards-sdk.es128.js +15 -783
  79. package/dist/es/standards-sdk.es128.js.map +1 -1
  80. package/dist/es/standards-sdk.es129.js +157 -10
  81. package/dist/es/standards-sdk.es129.js.map +1 -1
  82. package/dist/es/standards-sdk.es13.js +1 -1
  83. package/dist/es/standards-sdk.es130.js +198 -564
  84. package/dist/es/standards-sdk.es130.js.map +1 -1
  85. package/dist/es/standards-sdk.es131.js +703 -539
  86. package/dist/es/standards-sdk.es131.js.map +1 -1
  87. package/dist/es/standards-sdk.es132.js +12 -12
  88. package/dist/es/standards-sdk.es132.js.map +1 -1
  89. package/dist/es/standards-sdk.es133.js +567 -2
  90. package/dist/es/standards-sdk.es133.js.map +1 -1
  91. package/dist/es/standards-sdk.es134.js +610 -71
  92. package/dist/es/standards-sdk.es134.js.map +1 -1
  93. package/dist/es/standards-sdk.es135.js +12 -39
  94. package/dist/es/standards-sdk.es135.js.map +1 -1
  95. package/dist/es/standards-sdk.es136.js +2 -2
  96. package/dist/es/standards-sdk.es136.js.map +1 -1
  97. package/dist/es/standards-sdk.es137.js +42 -190
  98. package/dist/es/standards-sdk.es137.js.map +1 -1
  99. package/dist/es/standards-sdk.es138.js +39 -1139
  100. package/dist/es/standards-sdk.es138.js.map +1 -1
  101. package/dist/es/standards-sdk.es139.js +2 -306
  102. package/dist/es/standards-sdk.es139.js.map +1 -1
  103. package/dist/es/standards-sdk.es14.js +1 -1
  104. package/dist/es/standards-sdk.es140.js +231 -418
  105. package/dist/es/standards-sdk.es140.js.map +1 -1
  106. package/dist/es/standards-sdk.es141.js +1135 -350
  107. package/dist/es/standards-sdk.es141.js.map +1 -1
  108. package/dist/es/standards-sdk.es142.js +268 -1084
  109. package/dist/es/standards-sdk.es142.js.map +1 -1
  110. package/dist/es/standards-sdk.es143.js +418 -204
  111. package/dist/es/standards-sdk.es143.js.map +1 -1
  112. package/dist/es/standards-sdk.es144.js +350 -1562
  113. package/dist/es/standards-sdk.es144.js.map +1 -1
  114. package/dist/es/standards-sdk.es145.js +1061 -1096
  115. package/dist/es/standards-sdk.es145.js.map +1 -1
  116. package/dist/es/standards-sdk.es146.js +204 -13
  117. package/dist/es/standards-sdk.es146.js.map +1 -1
  118. package/dist/es/standards-sdk.es147.js +1541 -233
  119. package/dist/es/standards-sdk.es147.js.map +1 -1
  120. package/dist/es/standards-sdk.es148.js +1157 -4
  121. package/dist/es/standards-sdk.es148.js.map +1 -1
  122. package/dist/es/standards-sdk.es149.js +15 -79
  123. package/dist/es/standards-sdk.es149.js.map +1 -1
  124. package/dist/es/standards-sdk.es15.js +1 -1
  125. package/dist/es/standards-sdk.es150.js +250 -78
  126. package/dist/es/standards-sdk.es150.js.map +1 -1
  127. package/dist/es/standards-sdk.es151.js +4 -60
  128. package/dist/es/standards-sdk.es151.js.map +1 -1
  129. package/dist/es/standards-sdk.es152.js +80 -2546
  130. package/dist/es/standards-sdk.es152.js.map +1 -1
  131. package/dist/es/standards-sdk.es153.js +80 -152
  132. package/dist/es/standards-sdk.es153.js.map +1 -1
  133. package/dist/es/standards-sdk.es154.js +60 -7
  134. package/dist/es/standards-sdk.es154.js.map +1 -1
  135. package/dist/es/standards-sdk.es155.js +2547 -86
  136. package/dist/es/standards-sdk.es155.js.map +1 -1
  137. package/dist/es/standards-sdk.es156.js +144 -50
  138. package/dist/es/standards-sdk.es156.js.map +1 -1
  139. package/dist/es/standards-sdk.es157.js +7 -30
  140. package/dist/es/standards-sdk.es157.js.map +1 -1
  141. package/dist/es/standards-sdk.es158.js +86 -34
  142. package/dist/es/standards-sdk.es158.js.map +1 -1
  143. package/dist/es/standards-sdk.es159.js +65 -48
  144. package/dist/es/standards-sdk.es159.js.map +1 -1
  145. package/dist/es/standards-sdk.es16.js +5 -5
  146. package/dist/es/standards-sdk.es160.js +30 -138
  147. package/dist/es/standards-sdk.es160.js.map +1 -1
  148. package/dist/es/standards-sdk.es161.js +34 -42
  149. package/dist/es/standards-sdk.es161.js.map +1 -1
  150. package/dist/es/standards-sdk.es162.js +48 -12482
  151. package/dist/es/standards-sdk.es162.js.map +1 -1
  152. package/dist/es/standards-sdk.es163.js +12479 -53
  153. package/dist/es/standards-sdk.es163.js.map +1 -1
  154. package/dist/es/standards-sdk.es164.js +124 -97
  155. package/dist/es/standards-sdk.es164.js.map +1 -1
  156. package/dist/es/standards-sdk.es165.js +35 -74
  157. package/dist/es/standards-sdk.es165.js.map +1 -1
  158. package/dist/es/standards-sdk.es166.js +14 -197
  159. package/dist/es/standards-sdk.es166.js.map +1 -1
  160. package/dist/es/standards-sdk.es167.js +54 -15
  161. package/dist/es/standards-sdk.es167.js.map +1 -1
  162. package/dist/es/standards-sdk.es168.js +90 -651
  163. package/dist/es/standards-sdk.es168.js.map +1 -1
  164. package/dist/es/standards-sdk.es169.js +70 -161
  165. package/dist/es/standards-sdk.es169.js.map +1 -1
  166. package/dist/es/standards-sdk.es170.js +187 -309
  167. package/dist/es/standards-sdk.es170.js.map +1 -1
  168. package/dist/es/standards-sdk.es171.js +661 -335
  169. package/dist/es/standards-sdk.es171.js.map +1 -1
  170. package/dist/es/standards-sdk.es172.js +64 -444
  171. package/dist/es/standards-sdk.es172.js.map +1 -1
  172. package/dist/es/standards-sdk.es173.js +142 -301
  173. package/dist/es/standards-sdk.es173.js.map +1 -1
  174. package/dist/es/standards-sdk.es174.js +310 -64
  175. package/dist/es/standards-sdk.es174.js.map +1 -1
  176. package/dist/es/standards-sdk.es175.js +337 -64
  177. package/dist/es/standards-sdk.es175.js.map +1 -1
  178. package/dist/es/standards-sdk.es176.js +438 -124
  179. package/dist/es/standards-sdk.es176.js.map +1 -1
  180. package/dist/es/standards-sdk.es177.js +310 -496
  181. package/dist/es/standards-sdk.es177.js.map +1 -1
  182. package/dist/es/standards-sdk.es178.js +60 -243
  183. package/dist/es/standards-sdk.es178.js.map +1 -1
  184. package/dist/es/standards-sdk.es179.js +118 -175
  185. package/dist/es/standards-sdk.es179.js.map +1 -1
  186. package/dist/es/standards-sdk.es18.js +12 -12
  187. package/dist/es/standards-sdk.es180.js +465 -67
  188. package/dist/es/standards-sdk.es180.js.map +1 -1
  189. package/dist/es/standards-sdk.es181.js +250 -143
  190. package/dist/es/standards-sdk.es181.js.map +1 -1
  191. package/dist/es/standards-sdk.es182.js +172 -160
  192. package/dist/es/standards-sdk.es182.js.map +1 -1
  193. package/dist/es/standards-sdk.es183.js +65 -630
  194. package/dist/es/standards-sdk.es183.js.map +1 -1
  195. package/dist/es/standards-sdk.es184.js +128 -161
  196. package/dist/es/standards-sdk.es184.js.map +1 -1
  197. package/dist/es/standards-sdk.es185.js +144 -195
  198. package/dist/es/standards-sdk.es185.js.map +1 -1
  199. package/dist/es/standards-sdk.es186.js +668 -223
  200. package/dist/es/standards-sdk.es186.js.map +1 -1
  201. package/dist/es/standards-sdk.es187.js +188 -0
  202. package/dist/es/standards-sdk.es187.js.map +1 -0
  203. package/dist/es/standards-sdk.es188.js +238 -0
  204. package/dist/es/standards-sdk.es188.js.map +1 -0
  205. package/dist/es/standards-sdk.es189.js +242 -0
  206. package/dist/es/standards-sdk.es189.js.map +1 -0
  207. package/dist/es/standards-sdk.es19.js +9 -9
  208. package/dist/es/standards-sdk.es2.js +2 -2
  209. package/dist/es/standards-sdk.es20.js +1 -1
  210. package/dist/es/standards-sdk.es21.js +1 -1
  211. package/dist/es/standards-sdk.es22.js +1 -1
  212. package/dist/es/standards-sdk.es23.js +1 -1
  213. package/dist/es/standards-sdk.es24.js +1 -1
  214. package/dist/es/standards-sdk.es25.js +1 -1
  215. package/dist/es/standards-sdk.es26.js +1 -1
  216. package/dist/es/standards-sdk.es27.js +12 -12
  217. package/dist/es/standards-sdk.es30.js +2 -2
  218. package/dist/es/standards-sdk.es31.js +4 -4
  219. package/dist/es/standards-sdk.es32.js +1 -1
  220. package/dist/es/standards-sdk.es35.js +6 -6
  221. package/dist/es/standards-sdk.es36.js +4 -4
  222. package/dist/es/standards-sdk.es37.js +2 -2
  223. package/dist/es/standards-sdk.es38.js +2 -2
  224. package/dist/es/standards-sdk.es39.js +1 -1
  225. package/dist/es/standards-sdk.es4.js +2 -2
  226. package/dist/es/standards-sdk.es40.js +1 -1
  227. package/dist/es/standards-sdk.es41.js +2 -2
  228. package/dist/es/standards-sdk.es46.js +1 -1
  229. package/dist/es/standards-sdk.es5.js +2 -2
  230. package/dist/es/standards-sdk.es51.js +1 -1
  231. package/dist/es/standards-sdk.es53.js +1 -1
  232. package/dist/es/standards-sdk.es56.js +2 -2
  233. package/dist/es/standards-sdk.es59.js +1 -1
  234. package/dist/es/standards-sdk.es6.js +2 -2
  235. package/dist/es/standards-sdk.es60.js +1 -1
  236. package/dist/es/standards-sdk.es62.js +1 -1
  237. package/dist/es/standards-sdk.es63.js +2 -2
  238. package/dist/es/standards-sdk.es64.js +1 -1
  239. package/dist/es/standards-sdk.es65.js +1 -1
  240. package/dist/es/standards-sdk.es66.js +1 -1
  241. package/dist/es/standards-sdk.es67.js +7 -7
  242. package/dist/es/standards-sdk.es69.js +1 -1
  243. package/dist/es/standards-sdk.es7.js +1 -1
  244. package/dist/es/standards-sdk.es71.js +2 -2
  245. package/dist/es/standards-sdk.es72.js +3 -3
  246. package/dist/es/standards-sdk.es75.js +5 -5
  247. package/dist/es/standards-sdk.es76.js +3 -3
  248. package/dist/es/standards-sdk.es77.js +2 -2
  249. package/dist/es/standards-sdk.es78.js +1 -1
  250. package/dist/es/standards-sdk.es81.js +2 -2
  251. package/dist/es/standards-sdk.es83.js +2 -2
  252. package/dist/es/standards-sdk.es84.js +4 -4
  253. package/dist/es/standards-sdk.es85.js +1 -1
  254. package/dist/es/standards-sdk.es88.js +1 -1
  255. package/dist/es/standards-sdk.es89.js +2 -2
  256. package/dist/es/standards-sdk.es9.js +2 -2
  257. package/dist/es/standards-sdk.es90.js +4 -4
  258. package/dist/es/standards-sdk.es94.js +3 -3
  259. package/dist/es/standards-sdk.es96.js +2 -2
  260. package/dist/es/standards-sdk.es98.js +1 -1
  261. package/dist/es/standards-sdk.es99.js +3 -3
  262. package/package.json +1 -1
@@ -1,629 +1,793 @@
1
- import { PrivateKey } from "@hashgraph/sdk";
2
- var KeyType = /* @__PURE__ */ ((KeyType2) => {
3
- KeyType2["ED25519"] = "ed25519";
4
- KeyType2["ECDSA"] = "ecdsa";
5
- KeyType2["UNKNOWN"] = "unknown";
6
- return KeyType2;
7
- })(KeyType || {});
8
- const _KeyTypeDetector = class _KeyTypeDetector {
1
+ import { proto } from "@hashgraph/proto";
2
+ import { Buffer } from "buffer";
3
+ import { Hbar, Long, HbarUnit, Transaction } from "@hashgraph/sdk";
4
+ import { ethers } from "ethers";
5
+ import { TransactionParsingError } from "./standards-sdk.es132.js";
6
+ import { resolveTransactionSummary } from "./standards-sdk.es133.js";
7
+ import { HTSParser } from "./standards-sdk.es141.js";
8
+ import { HCSParser } from "./standards-sdk.es173.js";
9
+ import { FileParser } from "./standards-sdk.es174.js";
10
+ import { CryptoParser } from "./standards-sdk.es175.js";
11
+ import { SCSParser } from "./standards-sdk.es176.js";
12
+ import { UtilParser } from "./standards-sdk.es177.js";
13
+ import { ScheduleParser } from "./standards-sdk.es142.js";
14
+ import { transactionParserRegistry } from "./standards-sdk.es143.js";
15
+ import { getTransactionTypeFromBody, getHumanReadableTransactionType } from "./standards-sdk.es144.js";
16
+ class TransactionParser {
9
17
  /**
10
- * Detects private key type from various input formats without throwing errors
18
+ * Parse transaction bytes in any supported format (base64 or hex, regular or scheduled)
19
+ * This is the main entry point for transaction parsing with enhanced retry logic
11
20
  *
12
- * This detector is designed for private keys only. It uses various heuristics to determine
13
- * the key type for ambiguous 32-byte keys, including byte patterns and statistical analysis.
14
- *
15
- * For ambiguous cases (where confidence is 'uncertain'), if you have the associated account ID,
16
- * you can use the Hedera mirror node to confirm the key type.
17
- *
18
- * @param keyInput - The key to detect, can be a string (hex, base64, PEM), Buffer, or Uint8Array
19
- * @returns KeyInfo object containing the detected key type and metadata
20
- *
21
- * @example
22
- * // Detect from hex string
23
- * const info1 = KeyTypeDetector.detect('0x7f96cea0c0d9d5bfb3ab8a42cf0cea44d57f62f2e068f8e5a3251914a9252b04');
24
- *
25
- * // Detect from DER-encoded string
26
- * const info2 = KeyTypeDetector.detect(privateKey.toStringDer());
27
- *
28
- * // Detect from PEM format
29
- * const info3 = KeyTypeDetector.detect(`-----BEGIN PRIVATE KEY-----
30
- * MC4CAQAwBQYDK2VwBCIEIGRchBsQGQduAAGBQ7GAkKCKkmQ3EGCARwHsHiRqTNR9
31
- * -----END PRIVATE KEY-----`);
21
+ * @param transactionBytes - Transaction bytes in base64 or hex format
22
+ * @param options - Parsing options and configuration
23
+ * @returns Promise resolving to ParsedTransaction
32
24
  */
33
- static detect(keyInput) {
34
- try {
35
- let keyBytes;
36
- let originalFormat = "raw";
37
- if (typeof keyInput === "string") {
38
- let trimmed = keyInput.trim();
39
- if (trimmed.includes("-----BEGIN")) {
40
- return this.detectFromPem(trimmed);
41
- }
42
- if (trimmed.toLowerCase().startsWith("0x")) {
43
- trimmed = trimmed.substring(2);
25
+ static async parseTransactionBytes(transactionBytes, options = {}) {
26
+ const {
27
+ enableFallback = true,
28
+ strictMode = false,
29
+ includeRaw = true,
30
+ maxRetries = 2
31
+ } = options;
32
+ const validation = this.validateTransactionBytes(transactionBytes);
33
+ if (!validation.isValid && strictMode) {
34
+ throw new TransactionParsingError(
35
+ `Invalid transaction bytes format: ${validation.error}`,
36
+ "INVALID_FORMAT",
37
+ void 0,
38
+ transactionBytes
39
+ );
40
+ }
41
+ let lastError;
42
+ let retryCount = 0;
43
+ while (retryCount <= maxRetries) {
44
+ try {
45
+ const result = await this.parseTransaction(transactionBytes, options);
46
+ result.formatDetection = {
47
+ originalFormat: validation.format || "base64",
48
+ wasConverted: validation.format === "hex",
49
+ length: transactionBytes.length
50
+ };
51
+ return result;
52
+ } catch (error) {
53
+ lastError = error instanceof Error ? error : new Error(String(error));
54
+ retryCount++;
55
+ if (!enableFallback || retryCount > maxRetries) {
56
+ if (strictMode) {
57
+ throw new TransactionParsingError(
58
+ "Failed to parse transaction after all attempts",
59
+ "PARSING_FAILED",
60
+ lastError,
61
+ transactionBytes
62
+ );
63
+ }
64
+ break;
44
65
  }
45
- if (this.isValidHex(trimmed)) {
46
- keyBytes = this.hexToBytes(trimmed);
47
- originalFormat = "hex";
48
- } else if (this.isBase64(trimmed)) {
49
- keyBytes = Buffer.from(trimmed, "base64");
50
- originalFormat = "der";
51
- } else {
52
- return {
53
- type: "unknown",
54
- format: "raw",
55
- isPrivateKey: false,
56
- confidence: "certain"
66
+ try {
67
+ const result = this.parseScheduledTransaction(
68
+ transactionBytes,
69
+ options
70
+ );
71
+ result.formatDetection = {
72
+ originalFormat: validation.format || "base64",
73
+ wasConverted: false,
74
+ length: transactionBytes.length
57
75
  };
76
+ return result;
77
+ } catch (scheduledError) {
58
78
  }
59
- } else if (keyInput instanceof Buffer) {
60
- keyBytes = new Uint8Array(keyInput);
61
- } else {
62
- keyBytes = keyInput;
63
79
  }
64
- return this.detectFromBytes(keyBytes, originalFormat);
65
- } catch (error) {
66
- return {
67
- type: "unknown",
68
- format: "raw",
69
- isPrivateKey: false,
70
- confidence: "certain"
71
- };
72
80
  }
81
+ const fallbackResult = this.createFallbackResult(
82
+ transactionBytes,
83
+ lastError,
84
+ void 0
85
+ );
86
+ if (fallbackResult.details) {
87
+ fallbackResult.details.parseAttempts = Math.max(retryCount, 1);
88
+ }
89
+ return fallbackResult;
73
90
  }
74
91
  /**
75
- * Detect key type from raw bytes
92
+ * Parse a Transaction object directly using unified delegation approach
93
+ * This method delegates to specialized parsers for clean separation of concerns
76
94
  *
77
- * @param bytes - The raw bytes of the key
78
- * @param format - The original format of the key
79
- * @returns KeyInfo object with detection results
80
- * @private
95
+ * @param transaction - The Transaction object to parse
96
+ * @param originalBytes - The original transaction bytes (optional, for protobuf parsing)
97
+ * @param options - Parsing options
98
+ * @returns Parsed transaction data
81
99
  */
82
- static detectFromBytes(bytes, format) {
83
- if (this.hasPrefix(bytes, this.ED25519_PUBLIC_KEY_PREFIX)) {
84
- const keyStart = this.ED25519_PUBLIC_KEY_PREFIX.length;
85
- return {
86
- type: "ed25519",
87
- format: "der",
88
- isPrivateKey: false,
89
- rawBytes: bytes.slice(keyStart),
90
- confidence: "certain"
91
- };
100
+ static parseTransactionObject(transaction, originalBytesOrOptions, options = {}) {
101
+ let originalBytes;
102
+ let actualOptions;
103
+ if (originalBytesOrOptions && !Buffer.isBuffer(originalBytesOrOptions) && !(originalBytesOrOptions instanceof Uint8Array)) {
104
+ actualOptions = originalBytesOrOptions;
105
+ originalBytes = void 0;
106
+ } else {
107
+ originalBytes = originalBytesOrOptions;
108
+ actualOptions = options;
92
109
  }
93
- if (this.hasPrefix(bytes, this.ED25519_PRIVATE_KEY_PREFIX)) {
94
- const keyStart = this.ED25519_PRIVATE_KEY_PREFIX.length;
95
- if (bytes.length >= keyStart + 32) {
96
- return {
97
- type: "ed25519",
98
- format: "der",
99
- isPrivateKey: true,
100
- rawBytes: bytes.slice(keyStart, keyStart + 32),
101
- confidence: "certain"
102
- };
110
+ try {
111
+ const metadata = this.extractTransactionMetadata(transaction);
112
+ const htsResult = HTSParser.parseFromTransactionObject(transaction);
113
+ const cryptoResult = CryptoParser.parseFromTransactionObject(transaction);
114
+ const hcsResult = HCSParser.parseFromTransactionObject(transaction);
115
+ const fileResult = FileParser.parseFromTransactionObject(transaction);
116
+ const scsResult = SCSParser.parseFromTransactionObject(transaction);
117
+ const scheduleResult = ScheduleParser.parseFromTransactionObject(transaction);
118
+ const utilResult = UtilParser.parseFromTransactionObject(transaction);
119
+ const results = [
120
+ htsResult,
121
+ cryptoResult,
122
+ hcsResult,
123
+ fileResult,
124
+ scsResult,
125
+ scheduleResult,
126
+ utilResult
127
+ ];
128
+ const primaryResult = results.find((result2) => result2.type && result2.type !== "UNKNOWN") || {};
129
+ let finalType = "UNKNOWN";
130
+ let finalHumanReadableType = "Unknown Transaction";
131
+ let parsedTokenCreation;
132
+ let protoParsingResult = {};
133
+ if (originalBytes || transaction.toBytes) {
134
+ try {
135
+ const bytesToParse = originalBytes || transaction.toBytes();
136
+ const decoded = proto.TransactionList.decode(bytesToParse);
137
+ if (decoded.transactionList && decoded.transactionList.length > 0) {
138
+ const tx = decoded.transactionList[0];
139
+ if (tx.bodyBytes && tx.bodyBytes.length > 0) {
140
+ const txBody = proto.TransactionBody.decode(tx.bodyBytes);
141
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
142
+ finalType = typeResult.type;
143
+ finalHumanReadableType = typeResult.humanReadableType;
144
+ protoParsingResult = this.parseTransactionBodyDetails(
145
+ txBody,
146
+ finalType
147
+ );
148
+ if (protoParsingResult.tokenCreation) {
149
+ parsedTokenCreation = protoParsingResult.tokenCreation;
150
+ }
151
+ } else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
152
+ const signedTx = proto.SignedTransaction.decode(
153
+ tx.signedTransactionBytes
154
+ );
155
+ if (signedTx.bodyBytes) {
156
+ const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
157
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
158
+ finalType = typeResult.type;
159
+ finalHumanReadableType = typeResult.humanReadableType;
160
+ protoParsingResult = this.parseTransactionBodyDetails(
161
+ txBody,
162
+ finalType
163
+ );
164
+ if (protoParsingResult.tokenCreation) {
165
+ parsedTokenCreation = protoParsingResult.tokenCreation;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ } catch (protoError) {
171
+ }
103
172
  }
104
- }
105
- if (this.hasPrefix(bytes, this.ECDSA_SECP256K1_PUBLIC_KEY_PREFIX)) {
106
- const keyStart = this.ECDSA_SECP256K1_PUBLIC_KEY_PREFIX.length;
107
- return {
108
- type: "ecdsa",
109
- format: "der",
110
- isPrivateKey: false,
111
- rawBytes: bytes.slice(keyStart),
112
- confidence: "certain"
113
- };
114
- }
115
- if (this.hasPrefix(bytes, this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_SHORT)) {
116
- const keyStart = this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_SHORT.length;
117
- return {
118
- type: "ecdsa",
119
- format: "der",
120
- isPrivateKey: true,
121
- rawBytes: bytes.slice(keyStart),
122
- confidence: "certain"
123
- };
124
- }
125
- if (this.hasPrefix(bytes, this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX)) {
126
- const keyStart = this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX.length;
127
- return {
128
- type: "ecdsa",
129
- format: "der",
130
- isPrivateKey: true,
131
- rawBytes: bytes.slice(keyStart, keyStart + 32),
132
- confidence: "certain"
133
- };
134
- }
135
- if (this.hasPrefix(bytes, this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_LONG)) {
136
- const keyStart = this.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_LONG.length;
137
- return {
138
- type: "ecdsa",
139
- format: "der",
140
- isPrivateKey: true,
141
- rawBytes: bytes.slice(keyStart, keyStart + 32),
142
- confidence: "certain"
173
+ if (finalType === "UNKNOWN" && primaryResult.type) {
174
+ finalType = primaryResult.type;
175
+ finalHumanReadableType = primaryResult.humanReadableType || finalHumanReadableType;
176
+ }
177
+ const result = {
178
+ type: finalType,
179
+ humanReadableType: finalHumanReadableType,
180
+ transfers: [],
181
+ tokenTransfers: [],
182
+ ...metadata,
183
+ ...primaryResult,
184
+ raw: actualOptions.includeRaw ? transaction._transactionBody || {} : void 0
143
185
  };
144
- }
145
- if (bytes.length > 36 && this.containsECDSAPrivateKeyPattern(bytes)) {
186
+ this.mergeProtoParsingResults(
187
+ result,
188
+ protoParsingResult,
189
+ htsResult,
190
+ transaction,
191
+ originalBytes
192
+ );
193
+ result.transfers = cryptoResult.transfers || result.transfers || [];
194
+ result.tokenTransfers = cryptoResult.tokenTransfers || result.tokenTransfers || [];
195
+ return result;
196
+ } catch (error) {
146
197
  return {
147
- type: "ecdsa",
148
- format: "der",
149
- isPrivateKey: true,
150
- rawBytes: this.extractECDSAPrivateKey(bytes),
151
- confidence: "certain"
152
- };
153
- }
154
- switch (bytes.length) {
155
- case this.ED25519_PUBLIC_KEY_LENGTH:
156
- if (format === "hex") {
157
- const hexStr = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
158
- const privateResult = this.tryCreateKey(hexStr);
159
- if (privateResult.type !== "unknown") {
160
- return privateResult;
161
- }
198
+ type: "UNKNOWN",
199
+ humanReadableType: "Unknown Transaction",
200
+ transfers: [],
201
+ tokenTransfers: [],
202
+ raw: actualOptions.includeRaw ? {} : void 0,
203
+ details: {
204
+ error: `Failed to parse Transaction object: ${error instanceof Error ? error.message : String(error)}`
162
205
  }
163
- return {
164
- type: "unknown",
165
- format,
166
- isPrivateKey: false,
167
- rawBytes: bytes,
168
- confidence: "certain"
169
- };
170
- case this.ED25519_EXPANDED_PRIVATE_KEY_LENGTH:
171
- return {
172
- type: "ed25519",
173
- format,
174
- isPrivateKey: true,
175
- rawBytes: bytes,
176
- confidence: "certain"
177
- };
206
+ };
178
207
  }
179
- return {
180
- type: "unknown",
181
- format,
182
- isPrivateKey: false,
183
- rawBytes: bytes,
184
- confidence: "certain"
185
- };
186
208
  }
187
209
  /**
188
- * Detect key type from PEM format
189
- *
190
- * @param pem - The PEM-encoded key string
191
- * @returns KeyInfo object with detection results
192
- * @private
210
+ * Parse a base64 encoded transaction body using registry pattern
211
+ * @param transactionBodyBase64 - The base64 encoded transaction body
212
+ * @returns The parsed transaction
193
213
  */
194
- static detectFromPem(pem) {
195
- const trimmedPem = pem.trim();
196
- const isPrivateKey = trimmedPem.includes("PRIVATE KEY");
197
- const pemTypes = {
198
- EC_PRIVATE: /-----BEGIN EC PRIVATE KEY-----/,
199
- EC_PUBLIC: /-----BEGIN EC PUBLIC KEY-----/,
200
- PRIVATE: /-----BEGIN PRIVATE KEY-----/,
201
- PUBLIC: /-----BEGIN PUBLIC KEY-----/
202
- };
203
- let isECKey = false;
204
- for (const [type, regex] of Object.entries(pemTypes)) {
205
- if (regex.test(trimmedPem) && type.includes("EC")) {
206
- isECKey = true;
207
- break;
214
+ static parseTransactionBody(transactionBodyBase64) {
215
+ try {
216
+ const buffer = ethers.decodeBase64(transactionBodyBase64);
217
+ const txBody = proto.SchedulableTransactionBody.decode(buffer);
218
+ const transactionType = this.getTransactionType(txBody);
219
+ const result = {
220
+ type: transactionType,
221
+ humanReadableType: this.getHumanReadableType(transactionType),
222
+ transfers: [],
223
+ tokenTransfers: [],
224
+ raw: txBody
225
+ };
226
+ if (txBody.memo) {
227
+ result.memo = txBody.memo;
208
228
  }
209
- }
210
- const beginMarkerIndex = trimmedPem.indexOf("-----BEGIN ");
211
- if (beginMarkerIndex === -1) {
229
+ if (txBody.transactionFee) {
230
+ const hbarAmount = Hbar.fromTinybars(
231
+ Long.fromValue(txBody.transactionFee)
232
+ );
233
+ result.transactionFee = hbarAmount.toString(HbarUnit.Hbar);
234
+ }
235
+ this.applySchedulableTransactionParsing(txBody, result);
236
+ return result;
237
+ } catch (error) {
212
238
  return {
213
- type: "unknown",
214
- format: "pem",
215
- isPrivateKey,
216
- confidence: "certain"
239
+ type: "UNKNOWN",
240
+ humanReadableType: "Unknown Transaction",
241
+ transfers: [],
242
+ tokenTransfers: [],
243
+ raw: void 0,
244
+ details: {
245
+ error: `Failed to parse transaction body: ${error instanceof Error ? error.message : String(error)}`
246
+ }
217
247
  };
218
248
  }
219
- const beginLineEndIndex = trimmedPem.indexOf("\n", beginMarkerIndex);
220
- if (beginLineEndIndex === -1) {
249
+ }
250
+ /**
251
+ * Detect transaction type and human-readable type from transaction body protobuf
252
+ * Uses registry pattern to eliminate massive if-else chain
253
+ */
254
+ static detectTransactionTypeFromBody(txBody) {
255
+ return getTransactionTypeFromBody(txBody);
256
+ }
257
+ /**
258
+ * Parse details from a complete schedule response
259
+ * @param scheduleResponse - The schedule response to parse
260
+ * @returns The parsed transaction
261
+ */
262
+ static parseScheduleResponse(scheduleResponse) {
263
+ if (!scheduleResponse.transaction_body) {
221
264
  return {
222
- type: "unknown",
223
- format: "pem",
224
- isPrivateKey,
225
- confidence: "certain"
265
+ type: "UNKNOWN",
266
+ humanReadableType: "Unknown Transaction",
267
+ transfers: [],
268
+ tokenTransfers: [],
269
+ raw: void 0,
270
+ details: {
271
+ error: "Schedule response missing transaction_body"
272
+ }
226
273
  };
227
274
  }
228
- const endMarkerIndex = trimmedPem.lastIndexOf("-----END ");
229
- if (endMarkerIndex === -1 || endMarkerIndex <= beginLineEndIndex) {
230
- return {
231
- type: "unknown",
232
- format: "pem",
233
- isPrivateKey,
234
- confidence: "certain"
235
- };
275
+ const parsed = this.parseTransactionBody(scheduleResponse.transaction_body);
276
+ if (scheduleResponse.memo) {
277
+ parsed.memo = scheduleResponse.memo;
236
278
  }
237
- const base64Content = trimmedPem.slice(beginLineEndIndex + 1, endMarkerIndex).replace(/\s/g, "");
238
- if (!base64Content) {
279
+ return parsed;
280
+ }
281
+ /**
282
+ * Determine the transaction type using registry pattern
283
+ * @param txBody - The transaction body to determine the type of
284
+ * @returns The type of the transaction
285
+ */
286
+ static getTransactionType(txBody) {
287
+ return getTransactionTypeFromBody(txBody).type;
288
+ }
289
+ /**
290
+ * Convert technical transaction type to human-readable format using registry pattern
291
+ * @param type - The technical transaction type
292
+ * @returns The human-readable transaction type
293
+ */
294
+ static getHumanReadableType(type) {
295
+ return getHumanReadableTransactionType(type);
296
+ }
297
+ /**
298
+ * Get a human-readable summary of the transaction
299
+ * @param parsedTx - The parsed transaction
300
+ * @returns The human-readable summary of the transaction
301
+ */
302
+ static getTransactionSummary(parsedTx) {
303
+ return resolveTransactionSummary(parsedTx);
304
+ }
305
+ /**
306
+ * Validate transaction bytes format and encoding
307
+ * Enhanced validation with better format detection
308
+ */
309
+ static validateTransactionBytes(transactionBytes) {
310
+ if (!transactionBytes || typeof transactionBytes !== "string") {
239
311
  return {
240
- type: "unknown",
241
- format: "pem",
242
- isPrivateKey,
243
- confidence: "certain"
312
+ isValid: false,
313
+ error: "Transaction bytes must be a non-empty string"
244
314
  };
245
315
  }
246
- try {
247
- const derBytes = Buffer.from(base64Content, "base64");
248
- const result = this.detectFromBytes(new Uint8Array(derBytes), "der");
249
- if (result.type === "unknown" && isECKey) {
250
- return {
251
- type: "ecdsa",
252
- format: "pem",
253
- isPrivateKey,
254
- rawBytes: derBytes,
255
- confidence: "certain"
256
- };
316
+ const format = this.detectTransactionFormat(transactionBytes);
317
+ const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
318
+ const hexRegex = /^0x[0-9a-fA-F]+$/;
319
+ let isValid = false;
320
+ let error;
321
+ if (format === "hex") {
322
+ isValid = hexRegex.test(transactionBytes) && transactionBytes.length > 2;
323
+ if (!isValid) {
324
+ error = "Invalid hex format";
325
+ }
326
+ } else {
327
+ isValid = base64Regex.test(transactionBytes) && transactionBytes.length > 0;
328
+ if (!isValid) {
329
+ error = "Invalid base64 format";
257
330
  }
258
- return {
259
- ...result,
260
- format: "pem"
261
- };
262
- } catch {
263
- return {
264
- type: "unknown",
265
- format: "pem",
266
- isPrivateKey,
267
- confidence: "certain"
268
- };
269
331
  }
332
+ return {
333
+ isValid,
334
+ format,
335
+ error,
336
+ length: transactionBytes.length
337
+ };
270
338
  }
271
339
  /**
272
- * Try to create a key using Hedera SDK to validate the type
273
- *
274
- * @param keyInput - The key input string or bytes
275
- * @returns KeyInfo object with detection results
276
- * @private
340
+ * Detects the format of transaction bytes
341
+ * @param transactionBytes - The transaction bytes to analyze
342
+ * @returns The detected format ('base64' or 'hex')
343
+ */
344
+ static detectTransactionFormat(transactionBytes) {
345
+ return transactionBytes.startsWith("0x") ? "hex" : "base64";
346
+ }
347
+ /**
348
+ * Decodes transaction bytes from string to Uint8Array
349
+ * @param transactionBytes - The transaction bytes string (base64 or hex)
350
+ * @returns Decoded Uint8Array
351
+ * @throws TransactionParsingError if decoding fails
277
352
  */
278
- static tryCreateKey(keyInput) {
353
+ static decodeTransactionBytes(transactionBytes) {
279
354
  try {
280
- if (typeof keyInput === "string") {
281
- let keyStr = keyInput.trim();
282
- if (keyStr.toLowerCase().startsWith("0x")) {
283
- keyStr = keyStr.substring(2);
284
- }
285
- if (this.isValidHex(keyStr) && keyStr.length === 64) {
286
- const keyBytes = this.hexToBytes(keyStr);
287
- const signatureResult = this.detectBySignature(keyStr);
288
- if (signatureResult.type !== "unknown") {
289
- return {
290
- type: signatureResult.type,
291
- format: "hex",
292
- isPrivateKey: true,
293
- rawBytes: keyBytes,
294
- confidence: signatureResult.confidence,
295
- warning: signatureResult.warning
296
- };
297
- }
298
- return {
299
- type: "unknown",
300
- format: "hex",
301
- isPrivateKey: false,
302
- rawBytes: keyBytes,
303
- confidence: "certain"
304
- };
305
- }
355
+ const format = this.detectTransactionFormat(transactionBytes);
356
+ if (format === "hex") {
357
+ const hexString = transactionBytes.slice(2);
358
+ return new Uint8Array(Buffer.from(hexString, "hex"));
359
+ } else {
360
+ return new Uint8Array(Buffer.from(transactionBytes, "base64"));
306
361
  }
307
- } catch {
362
+ } catch (error) {
363
+ throw new TransactionParsingError(
364
+ "Failed to decode transaction bytes",
365
+ "DECODE_ERROR",
366
+ error instanceof Error ? error : void 0,
367
+ transactionBytes
368
+ );
308
369
  }
309
- return {
310
- type: "unknown",
311
- format: "hex",
312
- isPrivateKey: false,
313
- rawBytes: new Uint8Array(),
314
- confidence: "certain"
315
- };
316
370
  }
317
371
  /**
318
- * Detect key type by attempting to sign a message with both algorithms
319
- *
320
- * For ambiguous cases where both algorithms can use the key, this method
321
- * uses heuristics to make a best-effort determination. For production use
322
- * with ambiguous keys, consider using the Hedera mirror node to confirm
323
- * the key type if you have the associated account ID.
324
- *
325
- * @param hexKey - The hex string representation of the key
326
- * @returns Object containing type, confidence level, and optional warning
327
- * @private
372
+ * Check if transaction bytes represent a valid Hedera transaction
328
373
  */
329
- static detectBySignature(hexKey) {
330
- const keyBigInt = BigInt("0x" + hexKey);
331
- const secp256k1Order = BigInt(
332
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
333
- );
334
- if (keyBigInt === 0n) {
335
- return {
336
- type: "ed25519",
337
- confidence: "certain"
338
- };
339
- }
340
- if (keyBigInt >= secp256k1Order) {
341
- return {
342
- type: "ed25519",
343
- confidence: "certain"
344
- };
345
- }
346
- let ed25519CanSign = false;
347
- let ecdsaCanSign = false;
374
+ static async isValidHederaTransaction(transactionBytes) {
348
375
  try {
349
- const ed25519Key = PrivateKey.fromStringED25519(hexKey);
350
- const testMessage = new Uint8Array([1, 2, 3, 4, 5]);
351
- const signature = ed25519Key.sign(testMessage);
352
- if (ed25519Key.publicKey.verify(testMessage, signature)) {
353
- ed25519CanSign = true;
376
+ if (!this.validateTransactionBytes(transactionBytes).isValid) {
377
+ return false;
354
378
  }
379
+ const bytes = this.decodeTransactionBytes(transactionBytes);
380
+ Transaction.fromBytes(bytes);
381
+ return true;
355
382
  } catch {
383
+ return false;
356
384
  }
385
+ }
386
+ /**
387
+ * Legacy alias for decodeTransactionBytes - keeping for backward compatibility
388
+ */
389
+ static decodeBytesLegacy(transactionBytes) {
390
+ return this.decodeTransactionBytes(transactionBytes);
391
+ }
392
+ /**
393
+ * Parse transaction bytes into structured data using thin orchestration
394
+ * Delegates to specialized parsers for clean separation of concerns
395
+ */
396
+ static async parseTransaction(transactionBytes, options = {}) {
357
397
  try {
358
- const ecdsaKey = PrivateKey.fromStringECDSA(hexKey);
359
- const testMessage = new Uint8Array([1, 2, 3, 4, 5]);
360
- const signature = ecdsaKey.sign(testMessage);
361
- if (ecdsaKey.publicKey.verify(testMessage, signature)) {
362
- ecdsaCanSign = true;
363
- }
364
- } catch {
365
- }
366
- if (ed25519CanSign && ecdsaCanSign) {
367
- const keyBytes = this.hexToBytes(hexKey);
368
- if (keyBytes[0] === 168 && keyBytes[1] === 1) {
369
- return {
370
- type: "ed25519",
371
- confidence: "uncertain",
372
- warning: "Detection based on byte pattern heuristic. Both ED25519 and ECDSA accept this key."
373
- };
374
- }
375
- let highBytes = 0;
376
- for (const byte of keyBytes) {
377
- if (byte >= 128) highBytes++;
378
- }
379
- const highByteRatio = highBytes / keyBytes.length;
380
- if (highByteRatio >= 0.4 && highByteRatio <= 0.6) {
381
- return {
382
- type: "ecdsa",
383
- confidence: "uncertain",
384
- warning: "Detection based on entropy heuristic. Both ED25519 and ECDSA accept this key."
385
- };
386
- }
387
- return {
388
- type: "ecdsa",
389
- confidence: "uncertain",
390
- warning: "Detection based on entropy heuristic. Both ED25519 and ECDSA accept this key. Defaulting to ECDSA."
391
- };
392
- }
393
- if (ed25519CanSign && !ecdsaCanSign) {
394
- return {
395
- type: "ed25519",
396
- confidence: "certain"
398
+ const bytes = this.decodeTransactionBytes(transactionBytes);
399
+ const transaction = Transaction.fromBytes(bytes);
400
+ const metadata = this.extractTransactionMetadataEnhanced(transaction);
401
+ const parserResults = this.runAllParsers(transaction);
402
+ const primaryResult = parserResults.find(
403
+ (result2) => result2.type && result2.type !== "UNKNOWN"
404
+ ) || {};
405
+ const protoParsingResult = this.parseFromProtobuf(bytes);
406
+ const finalType = protoParsingResult.type || primaryResult.type || "UNKNOWN";
407
+ const finalHumanReadableType = protoParsingResult.humanReadableType || primaryResult.humanReadableType || "Unknown Transaction";
408
+ const result = {
409
+ type: finalType,
410
+ humanReadableType: finalHumanReadableType,
411
+ transfers: [],
412
+ tokenTransfers: [],
413
+ details: { ...metadata },
414
+ memo: typeof metadata.memo === "string" ? metadata.memo : void 0,
415
+ transactionId: typeof metadata.transactionId === "string" ? metadata.transactionId : void 0,
416
+ nodeAccountIds: Array.isArray(metadata.nodeAccountIds) ? metadata.nodeAccountIds : [],
417
+ maxTransactionFee: typeof metadata.maxTransactionFee === "string" ? metadata.maxTransactionFee : void 0,
418
+ validStart: typeof metadata.validStart === "string" ? metadata.validStart : void 0,
419
+ validDuration: typeof metadata.validDuration === "string" ? metadata.validDuration : void 0,
420
+ raw: options.includeRaw ? {} : void 0
397
421
  };
422
+ this.mergeAllResults(
423
+ result,
424
+ protoParsingResult,
425
+ primaryResult,
426
+ parserResults
427
+ );
428
+ return result;
429
+ } catch (error) {
430
+ throw new TransactionParsingError(
431
+ "Failed to parse as regular transaction",
432
+ "REGULAR_PARSING_FAILED",
433
+ error instanceof Error ? error : void 0,
434
+ transactionBytes
435
+ );
398
436
  }
399
- if (ecdsaCanSign && !ed25519CanSign) {
400
- return {
401
- type: "ecdsa",
402
- confidence: "certain"
437
+ }
438
+ /**
439
+ * Parse scheduled transaction body
440
+ */
441
+ static parseScheduledTransaction(transactionBytes, options = {}) {
442
+ try {
443
+ const parsedTx = this.parseTransactionBody(transactionBytes);
444
+ const validation = this.validateTransactionBytes(transactionBytes);
445
+ const enhancedResult = {
446
+ ...parsedTx,
447
+ details: {
448
+ ...parsedTx.details || {},
449
+ parseMethod: "scheduled",
450
+ validation,
451
+ parseAttempts: parsedTx.details?.parseAttempts || 1
452
+ },
453
+ formatDetection: {
454
+ originalFormat: validation.format || "base64",
455
+ wasConverted: false,
456
+ length: transactionBytes.length
457
+ }
403
458
  };
459
+ return enhancedResult;
460
+ } catch (error) {
461
+ throw new TransactionParsingError(
462
+ "Failed to parse as scheduled transaction",
463
+ "SCHEDULED_PARSING_FAILED",
464
+ error instanceof Error ? error : void 0,
465
+ transactionBytes
466
+ );
404
467
  }
468
+ }
469
+ /**
470
+ * Extract metadata from Transaction object (legacy method - keeping for backward compatibility)
471
+ */
472
+ static extractTransactionMetadata(transaction) {
405
473
  return {
406
- type: "unknown",
407
- confidence: "certain"
474
+ transactionId: transaction.transactionId?.toString(),
475
+ nodeAccountIds: transaction.nodeAccountIds?.map((id) => id.toString()) || [],
476
+ maxTransactionFee: transaction.maxTransactionFee?.toTinybars().toString() || "0",
477
+ memo: transaction._transactionMemo || void 0,
478
+ transfers: [],
479
+ tokenTransfers: []
408
480
  };
409
481
  }
410
482
  /**
411
- * Check if a string is valid hexadecimal with even length
412
- *
413
- * @param str - The string to check
414
- * @returns True if the string is valid hex with even length
415
- * @private
483
+ * Extract enhanced metadata from Transaction object
416
484
  */
417
- static isValidHex(str) {
418
- return /^[0-9a-fA-F]+$/.test(str) && str.length % 2 === 0;
485
+ static extractTransactionMetadataEnhanced(transaction) {
486
+ return {
487
+ transactionId: transaction.transactionId?.toString(),
488
+ nodeAccountIds: transaction.nodeAccountIds?.map((id) => id.toString()) || [],
489
+ maxTransactionFee: transaction.maxTransactionFee?.toTinybars().toString() || "0",
490
+ memo: transaction._transactionMemo || void 0,
491
+ validStart: transaction._transactionValidStart?.toString(),
492
+ validDuration: transaction._transactionValidDuration?.toString()
493
+ };
419
494
  }
420
495
  /**
421
- * Check if a string is valid base64
422
- *
423
- * @param str - The string to check
424
- * @returns True if the string is valid base64
425
- * @private
496
+ * Run all available parsers on a transaction
497
+ */
498
+ static runAllParsers(transaction) {
499
+ return [
500
+ HTSParser.parseFromTransactionObject(transaction),
501
+ CryptoParser.parseFromTransactionObject(transaction),
502
+ HCSParser.parseFromTransactionObject(transaction),
503
+ FileParser.parseFromTransactionObject(transaction),
504
+ SCSParser.parseFromTransactionObject(transaction),
505
+ ScheduleParser.parseFromTransactionObject(transaction),
506
+ UtilParser.parseFromTransactionObject(transaction)
507
+ ];
508
+ }
509
+ /**
510
+ * Parse transaction from protobuf bytes
426
511
  */
427
- static isBase64(str) {
512
+ static parseFromProtobuf(bytes) {
513
+ const result = {};
428
514
  try {
429
- return Buffer.from(str, "base64").toString("base64") === str;
430
- } catch {
431
- return false;
515
+ const decoded = proto.TransactionList.decode(bytes);
516
+ if (decoded.transactionList && decoded.transactionList.length > 0) {
517
+ const tx = decoded.transactionList[0];
518
+ let txBody = null;
519
+ if (tx.bodyBytes && tx.bodyBytes.length > 0) {
520
+ txBody = proto.TransactionBody.decode(tx.bodyBytes);
521
+ } else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
522
+ const signedTx = proto.SignedTransaction.decode(
523
+ tx.signedTransactionBytes
524
+ );
525
+ if (signedTx.bodyBytes) {
526
+ txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
527
+ }
528
+ }
529
+ if (txBody) {
530
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
531
+ result.type = typeResult.type;
532
+ result.humanReadableType = typeResult.humanReadableType;
533
+ const details = this.parseTransactionBodyDetails(
534
+ txBody,
535
+ typeResult.type
536
+ );
537
+ Object.assign(result, details);
538
+ }
539
+ }
540
+ } catch (error) {
432
541
  }
542
+ return result;
433
543
  }
434
544
  /**
435
- * Convert a hex string to bytes
436
- *
437
- * @param hex - The hex string to convert
438
- * @returns Uint8Array of bytes
439
- * @private
545
+ * Intelligently merge all parsing results
440
546
  */
441
- static hexToBytes(hex) {
442
- const bytes = new Uint8Array(hex.length / 2);
443
- for (let i = 0; i < hex.length; i += 2) {
444
- bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
445
- }
446
- return bytes;
547
+ static mergeAllResults(result, protoResult, primaryResult, parserResults) {
548
+ const cryptoResult = parserResults.find((r) => r.transfers || r.tokenTransfers) || {};
549
+ result.transfers = cryptoResult.transfers || result.transfers || [];
550
+ result.tokenTransfers = cryptoResult.tokenTransfers || result.tokenTransfers || [];
551
+ Object.keys(protoResult).forEach((key) => {
552
+ if (protoResult[key] !== void 0 && key !== "type" && key !== "humanReadableType") {
553
+ result[key] = protoResult[key];
554
+ }
555
+ });
556
+ Object.keys(primaryResult).forEach((key) => {
557
+ if (primaryResult[key] !== void 0 && !(key in result) && key !== "type" && key !== "humanReadableType") {
558
+ result[key] = primaryResult[key];
559
+ }
560
+ });
447
561
  }
448
562
  /**
449
- * Check if bytes start with a specific prefix
450
- *
451
- * @param bytes - The bytes to check
452
- * @param prefix - The prefix to look for
453
- * @returns True if bytes start with the prefix
454
- * @private
563
+ * Apply schedulable transaction parsing using registry pattern
564
+ * Eliminates conditional logic in parseTransactionBody
455
565
  */
456
- static hasPrefix(bytes, prefix) {
457
- if (bytes.length < prefix.length) return false;
458
- for (let i = 0; i < prefix.length; i++) {
459
- if (bytes[i] !== prefix[i]) return false;
566
+ static applySchedulableTransactionParsing(txBody, result) {
567
+ if (txBody.cryptoTransfer) {
568
+ CryptoParser.parseCryptoTransfers(txBody.cryptoTransfer, result);
569
+ }
570
+ if (txBody.cryptoDelete) {
571
+ result.cryptoDelete = CryptoParser.parseCryptoDelete(txBody.cryptoDelete);
572
+ }
573
+ if (txBody.cryptoCreateAccount) {
574
+ result.cryptoCreateAccount = CryptoParser.parseCryptoCreateAccount(
575
+ txBody.cryptoCreateAccount
576
+ );
577
+ }
578
+ if (txBody.cryptoUpdateAccount) {
579
+ result.cryptoUpdateAccount = CryptoParser.parseCryptoUpdateAccount(
580
+ txBody.cryptoUpdateAccount
581
+ );
582
+ }
583
+ if (txBody.cryptoApproveAllowance) {
584
+ result.cryptoApproveAllowance = CryptoParser.parseCryptoApproveAllowance(
585
+ txBody.cryptoApproveAllowance
586
+ );
587
+ }
588
+ if (txBody.cryptoDeleteAllowance) {
589
+ result.cryptoDeleteAllowance = CryptoParser.parseCryptoDeleteAllowance(
590
+ txBody.cryptoDeleteAllowance
591
+ );
592
+ }
593
+ if (txBody.contractCall) {
594
+ result.contractCall = SCSParser.parseContractCall(txBody.contractCall);
595
+ }
596
+ if (txBody.contractCreateInstance) {
597
+ result.contractCreate = SCSParser.parseContractCreate(
598
+ txBody.contractCreateInstance
599
+ );
600
+ }
601
+ if (txBody.contractUpdateInstance) {
602
+ result.contractUpdate = SCSParser.parseContractUpdate(
603
+ txBody.contractUpdateInstance
604
+ );
605
+ }
606
+ if (txBody.contractDeleteInstance) {
607
+ result.contractDelete = SCSParser.parseContractDelete(
608
+ txBody.contractDeleteInstance
609
+ );
610
+ }
611
+ if (txBody.tokenCreation) {
612
+ result.tokenCreation = HTSParser.parseTokenCreate(txBody.tokenCreation);
613
+ }
614
+ if (txBody.tokenMint) {
615
+ result.tokenMint = HTSParser.parseTokenMint(txBody.tokenMint);
616
+ }
617
+ if (txBody.tokenBurn) {
618
+ result.tokenBurn = HTSParser.parseTokenBurn(txBody.tokenBurn);
619
+ }
620
+ if (txBody.tokenUpdate) {
621
+ result.tokenUpdate = HTSParser.parseTokenUpdate(txBody.tokenUpdate);
622
+ }
623
+ if (txBody.tokenFeeScheduleUpdate) {
624
+ result.tokenFeeScheduleUpdate = HTSParser.parseTokenFeeScheduleUpdate(
625
+ txBody.tokenFeeScheduleUpdate
626
+ );
627
+ }
628
+ if (txBody.tokenFreeze) {
629
+ result.tokenFreeze = HTSParser.parseTokenFreeze(txBody.tokenFreeze);
630
+ }
631
+ if (txBody.tokenUnfreeze) {
632
+ result.tokenUnfreeze = HTSParser.parseTokenUnfreeze(txBody.tokenUnfreeze);
633
+ }
634
+ if (txBody.tokenGrantKyc) {
635
+ result.tokenGrantKyc = HTSParser.parseTokenGrantKyc(txBody.tokenGrantKyc);
636
+ }
637
+ if (txBody.tokenRevokeKyc) {
638
+ result.tokenRevokeKyc = HTSParser.parseTokenRevokeKyc(
639
+ txBody.tokenRevokeKyc
640
+ );
641
+ }
642
+ if (txBody.tokenPause) {
643
+ result.tokenPause = HTSParser.parseTokenPause(txBody.tokenPause);
644
+ }
645
+ if (txBody.tokenUnpause) {
646
+ result.tokenUnpause = HTSParser.parseTokenUnpause(txBody.tokenUnpause);
647
+ }
648
+ if (txBody.tokenWipe) {
649
+ result.tokenWipeAccount = HTSParser.parseTokenWipeAccount(
650
+ txBody.tokenWipe
651
+ );
652
+ }
653
+ if (txBody.tokenDeletion) {
654
+ result.tokenDelete = HTSParser.parseTokenDelete(txBody.tokenDeletion);
655
+ }
656
+ if (txBody.tokenAssociate) {
657
+ result.tokenAssociate = HTSParser.parseTokenAssociate(
658
+ txBody.tokenAssociate
659
+ );
660
+ }
661
+ if (txBody.tokenDissociate) {
662
+ result.tokenDissociate = HTSParser.parseTokenDissociate(
663
+ txBody.tokenDissociate
664
+ );
665
+ }
666
+ if (txBody.tokenAirdrop) {
667
+ result.tokenAirdrop = HTSParser.parseTokenAirdropFromProto(
668
+ txBody.tokenAirdrop
669
+ );
670
+ }
671
+ if (txBody.consensusCreateTopic) {
672
+ result.consensusCreateTopic = HCSParser.parseConsensusCreateTopic(
673
+ txBody.consensusCreateTopic
674
+ );
675
+ }
676
+ if (txBody.consensusSubmitMessage) {
677
+ result.consensusSubmitMessage = HCSParser.parseConsensusSubmitMessage(
678
+ txBody.consensusSubmitMessage
679
+ );
680
+ }
681
+ if (txBody.consensusUpdateTopic) {
682
+ result.consensusUpdateTopic = HCSParser.parseConsensusUpdateTopic(
683
+ txBody.consensusUpdateTopic
684
+ );
685
+ }
686
+ if (txBody.consensusDeleteTopic) {
687
+ result.consensusDeleteTopic = HCSParser.parseConsensusDeleteTopic(
688
+ txBody.consensusDeleteTopic
689
+ );
690
+ }
691
+ if (txBody.fileCreate) {
692
+ result.fileCreate = FileParser.parseFileCreate(txBody.fileCreate);
693
+ }
694
+ if (txBody.fileAppend) {
695
+ result.fileAppend = FileParser.parseFileAppend(txBody.fileAppend);
696
+ }
697
+ if (txBody.fileUpdate) {
698
+ result.fileUpdate = FileParser.parseFileUpdate(txBody.fileUpdate);
699
+ }
700
+ if (txBody.fileDelete) {
701
+ result.fileDelete = FileParser.parseFileDelete(txBody.fileDelete);
702
+ }
703
+ if (txBody.utilPrng) {
704
+ result.utilPrng = UtilParser.parseUtilPrng(txBody.utilPrng);
460
705
  }
461
- return true;
462
706
  }
463
707
  /**
464
- * Check if bytes contain an ECDSA private key pattern
465
- *
466
- * @param bytes - The bytes to check
467
- * @returns True if ECDSA private key pattern is found
468
- * @private
708
+ * Parse transaction body details for all supported transaction types
709
+ * Uses a scalable registry pattern instead of if-else chains
469
710
  */
470
- static containsECDSAPrivateKeyPattern(bytes) {
471
- for (let i = 0; i < bytes.length - 7; i++) {
472
- if (bytes[i] === 48 && bytes[i + 1] === 116 && bytes[i + 2] === 2 && bytes[i + 3] === 1 && bytes[i + 4] === 1 && bytes[i + 5] === 4 && bytes[i + 6] === 32) {
473
- return true;
711
+ static parseTransactionBodyDetails(txBody, transactionType) {
712
+ const result = {};
713
+ const parserConfig = transactionParserRegistry[transactionType];
714
+ if (parserConfig) {
715
+ const bodyData = txBody[parserConfig.bodyField];
716
+ if (bodyData) {
717
+ const parserResult = parserConfig.parser(bodyData);
718
+ if (parserConfig.spreadResult) {
719
+ Object.assign(result, parserResult);
720
+ } else {
721
+ result[parserConfig.resultField] = parserResult;
722
+ }
474
723
  }
475
724
  }
476
- return false;
725
+ return result;
477
726
  }
478
727
  /**
479
- * Extract ECDSA private key from DER structure
480
- *
481
- * @param bytes - The DER encoded bytes
482
- * @returns The extracted private key bytes
483
- * @private
728
+ * Merge protobuf parsing results with parser results using registry pattern
729
+ * Eliminates transactionFields array and forEach logic
484
730
  */
485
- static extractECDSAPrivateKey(bytes) {
486
- for (let i = 0; i < bytes.length - 32; i++) {
487
- if (bytes[i] === 4 && bytes[i + 1] === 32) {
488
- return bytes.slice(i + 2, i + 34);
731
+ static mergeProtoParsingResults(result, protoResult, htsResult, transaction, originalBytes) {
732
+ const fieldsToMerge = Object.values(transactionParserRegistry).map(
733
+ (config) => config.resultField
734
+ );
735
+ for (const field of fieldsToMerge) {
736
+ const protoValue = protoResult[field];
737
+ const htsValue = htsResult[field];
738
+ if (protoValue !== void 0) {
739
+ result[field] = protoValue;
740
+ } else if (htsValue !== void 0) {
741
+ result[field] = htsValue;
742
+ } else {
743
+ this.handleSpecialFieldExtraction(result, field, transaction);
489
744
  }
490
745
  }
491
- return bytes;
492
746
  }
493
- };
494
- _KeyTypeDetector.ED25519_PUBLIC_KEY_LENGTH = 32;
495
- _KeyTypeDetector.ED25519_EXPANDED_PRIVATE_KEY_LENGTH = 64;
496
- _KeyTypeDetector.ED25519_PUBLIC_KEY_PREFIX = Buffer.from([
497
- 48,
498
- 42,
499
- 48,
500
- 5,
501
- 6,
502
- 3,
503
- 43,
504
- 101,
505
- 112,
506
- 3,
507
- 33,
508
- 0
509
- ]);
510
- _KeyTypeDetector.ED25519_PRIVATE_KEY_PREFIX = Buffer.from([
511
- 48,
512
- 46,
513
- 2,
514
- 1,
515
- 0,
516
- 48,
517
- 5,
518
- 6,
519
- 3,
520
- 43,
521
- 101,
522
- 112,
523
- 4,
524
- 34,
525
- 4,
526
- 32
527
- ]);
528
- _KeyTypeDetector.ECDSA_SECP256K1_PUBLIC_KEY_PREFIX = Buffer.from([
529
- 48,
530
- 86,
531
- 48,
532
- 16,
533
- 6,
534
- 7,
535
- 42,
536
- 134,
537
- 72,
538
- 206,
539
- 61,
540
- 2,
541
- 1,
542
- 6,
543
- 5,
544
- 43,
545
- 129,
546
- 4,
547
- 0,
548
- 10,
549
- 3,
550
- 66,
551
- 0
552
- ]);
553
- _KeyTypeDetector.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX = Buffer.from([
554
- 48,
555
- 116,
556
- 2,
557
- 1,
558
- 1,
559
- 4,
560
- 32
561
- ]);
562
- _KeyTypeDetector.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_SHORT = Buffer.from([
563
- 48,
564
- 48,
565
- 2,
566
- 1,
567
- 0,
568
- 48,
569
- 7,
570
- 6,
571
- 5,
572
- 43,
573
- 129,
574
- 4,
575
- 0,
576
- 10,
577
- 4,
578
- 34,
579
- 4,
580
- 32
581
- ]);
582
- _KeyTypeDetector.ECDSA_SECP256K1_PRIVATE_KEY_PREFIX_LONG = Buffer.from(
583
- [48, 119, 2, 1, 1, 4, 32]
584
- );
585
- let KeyTypeDetector = _KeyTypeDetector;
586
- function detectKeyTypeFromString(privateKeyString) {
587
- const keyInfo = KeyTypeDetector.detect(privateKeyString);
588
- if (keyInfo.type !== "unknown") {
589
- try {
590
- const privateKey = keyInfo.type === "ecdsa" ? PrivateKey.fromStringECDSA(privateKeyString) : PrivateKey.fromStringED25519(privateKeyString);
591
- const result = {
592
- detectedType: keyInfo.type,
593
- privateKey
594
- };
595
- if (keyInfo.confidence === "uncertain") {
596
- result.warning = `Key type detection is uncertain. If you have the associated account ID, consider using the Hedera mirror node to confirm the key type.`;
747
+ /**
748
+ * Handle special field extraction cases using registry pattern
749
+ */
750
+ static handleSpecialFieldExtraction(result, field, transaction) {
751
+ if (field === "tokenCreation" && result.type === "TOKENCREATE") {
752
+ const extracted = HTSParser.extractTokenCreationFromTransaction(transaction);
753
+ if (extracted) {
754
+ result[field] = extracted;
755
+ }
756
+ } else if (field === "tokenAirdrop" && result.type === "TOKENAIRDROP") {
757
+ const extracted = HTSParser.extractTokenAirdropFromTransaction(transaction);
758
+ if (extracted) {
759
+ result[field] = extracted;
597
760
  }
598
- return result;
599
- } catch (error) {
600
761
  }
601
762
  }
602
- try {
603
- const privateKey = PrivateKey.fromStringECDSA(privateKeyString);
763
+ /**
764
+ * Create fallback result when all parsing methods fail
765
+ */
766
+ static createFallbackResult(transactionBytes, primaryError, secondaryError) {
767
+ const validation = this.validateTransactionBytes(transactionBytes);
604
768
  return {
605
- detectedType: "ecdsa",
606
- privateKey,
607
- warning: `Using ECDSA as default. If you have the associated account ID, consider using the Hedera mirror node to confirm the key type.`
769
+ type: "UNKNOWN",
770
+ humanReadableType: "Unknown Transaction",
771
+ transfers: [],
772
+ tokenTransfers: [],
773
+ details: {
774
+ rawBytes: transactionBytes.length > 100 ? transactionBytes.substring(0, 100) + "..." : transactionBytes,
775
+ primaryError: primaryError?.message,
776
+ secondaryError: secondaryError?.message,
777
+ parseAttempts: secondaryError ? 2 : 1,
778
+ validation
779
+ },
780
+ formatDetection: {
781
+ originalFormat: validation.format || "base64",
782
+ wasConverted: false,
783
+ length: transactionBytes.length
784
+ },
785
+ raw: {}
608
786
  };
609
- } catch (ecdsaError) {
610
- try {
611
- const privateKey = PrivateKey.fromStringED25519(privateKeyString);
612
- return {
613
- detectedType: "ed25519",
614
- privateKey,
615
- warning: `Using ED25519 as fallback. If you have the associated account ID, consider using the Hedera mirror node to confirm the key type.`
616
- };
617
- } catch (ed25519Error) {
618
- throw new Error(
619
- `Failed to parse private key as either ECDSA or ED25519: ${ecdsaError}`
620
- );
621
- }
622
787
  }
623
788
  }
624
789
  export {
625
- KeyType,
626
- KeyTypeDetector,
627
- detectKeyTypeFromString
790
+ TransactionParser,
791
+ TransactionParsingError
628
792
  };
629
793
  //# sourceMappingURL=standards-sdk.es131.js.map