@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,364 @@
1
+ /**
2
+ * HSuite Native Connect
3
+ * Copyright 2024-2025 HSuite (https://hsuite.finance)
4
+ *
5
+ * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
6
+ *
7
+ * This file is part of HSuite Native Connect. For commercial licensing,
8
+ * visit https://hsuite.finance/licensing
9
+ */
10
+
11
+ /**
12
+ * @file walletconnect-client-manager.ts
13
+ * @description WalletConnect SignClient lifecycle management
14
+ *
15
+ * Handles:
16
+ * - SignClient initialization with projectId
17
+ * - Client reuse across multiple connections
18
+ * - Session restoration from IndexedDB
19
+ * - Event listener registration
20
+ *
21
+ * Extracted from WalletConnectV2Provider to reduce file size.
22
+ */
23
+
24
+ import { getLogger } from '@hsuite/native-connect-sdk';
25
+ import { WalletConnectModal } from '@walletconnect/modal';
26
+ import SignClient from '@walletconnect/sign-client';
27
+
28
+ import { SessionHealthManager } from './session-health';
29
+
30
+ const logger = getLogger().scoped?.('WCClientManager') ?? getLogger();
31
+
32
+ /**
33
+ * Storage key for persisted projectId
34
+ */
35
+ const STORAGE_KEY_PROJECT_ID = 'hsuite.walletconnect.projectId';
36
+
37
+ /**
38
+ * WalletConnect app metadata
39
+ */
40
+ export interface WCAppMetadata {
41
+ name: string;
42
+ description: string;
43
+ url: string;
44
+ icons: string[];
45
+ }
46
+
47
+ /**
48
+ * WalletConnect Client Manager
49
+ *
50
+ * Manages the SignClient instance lifecycle.
51
+ * Handles initialization, session restoration, and cleanup.
52
+ */
53
+ export class WalletConnectClientManager {
54
+ private client?: SignClient;
55
+ private modal?: WalletConnectModal;
56
+ private projectId?: string;
57
+ private sessionHealth?: SessionHealthManager;
58
+
59
+ /**
60
+ * Initialize or return existing SignClient.
61
+ *
62
+ * @param projectId - WalletConnect Cloud project ID
63
+ * @param metadata - App metadata for wallet display
64
+ * @returns Initialized SignClient instance
65
+ */
66
+ async initialize(projectId: string, metadata: WCAppMetadata): Promise<SignClient> {
67
+ if (this.client && this.projectId === projectId) {
68
+ return this.client;
69
+ }
70
+
71
+ logger.debug('Initializing SignClient', { projectId: projectId.substring(0, 8) });
72
+
73
+ // Store projectId for session restoration
74
+ this.projectId = projectId;
75
+ this.persistProjectId(projectId);
76
+
77
+ // Use 'fatal' logger to suppress pino noise from WalletConnect SDK
78
+ this.client = await SignClient.init({
79
+ projectId,
80
+ logger: 'fatal',
81
+ metadata,
82
+ });
83
+
84
+ // Initialize session health manager for relay subscription management
85
+ this.sessionHealth = new SessionHealthManager(this.client);
86
+
87
+ logger.info('SignClient initialized with session health manager');
88
+ return this.client;
89
+ }
90
+
91
+ /**
92
+ * Get the current client instance.
93
+ * @throws Error if not initialized
94
+ */
95
+ getClient(): SignClient {
96
+ if (!this.client) {
97
+ throw new Error('WalletConnect client not initialized');
98
+ }
99
+ return this.client;
100
+ }
101
+
102
+ /**
103
+ * Check if client is initialized.
104
+ */
105
+ isInitialized(): boolean {
106
+ return !!this.client;
107
+ }
108
+
109
+ /**
110
+ * Restore client from stored projectId.
111
+ * Used for session restoration on page reload.
112
+ *
113
+ * @param metadata - App metadata
114
+ * @returns Client if restoration succeeded, undefined otherwise
115
+ */
116
+ async restoreClient(metadata: WCAppMetadata): Promise<SignClient | undefined> {
117
+ const storedProjectId = this.getStoredProjectId();
118
+ if (!storedProjectId) {
119
+ logger.debug('No stored projectId, skipping client restoration');
120
+ return undefined;
121
+ }
122
+
123
+ try {
124
+ return await this.initialize(storedProjectId, metadata);
125
+ } catch (error) {
126
+ logger.error('Failed to restore client', {
127
+ error: error instanceof Error ? error.message : String(error),
128
+ });
129
+ return undefined;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Get all active sessions from the client.
135
+ */
136
+ getActiveSessions(): any[] {
137
+ if (!this.client) {
138
+ return [];
139
+ }
140
+ return this.client.session.getAll();
141
+ }
142
+
143
+ /**
144
+ * Get a specific session by topic.
145
+ * @param topic
146
+ */
147
+ getSession(topic: string): any | undefined {
148
+ if (!this.client) {
149
+ return undefined;
150
+ }
151
+ try {
152
+ return this.client.session.get(topic);
153
+ } catch {
154
+ return undefined;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Create and return a modal for QR code display.
160
+ * @param projectId
161
+ * @param chains
162
+ */
163
+ createModal(projectId: string, chains: string[]): WalletConnectModal {
164
+ this.modal = new WalletConnectModal({
165
+ projectId,
166
+ chains,
167
+ });
168
+ return this.modal;
169
+ }
170
+
171
+ /**
172
+ * Close the modal if open.
173
+ */
174
+ closeModal(): void {
175
+ if (this.modal) {
176
+ this.modal.closeModal();
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Connect to wallet and get session.
182
+ *
183
+ * @param optionalNamespaces - Namespace configuration
184
+ * @param sessionProperties - Optional session properties (e.g., preferredNetwork)
185
+ * @returns URI and approval promise
186
+ */
187
+ async connect(
188
+ optionalNamespaces: Record<string, any>,
189
+ sessionProperties?: Record<string, string>,
190
+ ): Promise<{
191
+ uri?: string;
192
+ approval: () => Promise<any>;
193
+ }> {
194
+ if (!this.client) {
195
+ throw new Error('Client not initialized');
196
+ }
197
+
198
+ const connectParams: any = { optionalNamespaces };
199
+
200
+ // Add session properties if provided
201
+ // This allows passing metadata like preferredNetwork to the wallet
202
+ if (sessionProperties) {
203
+ connectParams.sessionProperties = sessionProperties;
204
+ }
205
+
206
+ logger.debug('Connecting with params', {
207
+ namespaces: Object.keys(optionalNamespaces),
208
+ hasSessionProperties: !!sessionProperties,
209
+ });
210
+
211
+ return this.client.connect(connectParams);
212
+ }
213
+
214
+ /**
215
+ * Disconnect a session.
216
+ * @param topic
217
+ * @param reason
218
+ * @param reason.code
219
+ * @param reason.message
220
+ */
221
+ async disconnect(topic: string, reason?: { code: number; message: string }): Promise<void> {
222
+ if (!this.client) {
223
+ return;
224
+ }
225
+ await this.client.disconnect({
226
+ topic,
227
+ reason: reason || { code: 6000, message: 'User disconnected' },
228
+ });
229
+ }
230
+
231
+ /**
232
+ * Register event listener on the client.
233
+ * @param event
234
+ * @param handler
235
+ */
236
+ on(event: string, handler: (event: any) => void): void {
237
+ if (!this.client) {
238
+ return;
239
+ }
240
+ (this.client as any).on(event, handler);
241
+ }
242
+
243
+ /**
244
+ * Send a request to a session.
245
+ *
246
+ * Features:
247
+ * - Automatically ensures session health by pinging before the request
248
+ * - Runs keep-alive pings during long-running requests (e.g., transaction approval)
249
+ * - Prevents stale relay subscription issues that cause empty error objects
250
+ *
251
+ * @param params - Request parameters including topic, chainId, and request data
252
+ * @param params.expiry - Optional expiry time in seconds (default: 300)
253
+ * @param params.topic
254
+ * @param params.chainId
255
+ * @param params.request
256
+ * @param params.request.method
257
+ * @param params.request.params
258
+ * @returns Promise resolving to the request result
259
+ */
260
+ async request<T = unknown>(params: {
261
+ topic: string;
262
+ chainId: string;
263
+ request: { method: string; params: unknown };
264
+ expiry?: number;
265
+ }): Promise<T> {
266
+ if (!this.client) {
267
+ throw new Error('Client not initialized');
268
+ }
269
+
270
+ // Ensure session health before request (transparent to caller)
271
+ // This pings the session if needed to refresh relay subscription
272
+ if (this.sessionHealth) {
273
+ await this.sessionHealth.ensureSessionHealth(params.topic);
274
+ }
275
+
276
+ // Keep-alive pings during long-running requests (e.g., transaction approval)
277
+ // WC relay has ~30s subscription timeout, so we ping every 20s to keep it alive
278
+ const KEEP_ALIVE_INTERVAL_MS = 20000;
279
+ let keepAliveInterval: ReturnType<typeof setInterval> | undefined;
280
+
281
+ const startKeepAlive = () => {
282
+ keepAliveInterval = setInterval(async () => {
283
+ try {
284
+ logger.debug('Keep-alive ping during request', {
285
+ topic: params.topic?.substring(0, 16) + '...',
286
+ method: params.request.method,
287
+ });
288
+ if (this.client) {
289
+ await Promise.race([
290
+ this.client.ping({ topic: params.topic }),
291
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Ping timeout')), 5000)),
292
+ ]);
293
+ }
294
+ } catch (err) {
295
+ // Log but don't throw - ping failure during wait is not critical
296
+ logger.debug('Keep-alive ping failed (non-critical)', {
297
+ error: err instanceof Error ? err.message : String(err),
298
+ });
299
+ }
300
+ }, KEEP_ALIVE_INTERVAL_MS);
301
+ };
302
+
303
+ const stopKeepAlive = () => {
304
+ if (keepAliveInterval) {
305
+ clearInterval(keepAliveInterval);
306
+ keepAliveInterval = undefined;
307
+ }
308
+ };
309
+
310
+ // Start keep-alive pings
311
+ startKeepAlive();
312
+
313
+ try {
314
+ const result = await this.client.request<T>(params);
315
+ return result;
316
+ } finally {
317
+ // Always stop keep-alive, whether success or error
318
+ stopKeepAlive();
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Get the session health manager for advanced operations.
324
+ *
325
+ * Use this if you need to:
326
+ * - Force refresh a subscription
327
+ * - Clear ping cache
328
+ * - Access health manager directly
329
+ *
330
+ * @returns SessionHealthManager instance or undefined if not initialized
331
+ */
332
+ getSessionHealthManager(): SessionHealthManager | undefined {
333
+ return this.sessionHealth;
334
+ }
335
+
336
+ // ========== STORAGE ==========
337
+
338
+ private persistProjectId(projectId: string): void {
339
+ try {
340
+ window.localStorage?.setItem(STORAGE_KEY_PROJECT_ID, projectId);
341
+ } catch {
342
+ logger.warn('Failed to persist projectId');
343
+ }
344
+ }
345
+
346
+ private getStoredProjectId(): string | null {
347
+ try {
348
+ return window.localStorage?.getItem(STORAGE_KEY_PROJECT_ID) ?? null;
349
+ } catch {
350
+ return null;
351
+ }
352
+ }
353
+
354
+ /**
355
+ * Clear stored projectId.
356
+ */
357
+ clearStoredProjectId(): void {
358
+ try {
359
+ window.localStorage?.removeItem(STORAGE_KEY_PROJECT_ID);
360
+ } catch {
361
+ // Ignore
362
+ }
363
+ }
364
+ }
@@ -0,0 +1,348 @@
1
+ /**
2
+ * @file walletconnect-provider.integration.spec.ts
3
+ * @description Integration tests for WalletConnectV2Provider
4
+ *
5
+ * @compodoc
6
+ * These tests verify the WalletConnect v2 provider integration.
7
+ * Some tests are skipped due to complex session state requirements.
8
+ */
9
+
10
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
11
+ import { TestBed } from '@angular/core/testing';
12
+ import { WalletConnectV2Provider } from './walletconnect-provider';
13
+ import { SignerFactory } from '../signers/signer-factory';
14
+ import { HederaSigner } from '../signers/hedera-signer';
15
+ import { XrplSigner } from '../signers/xrpl-signer';
16
+ import type { WalletConnectV2Config } from './walletconnect-types';
17
+
18
+ // Mock WalletConnect modules
19
+ vi.mock('@walletconnect/sign-client', () => ({
20
+ default: {
21
+ init: vi.fn(),
22
+ },
23
+ }));
24
+
25
+ vi.mock('@walletconnect/modal', () => ({
26
+ WalletConnectModal: vi.fn(),
27
+ }));
28
+
29
+ describe('WalletConnectV2Provider Integration Tests', () => {
30
+ let provider: WalletConnectV2Provider;
31
+ // Note: SignerFactory uses static methods, no need to inject
32
+ let mockSignClient: any;
33
+ let mockModal: any;
34
+
35
+ beforeEach(async () => {
36
+ // Clear localStorage
37
+ localStorage.clear();
38
+
39
+ // Mock SignClient
40
+ mockSignClient = {
41
+ connect: vi.fn().mockResolvedValue({
42
+ uri: 'wc:test-uri',
43
+ approval: vi.fn().mockResolvedValue({
44
+ topic: 'test-topic',
45
+ namespaces: {
46
+ hedera: {
47
+ accounts: ['hedera:testnet:0.0.12345'],
48
+ methods: ['hedera_signTransaction'],
49
+ chains: ['hedera:testnet']
50
+ }
51
+ }
52
+ })
53
+ }),
54
+ disconnect: vi.fn().mockResolvedValue(undefined),
55
+ request: vi.fn(),
56
+ session: {
57
+ getAll: vi.fn().mockReturnValue([])
58
+ },
59
+ on: vi.fn()
60
+ };
61
+
62
+ // Mock Modal
63
+ mockModal = {
64
+ openModal: vi.fn().mockResolvedValue(undefined),
65
+ closeModal: vi.fn()
66
+ };
67
+
68
+ const { default: SignClient } = await import('@walletconnect/sign-client');
69
+ const { WalletConnectModal } = await import('@walletconnect/modal');
70
+
71
+ vi.mocked(SignClient.init).mockResolvedValue(mockSignClient);
72
+ vi.mocked(WalletConnectModal).mockImplementation(() => mockModal);
73
+
74
+ TestBed.configureTestingModule({
75
+ providers: [
76
+ WalletConnectV2Provider,
77
+ HederaSigner,
78
+ XrplSigner
79
+ ]
80
+ });
81
+
82
+ provider = TestBed.inject(WalletConnectV2Provider);
83
+ });
84
+
85
+ describe('Provider Metadata', () => {
86
+ it('should have correct metadata', () => {
87
+ expect(provider.id).toBe('walletconnect-v2');
88
+ expect(provider.metadata.type).toBe('walletconnect-v2');
89
+ expect(provider.metadata.name).toBe('WalletConnect');
90
+ });
91
+ });
92
+
93
+ describe('Connection Flow', () => {
94
+ const config: WalletConnectV2Config = {
95
+ type: 'walletconnect-v2',
96
+ projectId: 'test-project-id',
97
+ ledgerId: 'hedera',
98
+ networkId: 'hedera:testnet',
99
+ appName: 'Test dApp'
100
+ };
101
+
102
+ it('should connect successfully with Hedera', async () => {
103
+ await provider.connect(config);
104
+
105
+ expect(provider.status()).toBe('connected');
106
+ expect(provider.accounts()).toHaveLength(1);
107
+ expect(provider.accounts()[0].address).toBe('0.0.12345');
108
+ });
109
+
110
+ it('should initialize SignClient with correct params', async () => {
111
+ const { default: SignClient } = await import('@walletconnect/sign-client');
112
+
113
+ await provider.connect(config);
114
+
115
+ expect(SignClient.init).toHaveBeenCalledWith(
116
+ expect.objectContaining({
117
+ projectId: 'test-project-id',
118
+ metadata: expect.objectContaining({
119
+ name: 'Test dApp'
120
+ })
121
+ })
122
+ );
123
+ });
124
+
125
+ it('should open modal with URI', async () => {
126
+ await provider.connect(config);
127
+
128
+ expect(mockModal.openModal).toHaveBeenCalledWith({
129
+ uri: 'wc:test-uri'
130
+ });
131
+ });
132
+
133
+ it('should close modal after approval', async () => {
134
+ await provider.connect(config);
135
+
136
+ expect(mockModal.closeModal).toHaveBeenCalled();
137
+ });
138
+
139
+ it('should store user network selection in localStorage', async () => {
140
+ await provider.connect(config);
141
+
142
+ // The provider stores user's network selection per session topic for restoration
143
+ // Check that the network selection was stored (using the test-topic from mock)
144
+ expect(localStorage.getItem('wc_user_network_selection_test-topic')).toBe('hedera:testnet');
145
+ });
146
+
147
+ it('should set error state if connection fails', async () => {
148
+ const { default: SignClient } = await import('@walletconnect/sign-client');
149
+ vi.mocked(SignClient.init).mockRejectedValue(new Error('Network error'));
150
+
151
+ await expect(provider.connect(config)).rejects.toThrow();
152
+
153
+ expect(provider.status()).toBe('error');
154
+ expect(provider.error()).toContain('Network error');
155
+ });
156
+ });
157
+
158
+ // Transaction signing tests - provider delegates to signers via the orchestrator
159
+ describe('Transaction Signing', () => {
160
+ beforeEach(async () => {
161
+ // Connect first
162
+ await provider.connect({
163
+ type: 'walletconnect-v2',
164
+ projectId: 'test-project-id',
165
+ ledgerId: 'hedera',
166
+ networkId: 'hedera:testnet'
167
+ });
168
+
169
+ mockSignClient.request.mockResolvedValue({
170
+ signatureMap: 'signed-result'
171
+ });
172
+ });
173
+
174
+ it('should throw error when signing with unknown account address', async () => {
175
+ // Attempt to sign with an account that doesn't exist in the session
176
+ await expect(provider.signTransaction({
177
+ ledgerId: 'hedera',
178
+ networkId: 'hedera:testnet',
179
+ accountAddress: '0.0.99999', // Not in session
180
+ payload: 'base64TransactionHere'
181
+ })).rejects.toThrow('No WalletConnect session found for account');
182
+ });
183
+
184
+ it('should throw error when no session exists for account', async () => {
185
+ // Disconnect first - this clears all sessions
186
+ await provider.disconnect();
187
+
188
+ // Create new provider that's not connected
189
+ const disconnectedProvider = TestBed.inject(WalletConnectV2Provider);
190
+
191
+ // The session lookup happens first, so we get "No WalletConnect session" error
192
+ await expect(disconnectedProvider.signTransaction({
193
+ ledgerId: 'hedera',
194
+ networkId: 'hedera:testnet',
195
+ accountAddress: '0.0.12345',
196
+ payload: 'base64'
197
+ })).rejects.toThrow('No WalletConnect session found for account');
198
+ });
199
+ });
200
+
201
+ // Transaction submission tests - provider delegates to signers via the orchestrator
202
+ describe('Transaction Submission', () => {
203
+ beforeEach(async () => {
204
+ await provider.connect({
205
+ type: 'walletconnect-v2',
206
+ projectId: 'test-project-id',
207
+ ledgerId: 'hedera',
208
+ networkId: 'hedera:testnet'
209
+ });
210
+
211
+ mockSignClient.request.mockResolvedValue({
212
+ transactionId: '0.0.12345@1699999999.123'
213
+ });
214
+ });
215
+
216
+ it('should throw error when submitting with unknown account address', async () => {
217
+ // Attempt to submit with an account that doesn't exist in the session
218
+ await expect(provider.submitTransaction({
219
+ ledgerId: 'hedera',
220
+ networkId: 'hedera:testnet',
221
+ accountAddress: '0.0.99999', // Not in session
222
+ payload: 'base64TransactionHere'
223
+ })).rejects.toThrow('No WalletConnect session found for account');
224
+ });
225
+
226
+ it('should throw error when no session exists for account', async () => {
227
+ // Disconnect first - this clears all sessions
228
+ await provider.disconnect();
229
+
230
+ // Create new provider that's not connected
231
+ const disconnectedProvider = TestBed.inject(WalletConnectV2Provider);
232
+
233
+ // The session lookup happens first, so we get "No WalletConnect session" error
234
+ await expect(disconnectedProvider.submitTransaction({
235
+ ledgerId: 'hedera',
236
+ networkId: 'hedera:testnet',
237
+ accountAddress: '0.0.12345',
238
+ payload: 'base64'
239
+ })).rejects.toThrow('No WalletConnect session found for account');
240
+ });
241
+ });
242
+
243
+ describe('Disconnection', () => {
244
+ it('should disconnect and clear state', async () => {
245
+ // Connect first
246
+ await provider.connect({
247
+ type: 'walletconnect-v2',
248
+ projectId: 'test-project-id',
249
+ ledgerId: 'hedera',
250
+ networkId: 'hedera:testnet'
251
+ });
252
+
253
+ expect(provider.status()).toBe('connected');
254
+
255
+ // Disconnect
256
+ await provider.disconnect();
257
+
258
+ expect(provider.status()).toBe('disconnected');
259
+ expect(provider.accounts()).toHaveLength(0);
260
+ expect(mockSignClient.disconnect).toHaveBeenCalledWith({
261
+ topic: 'test-topic',
262
+ reason: expect.any(Object)
263
+ });
264
+ });
265
+
266
+ it('should close modal on disconnect', async () => {
267
+ await provider.connect({
268
+ type: 'walletconnect-v2',
269
+ projectId: 'test-project-id',
270
+ ledgerId: 'hedera',
271
+ networkId: 'hedera:testnet'
272
+ });
273
+
274
+ await provider.disconnect();
275
+
276
+ // Modal closed during disconnect cleanup
277
+ expect(mockModal.closeModal).toHaveBeenCalled();
278
+ });
279
+ });
280
+
281
+ describe('Session Restoration', () => {
282
+ it('should restore session from localStorage', async () => {
283
+ // Set up stored session
284
+ localStorage.setItem('hsuite.walletconnect.projectId', 'stored-project-id');
285
+ localStorage.setItem('hsuite.walletconnect.ledgerId', 'hedera');
286
+ localStorage.setItem('hsuite.walletconnect.networkId', 'hedera:testnet');
287
+
288
+ mockSignClient.session.getAll.mockReturnValue([
289
+ {
290
+ topic: 'stored-topic',
291
+ namespaces: {
292
+ hedera: {
293
+ accounts: ['hedera:testnet:0.0.99999']
294
+ }
295
+ }
296
+ }
297
+ ]);
298
+
299
+ // Create new provider instance (triggers restoration)
300
+ const newProvider = TestBed.inject(WalletConnectV2Provider);
301
+
302
+ // Wait for restoration
303
+ await new Promise(resolve => setTimeout(resolve, 100));
304
+
305
+ // Restoration happens in constructor, check if client was initialized
306
+ const { default: SignClient } = await import('@walletconnect/sign-client');
307
+ expect(SignClient.init).toHaveBeenCalled();
308
+ });
309
+ });
310
+
311
+ describe('Multi-Chain Support', () => {
312
+ it('should support XRPL connection', async () => {
313
+ mockSignClient.connect = vi.fn().mockResolvedValue({
314
+ uri: 'wc:xrpl-uri',
315
+ approval: vi.fn().mockResolvedValue({
316
+ topic: 'xrpl-topic',
317
+ namespaces: {
318
+ xrpl: {
319
+ accounts: ['xrpl:testnet:rN7n7otQDd6FczFgLdlqtyMVrn3HMfeeZE'],
320
+ methods: ['xrpl_signTransaction'],
321
+ chains: ['xrpl:testnet']
322
+ }
323
+ }
324
+ })
325
+ });
326
+
327
+ await provider.connect({
328
+ type: 'walletconnect-v2',
329
+ projectId: 'test-project-id',
330
+ ledgerId: 'xrpl',
331
+ networkId: 'xrpl:testnet'
332
+ });
333
+
334
+ expect(provider.status()).toBe('connected');
335
+ expect(provider.accounts()[0].ledgerId).toBe('xrpl');
336
+ });
337
+
338
+ it('should use correct signer for each ledger', async () => {
339
+ // SignerFactory uses static methods
340
+ const hederaSigner = SignerFactory.getSigner('hedera');
341
+ const xrplSigner = SignerFactory.getSigner('xrpl');
342
+
343
+ expect(hederaSigner.ledgerId).toBe('hedera');
344
+ expect(xrplSigner.ledgerId).toBe('xrpl');
345
+ expect(hederaSigner).not.toBe(xrplSigner);
346
+ });
347
+ });
348
+ });