@hsuite/native-connect-angular 1.0.0

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 (276) hide show
  1. package/README.md +48 -0
  2. package/USAGE_EXAMPLES.md +476 -0
  3. package/assets/wallets/extension.svg +7 -0
  4. package/assets/wallets/hashpack.svg +6 -0
  5. package/assets/wallets/hsuite.svg +11 -0
  6. package/assets/wallets/kabila.svg +11 -0
  7. package/assets/wallets/walletconnect.svg +13 -0
  8. package/coverage/base.css +224 -0
  9. package/coverage/block-navigation.js +87 -0
  10. package/coverage/coverage-summary.json +50 -0
  11. package/coverage/favicon.png +0 -0
  12. package/coverage/index.html +476 -0
  13. package/coverage/lcov-report/base.css +224 -0
  14. package/coverage/lcov-report/block-navigation.js +87 -0
  15. package/coverage/lcov-report/favicon.png +0 -0
  16. package/coverage/lcov-report/index.html +476 -0
  17. package/coverage/lcov-report/lib/components/account-selector/account-actions/account-actions.component.ts.html +868 -0
  18. package/coverage/lcov-report/lib/components/account-selector/account-actions/index.html +116 -0
  19. package/coverage/lcov-report/lib/components/account-selector/account-filter/account-filter.component.ts.html +1288 -0
  20. package/coverage/lcov-report/lib/components/account-selector/account-filter/index.html +116 -0
  21. package/coverage/lcov-report/lib/components/account-selector/account-formatting.service.ts.html +685 -0
  22. package/coverage/lcov-report/lib/components/account-selector/account-grouping.service.ts.html +766 -0
  23. package/coverage/lcov-report/lib/components/account-selector/account-list/account-list.component.ts.html +1495 -0
  24. package/coverage/lcov-report/lib/components/account-selector/account-list/index.html +116 -0
  25. package/coverage/lcov-report/lib/components/account-selector/account-selector.component.ts.html +1495 -0
  26. package/coverage/lcov-report/lib/components/account-selector/account-selector.service.ts.html +1588 -0
  27. package/coverage/lcov-report/lib/components/account-selector/index.html +161 -0
  28. package/coverage/lcov-report/lib/components/wallet-account-display/index.html +116 -0
  29. package/coverage/lcov-report/lib/components/wallet-account-display/wallet-account-display.component.ts.html +505 -0
  30. package/coverage/lcov-report/lib/components/wallet-connect-button/index.html +116 -0
  31. package/coverage/lcov-report/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +805 -0
  32. package/coverage/lcov-report/lib/components/wallet-connect-prompt/index.html +116 -0
  33. package/coverage/lcov-report/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +409 -0
  34. package/coverage/lcov-report/lib/components/wallet-connected-guard/index.html +116 -0
  35. package/coverage/lcov-report/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +304 -0
  36. package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +436 -0
  37. package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/index.html +116 -0
  38. package/coverage/lcov-report/lib/components/wallet-connection-modal/index.html +116 -0
  39. package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/index.html +116 -0
  40. package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +2287 -0
  41. package/coverage/lcov-report/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +2275 -0
  42. package/coverage/lcov-report/lib/components/wallet-session-display/index.html +116 -0
  43. package/coverage/lcov-report/lib/components/wallet-session-display/wallet-session-display.component.ts.html +676 -0
  44. package/coverage/lcov-report/lib/components/wallet-transaction-status/index.html +116 -0
  45. package/coverage/lcov-report/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +703 -0
  46. package/coverage/lcov-report/lib/directives/index.html +146 -0
  47. package/coverage/lcov-report/lib/directives/wallet-connected.directive.ts.html +670 -0
  48. package/coverage/lcov-report/lib/directives/wallet-context.directive.ts.html +547 -0
  49. package/coverage/lcov-report/lib/directives/wallet-events.directive.ts.html +781 -0
  50. package/coverage/lcov-report/lib/hsuite-wallet.module.ts.html +715 -0
  51. package/coverage/lcov-report/lib/index.html +116 -0
  52. package/coverage/lcov-report/lib/models/connection-config.model.ts.html +280 -0
  53. package/coverage/lcov-report/lib/models/index.html +131 -0
  54. package/coverage/lcov-report/lib/models/provider-types.ts.html +577 -0
  55. package/coverage/lcov-report/lib/providers/base-wallet-provider.ts.html +1138 -0
  56. package/coverage/lcov-report/lib/providers/hsuite-native/channel-client.service.ts.html +2671 -0
  57. package/coverage/lcov-report/lib/providers/hsuite-native/index.html +116 -0
  58. package/coverage/lcov-report/lib/providers/hsuite-native-provider.ts.html +2347 -0
  59. package/coverage/lcov-report/lib/providers/index.html +146 -0
  60. package/coverage/lcov-report/lib/providers/p2p-native/index.html +131 -0
  61. package/coverage/lcov-report/lib/providers/p2p-native/p2p-native.provider.ts.html +2254 -0
  62. package/coverage/lcov-report/lib/providers/p2p-native/p2p-session-manager.ts.html +2170 -0
  63. package/coverage/lcov-report/lib/providers/wallet-error-handler.ts.html +1132 -0
  64. package/coverage/lcov-report/lib/providers/walletconnect/core/index.html +176 -0
  65. package/coverage/lcov-report/lib/providers/walletconnect/core/session-health.ts.html +673 -0
  66. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1177 -0
  67. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-provider.ts.html +2563 -0
  68. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +904 -0
  69. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +982 -0
  70. package/coverage/lcov-report/lib/providers/walletconnect/signers/hedera-signer.ts.html +1915 -0
  71. package/coverage/lcov-report/lib/providers/walletconnect/signers/index.html +146 -0
  72. package/coverage/lcov-report/lib/providers/walletconnect/signers/signer-factory.ts.html +445 -0
  73. package/coverage/lcov-report/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1519 -0
  74. package/coverage/lcov-report/lib/services/index.html +191 -0
  75. package/coverage/lcov-report/lib/services/logger.service.ts.html +463 -0
  76. package/coverage/lcov-report/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1840 -0
  77. package/coverage/lcov-report/lib/services/transaction-builders/hedera-amount-utils.ts.html +337 -0
  78. package/coverage/lcov-report/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +3940 -0
  79. package/coverage/lcov-report/lib/services/transaction-builders/index.html +161 -0
  80. package/coverage/lcov-report/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +2581 -0
  81. package/coverage/lcov-report/lib/services/transaction.service.ts.html +1123 -0
  82. package/coverage/lcov-report/lib/services/unified-wallet.service.ts.html +2641 -0
  83. package/coverage/lcov-report/lib/services/wallet-context.service.ts.html +637 -0
  84. package/coverage/lcov-report/lib/services/wallet-event-bus.service.ts.html +643 -0
  85. package/coverage/lcov-report/lib/services/wallet-providers.service.ts.html +496 -0
  86. package/coverage/lcov-report/lib/transports/chrome-extension-transport.ts.html +823 -0
  87. package/coverage/lcov-report/lib/transports/index.html +116 -0
  88. package/coverage/lcov-report/lib/utils/index.html +116 -0
  89. package/coverage/lcov-report/lib/utils/ledger-icons.util.ts.html +319 -0
  90. package/coverage/lcov-report/prettify.css +1 -0
  91. package/coverage/lcov-report/prettify.js +2 -0
  92. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  93. package/coverage/lcov-report/sorter.js +210 -0
  94. package/coverage/lcov.info +19252 -0
  95. package/coverage/lib/components/account-selector/account-actions/account-actions.component.ts.html +868 -0
  96. package/coverage/lib/components/account-selector/account-actions/index.html +116 -0
  97. package/coverage/lib/components/account-selector/account-filter/account-filter.component.ts.html +1288 -0
  98. package/coverage/lib/components/account-selector/account-filter/index.html +116 -0
  99. package/coverage/lib/components/account-selector/account-formatting.service.ts.html +685 -0
  100. package/coverage/lib/components/account-selector/account-grouping.service.ts.html +766 -0
  101. package/coverage/lib/components/account-selector/account-list/account-list.component.ts.html +1495 -0
  102. package/coverage/lib/components/account-selector/account-list/index.html +116 -0
  103. package/coverage/lib/components/account-selector/account-selector.component.ts.html +1495 -0
  104. package/coverage/lib/components/account-selector/account-selector.service.ts.html +1588 -0
  105. package/coverage/lib/components/account-selector/index.html +161 -0
  106. package/coverage/lib/components/wallet-account-display/index.html +116 -0
  107. package/coverage/lib/components/wallet-account-display/wallet-account-display.component.ts.html +505 -0
  108. package/coverage/lib/components/wallet-connect-button/index.html +116 -0
  109. package/coverage/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +805 -0
  110. package/coverage/lib/components/wallet-connect-prompt/index.html +116 -0
  111. package/coverage/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +409 -0
  112. package/coverage/lib/components/wallet-connected-guard/index.html +116 -0
  113. package/coverage/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +304 -0
  114. package/coverage/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +436 -0
  115. package/coverage/lib/components/wallet-connection-modal/connection-method-step/index.html +116 -0
  116. package/coverage/lib/components/wallet-connection-modal/index.html +116 -0
  117. package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/index.html +116 -0
  118. package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +2287 -0
  119. package/coverage/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +2275 -0
  120. package/coverage/lib/components/wallet-session-display/index.html +116 -0
  121. package/coverage/lib/components/wallet-session-display/wallet-session-display.component.ts.html +676 -0
  122. package/coverage/lib/components/wallet-transaction-status/index.html +116 -0
  123. package/coverage/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +703 -0
  124. package/coverage/lib/directives/index.html +146 -0
  125. package/coverage/lib/directives/wallet-connected.directive.ts.html +670 -0
  126. package/coverage/lib/directives/wallet-context.directive.ts.html +547 -0
  127. package/coverage/lib/directives/wallet-events.directive.ts.html +781 -0
  128. package/coverage/lib/hsuite-wallet.module.ts.html +715 -0
  129. package/coverage/lib/index.html +116 -0
  130. package/coverage/lib/models/connection-config.model.ts.html +280 -0
  131. package/coverage/lib/models/index.html +131 -0
  132. package/coverage/lib/models/provider-types.ts.html +577 -0
  133. package/coverage/lib/providers/base-wallet-provider.ts.html +1138 -0
  134. package/coverage/lib/providers/hsuite-native/channel-client.service.ts.html +2671 -0
  135. package/coverage/lib/providers/hsuite-native/index.html +116 -0
  136. package/coverage/lib/providers/hsuite-native-provider.ts.html +2347 -0
  137. package/coverage/lib/providers/index.html +146 -0
  138. package/coverage/lib/providers/p2p-native/index.html +131 -0
  139. package/coverage/lib/providers/p2p-native/p2p-native.provider.ts.html +2254 -0
  140. package/coverage/lib/providers/p2p-native/p2p-session-manager.ts.html +2170 -0
  141. package/coverage/lib/providers/wallet-error-handler.ts.html +1132 -0
  142. package/coverage/lib/providers/walletconnect/core/index.html +176 -0
  143. package/coverage/lib/providers/walletconnect/core/session-health.ts.html +673 -0
  144. package/coverage/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1177 -0
  145. package/coverage/lib/providers/walletconnect/core/walletconnect-provider.ts.html +2563 -0
  146. package/coverage/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +904 -0
  147. package/coverage/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +982 -0
  148. package/coverage/lib/providers/walletconnect/signers/hedera-signer.ts.html +1915 -0
  149. package/coverage/lib/providers/walletconnect/signers/index.html +146 -0
  150. package/coverage/lib/providers/walletconnect/signers/signer-factory.ts.html +445 -0
  151. package/coverage/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1519 -0
  152. package/coverage/lib/services/index.html +191 -0
  153. package/coverage/lib/services/logger.service.ts.html +463 -0
  154. package/coverage/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1840 -0
  155. package/coverage/lib/services/transaction-builders/hedera-amount-utils.ts.html +337 -0
  156. package/coverage/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +3940 -0
  157. package/coverage/lib/services/transaction-builders/index.html +161 -0
  158. package/coverage/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +2581 -0
  159. package/coverage/lib/services/transaction.service.ts.html +1123 -0
  160. package/coverage/lib/services/unified-wallet.service.ts.html +2641 -0
  161. package/coverage/lib/services/wallet-context.service.ts.html +637 -0
  162. package/coverage/lib/services/wallet-event-bus.service.ts.html +643 -0
  163. package/coverage/lib/services/wallet-providers.service.ts.html +496 -0
  164. package/coverage/lib/transports/chrome-extension-transport.ts.html +823 -0
  165. package/coverage/lib/transports/index.html +116 -0
  166. package/coverage/lib/utils/index.html +116 -0
  167. package/coverage/lib/utils/ledger-icons.util.ts.html +319 -0
  168. package/coverage/prettify.css +1 -0
  169. package/coverage/prettify.js +2 -0
  170. package/coverage/sort-arrow-sprite.png +0 -0
  171. package/coverage/sorter.js +210 -0
  172. package/dist/README.md +48 -0
  173. package/dist/fesm2022/hsuite-native-connect-angular.mjs +14592 -0
  174. package/dist/fesm2022/hsuite-native-connect-angular.mjs.map +1 -0
  175. package/dist/index.d.ts +6949 -0
  176. package/examples/minimal-connect.ts +178 -0
  177. package/examples/multi-protocol.ts +495 -0
  178. package/examples/transaction-signing.ts +361 -0
  179. package/jest.config.json +45 -0
  180. package/karma.conf.js +42 -0
  181. package/ng-package.json +20 -0
  182. package/package.json +60 -0
  183. package/src/index.ts +203 -0
  184. package/src/lib/components/account-selector/account-actions/account-actions.component.ts +261 -0
  185. package/src/lib/components/account-selector/account-filter/account-filter.component.ts +401 -0
  186. package/src/lib/components/account-selector/account-formatting.service.ts +200 -0
  187. package/src/lib/components/account-selector/account-grouping.service.ts +227 -0
  188. package/src/lib/components/account-selector/account-list/account-list.component.ts +470 -0
  189. package/src/lib/components/account-selector/account-selector.component.html +135 -0
  190. package/src/lib/components/account-selector/account-selector.component.scss +2039 -0
  191. package/src/lib/components/account-selector/account-selector.component.ts +470 -0
  192. package/src/lib/components/account-selector/account-selector.service.ts +501 -0
  193. package/src/lib/components/wallet-account-display/wallet-account-display.component.html +34 -0
  194. package/src/lib/components/wallet-account-display/wallet-account-display.component.scss +99 -0
  195. package/src/lib/components/wallet-account-display/wallet-account-display.component.ts +140 -0
  196. package/src/lib/components/wallet-connect-button/wallet-connect-button.component.html +14 -0
  197. package/src/lib/components/wallet-connect-button/wallet-connect-button.component.scss +272 -0
  198. package/src/lib/components/wallet-connect-button/wallet-connect-button.component.ts +240 -0
  199. package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.html +24 -0
  200. package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.scss +50 -0
  201. package/src/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts +108 -0
  202. package/src/lib/components/wallet-connected-guard/wallet-connected-guard.component.html +24 -0
  203. package/src/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts +73 -0
  204. package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.html +56 -0
  205. package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.scss +218 -0
  206. package/src/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts +117 -0
  207. package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.html +94 -0
  208. package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.scss +272 -0
  209. package/src/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts +734 -0
  210. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.html +197 -0
  211. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.scss +678 -0
  212. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts +730 -0
  213. package/src/lib/components/wallet-session-display/wallet-session-display.component.html +110 -0
  214. package/src/lib/components/wallet-session-display/wallet-session-display.component.scss +179 -0
  215. package/src/lib/components/wallet-session-display/wallet-session-display.component.ts +197 -0
  216. package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.html +65 -0
  217. package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.scss +254 -0
  218. package/src/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts +206 -0
  219. package/src/lib/directives/wallet-connected.directive.ts +195 -0
  220. package/src/lib/directives/wallet-context.directive.ts +154 -0
  221. package/src/lib/directives/wallet-events.directive.ts +232 -0
  222. package/src/lib/hsuite-wallet.module.ts +210 -0
  223. package/src/lib/models/connection-config.model.ts +65 -0
  224. package/src/lib/models/provider-types.ts +164 -0
  225. package/src/lib/models/unified-account.model.ts +76 -0
  226. package/src/lib/models/wallet-context.model.ts +121 -0
  227. package/src/lib/models/wallet-events.model.ts +158 -0
  228. package/src/lib/providers/base-wallet-provider.ts +351 -0
  229. package/src/lib/providers/hsuite-native/channel-client.service.spec.ts +73 -0
  230. package/src/lib/providers/hsuite-native/channel-client.service.ts +862 -0
  231. package/src/lib/providers/hsuite-native/index.ts +8 -0
  232. package/src/lib/providers/hsuite-native-provider.ts +754 -0
  233. package/src/lib/providers/mobile-native/mobile-native.provider.spec.ts +19 -0
  234. package/src/lib/providers/p2p-native/index.ts +30 -0
  235. package/src/lib/providers/p2p-native/p2p-native.provider.spec.ts +523 -0
  236. package/src/lib/providers/p2p-native/p2p-native.provider.ts +723 -0
  237. package/src/lib/providers/p2p-native/p2p-session-manager.ts +695 -0
  238. package/src/lib/providers/wallet-error-handler.ts +349 -0
  239. package/src/lib/providers/walletconnect/core/base-signer.interface.ts +122 -0
  240. package/src/lib/providers/walletconnect/core/session-health.ts +196 -0
  241. package/src/lib/providers/walletconnect/core/walletconnect-client-manager.ts +364 -0
  242. package/src/lib/providers/walletconnect/core/walletconnect-provider.integration.spec.ts +348 -0
  243. package/src/lib/providers/walletconnect/core/walletconnect-provider.ts +826 -0
  244. package/src/lib/providers/walletconnect/core/walletconnect-session-store.ts +273 -0
  245. package/src/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts +299 -0
  246. package/src/lib/providers/walletconnect/core/walletconnect-types.ts +48 -0
  247. package/src/lib/providers/walletconnect/index.ts +33 -0
  248. package/src/lib/providers/walletconnect/signers/hedera-signer.spec.ts +367 -0
  249. package/src/lib/providers/walletconnect/signers/hedera-signer.ts +610 -0
  250. package/src/lib/providers/walletconnect/signers/signer-factory.spec.ts +62 -0
  251. package/src/lib/providers/walletconnect/signers/signer-factory.ts +120 -0
  252. package/src/lib/providers/walletconnect/signers/xrpl-signer.spec.ts +296 -0
  253. package/src/lib/providers/walletconnect/signers/xrpl-signer.ts +478 -0
  254. package/src/lib/services/logger.service.ts +126 -0
  255. package/src/lib/services/transaction-builders/base-transaction-builder.service.ts +585 -0
  256. package/src/lib/services/transaction-builders/hedera-amount-utils.ts +84 -0
  257. package/src/lib/services/transaction-builders/hedera-transaction-builder.service.spec.ts +741 -0
  258. package/src/lib/services/transaction-builders/hedera-transaction-builder.service.ts +1285 -0
  259. package/src/lib/services/transaction-builders/index.ts +54 -0
  260. package/src/lib/services/transaction-builders/xrpl-transaction-builder.service.spec.ts +937 -0
  261. package/src/lib/services/transaction-builders/xrpl-transaction-builder.service.ts +832 -0
  262. package/src/lib/services/transaction.service.ts +346 -0
  263. package/src/lib/services/unified-wallet.service.spec.ts +1382 -0
  264. package/src/lib/services/unified-wallet.service.ts +852 -0
  265. package/src/lib/services/wallet-context.service.ts +184 -0
  266. package/src/lib/services/wallet-event-bus.service.ts +186 -0
  267. package/src/lib/services/wallet-providers.service.ts +137 -0
  268. package/src/lib/transports/chrome-extension-transport.ts +246 -0
  269. package/src/lib/utils/index.ts +14 -0
  270. package/src/lib/utils/ledger-icons.util.ts +78 -0
  271. package/test/test-setup.ts +21 -0
  272. package/test-setup.ts +63 -0
  273. package/tsconfig.build.json +11 -0
  274. package/tsconfig.json +29 -0
  275. package/tsconfig.spec.json +15 -0
  276. package/vitest.config.ts +48 -0
@@ -0,0 +1,741 @@
1
+ /**
2
+ * @fileoverview Unit tests for HederaTransactionBuilderService
3
+ *
4
+ * Tests cover:
5
+ * - HBAR/token/NFT transfer transactions
6
+ * - Token association/dissociation
7
+ * - Atomic transactions with multiple transfers
8
+ * - Token/topic/account creation
9
+ * - Multisig key configuration
10
+ * - Error handling
11
+ *
12
+ * @module services/transaction-builders/hedera-transaction-builder
13
+ * @since 2.0.0
14
+ */
15
+
16
+ import { TestBed } from '@angular/core/testing';
17
+ import { describe, it, expect, beforeEach, vi, type MockedFunction } from 'vitest';
18
+ import {
19
+ HederaTransactionBuilderService,
20
+ type HederaKeyConfig,
21
+ type TokenCreateOptions,
22
+ type TopicCreateOptions,
23
+ type AccountCreateOptions,
24
+ } from './hedera-transaction-builder.service';
25
+ import { UnifiedWalletService } from '../unified-wallet.service';
26
+ import { LoggerService } from '../logger.service';
27
+ import { signal } from '@angular/core';
28
+ import type { WalletAccount } from '@hsuite/native-connect-types';
29
+
30
+ // Mock Hedera SDK
31
+ vi.mock('@hashgraph/sdk', () => {
32
+ const mockTransactionId = {
33
+ generate: vi.fn().mockReturnValue('mock-tx-id'),
34
+ };
35
+
36
+ const mockAccountId = {
37
+ fromString: vi.fn((s: string) => ({ toString: () => s })),
38
+ };
39
+
40
+ const mockTokenId = {
41
+ fromString: vi.fn((s: string) => ({ toString: () => s })),
42
+ };
43
+
44
+ const mockHbar = vi.fn((amount: number) => ({
45
+ toTinybars: () => amount * 100_000_000,
46
+ amount,
47
+ }));
48
+ mockHbar.fromTinybars = vi.fn((amount: number) => ({ amount }));
49
+
50
+ const createMockTransaction = () => ({
51
+ setTransactionId: vi.fn().mockReturnThis(),
52
+ freezeWith: vi.fn().mockResolvedValue({
53
+ toBytes: () => new Uint8Array([1, 2, 3, 4]),
54
+ }),
55
+ toBytes: () => new Uint8Array([1, 2, 3, 4]),
56
+ addHbarTransfer: vi.fn().mockReturnThis(),
57
+ addTokenTransfer: vi.fn().mockReturnThis(),
58
+ addNftTransfer: vi.fn().mockReturnThis(),
59
+ setAccountId: vi.fn().mockReturnThis(),
60
+ setTokenIds: vi.fn().mockReturnThis(),
61
+ setBatchKey: vi.fn().mockReturnThis(),
62
+ setAmount: vi.fn().mockReturnThis(),
63
+ setTokenId: vi.fn().mockReturnThis(),
64
+ setMetadata: vi.fn().mockReturnThis(),
65
+ setScheduledTransaction: vi.fn().mockReturnThis(),
66
+ setPayerAccountId: vi.fn().mockReturnThis(),
67
+ setScheduleMemo: vi.fn().mockReturnThis(),
68
+ setTokenName: vi.fn().mockReturnThis(),
69
+ setTokenSymbol: vi.fn().mockReturnThis(),
70
+ setDecimals: vi.fn().mockReturnThis(),
71
+ setInitialSupply: vi.fn().mockReturnThis(),
72
+ setTreasuryAccountId: vi.fn().mockReturnThis(),
73
+ setTokenType: vi.fn().mockReturnThis(),
74
+ setSupplyType: vi.fn().mockReturnThis(),
75
+ setMaxSupply: vi.fn().mockReturnThis(),
76
+ setTokenMemo: vi.fn().mockReturnThis(),
77
+ setAdminKey: vi.fn().mockReturnThis(),
78
+ setSupplyKey: vi.fn().mockReturnThis(),
79
+ setFreezeKey: vi.fn().mockReturnThis(),
80
+ setWipeKey: vi.fn().mockReturnThis(),
81
+ setPauseKey: vi.fn().mockReturnThis(),
82
+ setKycKey: vi.fn().mockReturnThis(),
83
+ setFeeScheduleKey: vi.fn().mockReturnThis(),
84
+ setTopicMemo: vi.fn().mockReturnThis(),
85
+ setAutoRenewAccountId: vi.fn().mockReturnThis(),
86
+ setSubmitKey: vi.fn().mockReturnThis(),
87
+ setKey: vi.fn().mockReturnThis(),
88
+ setInitialBalance: vi.fn().mockReturnThis(),
89
+ setAccountMemo: vi.fn().mockReturnThis(),
90
+ setMaxAutomaticTokenAssociations: vi.fn().mockReturnThis(),
91
+ setReceiverSignatureRequired: vi.fn().mockReturnThis(),
92
+ setAlias: vi.fn().mockReturnThis(),
93
+ addTransaction: vi.fn().mockReturnThis(),
94
+ setInnerTransactionIndex: vi.fn().mockReturnThis(),
95
+ });
96
+
97
+ const mockNftId = vi.fn((tokenId: unknown, serial: number) => ({
98
+ tokenId,
99
+ serial,
100
+ }));
101
+
102
+ const mockPublicKey = {
103
+ fromString: vi.fn((s: string) => ({ _key: s, toString: () => s })),
104
+ };
105
+
106
+ const mockKeyList = vi.fn((keys: unknown[], threshold: number) => ({
107
+ keys,
108
+ threshold,
109
+ }));
110
+
111
+ const mockPrivateKey = {
112
+ generate: vi.fn().mockReturnValue({
113
+ publicKey: { toString: () => 'mock-public-key' },
114
+ }),
115
+ };
116
+
117
+ const mockClient = {
118
+ forMainnet: vi.fn().mockReturnValue({ network: 'mainnet' }),
119
+ forTestnet: vi.fn().mockReturnValue({ network: 'testnet' }),
120
+ forPreviewnet: vi.fn().mockReturnValue({ network: 'previewnet' }),
121
+ };
122
+
123
+ const TokenType = {
124
+ FungibleCommon: 0,
125
+ NonFungibleUnique: 1,
126
+ };
127
+
128
+ const TokenSupplyType = {
129
+ Infinite: 0,
130
+ Finite: 1,
131
+ };
132
+
133
+ return {
134
+ TransferTransaction: vi.fn(createMockTransaction),
135
+ TokenAssociateTransaction: vi.fn(createMockTransaction),
136
+ TokenDissociateTransaction: vi.fn(createMockTransaction),
137
+ TokenCreateTransaction: vi.fn(createMockTransaction),
138
+ TokenMintTransaction: vi.fn(createMockTransaction),
139
+ TokenBurnTransaction: vi.fn(createMockTransaction),
140
+ TopicCreateTransaction: vi.fn(createMockTransaction),
141
+ TopicMessageSubmitTransaction: vi.fn(createMockTransaction),
142
+ AccountCreateTransaction: vi.fn(createMockTransaction),
143
+ AccountUpdateTransaction: vi.fn(createMockTransaction),
144
+ ScheduleCreateTransaction: vi.fn(createMockTransaction),
145
+ BatchTransaction: vi.fn(createMockTransaction),
146
+ Transaction: vi.fn(createMockTransaction),
147
+ TransactionId: mockTransactionId,
148
+ AccountId: mockAccountId,
149
+ TokenId: mockTokenId,
150
+ NftId: mockNftId,
151
+ Hbar: mockHbar,
152
+ Client: mockClient,
153
+ PublicKey: mockPublicKey,
154
+ PrivateKey: mockPrivateKey,
155
+ KeyList: mockKeyList,
156
+ Key: vi.fn(),
157
+ TokenType,
158
+ TokenSupplyType,
159
+ };
160
+ });
161
+
162
+ describe('HederaTransactionBuilderService', () => {
163
+ let service: HederaTransactionBuilderService;
164
+ let mockWalletService: {
165
+ activeAccount: ReturnType<typeof signal<WalletAccount | undefined>>;
166
+ };
167
+ let mockLogger: {
168
+ debug: MockedFunction<(...args: unknown[]) => void>;
169
+ warn: MockedFunction<(...args: unknown[]) => void>;
170
+ error: MockedFunction<(...args: unknown[]) => void>;
171
+ scoped: MockedFunction<(scope: string) => typeof mockLogger>;
172
+ };
173
+
174
+ const mockAccount: WalletAccount = {
175
+ address: '0.0.12345',
176
+ ledgerId: 'hedera',
177
+ networkId: 'hedera:testnet',
178
+ label: 'Test Account',
179
+ balance: '100',
180
+ metadata: {
181
+ publicKey: 'mock-public-key-hex',
182
+ },
183
+ };
184
+
185
+ beforeEach(async () => {
186
+ mockWalletService = {
187
+ activeAccount: signal<WalletAccount | undefined>(mockAccount),
188
+ };
189
+
190
+ mockLogger = {
191
+ debug: vi.fn(),
192
+ warn: vi.fn(),
193
+ error: vi.fn(),
194
+ scoped: vi.fn().mockReturnThis(),
195
+ };
196
+
197
+ await TestBed.configureTestingModule({
198
+ providers: [
199
+ HederaTransactionBuilderService,
200
+ { provide: UnifiedWalletService, useValue: mockWalletService },
201
+ { provide: LoggerService, useValue: mockLogger },
202
+ ],
203
+ }).compileComponents();
204
+
205
+ service = TestBed.inject(HederaTransactionBuilderService);
206
+ });
207
+
208
+ it('should create', () => {
209
+ expect(service).toBeTruthy();
210
+ });
211
+
212
+ // ==================== HBAR TRANSFER ====================
213
+ describe('buildSendHbar', () => {
214
+ it('should build HBAR transfer transaction', async () => {
215
+ const result = await service.buildSendHbar('0.0.12345', '0.0.67890', 10);
216
+
217
+ expect(result).toBeDefined();
218
+ expect(typeof result).toBe('string');
219
+ // Base64 encoded
220
+ expect(result.match(/^[A-Za-z0-9+/]+=*$/)).toBeTruthy();
221
+ });
222
+
223
+ it('should throw error when no active wallet session', async () => {
224
+ mockWalletService.activeAccount.set(undefined);
225
+
226
+ await expect(service.buildSendHbar('0.0.12345', '0.0.67890', 10)).rejects.toThrow(
227
+ 'No active wallet session',
228
+ );
229
+ });
230
+ });
231
+
232
+ // ==================== TOKEN TRANSFER ====================
233
+ describe('buildSendToken', () => {
234
+ it('should build token transfer transaction', async () => {
235
+ const result = await service.buildSendToken('0.0.12345', '0.0.67890', '0.0.98765', 100, 8);
236
+
237
+ expect(result).toBeDefined();
238
+ expect(typeof result).toBe('string');
239
+ });
240
+
241
+ it('should use default decimals of 0', async () => {
242
+ const result = await service.buildSendToken('0.0.12345', '0.0.67890', '0.0.98765', 100);
243
+
244
+ expect(result).toBeDefined();
245
+ });
246
+ });
247
+
248
+ // ==================== NFT TRANSFER ====================
249
+ describe('buildSendNft', () => {
250
+ it('should build NFT transfer transaction', async () => {
251
+ const result = await service.buildSendNft('0.0.12345', '0.0.67890', '0.0.98765', 1);
252
+
253
+ expect(result).toBeDefined();
254
+ expect(typeof result).toBe('string');
255
+ });
256
+ });
257
+
258
+ // ==================== TOKEN ASSOCIATION ====================
259
+ describe('buildAssociateToken', () => {
260
+ it('should build token association transaction', async () => {
261
+ const result = await service.buildAssociateToken('0.0.12345', ['0.0.98765']);
262
+
263
+ expect(result).toBeDefined();
264
+ expect(typeof result).toBe('string');
265
+ });
266
+
267
+ it('should handle multiple token IDs', async () => {
268
+ const result = await service.buildAssociateToken('0.0.12345', [
269
+ '0.0.98765',
270
+ '0.0.98766',
271
+ '0.0.98767',
272
+ ]);
273
+
274
+ expect(result).toBeDefined();
275
+ });
276
+ });
277
+
278
+ // ==================== TOKEN DISSOCIATION ====================
279
+ describe('buildDissociateToken', () => {
280
+ it('should build token dissociation transaction', async () => {
281
+ const result = await service.buildDissociateToken('0.0.12345', ['0.0.98765']);
282
+
283
+ expect(result).toBeDefined();
284
+ expect(typeof result).toBe('string');
285
+ });
286
+ });
287
+
288
+ // ==================== SCHEDULED TRANSACTION ====================
289
+ describe('buildScheduledTransaction', () => {
290
+ it('should build scheduled transaction', async () => {
291
+ const innerTxBase64 = btoa('mock-inner-tx');
292
+ const result = await service.buildScheduledTransaction(innerTxBase64, '0.0.12345');
293
+
294
+ expect(result).toBeDefined();
295
+ expect(typeof result).toBe('string');
296
+ });
297
+
298
+ it('should build scheduled transaction with memo', async () => {
299
+ const innerTxBase64 = btoa('mock-inner-tx');
300
+ const result = await service.buildScheduledTransaction(
301
+ innerTxBase64,
302
+ '0.0.12345',
303
+ 'Test scheduled transaction',
304
+ );
305
+
306
+ expect(result).toBeDefined();
307
+ });
308
+ });
309
+
310
+ // ==================== BATCH TRANSACTIONS ====================
311
+ describe('buildBatchTransactions', () => {
312
+ it('should return transactions as-is', async () => {
313
+ const transactions = ['tx1', 'tx2', 'tx3'];
314
+ const result = await service.buildBatchTransactions(transactions);
315
+
316
+ expect(result).toEqual(transactions);
317
+ });
318
+ });
319
+
320
+ // ==================== ATOMIC TRANSACTION ====================
321
+ describe('buildAtomicTransaction', () => {
322
+ it('should build atomic transaction with HBAR transfers', async () => {
323
+ const result = await service.buildAtomicTransaction([
324
+ {
325
+ type: 'hbar',
326
+ fromAccount: '0.0.12345',
327
+ toAccount: '0.0.67890',
328
+ amount: 10,
329
+ },
330
+ {
331
+ type: 'hbar',
332
+ fromAccount: '0.0.12345',
333
+ toAccount: '0.0.11111',
334
+ amount: 5,
335
+ },
336
+ ]);
337
+
338
+ expect(result).toBeDefined();
339
+ expect(typeof result).toBe('string');
340
+ });
341
+
342
+ it('should build atomic transaction with token transfers', async () => {
343
+ const result = await service.buildAtomicTransaction([
344
+ {
345
+ type: 'token',
346
+ fromAccount: '0.0.12345',
347
+ toAccount: '0.0.67890',
348
+ amount: 100,
349
+ tokenId: '0.0.98765',
350
+ decimals: 8,
351
+ },
352
+ ]);
353
+
354
+ expect(result).toBeDefined();
355
+ });
356
+
357
+ it('should build atomic transaction with mixed transfers', async () => {
358
+ const result = await service.buildAtomicTransaction([
359
+ {
360
+ type: 'hbar',
361
+ fromAccount: '0.0.12345',
362
+ toAccount: '0.0.67890',
363
+ amount: 10,
364
+ },
365
+ {
366
+ type: 'token',
367
+ fromAccount: '0.0.12345',
368
+ toAccount: '0.0.67890',
369
+ amount: 100,
370
+ tokenId: '0.0.98765',
371
+ },
372
+ ]);
373
+
374
+ expect(result).toBeDefined();
375
+ });
376
+
377
+ it('should throw error for empty transfers', async () => {
378
+ await expect(service.buildAtomicTransaction([])).rejects.toThrow(
379
+ 'At least one transfer is required',
380
+ );
381
+ });
382
+ });
383
+
384
+ // ==================== TOKEN CREATE ====================
385
+ describe('buildTokenCreate', () => {
386
+ it('should build token creation with object options', async () => {
387
+ const options: TokenCreateOptions = {
388
+ name: 'Test Token',
389
+ symbol: 'TST',
390
+ decimals: 8,
391
+ initialSupply: 1_000_000,
392
+ };
393
+
394
+ const result = await service.buildTokenCreate('0.0.12345', options);
395
+
396
+ expect(result).toBeDefined();
397
+ expect(typeof result).toBe('string');
398
+ });
399
+
400
+ it('should build token creation with positional args', async () => {
401
+ const result = await service.buildTokenCreate('0.0.12345', 'Test Token', 'TST', 8, 1_000_000);
402
+
403
+ expect(result).toBeDefined();
404
+ });
405
+
406
+ it('should build NFT token creation', async () => {
407
+ const options: TokenCreateOptions = {
408
+ name: 'Test NFT',
409
+ symbol: 'TNFT',
410
+ decimals: 0,
411
+ initialSupply: 0,
412
+ tokenType: 'NFT',
413
+ };
414
+
415
+ const result = await service.buildTokenCreate('0.0.12345', options);
416
+
417
+ expect(result).toBeDefined();
418
+ });
419
+
420
+ it('should build token with max supply', async () => {
421
+ const options: TokenCreateOptions = {
422
+ name: 'Limited Token',
423
+ symbol: 'LTD',
424
+ decimals: 8,
425
+ initialSupply: 1_000_000,
426
+ maxSupply: 10_000_000,
427
+ };
428
+
429
+ const result = await service.buildTokenCreate('0.0.12345', options);
430
+
431
+ expect(result).toBeDefined();
432
+ });
433
+
434
+ it('should build token with memo', async () => {
435
+ const options: TokenCreateOptions = {
436
+ name: 'Memo Token',
437
+ symbol: 'MEM',
438
+ decimals: 8,
439
+ initialSupply: 1_000_000,
440
+ memo: 'This is a test token',
441
+ };
442
+
443
+ const result = await service.buildTokenCreate('0.0.12345', options);
444
+
445
+ expect(result).toBeDefined();
446
+ });
447
+ });
448
+
449
+ // ==================== TOPIC CREATE ====================
450
+ describe('buildTopicCreate', () => {
451
+ it('should build topic creation transaction', async () => {
452
+ const options: TopicCreateOptions = {
453
+ memo: 'Test topic',
454
+ };
455
+
456
+ const result = await service.buildTopicCreate('0.0.12345', options);
457
+
458
+ expect(result).toBeDefined();
459
+ expect(typeof result).toBe('string');
460
+ });
461
+
462
+ it('should build topic with simple memo string', async () => {
463
+ const result = await service.buildTopicCreate('0.0.12345', 'Simple memo');
464
+
465
+ expect(result).toBeDefined();
466
+ });
467
+
468
+ it('should build topic with auto-renew account', async () => {
469
+ const options: TopicCreateOptions = {
470
+ memo: 'Auto-renew topic',
471
+ autoRenewAccountId: '0.0.67890',
472
+ };
473
+
474
+ const result = await service.buildTopicCreate('0.0.12345', options);
475
+
476
+ expect(result).toBeDefined();
477
+ });
478
+ });
479
+
480
+ // ==================== ACCOUNT CREATE ====================
481
+ describe('buildAccountCreate', () => {
482
+ it('should build account creation transaction', async () => {
483
+ const options: AccountCreateOptions = {
484
+ initialBalance: 10,
485
+ key: { publicKey: 'mock-public-key' },
486
+ };
487
+
488
+ const result = await service.buildAccountCreate('0.0.12345', options);
489
+
490
+ expect(result).toBeDefined();
491
+ expect(typeof result).toBe('string');
492
+ });
493
+
494
+ it('should build account with memo', async () => {
495
+ const options: AccountCreateOptions = {
496
+ initialBalance: 10,
497
+ memo: 'Test account',
498
+ };
499
+
500
+ const result = await service.buildAccountCreate('0.0.12345', options);
501
+
502
+ expect(result).toBeDefined();
503
+ });
504
+
505
+ it('should build account with max automatic associations', async () => {
506
+ const options: AccountCreateOptions = {
507
+ initialBalance: 10,
508
+ maxAutomaticTokenAssociations: 100,
509
+ };
510
+
511
+ const result = await service.buildAccountCreate('0.0.12345', options);
512
+
513
+ expect(result).toBeDefined();
514
+ });
515
+
516
+ it('should build account requiring receiver signature', async () => {
517
+ const options: AccountCreateOptions = {
518
+ initialBalance: 10,
519
+ receiverSignatureRequired: true,
520
+ };
521
+
522
+ const result = await service.buildAccountCreate('0.0.12345', options);
523
+
524
+ expect(result).toBeDefined();
525
+ });
526
+
527
+ it('should build multisig account', async () => {
528
+ const options: AccountCreateOptions = {
529
+ initialBalance: 10,
530
+ key: {
531
+ signerPublicKeys: ['key1', 'key2', 'key3'],
532
+ threshold: 2,
533
+ },
534
+ };
535
+
536
+ const result = await service.buildAccountCreate('0.0.12345', options);
537
+
538
+ expect(result).toBeDefined();
539
+ });
540
+ });
541
+
542
+ // ==================== ACCOUNT UPDATE ====================
543
+ describe('buildAccountUpdate', () => {
544
+ it('should build account update transaction', async () => {
545
+ const result = await service.buildAccountUpdate('0.0.12345', {
546
+ key: { publicKey: 'new-public-key' },
547
+ });
548
+
549
+ expect(result).toBeDefined();
550
+ expect(typeof result).toBe('string');
551
+ });
552
+
553
+ it('should build account update with memo', async () => {
554
+ const result = await service.buildAccountUpdate('0.0.12345', {
555
+ memo: 'Updated memo',
556
+ });
557
+
558
+ expect(result).toBeDefined();
559
+ });
560
+
561
+ it('should build account update with max automatic associations', async () => {
562
+ const result = await service.buildAccountUpdate('0.0.12345', {
563
+ maxAutomaticTokenAssociations: 50,
564
+ });
565
+
566
+ expect(result).toBeDefined();
567
+ });
568
+ });
569
+
570
+ // ==================== BATCH INNER TRANSACTIONS ====================
571
+ describe('buildBatchInnerTransactions', () => {
572
+ const mockBatchKey = 'mock-batch-public-key';
573
+
574
+ it('should build batch with send-hbar', async () => {
575
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
576
+ { type: 'send-hbar', toAccount: '0.0.67890', amount: 100_000_000 },
577
+ ]);
578
+
579
+ expect(result).toBeDefined();
580
+ expect(Array.isArray(result)).toBe(true);
581
+ expect(result.length).toBe(1);
582
+ expect(result[0].payload).toBeDefined();
583
+ expect(result[0].description).toContain('tinybar');
584
+ });
585
+
586
+ it('should build batch with send-token', async () => {
587
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
588
+ {
589
+ type: 'send-token',
590
+ toAccount: '0.0.67890',
591
+ tokenId: '0.0.98765',
592
+ amount: 1000,
593
+ },
594
+ ]);
595
+
596
+ expect(result).toBeDefined();
597
+ expect(result.length).toBe(1);
598
+ });
599
+
600
+ it('should build batch with token-mint', async () => {
601
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
602
+ { type: 'token-mint', tokenId: '0.0.98765', amount: 100 },
603
+ ]);
604
+
605
+ expect(result).toBeDefined();
606
+ expect(result.length).toBe(1);
607
+ });
608
+
609
+ it('should build batch with token-mint and metadata', async () => {
610
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
611
+ { type: 'token-mint', tokenId: '0.0.98765', amount: 1, metadata: 'test-metadata' },
612
+ ]);
613
+
614
+ expect(result).toBeDefined();
615
+ });
616
+
617
+ it('should build batch with token-associate', async () => {
618
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
619
+ { type: 'token-associate', tokenId: '0.0.98765' },
620
+ ]);
621
+
622
+ expect(result).toBeDefined();
623
+ expect(result.length).toBe(1);
624
+ });
625
+
626
+ it('should build batch with multiple transactions', async () => {
627
+ const result = await service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
628
+ { type: 'send-hbar', toAccount: '0.0.67890', amount: 100_000_000 },
629
+ { type: 'send-hbar', toAccount: '0.0.11111', amount: 50_000_000 },
630
+ { type: 'token-associate', tokenId: '0.0.98765' },
631
+ ]);
632
+
633
+ expect(result).toBeDefined();
634
+ expect(result.length).toBe(3);
635
+ });
636
+
637
+ it('should throw error for unknown transaction type', async () => {
638
+ await expect(
639
+ service.buildBatchInnerTransactions('0.0.12345', mockBatchKey, [
640
+ { type: 'unknown-type' as any, toAccount: '0.0.67890' },
641
+ ]),
642
+ ).rejects.toThrow('Unknown transaction type');
643
+ });
644
+ });
645
+
646
+ // ==================== KEY CONFIG ====================
647
+ describe('key configuration', () => {
648
+ it('should auto-detect single-sig key from active account', async () => {
649
+ // Active account has publicKey in metadata
650
+ const options: TokenCreateOptions = {
651
+ name: 'Auto Key Token',
652
+ symbol: 'AKT',
653
+ decimals: 8,
654
+ initialSupply: 1_000_000,
655
+ };
656
+
657
+ const result = await service.buildTokenCreate('0.0.12345', options);
658
+
659
+ expect(result).toBeDefined();
660
+ // The logger should have been called with debug about single-sig
661
+ });
662
+
663
+ it('should auto-detect multisig key from active account', async () => {
664
+ // Set up multisig account
665
+ mockWalletService.activeAccount.set({
666
+ ...mockAccount,
667
+ metadata: {
668
+ isMultisig: true,
669
+ signerPublicKeys: ['key1', 'key2', 'key3'],
670
+ threshold: 2,
671
+ },
672
+ });
673
+
674
+ const options: TokenCreateOptions = {
675
+ name: 'Multisig Token',
676
+ symbol: 'MST',
677
+ decimals: 8,
678
+ initialSupply: 1_000_000,
679
+ };
680
+
681
+ const result = await service.buildTokenCreate('0.0.12345', options);
682
+
683
+ expect(result).toBeDefined();
684
+ });
685
+
686
+ it('should use explicitly provided key config over auto-detected', async () => {
687
+ const options: TokenCreateOptions = {
688
+ name: 'Explicit Key Token',
689
+ symbol: 'EKT',
690
+ decimals: 8,
691
+ initialSupply: 1_000_000,
692
+ adminKey: { publicKey: 'explicit-admin-key' },
693
+ supplyKey: { publicKey: 'explicit-supply-key' },
694
+ };
695
+
696
+ const result = await service.buildTokenCreate('0.0.12345', options);
697
+
698
+ expect(result).toBeDefined();
699
+ });
700
+ });
701
+
702
+ // ==================== NETWORK SELECTION ====================
703
+ describe('network selection', () => {
704
+ it('should use testnet for hedera:testnet', async () => {
705
+ mockWalletService.activeAccount.set({
706
+ ...mockAccount,
707
+ networkId: 'hedera:testnet',
708
+ });
709
+
710
+ const result = await service.buildSendHbar('0.0.12345', '0.0.67890', 10);
711
+
712
+ expect(result).toBeDefined();
713
+ });
714
+
715
+ it('should use mainnet for hedera:mainnet', async () => {
716
+ mockWalletService.activeAccount.set({
717
+ ...mockAccount,
718
+ networkId: 'hedera:mainnet',
719
+ });
720
+
721
+ const result = await service.buildSendHbar('0.0.12345', '0.0.67890', 10);
722
+
723
+ expect(result).toBeDefined();
724
+ });
725
+
726
+ it('should default to testnet for unknown network', async () => {
727
+ mockWalletService.activeAccount.set({
728
+ ...mockAccount,
729
+ networkId: 'hedera:unknown',
730
+ });
731
+
732
+ const result = await service.buildSendHbar('0.0.12345', '0.0.67890', 10);
733
+
734
+ expect(result).toBeDefined();
735
+ expect(mockLogger.warn).toHaveBeenCalledWith(
736
+ 'Unknown Hedera network, defaulting to testnet',
737
+ expect.any(Object),
738
+ );
739
+ });
740
+ });
741
+ });