@hashgraphonline/standards-sdk 0.0.174 → 0.0.176

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 (93) hide show
  1. package/dist/cjs/{index-xQfUfn20.cjs → index-DBI7RYzm.cjs} +19 -19
  2. package/dist/cjs/{index-xQfUfn20.cjs.map → index-DBI7RYzm.cjs.map} +1 -1
  3. package/dist/cjs/{index-DNOBUKZd-g0uNa1rQ.cjs → index-DNOBUKZd-PuaZE8zI.cjs} +2 -2
  4. package/dist/cjs/{index-DNOBUKZd-g0uNa1rQ.cjs.map → index-DNOBUKZd-PuaZE8zI.cjs.map} +1 -1
  5. package/dist/cjs/standards-sdk.cjs +1 -1
  6. package/dist/cjs/{standards-sdk.es47-LpJXpYet-fj1bqMZs.cjs → standards-sdk.es47-LpJXpYet-Dn0a_M7H.cjs} +2 -2
  7. package/dist/cjs/{standards-sdk.es47-LpJXpYet-fj1bqMZs.cjs.map → standards-sdk.es47-LpJXpYet-Dn0a_M7H.cjs.map} +1 -1
  8. package/dist/cjs/{standards-sdk.es48-PT6ZHlCU-vkSluOOc.cjs → standards-sdk.es48-PT6ZHlCU-CpnblkfW.cjs} +2 -2
  9. package/dist/cjs/{standards-sdk.es48-PT6ZHlCU-vkSluOOc.cjs.map → standards-sdk.es48-PT6ZHlCU-CpnblkfW.cjs.map} +1 -1
  10. package/dist/cjs/{standards-sdk.es49-BoFc-ELK-DC0zfqT0.cjs → standards-sdk.es49-BoFc-ELK-AFqdqMBQ.cjs} +2 -2
  11. package/dist/cjs/{standards-sdk.es49-BoFc-ELK-DC0zfqT0.cjs.map → standards-sdk.es49-BoFc-ELK-AFqdqMBQ.cjs.map} +1 -1
  12. package/dist/cjs/{standards-sdk.es50-miBtNmtl-B2MpsQnf.cjs → standards-sdk.es50-miBtNmtl-BXhMfUtd.cjs} +2 -2
  13. package/dist/cjs/{standards-sdk.es50-miBtNmtl-B2MpsQnf.cjs.map → standards-sdk.es50-miBtNmtl-BXhMfUtd.cjs.map} +1 -1
  14. package/dist/cjs/{standards-sdk.es51-rS2UvvV5-CRkd1bF-.cjs → standards-sdk.es51-rS2UvvV5-Bh2x7xrp.cjs} +2 -2
  15. package/dist/cjs/{standards-sdk.es51-rS2UvvV5-CRkd1bF-.cjs.map → standards-sdk.es51-rS2UvvV5-Bh2x7xrp.cjs.map} +1 -1
  16. package/dist/cjs/{standards-sdk.es52-D-lvSMBY-DdUJIqZX.cjs → standards-sdk.es52-D-lvSMBY-DvI5ClIb.cjs} +2 -2
  17. package/dist/cjs/{standards-sdk.es52-D-lvSMBY-DdUJIqZX.cjs.map → standards-sdk.es52-D-lvSMBY-DvI5ClIb.cjs.map} +1 -1
  18. package/dist/cjs/utils/parsers/crypto-parser.d.ts +37 -0
  19. package/dist/cjs/utils/parsers/crypto-parser.d.ts.map +1 -1
  20. package/dist/cjs/utils/parsers/file-parser.d.ts +46 -0
  21. package/dist/cjs/utils/parsers/file-parser.d.ts.map +1 -1
  22. package/dist/cjs/utils/parsers/hcs-parser.d.ts +10 -0
  23. package/dist/cjs/utils/parsers/hcs-parser.d.ts.map +1 -1
  24. package/dist/cjs/utils/parsers/hts-parser.d.ts +23 -5
  25. package/dist/cjs/utils/parsers/hts-parser.d.ts.map +1 -1
  26. package/dist/cjs/utils/parsers/parser-utils.d.ts +11 -0
  27. package/dist/cjs/utils/parsers/parser-utils.d.ts.map +1 -1
  28. package/dist/cjs/utils/parsers/schedule-parser.d.ts +56 -11
  29. package/dist/cjs/utils/parsers/schedule-parser.d.ts.map +1 -1
  30. package/dist/cjs/utils/parsers/scs-parser.d.ts +51 -0
  31. package/dist/cjs/utils/parsers/scs-parser.d.ts.map +1 -1
  32. package/dist/cjs/utils/parsers/util-parser.d.ts +72 -1
  33. package/dist/cjs/utils/parsers/util-parser.d.ts.map +1 -1
  34. package/dist/cjs/utils/transaction-parser-types.d.ts +60 -0
  35. package/dist/cjs/utils/transaction-parser-types.d.ts.map +1 -1
  36. package/dist/cjs/utils/transaction-parser.d.ts +16 -14
  37. package/dist/cjs/utils/transaction-parser.d.ts.map +1 -1
  38. package/dist/es/standards-sdk.es35.js +388 -387
  39. package/dist/es/standards-sdk.es35.js.map +1 -1
  40. package/dist/es/standards-sdk.es36.js.map +1 -1
  41. package/dist/es/standards-sdk.es39.js +385 -18
  42. package/dist/es/standards-sdk.es39.js.map +1 -1
  43. package/dist/es/standards-sdk.es40.js +209 -86
  44. package/dist/es/standards-sdk.es40.js.map +1 -1
  45. package/dist/es/standards-sdk.es50.js +55 -0
  46. package/dist/es/standards-sdk.es50.js.map +1 -1
  47. package/dist/es/standards-sdk.es51.js +249 -1
  48. package/dist/es/standards-sdk.es51.js.map +1 -1
  49. package/dist/es/standards-sdk.es52.js +90 -0
  50. package/dist/es/standards-sdk.es52.js.map +1 -1
  51. package/dist/es/standards-sdk.es53.js +268 -9
  52. package/dist/es/standards-sdk.es53.js.map +1 -1
  53. package/dist/es/standards-sdk.es54.js +306 -0
  54. package/dist/es/standards-sdk.es54.js.map +1 -1
  55. package/dist/es/standards-sdk.es55.js +32 -0
  56. package/dist/es/standards-sdk.es55.js.map +1 -1
  57. package/dist/es/utils/parsers/crypto-parser.d.ts +37 -0
  58. package/dist/es/utils/parsers/crypto-parser.d.ts.map +1 -1
  59. package/dist/es/utils/parsers/file-parser.d.ts +46 -0
  60. package/dist/es/utils/parsers/file-parser.d.ts.map +1 -1
  61. package/dist/es/utils/parsers/hcs-parser.d.ts +10 -0
  62. package/dist/es/utils/parsers/hcs-parser.d.ts.map +1 -1
  63. package/dist/es/utils/parsers/hts-parser.d.ts +23 -5
  64. package/dist/es/utils/parsers/hts-parser.d.ts.map +1 -1
  65. package/dist/es/utils/parsers/parser-utils.d.ts +11 -0
  66. package/dist/es/utils/parsers/parser-utils.d.ts.map +1 -1
  67. package/dist/es/utils/parsers/schedule-parser.d.ts +56 -11
  68. package/dist/es/utils/parsers/schedule-parser.d.ts.map +1 -1
  69. package/dist/es/utils/parsers/scs-parser.d.ts +51 -0
  70. package/dist/es/utils/parsers/scs-parser.d.ts.map +1 -1
  71. package/dist/es/utils/parsers/util-parser.d.ts +72 -1
  72. package/dist/es/utils/parsers/util-parser.d.ts.map +1 -1
  73. package/dist/es/utils/transaction-parser-types.d.ts +60 -0
  74. package/dist/es/utils/transaction-parser-types.d.ts.map +1 -1
  75. package/dist/es/utils/transaction-parser.d.ts +16 -14
  76. package/dist/es/utils/transaction-parser.d.ts.map +1 -1
  77. package/package.json +1 -1
  78. package/dist/cjs/utils/__tests__/hts-parser.test.d.ts +0 -2
  79. package/dist/cjs/utils/__tests__/hts-parser.test.d.ts.map +0 -1
  80. package/dist/cjs/utils/__tests__/schedule-parser.test.d.ts +0 -2
  81. package/dist/cjs/utils/__tests__/schedule-parser.test.d.ts.map +0 -1
  82. package/dist/cjs/utils/__tests__/token-create-parsing.test.d.ts +0 -2
  83. package/dist/cjs/utils/__tests__/token-create-parsing.test.d.ts.map +0 -1
  84. package/dist/cjs/utils/__tests__/transaction-parser.test.d.ts +0 -2
  85. package/dist/cjs/utils/__tests__/transaction-parser.test.d.ts.map +0 -1
  86. package/dist/es/utils/__tests__/hts-parser.test.d.ts +0 -2
  87. package/dist/es/utils/__tests__/hts-parser.test.d.ts.map +0 -1
  88. package/dist/es/utils/__tests__/schedule-parser.test.d.ts +0 -2
  89. package/dist/es/utils/__tests__/schedule-parser.test.d.ts.map +0 -1
  90. package/dist/es/utils/__tests__/token-create-parsing.test.d.ts +0 -2
  91. package/dist/es/utils/__tests__/token-create-parsing.test.d.ts.map +0 -1
  92. package/dist/es/utils/__tests__/transaction-parser.test.d.ts +0 -2
  93. package/dist/es/utils/__tests__/transaction-parser.test.d.ts.map +0 -1
@@ -86,91 +86,100 @@ class TransactionParser {
86
86
  return fallbackResult;
87
87
  }
88
88
  /**
89
- * Parse a Transaction object directly
90
- * This method extracts data from Transaction objects created by the Hedera SDK
89
+ * Parse a Transaction object directly using unified delegation approach
90
+ * This method delegates to specialized parsers for clean separation of concerns
91
91
  *
92
92
  * @param transaction - The Transaction object to parse
93
+ * @param originalBytes - The original transaction bytes (optional, for protobuf parsing)
93
94
  * @param options - Parsing options
94
95
  * @returns Parsed transaction data
95
96
  */
96
- static parseTransactionObject(transaction, options = {}) {
97
+ static parseTransactionObject(transaction, originalBytes, options = {}) {
97
98
  try {
98
99
  const metadata = this.extractTransactionMetadata(transaction);
99
- const specificData = this.parseTransactionSpecificData(transaction);
100
- const scheduleData = ScheduleParser.parseScheduleTransaction(transaction);
101
- let type = "UNKNOWN";
102
- let humanReadableType = "Unknown Transaction";
103
- try {
104
- const transactionBytes = transaction.toBytes();
105
- const decoded = proto.TransactionList.decode(transactionBytes);
106
- if (decoded.transactionList && decoded.transactionList.length > 0) {
107
- const tx = decoded.transactionList[0];
108
- if (tx.signedTransactionBytes) {
109
- const signedTx = proto.SignedTransaction.decode(
110
- tx.signedTransactionBytes
111
- );
112
- if (signedTx.bodyBytes) {
113
- const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
114
- if (txBody.tokenCreation) {
115
- type = "TOKENCREATE";
116
- humanReadableType = "Token Creation";
117
- } else if (txBody.tokenAirdrop) {
118
- type = "TOKENAIRDROP";
119
- humanReadableType = "Token Airdrop";
120
- } else if (txBody.cryptoTransfer) {
121
- type = "CRYPTOTRANSFER";
122
- humanReadableType = "Crypto Transfer";
123
- } else if (txBody.consensusSubmitMessage) {
124
- type = "CONSENSUSSUBMITMESSAGE";
125
- humanReadableType = "Submit Message";
126
- } else if (txBody.contractCall) {
127
- type = "CONTRACTCALL";
128
- humanReadableType = "Contract Call";
129
- } else if (txBody.cryptoCreateAccount) {
130
- type = "ACCOUNTCREATE";
131
- humanReadableType = "Account Creation";
132
- } else if (txBody.tokenMint) {
133
- type = "TOKENMINT";
134
- humanReadableType = "Token Mint";
135
- } else if (txBody.tokenBurn) {
136
- type = "TOKENBURN";
137
- humanReadableType = "Token Burn";
138
- } else if (txBody.tokenAssociate) {
139
- type = "TOKENASSOCIATE";
140
- humanReadableType = "Token Association";
141
- } else if (txBody.fileCreate) {
142
- type = "FILECREATE";
143
- humanReadableType = "File Creation";
144
- } else if (txBody.consensusCreateTopic) {
145
- type = "TOPICCREATE";
146
- humanReadableType = "Topic Creation";
100
+ const htsResult = HTSParser.parseFromTransactionObject(transaction);
101
+ const cryptoResult = CryptoParser.parseFromTransactionObject(transaction);
102
+ const hcsResult = HCSParser.parseFromTransactionObject(transaction);
103
+ const fileResult = FileParser.parseFromTransactionObject(transaction);
104
+ const scsResult = SCSParser.parseFromTransactionObject(transaction);
105
+ const scheduleResult = ScheduleParser.parseFromTransactionObject(transaction);
106
+ const utilResult = UtilParser.parseFromTransactionObject(transaction);
107
+ const results = [
108
+ htsResult,
109
+ cryptoResult,
110
+ hcsResult,
111
+ fileResult,
112
+ scsResult,
113
+ scheduleResult,
114
+ utilResult
115
+ ];
116
+ const primaryResult = results.find((result2) => result2.type && result2.type !== "UNKNOWN") || {};
117
+ let finalType = "UNKNOWN";
118
+ let finalHumanReadableType = "Unknown Transaction";
119
+ let parsedTokenCreation;
120
+ let protoParsingResult = {};
121
+ if (originalBytes || transaction.toBytes) {
122
+ try {
123
+ const bytesToParse = originalBytes || transaction.toBytes();
124
+ const decoded = proto.TransactionList.decode(bytesToParse);
125
+ if (decoded.transactionList && decoded.transactionList.length > 0) {
126
+ const tx = decoded.transactionList[0];
127
+ if (tx.bodyBytes && tx.bodyBytes.length > 0) {
128
+ const txBody = proto.TransactionBody.decode(tx.bodyBytes);
129
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
130
+ finalType = typeResult.type;
131
+ finalHumanReadableType = typeResult.humanReadableType;
132
+ protoParsingResult = this.parseTransactionBodyDetails(
133
+ txBody,
134
+ finalType
135
+ );
136
+ if (protoParsingResult.tokenCreation) {
137
+ parsedTokenCreation = protoParsingResult.tokenCreation;
138
+ }
139
+ } else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
140
+ const signedTx = proto.SignedTransaction.decode(
141
+ tx.signedTransactionBytes
142
+ );
143
+ if (signedTx.bodyBytes) {
144
+ const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
145
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
146
+ finalType = typeResult.type;
147
+ finalHumanReadableType = typeResult.humanReadableType;
148
+ protoParsingResult = this.parseTransactionBodyDetails(
149
+ txBody,
150
+ finalType
151
+ );
152
+ if (protoParsingResult.tokenCreation) {
153
+ parsedTokenCreation = protoParsingResult.tokenCreation;
154
+ }
147
155
  }
148
156
  }
149
157
  }
158
+ } catch (protoError) {
150
159
  }
151
- } catch (protoError) {
152
- console.warn("Failed to parse transaction protobuf:", protoError);
153
160
  }
154
- if (type === "UNKNOWN" && specificData.type) {
155
- type = specificData.type;
156
- humanReadableType = specificData.humanReadableType || humanReadableType;
161
+ if (finalType === "UNKNOWN" && primaryResult.type) {
162
+ finalType = primaryResult.type;
163
+ finalHumanReadableType = primaryResult.humanReadableType || finalHumanReadableType;
157
164
  }
158
165
  const result = {
159
- type,
160
- humanReadableType,
166
+ type: finalType,
167
+ humanReadableType: finalHumanReadableType,
168
+ transfers: [],
169
+ tokenTransfers: [],
161
170
  ...metadata,
162
- ...specificData,
163
- ...scheduleData,
171
+ ...primaryResult,
164
172
  raw: options.includeRaw ? transaction._transactionBody || {} : void 0
165
173
  };
166
- if (type === "TOKENCREATE") {
167
- const tokenCreation = this.extractTokenCreation(transaction);
168
- if (tokenCreation) {
169
- result.tokenCreation = tokenCreation;
170
- }
171
- }
172
- result.transfers = result.transfers || [];
173
- result.tokenTransfers = result.tokenTransfers || [];
174
+ this.mergeProtoParsingResults(
175
+ result,
176
+ protoParsingResult,
177
+ htsResult,
178
+ transaction,
179
+ originalBytes
180
+ );
181
+ result.transfers = cryptoResult.transfers || result.transfers || [];
182
+ result.tokenTransfers = cryptoResult.tokenTransfers || result.tokenTransfers || [];
174
183
  return result;
175
184
  } catch (error) {
176
185
  return {
@@ -370,6 +379,109 @@ class TransactionParser {
370
379
  };
371
380
  }
372
381
  }
382
+ /**
383
+ * Detect transaction type and human-readable type from transaction body protobuf
384
+ * Centralized method to eliminate duplication across parsing methods
385
+ */
386
+ static detectTransactionTypeFromBody(txBody) {
387
+ if (txBody.tokenCreation) {
388
+ return { type: "TOKENCREATE", humanReadableType: "Token Creation" };
389
+ } else if (txBody.tokenAirdrop) {
390
+ return { type: "TOKENAIRDROP", humanReadableType: "Token Airdrop" };
391
+ } else if (txBody.cryptoTransfer) {
392
+ return { type: "CRYPTOTRANSFER", humanReadableType: "Crypto Transfer" };
393
+ } else if (txBody.consensusSubmitMessage) {
394
+ return {
395
+ type: "CONSENSUSSUBMITMESSAGE",
396
+ humanReadableType: "Submit Message"
397
+ };
398
+ } else if (txBody.contractCall) {
399
+ return { type: "CONTRACTCALL", humanReadableType: "Contract Call" };
400
+ } else if (txBody.cryptoCreateAccount) {
401
+ return { type: "ACCOUNTCREATE", humanReadableType: "Account Creation" };
402
+ } else if (txBody.cryptoUpdateAccount) {
403
+ return { type: "ACCOUNTUPDATE", humanReadableType: "Account Update" };
404
+ } else if (txBody.cryptoDelete) {
405
+ return { type: "ACCOUNTDELETE", humanReadableType: "Account Deletion" };
406
+ } else if (txBody.cryptoApproveAllowance) {
407
+ return {
408
+ type: "APPROVEALLOWANCE",
409
+ humanReadableType: "Approve Allowance"
410
+ };
411
+ } else if (txBody.cryptoDeleteAllowance) {
412
+ return { type: "DELETEALLOWANCE", humanReadableType: "Delete Allowance" };
413
+ } else if (txBody.tokenMint) {
414
+ return { type: "TOKENMINT", humanReadableType: "Token Mint" };
415
+ } else if (txBody.tokenBurn) {
416
+ return { type: "TOKENBURN", humanReadableType: "Token Burn" };
417
+ } else if (txBody.tokenUpdate) {
418
+ return { type: "TOKENUPDATE", humanReadableType: "Token Update" };
419
+ } else if (txBody.tokenDeletion) {
420
+ return { type: "TOKENDELETE", humanReadableType: "Token Deletion" };
421
+ } else if (txBody.tokenAssociate) {
422
+ return { type: "TOKENASSOCIATE", humanReadableType: "Token Association" };
423
+ } else if (txBody.tokenDissociate) {
424
+ return {
425
+ type: "TOKENDISSOCIATE",
426
+ humanReadableType: "Token Dissociation"
427
+ };
428
+ } else if (txBody.tokenFreeze) {
429
+ return { type: "TOKENFREEZE", humanReadableType: "Token Freeze" };
430
+ } else if (txBody.tokenUnfreeze) {
431
+ return { type: "TOKENUNFREEZE", humanReadableType: "Token Unfreeze" };
432
+ } else if (txBody.tokenGrantKyc) {
433
+ return { type: "TOKENGRANTKYC", humanReadableType: "Token Grant KYC" };
434
+ } else if (txBody.tokenRevokeKyc) {
435
+ return { type: "TOKENREVOKEKYC", humanReadableType: "Token Revoke KYC" };
436
+ } else if (txBody.tokenWipe) {
437
+ return { type: "TOKENWIPE", humanReadableType: "Token Wipe" };
438
+ } else if (txBody.tokenPause) {
439
+ return { type: "TOKENPAUSE", humanReadableType: "Token Pause" };
440
+ } else if (txBody.tokenUnpause) {
441
+ return { type: "TOKENUNPAUSE", humanReadableType: "Token Unpause" };
442
+ } else if (txBody.tokenFeeScheduleUpdate) {
443
+ return {
444
+ type: "TOKENFEESCHEDULEUPDATE",
445
+ humanReadableType: "Token Fee Schedule Update"
446
+ };
447
+ } else if (txBody.fileCreate) {
448
+ return { type: "FILECREATE", humanReadableType: "File Creation" };
449
+ } else if (txBody.fileUpdate) {
450
+ return { type: "FILEUPDATE", humanReadableType: "File Update" };
451
+ } else if (txBody.fileDelete) {
452
+ return { type: "FILEDELETE", humanReadableType: "File Deletion" };
453
+ } else if (txBody.fileAppend) {
454
+ return { type: "FILEAPPEND", humanReadableType: "File Append" };
455
+ } else if (txBody.consensusCreateTopic) {
456
+ return { type: "TOPICCREATE", humanReadableType: "Topic Creation" };
457
+ } else if (txBody.consensusUpdateTopic) {
458
+ return { type: "TOPICUPDATE", humanReadableType: "Topic Update" };
459
+ } else if (txBody.consensusDeleteTopic) {
460
+ return { type: "TOPICDELETE", humanReadableType: "Topic Deletion" };
461
+ } else if (txBody.contractCreateInstance) {
462
+ return { type: "CONTRACTCREATE", humanReadableType: "Contract Creation" };
463
+ } else if (txBody.contractUpdateInstance) {
464
+ return { type: "CONTRACTUPDATE", humanReadableType: "Contract Update" };
465
+ } else if (txBody.contractDeleteInstance) {
466
+ return { type: "CONTRACTDELETE", humanReadableType: "Contract Deletion" };
467
+ } else if (txBody.scheduleCreate) {
468
+ return { type: "SCHEDULECREATE", humanReadableType: "Schedule Creation" };
469
+ } else if (txBody.scheduleSign) {
470
+ return { type: "SCHEDULESIGN", humanReadableType: "Schedule Sign" };
471
+ } else if (txBody.scheduleDelete) {
472
+ return { type: "SCHEDULEDELETE", humanReadableType: "Schedule Deletion" };
473
+ } else if (txBody.utilPrng) {
474
+ return { type: "PRNG", humanReadableType: "Pseudo Random Number" };
475
+ } else if (txBody.freeze) {
476
+ return { type: "FREEZE", humanReadableType: "Network Freeze" };
477
+ } else if (txBody.systemDelete) {
478
+ return { type: "SYSTEMDELETE", humanReadableType: "System Delete" };
479
+ } else if (txBody.systemUndelete) {
480
+ return { type: "SYSTEMUNDELETE", humanReadableType: "System Undelete" };
481
+ } else {
482
+ return { type: "UNKNOWN", humanReadableType: "Unknown Transaction" };
483
+ }
484
+ }
373
485
  /**
374
486
  * Parse details from a complete schedule response
375
487
  * @param scheduleResponse - The schedule response to parse
@@ -400,79 +512,42 @@ class TransactionParser {
400
512
  * @returns The type of the transaction
401
513
  */
402
514
  static getTransactionType(txBody) {
403
- let transactionType = "unknown";
404
- if (txBody.cryptoTransfer) {
405
- transactionType = "cryptoTransfer";
406
- } else if (txBody.cryptoCreateAccount) {
407
- transactionType = "cryptoCreateAccount";
408
- } else if (txBody.cryptoUpdateAccount) {
409
- transactionType = "cryptoUpdateAccount";
410
- } else if (txBody.cryptoApproveAllowance) {
411
- transactionType = "cryptoApproveAllowance";
412
- } else if (txBody.cryptoDeleteAllowance) {
413
- transactionType = "cryptoDeleteAllowance";
414
- } else if (txBody.cryptoDelete) {
415
- transactionType = "cryptoDelete";
416
- } else if (txBody.consensusCreateTopic) {
417
- transactionType = "consensusCreateTopic";
418
- } else if (txBody.consensusUpdateTopic) {
419
- transactionType = "consensusUpdateTopic";
420
- } else if (txBody.consensusSubmitMessage) {
421
- transactionType = "consensusSubmitMessage";
422
- } else if (txBody.consensusDeleteTopic) {
423
- transactionType = "consensusDeleteTopic";
424
- } else if (txBody.fileCreate) {
425
- transactionType = "fileCreate";
426
- } else if (txBody.fileAppend) {
427
- transactionType = "fileAppend";
428
- } else if (txBody.fileUpdate) {
429
- transactionType = "fileUpdate";
430
- } else if (txBody.fileDelete) {
431
- transactionType = "fileDelete";
432
- } else if (txBody.contractCall) {
433
- transactionType = "contractCall";
434
- } else if (txBody.contractCreateInstance) {
435
- transactionType = "contractCreate";
436
- } else if (txBody.contractUpdateInstance) {
437
- transactionType = "contractUpdate";
438
- } else if (txBody.contractDeleteInstance) {
439
- transactionType = "contractDelete";
440
- } else if (txBody.tokenCreation) {
441
- transactionType = "tokenCreate";
442
- } else if (txBody.tokenUpdate) {
443
- transactionType = "tokenUpdate";
444
- } else if (txBody.tokenDeletion) {
445
- transactionType = "tokenDelete";
446
- } else if (txBody.tokenAssociate) {
447
- transactionType = "tokenAssociate";
448
- } else if (txBody.tokenDissociate) {
449
- transactionType = "tokenDissociate";
450
- } else if (txBody.tokenMint) {
451
- transactionType = "tokenMint";
452
- } else if (txBody.tokenBurn) {
453
- transactionType = "tokenBurn";
454
- } else if (txBody.tokenFeeScheduleUpdate) {
455
- transactionType = "tokenFeeScheduleUpdate";
456
- } else if (txBody.tokenFreeze) {
457
- transactionType = "tokenFreeze";
458
- } else if (txBody.tokenUnfreeze) {
459
- transactionType = "tokenUnfreeze";
460
- } else if (txBody.tokenGrantKyc) {
461
- transactionType = "tokenGrantKyc";
462
- } else if (txBody.tokenRevokeKyc) {
463
- transactionType = "tokenRevokeKyc";
464
- } else if (txBody.tokenPause) {
465
- transactionType = "tokenPause";
466
- } else if (txBody.tokenUnpause) {
467
- transactionType = "tokenUnpause";
468
- } else if (txBody.tokenWipe) {
469
- transactionType = "tokenWipe";
470
- } else if (txBody.tokenAirdrop) {
471
- transactionType = "tokenAirdrop";
472
- } else if (txBody.utilPrng) {
473
- transactionType = "utilPrng";
474
- }
475
- return transactionType;
515
+ if (txBody.tokenCreation) return "tokenCreate";
516
+ if (txBody.tokenAirdrop) return "tokenAirdrop";
517
+ if (txBody.cryptoTransfer) return "cryptoTransfer";
518
+ if (txBody.consensusSubmitMessage) return "consensusSubmitMessage";
519
+ if (txBody.contractCall) return "contractCall";
520
+ if (txBody.cryptoCreateAccount) return "cryptoCreateAccount";
521
+ if (txBody.cryptoUpdateAccount) return "cryptoUpdateAccount";
522
+ if (txBody.cryptoApproveAllowance) return "cryptoApproveAllowance";
523
+ if (txBody.cryptoDeleteAllowance) return "cryptoDeleteAllowance";
524
+ if (txBody.cryptoDelete) return "cryptoDelete";
525
+ if (txBody.consensusCreateTopic) return "consensusCreateTopic";
526
+ if (txBody.consensusUpdateTopic) return "consensusUpdateTopic";
527
+ if (txBody.consensusDeleteTopic) return "consensusDeleteTopic";
528
+ if (txBody.fileCreate) return "fileCreate";
529
+ if (txBody.fileAppend) return "fileAppend";
530
+ if (txBody.fileUpdate) return "fileUpdate";
531
+ if (txBody.fileDelete) return "fileDelete";
532
+ if (txBody.contractCreateInstance) return "contractCreate";
533
+ if (txBody.contractUpdateInstance) return "contractUpdate";
534
+ if (txBody.contractDeleteInstance) return "contractDelete";
535
+ if (txBody.tokenUpdate) return "tokenUpdate";
536
+ if (txBody.tokenDeletion) return "tokenDelete";
537
+ if (txBody.tokenAssociate) return "tokenAssociate";
538
+ if (txBody.tokenDissociate) return "tokenDissociate";
539
+ if (txBody.tokenMint) return "tokenMint";
540
+ if (txBody.tokenBurn) return "tokenBurn";
541
+ if (txBody.tokenFeeScheduleUpdate) return "tokenFeeScheduleUpdate";
542
+ if (txBody.tokenFreeze) return "tokenFreeze";
543
+ if (txBody.tokenUnfreeze) return "tokenUnfreeze";
544
+ if (txBody.tokenGrantKyc) return "tokenGrantKyc";
545
+ if (txBody.tokenRevokeKyc) return "tokenRevokeKyc";
546
+ if (txBody.tokenPause) return "tokenPause";
547
+ if (txBody.tokenUnpause) return "tokenUnpause";
548
+ if (txBody.tokenWipe) return "tokenWipe";
549
+ if (txBody.utilPrng) return "utilPrng";
550
+ return "unknown";
476
551
  }
477
552
  /**
478
553
  * Convert technical transaction type to human-readable format
@@ -868,148 +943,129 @@ class TransactionParser {
868
943
  return this.decodeTransactionBytes(transactionBytes);
869
944
  }
870
945
  /**
871
- * Parse transaction bytes into structured data
946
+ * Parse transaction bytes into structured data using thin orchestration
947
+ * Delegates to specialized parsers for clean separation of concerns
872
948
  */
873
949
  static async parseTransaction(transactionBytes, options = {}) {
874
950
  try {
875
951
  const bytes = this.decodeTransactionBytes(transactionBytes);
876
952
  const transaction = Transaction.fromBytes(bytes);
877
953
  const metadata = this.extractTransactionMetadataEnhanced(transaction);
878
- const hbarTransfers = this.extractHbarTransfersFromTransaction(transaction);
879
- const tokenTransfers = this.extractTokenTransfersFromTransaction(transaction);
880
- const tokenCreation = this.extractTokenCreation(transaction);
881
- const tokenAirdrop = this.extractTokenAirdrop(transaction);
882
- const htsResult = HTSParser.parseHTSTransaction(transaction);
883
- const scheduleResult = ScheduleParser.parseScheduleTransaction(transaction);
954
+ const htsResult = HTSParser.parseFromTransactionObject(transaction);
955
+ const cryptoResult = CryptoParser.parseFromTransactionObject(transaction);
956
+ const hcsResult = HCSParser.parseFromTransactionObject(transaction);
957
+ const fileResult = FileParser.parseFromTransactionObject(transaction);
958
+ const scsResult = SCSParser.parseFromTransactionObject(transaction);
959
+ const scheduleResult = ScheduleParser.parseFromTransactionObject(transaction);
960
+ const utilResult = UtilParser.parseFromTransactionObject(transaction);
961
+ const results = [
962
+ htsResult,
963
+ cryptoResult,
964
+ hcsResult,
965
+ fileResult,
966
+ scsResult,
967
+ scheduleResult,
968
+ utilResult
969
+ ];
970
+ const primaryResult = results.find((result2) => result2.type && result2.type !== "UNKNOWN") || {};
884
971
  let transactionType = "UNKNOWN";
885
972
  let humanReadableType = "Unknown Transaction";
973
+ let parsedTokenCreation;
886
974
  try {
887
- const transactionBytes2 = transaction.toBytes();
888
- const decoded = proto.TransactionList.decode(transactionBytes2);
975
+ const decoded = proto.TransactionList.decode(bytes);
889
976
  if (decoded.transactionList && decoded.transactionList.length > 0) {
890
977
  const tx = decoded.transactionList[0];
891
- if (tx.signedTransactionBytes) {
978
+ if (tx.bodyBytes && tx.bodyBytes.length > 0) {
979
+ const txBody = proto.TransactionBody.decode(tx.bodyBytes);
980
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
981
+ transactionType = typeResult.type;
982
+ humanReadableType = typeResult.humanReadableType;
983
+ const protoParsingResult = this.parseTransactionBodyDetails(
984
+ txBody,
985
+ transactionType
986
+ );
987
+ if (protoParsingResult.tokenCreation) {
988
+ parsedTokenCreation = protoParsingResult.tokenCreation;
989
+ }
990
+ } else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
892
991
  const signedTx = proto.SignedTransaction.decode(
893
992
  tx.signedTransactionBytes
894
993
  );
895
994
  if (signedTx.bodyBytes) {
896
995
  const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
897
- if (txBody.cryptoTransfer) {
898
- transactionType = "CRYPTOTRANSFER";
899
- humanReadableType = "Crypto Transfer";
900
- } else if (txBody.tokenCreation) {
901
- transactionType = "TOKENCREATE";
902
- humanReadableType = "Token Creation";
903
- } else if (txBody.tokenAirdrop) {
904
- transactionType = "TOKENAIRDROP";
905
- humanReadableType = "Token Airdrop";
906
- } else if (txBody.consensusSubmitMessage) {
907
- transactionType = "CONSENSUSSUBMITMESSAGE";
908
- humanReadableType = "Submit Message";
909
- } else if (txBody.contractCall) {
910
- transactionType = "CONTRACTCALL";
911
- humanReadableType = "Contract Call";
912
- } else if (txBody.cryptoCreateAccount) {
913
- transactionType = "ACCOUNTCREATE";
914
- humanReadableType = "Account Creation";
915
- } else if (txBody.tokenMint) {
916
- transactionType = "TOKENMINT";
917
- humanReadableType = "Token Mint";
918
- } else if (txBody.tokenBurn) {
919
- transactionType = "TOKENBURN";
920
- humanReadableType = "Token Burn";
921
- } else if (txBody.tokenAssociate) {
922
- transactionType = "TOKENASSOCIATE";
923
- humanReadableType = "Token Association";
924
- } else if (txBody.fileCreate) {
925
- transactionType = "FILECREATE";
926
- humanReadableType = "File Creation";
927
- } else if (txBody.consensusCreateTopic) {
928
- transactionType = "TOPICCREATE";
929
- humanReadableType = "Topic Creation";
996
+ const typeResult = this.detectTransactionTypeFromBody(txBody);
997
+ transactionType = typeResult.type;
998
+ humanReadableType = typeResult.humanReadableType;
999
+ const protoParsingResult = this.parseTransactionBodyDetails(
1000
+ txBody,
1001
+ transactionType
1002
+ );
1003
+ if (protoParsingResult.tokenCreation) {
1004
+ parsedTokenCreation = protoParsingResult.tokenCreation;
930
1005
  }
931
1006
  }
932
1007
  }
933
1008
  }
934
1009
  } catch (protoError) {
935
- console.warn("Failed to parse transaction protobuf:", protoError);
936
- }
937
- if (transactionType === "UNKNOWN") {
938
- transactionType = htsResult.type || scheduleResult.type || "UNKNOWN";
939
- humanReadableType = htsResult.humanReadableType || scheduleResult.humanReadableType || "Unknown Transaction";
940
- if (!transactionType || transactionType === "UNKNOWN") {
941
- if (tokenCreation) {
942
- transactionType = "TOKENCREATE";
943
- humanReadableType = "Token Creation";
944
- } else if (tokenAirdrop) {
945
- transactionType = "TOKENAIRDROP";
946
- humanReadableType = "Token Airdrop";
947
- } else if (hbarTransfers.length > 0) {
948
- transactionType = "CRYPTOTRANSFER";
949
- humanReadableType = "HBAR Transfer";
950
- } else if (tokenTransfers.length > 0) {
951
- transactionType = "TOKENTRANSFER";
952
- humanReadableType = "Token Transfer";
953
- }
954
- }
955
1010
  }
956
- const convertedTransfers = hbarTransfers.map((transfer) => ({
957
- accountId: transfer.accountId,
958
- amount: transfer.amount.toString() + " ",
959
- isDecimal: true
960
- }));
961
- const convertedTokenTransfers = tokenTransfers.flatMap(
962
- (tokenGroup) => tokenGroup.transfers.map((transfer) => ({
963
- tokenId: tokenGroup.tokenId,
964
- accountId: transfer.accountId,
965
- amount: transfer.amount
966
- }))
967
- );
1011
+ if (transactionType === "UNKNOWN" && primaryResult.type) {
1012
+ transactionType = primaryResult.type;
1013
+ humanReadableType = primaryResult.humanReadableType || "Unknown Transaction";
1014
+ }
968
1015
  const result = {
969
1016
  type: transactionType,
970
1017
  humanReadableType,
971
- transfers: convertedTransfers,
972
- tokenTransfers: convertedTokenTransfers,
1018
+ transfers: cryptoResult.transfers || [],
1019
+ tokenTransfers: cryptoResult.tokenTransfers || [],
973
1020
  details: {
974
- ...metadata,
975
- transferCount: hbarTransfers.length + tokenTransfers.length
1021
+ ...metadata
976
1022
  },
977
- memo: metadata.memo,
978
- transactionId: metadata.transactionId,
979
- nodeAccountIds: metadata.nodeAccountIds,
980
- maxTransactionFee: metadata.maxTransactionFee,
981
- validStart: metadata.validStart,
982
- validDuration: metadata.validDuration,
1023
+ memo: typeof metadata.memo === "string" ? metadata.memo : void 0,
1024
+ transactionId: typeof metadata.transactionId === "string" ? metadata.transactionId : void 0,
1025
+ nodeAccountIds: Array.isArray(metadata.nodeAccountIds) ? metadata.nodeAccountIds : [],
1026
+ maxTransactionFee: typeof metadata.maxTransactionFee === "string" ? metadata.maxTransactionFee : void 0,
1027
+ validStart: typeof metadata.validStart === "string" ? metadata.validStart : void 0,
1028
+ validDuration: typeof metadata.validDuration === "string" ? metadata.validDuration : void 0,
1029
+ ...primaryResult,
983
1030
  raw: options.includeRaw ? {} : void 0
984
1031
  };
985
- if (htsResult.type && transactionType === "UNKNOWN") {
986
- Object.assign(result, htsResult);
987
- } else if (htsResult.type && transactionType !== "UNKNOWN") {
988
- const {
989
- type: htsType,
990
- humanReadableType: htsHumanType,
991
- ...htsData
992
- } = htsResult;
993
- Object.assign(result, htsData);
994
- }
995
- if (scheduleResult.type && transactionType === "UNKNOWN") {
996
- Object.assign(result, scheduleResult);
997
- } else if (scheduleResult.type && transactionType !== "UNKNOWN") {
998
- const {
999
- type: scheduleType,
1000
- humanReadableType: scheduleHumanType,
1001
- ...scheduleData
1002
- } = scheduleResult;
1003
- Object.assign(result, scheduleData);
1004
- }
1005
- if (transactionType === "TOKENCREATE" || tokenCreation) {
1006
- const tokenCreationData = tokenCreation || this.extractTokenCreation(transaction);
1032
+ if (transactionType === "TOKENCREATE") {
1033
+ const tokenCreationData = parsedTokenCreation || htsResult.tokenCreation || HTSParser.extractTokenCreationFromTransaction(transaction);
1007
1034
  if (tokenCreationData) {
1008
1035
  result.tokenCreation = tokenCreationData;
1009
1036
  }
1010
1037
  }
1011
- if (tokenAirdrop && !result.tokenAirdrop) {
1012
- result.tokenAirdrop = tokenAirdrop;
1038
+ if (htsResult.tokenAirdrop && !result.tokenAirdrop) {
1039
+ result.tokenAirdrop = htsResult.tokenAirdrop;
1040
+ }
1041
+ if (transactionType === "TOKENAIRDROP" && !result.tokenAirdrop) {
1042
+ try {
1043
+ const buffer = Buffer.from(transactionBytes, "base64");
1044
+ const decoded = proto.TransactionList.decode(buffer);
1045
+ if (decoded.transactionList && decoded.transactionList.length > 0) {
1046
+ const tx = decoded.transactionList[0];
1047
+ let txBody = null;
1048
+ if (tx.bodyBytes && tx.bodyBytes.length > 0) {
1049
+ txBody = proto.TransactionBody.decode(tx.bodyBytes);
1050
+ } else if (tx.signedTransactionBytes && tx.signedTransactionBytes.length > 0) {
1051
+ const signedTx = proto.SignedTransaction.decode(
1052
+ tx.signedTransactionBytes
1053
+ );
1054
+ if (signedTx.bodyBytes) {
1055
+ txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
1056
+ }
1057
+ }
1058
+ if (txBody && txBody.tokenAirdrop) {
1059
+ const parsedAirdrop = HTSParser.parseTokenAirdropFromProto(
1060
+ txBody.tokenAirdrop
1061
+ );
1062
+ if (parsedAirdrop) {
1063
+ result.tokenAirdrop = parsedAirdrop;
1064
+ }
1065
+ }
1066
+ }
1067
+ } catch (error) {
1068
+ }
1013
1069
  }
1014
1070
  return result;
1015
1071
  } catch (error) {
@@ -1079,154 +1135,99 @@ class TransactionParser {
1079
1135
  };
1080
1136
  }
1081
1137
  /**
1082
- * Parse transaction-specific data using specialized parsers
1138
+ * Parse transaction body details for all supported transaction types
1139
+ * This is the DRY, unified approach that delegates to appropriate parsers
1083
1140
  */
1084
- static parseTransactionSpecificData(transaction) {
1141
+ static parseTransactionBodyDetails(txBody, transactionType) {
1085
1142
  const result = {};
1086
- const htsData = HTSParser.parseHTSTransaction(transaction);
1087
- Object.assign(result, htsData);
1088
- const transfers = this.extractHbarTransfersFromTransaction(transaction);
1089
- const tokenTransfers = this.extractTokenTransfersFromTransaction(transaction);
1090
- if (transfers.length > 0) {
1091
- result.transfers = transfers.map((t) => ({
1092
- accountId: t.accountId,
1093
- amount: t.amount.toString(),
1094
- isDecimal: true
1095
- }));
1096
- }
1097
- if (tokenTransfers.length > 0) {
1098
- result.tokenTransfers = tokenTransfers.flatMap(
1099
- (tt) => tt.transfers.map((t) => ({
1100
- tokenId: tt.tokenId,
1101
- accountId: t.accountId,
1102
- amount: t.amount
1103
- }))
1143
+ if (txBody.tokenCreation && transactionType === "TOKENCREATE") {
1144
+ result.tokenCreation = HTSParser.parseTokenCreate(txBody.tokenCreation);
1145
+ } else if (txBody.tokenMint && transactionType === "TOKENMINT") {
1146
+ result.tokenMint = HTSParser.parseTokenMint(txBody.tokenMint);
1147
+ } else if (txBody.tokenBurn && transactionType === "TOKENBURN") {
1148
+ result.tokenBurn = HTSParser.parseTokenBurn(txBody.tokenBurn);
1149
+ } else if (txBody.tokenUpdate && transactionType === "TOKENUPDATE") {
1150
+ result.tokenUpdate = HTSParser.parseTokenUpdate(txBody.tokenUpdate);
1151
+ } else if (txBody.tokenDeletion && transactionType === "TOKENDELETE") {
1152
+ result.tokenDelete = HTSParser.parseTokenDelete(txBody.tokenDeletion);
1153
+ } else if (txBody.tokenAssociate && transactionType === "TOKENASSOCIATE") {
1154
+ result.tokenAssociate = HTSParser.parseTokenAssociate(
1155
+ txBody.tokenAssociate
1156
+ );
1157
+ } else if (txBody.tokenDissociate && transactionType === "TOKENDISSOCIATE") {
1158
+ result.tokenDissociate = HTSParser.parseTokenDissociate(
1159
+ txBody.tokenDissociate
1160
+ );
1161
+ } else if (txBody.tokenFreeze && transactionType === "TOKENFREEZE") {
1162
+ result.tokenFreeze = HTSParser.parseTokenFreeze(txBody.tokenFreeze);
1163
+ } else if (txBody.tokenUnfreeze && transactionType === "TOKENUNFREEZE") {
1164
+ result.tokenUnfreeze = HTSParser.parseTokenUnfreeze(txBody.tokenUnfreeze);
1165
+ } else if (txBody.tokenGrantKyc && transactionType === "TOKENGRANTKYC") {
1166
+ result.tokenGrantKyc = HTSParser.parseTokenGrantKyc(txBody.tokenGrantKyc);
1167
+ } else if (txBody.tokenRevokeKyc && transactionType === "TOKENREVOKEKYC") {
1168
+ result.tokenRevokeKyc = HTSParser.parseTokenRevokeKyc(
1169
+ txBody.tokenRevokeKyc
1170
+ );
1171
+ } else if (txBody.tokenPause && transactionType === "TOKENPAUSE") {
1172
+ result.tokenPause = HTSParser.parseTokenPause(txBody.tokenPause);
1173
+ } else if (txBody.tokenUnpause && transactionType === "TOKENUNPAUSE") {
1174
+ result.tokenUnpause = HTSParser.parseTokenUnpause(txBody.tokenUnpause);
1175
+ } else if (txBody.tokenWipe && transactionType === "TOKENWIPEACCOUNT") {
1176
+ result.tokenWipeAccount = HTSParser.parseTokenWipeAccount(
1177
+ txBody.tokenWipe
1178
+ );
1179
+ } else if (txBody.tokenFeeScheduleUpdate && transactionType === "TOKENFEESCHEDULEUPDATE") {
1180
+ result.tokenFeeScheduleUpdate = HTSParser.parseTokenFeeScheduleUpdate(
1181
+ txBody.tokenFeeScheduleUpdate
1182
+ );
1183
+ } else if (txBody.tokenAirdrop && transactionType === "TOKENAIRDROP") {
1184
+ result.tokenAirdrop = HTSParser.parseTokenAirdropFromProto(
1185
+ txBody.tokenAirdrop
1104
1186
  );
1105
1187
  }
1106
1188
  return result;
1107
1189
  }
1108
1190
  /**
1109
- * Extract HBAR transfers from Transaction object
1110
- */
1111
- static extractHbarTransfersFromTransaction(transaction) {
1112
- const transfers = [];
1113
- try {
1114
- const hbarTransfers = transaction._hbarTransfers;
1115
- if (Array.isArray(hbarTransfers)) {
1116
- hbarTransfers.forEach((transfer) => {
1117
- if (transfer.accountId && transfer.amount) {
1118
- const amountInTinybars = transfer.amount.toTinybars();
1119
- const amountInHbar = Number(amountInTinybars) / 1e8;
1120
- transfers.push({
1121
- accountId: transfer.accountId.toString(),
1122
- amount: amountInHbar
1123
- });
1124
- }
1125
- });
1126
- }
1127
- } catch (error) {
1128
- }
1129
- return transfers;
1130
- }
1131
- /**
1132
- * Extract token transfers from Transaction object
1191
+ * Merge protobuf parsing results with parser results using unified prioritization
1133
1192
  */
1134
- static extractTokenTransfersFromTransaction(transaction) {
1135
- const tokenTransfers = [];
1136
- try {
1137
- const tokenTransfersList = transaction._tokenTransfers;
1138
- if (Array.isArray(tokenTransfersList)) {
1139
- tokenTransfersList.forEach((tokenTransfer) => {
1140
- if (tokenTransfer.tokenId && Array.isArray(tokenTransfer.transfers)) {
1141
- const transfers = tokenTransfer.transfers.map((transfer) => ({
1142
- accountId: transfer.accountId?.toString() || "Unknown",
1143
- amount: Number(transfer.amount || 0)
1144
- }));
1145
- tokenTransfers.push({
1146
- tokenId: tokenTransfer.tokenId.toString(),
1147
- transfers
1148
- });
1149
- }
1150
- });
1151
- }
1152
- } catch (error) {
1153
- console.warn("Failed to extract token transfers:", error);
1154
- }
1155
- return tokenTransfers;
1156
- }
1157
- static extractTokenCreation(transaction) {
1158
- try {
1159
- const transactionBytes = transaction.toBytes();
1160
- const decoded = proto.TransactionList.decode(transactionBytes);
1161
- if (decoded.transactionList && decoded.transactionList.length > 0) {
1162
- const tx = decoded.transactionList[0];
1163
- if (tx.signedTransactionBytes) {
1164
- const signedTx = proto.SignedTransaction.decode(
1165
- tx.signedTransactionBytes
1166
- );
1167
- if (signedTx.bodyBytes) {
1168
- const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
1169
- if (txBody.tokenCreation) {
1170
- const tokenCreation = txBody.tokenCreation;
1171
- return {
1172
- tokenName: tokenCreation.name || "Unknown Token",
1173
- tokenSymbol: tokenCreation.symbol || "UNKNOWN",
1174
- initialSupply: tokenCreation.initialSupply?.toString() || "0",
1175
- decimals: Number(tokenCreation.decimals || 0),
1176
- maxSupply: tokenCreation.maxSupply?.toString(),
1177
- tokenType: tokenCreation.tokenType || "FUNGIBLE_COMMON",
1178
- supplyType: tokenCreation.supplyType || "INFINITE",
1179
- tokenMemo: tokenCreation.memo || "",
1180
- treasuryAccountId: tokenCreation.treasury?.toString() || "Unknown"
1181
- };
1182
- }
1183
- }
1193
+ static mergeProtoParsingResults(result, protoResult, htsResult, transaction, originalBytes) {
1194
+ const transactionFields = [
1195
+ "tokenCreation",
1196
+ "tokenMint",
1197
+ "tokenBurn",
1198
+ "tokenUpdate",
1199
+ "tokenDelete",
1200
+ "tokenAssociate",
1201
+ "tokenDissociate",
1202
+ "tokenFreeze",
1203
+ "tokenUnfreeze",
1204
+ "tokenGrantKyc",
1205
+ "tokenRevokeKyc",
1206
+ "tokenPause",
1207
+ "tokenUnpause",
1208
+ "tokenWipeAccount",
1209
+ "tokenFeeScheduleUpdate",
1210
+ "tokenAirdrop"
1211
+ ];
1212
+ transactionFields.forEach((field) => {
1213
+ const protoValue = protoResult[field];
1214
+ const htsValue = htsResult[field];
1215
+ if (protoValue !== void 0) {
1216
+ result[field] = protoValue;
1217
+ } else if (htsValue !== void 0) {
1218
+ result[field] = htsValue;
1219
+ } else if (field === "tokenCreation" && result.type === "TOKENCREATE") {
1220
+ const extracted = HTSParser.extractTokenCreationFromTransaction(transaction);
1221
+ if (extracted) {
1222
+ result[field] = extracted;
1184
1223
  }
1185
- }
1186
- return null;
1187
- } catch (error) {
1188
- if (process.env.NODE_ENV === "development") {
1189
- console.warn("Failed to extract token creation data:", error);
1190
- }
1191
- return null;
1192
- }
1193
- }
1194
- static extractTokenAirdrop(transaction) {
1195
- try {
1196
- const transactionBytes = transaction.toBytes();
1197
- const decoded = proto.TransactionList.decode(transactionBytes);
1198
- if (decoded.transactionList && decoded.transactionList.length > 0) {
1199
- const tx = decoded.transactionList[0];
1200
- if (tx.signedTransactionBytes) {
1201
- const signedTx = proto.SignedTransaction.decode(
1202
- tx.signedTransactionBytes
1203
- );
1204
- if (signedTx.bodyBytes) {
1205
- const txBody = proto.TransactionBody.decode(signedTx.bodyBytes);
1206
- if (txBody.tokenAirdrop) {
1207
- const airdrop = txBody.tokenAirdrop;
1208
- const tokenTransfers = airdrop.tokenTransfers || [];
1209
- return {
1210
- tokenTransfers: tokenTransfers.map(
1211
- (transfer) => ({
1212
- tokenId: transfer.token?.toString() || "Unknown",
1213
- transfers: (transfer.transfers || []).map(
1214
- (t) => ({
1215
- accountId: t.accountID?.toString() || "Unknown",
1216
- amount: t.amount?.toString() || "0"
1217
- })
1218
- )
1219
- })
1220
- )
1221
- };
1222
- }
1223
- }
1224
+ } else if (field === "tokenAirdrop" && result.type === "TOKENAIRDROP") {
1225
+ const extracted = HTSParser.extractTokenAirdropFromTransaction(transaction);
1226
+ if (extracted) {
1227
+ result[field] = extracted;
1224
1228
  }
1225
1229
  }
1226
- return null;
1227
- } catch (error) {
1228
- return null;
1229
- }
1230
+ });
1230
1231
  }
1231
1232
  /**
1232
1233
  * Create fallback result when all parsing methods fail