@hsuite/native-connect-angular 1.0.0 → 2.1.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 (162) hide show
  1. package/coverage/coverage-summary.json +49 -49
  2. package/coverage/index.html +122 -122
  3. package/coverage/lcov-report/index.html +122 -122
  4. package/coverage/lcov-report/lib/components/account-selector/account-actions/account-actions.component.ts.html +1 -1
  5. package/coverage/lcov-report/lib/components/account-selector/account-actions/index.html +1 -1
  6. package/coverage/lcov-report/lib/components/account-selector/account-filter/account-filter.component.ts.html +1 -1
  7. package/coverage/lcov-report/lib/components/account-selector/account-filter/index.html +1 -1
  8. package/coverage/lcov-report/lib/components/account-selector/account-formatting.service.ts.html +1 -1
  9. package/coverage/lcov-report/lib/components/account-selector/account-grouping.service.ts.html +1 -1
  10. package/coverage/lcov-report/lib/components/account-selector/account-list/account-list.component.ts.html +1 -1
  11. package/coverage/lcov-report/lib/components/account-selector/account-list/index.html +1 -1
  12. package/coverage/lcov-report/lib/components/account-selector/account-selector.component.ts.html +1 -1
  13. package/coverage/lcov-report/lib/components/account-selector/account-selector.service.ts.html +1 -1
  14. package/coverage/lcov-report/lib/components/account-selector/index.html +1 -1
  15. package/coverage/lcov-report/lib/components/wallet-account-display/index.html +1 -1
  16. package/coverage/lcov-report/lib/components/wallet-account-display/wallet-account-display.component.ts.html +1 -1
  17. package/coverage/lcov-report/lib/components/wallet-connect-button/index.html +21 -21
  18. package/coverage/lcov-report/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +475 -451
  19. package/coverage/lcov-report/lib/components/wallet-connect-prompt/index.html +1 -1
  20. package/coverage/lcov-report/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +1 -1
  21. package/coverage/lcov-report/lib/components/wallet-connected-guard/index.html +1 -1
  22. package/coverage/lcov-report/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +1 -1
  23. package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +148 -148
  24. package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/index.html +17 -17
  25. package/coverage/lcov-report/lib/components/wallet-connection-modal/index.html +21 -21
  26. package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/index.html +17 -17
  27. package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +838 -838
  28. package/coverage/lcov-report/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +1182 -987
  29. package/coverage/lcov-report/lib/components/wallet-session-display/index.html +1 -1
  30. package/coverage/lcov-report/lib/components/wallet-session-display/wallet-session-display.component.ts.html +1 -1
  31. package/coverage/lcov-report/lib/components/wallet-transaction-status/index.html +1 -1
  32. package/coverage/lcov-report/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +1 -1
  33. package/coverage/lcov-report/lib/directives/index.html +1 -1
  34. package/coverage/lcov-report/lib/directives/wallet-connected.directive.ts.html +1 -1
  35. package/coverage/lcov-report/lib/directives/wallet-context.directive.ts.html +1 -1
  36. package/coverage/lcov-report/lib/directives/wallet-events.directive.ts.html +1 -1
  37. package/coverage/lcov-report/lib/hsuite-wallet.module.ts.html +1 -1
  38. package/coverage/lcov-report/lib/index.html +1 -1
  39. package/coverage/lcov-report/lib/models/connection-config.model.ts.html +1 -1
  40. package/coverage/lcov-report/lib/models/index.html +1 -1
  41. package/coverage/lcov-report/lib/models/provider-types.ts.html +1 -1
  42. package/coverage/lcov-report/lib/providers/base-wallet-provider.ts.html +20 -20
  43. package/coverage/lcov-report/lib/providers/hsuite-native/channel-client.service.ts.html +637 -637
  44. package/coverage/lcov-report/lib/providers/hsuite-native/index.html +19 -19
  45. package/coverage/lcov-report/lib/providers/hsuite-native-provider.ts.html +1 -1
  46. package/coverage/lcov-report/lib/providers/index.html +18 -18
  47. package/coverage/lcov-report/lib/providers/p2p-native/index.html +20 -20
  48. package/coverage/lcov-report/lib/providers/p2p-native/p2p-native.provider.ts.html +993 -993
  49. package/coverage/lcov-report/lib/providers/p2p-native/p2p-session-manager.ts.html +1 -1
  50. package/coverage/lcov-report/lib/providers/wallet-error-handler.ts.html +1 -1
  51. package/coverage/lcov-report/lib/providers/walletconnect/core/index.html +65 -65
  52. package/coverage/lcov-report/lib/providers/walletconnect/core/session-health.ts.html +240 -240
  53. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +559 -559
  54. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-provider.ts.html +1104 -1104
  55. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +493 -493
  56. package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +366 -366
  57. package/coverage/lcov-report/lib/providers/walletconnect/signers/hedera-signer.ts.html +730 -730
  58. package/coverage/lcov-report/lib/providers/walletconnect/signers/index.html +43 -43
  59. package/coverage/lcov-report/lib/providers/walletconnect/signers/signer-factory.ts.html +234 -234
  60. package/coverage/lcov-report/lib/providers/walletconnect/signers/xrpl-signer.ts.html +650 -650
  61. package/coverage/lcov-report/lib/services/index.html +31 -31
  62. package/coverage/lcov-report/lib/services/logger.service.ts.html +4 -4
  63. package/coverage/lcov-report/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1 -1
  64. package/coverage/lcov-report/lib/services/transaction-builders/hedera-amount-utils.ts.html +155 -155
  65. package/coverage/lcov-report/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +2156 -2156
  66. package/coverage/lcov-report/lib/services/transaction-builders/index.html +43 -43
  67. package/coverage/lcov-report/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +1674 -1674
  68. package/coverage/lcov-report/lib/services/transaction.service.ts.html +4 -7
  69. package/coverage/lcov-report/lib/services/unified-wallet.service.ts.html +7 -10
  70. package/coverage/lcov-report/lib/services/wallet-context.service.ts.html +1 -1
  71. package/coverage/lcov-report/lib/services/wallet-event-bus.service.ts.html +249 -249
  72. package/coverage/lcov-report/lib/services/wallet-providers.service.ts.html +4 -7
  73. package/coverage/lcov-report/lib/transports/chrome-extension-transport.ts.html +1 -1
  74. package/coverage/lcov-report/lib/transports/index.html +1 -1
  75. package/coverage/lcov-report/lib/utils/index.html +1 -1
  76. package/coverage/lcov-report/lib/utils/ledger-icons.util.ts.html +1 -1
  77. package/coverage/lcov.info +14420 -14977
  78. package/coverage/lib/components/account-selector/account-actions/account-actions.component.ts.html +1 -1
  79. package/coverage/lib/components/account-selector/account-actions/index.html +1 -1
  80. package/coverage/lib/components/account-selector/account-filter/account-filter.component.ts.html +1 -1
  81. package/coverage/lib/components/account-selector/account-filter/index.html +1 -1
  82. package/coverage/lib/components/account-selector/account-formatting.service.ts.html +1 -1
  83. package/coverage/lib/components/account-selector/account-grouping.service.ts.html +1 -1
  84. package/coverage/lib/components/account-selector/account-list/account-list.component.ts.html +1 -1
  85. package/coverage/lib/components/account-selector/account-list/index.html +1 -1
  86. package/coverage/lib/components/account-selector/account-selector.component.ts.html +1 -1
  87. package/coverage/lib/components/account-selector/account-selector.service.ts.html +1 -1
  88. package/coverage/lib/components/account-selector/index.html +1 -1
  89. package/coverage/lib/components/wallet-account-display/index.html +1 -1
  90. package/coverage/lib/components/wallet-account-display/wallet-account-display.component.ts.html +1 -1
  91. package/coverage/lib/components/wallet-connect-button/index.html +21 -21
  92. package/coverage/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +475 -451
  93. package/coverage/lib/components/wallet-connect-prompt/index.html +1 -1
  94. package/coverage/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +1 -1
  95. package/coverage/lib/components/wallet-connected-guard/index.html +1 -1
  96. package/coverage/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +1 -1
  97. package/coverage/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +148 -148
  98. package/coverage/lib/components/wallet-connection-modal/connection-method-step/index.html +17 -17
  99. package/coverage/lib/components/wallet-connection-modal/index.html +21 -21
  100. package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/index.html +17 -17
  101. package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +838 -838
  102. package/coverage/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +1182 -987
  103. package/coverage/lib/components/wallet-session-display/index.html +1 -1
  104. package/coverage/lib/components/wallet-session-display/wallet-session-display.component.ts.html +1 -1
  105. package/coverage/lib/components/wallet-transaction-status/index.html +1 -1
  106. package/coverage/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +1 -1
  107. package/coverage/lib/directives/index.html +1 -1
  108. package/coverage/lib/directives/wallet-connected.directive.ts.html +1 -1
  109. package/coverage/lib/directives/wallet-context.directive.ts.html +1 -1
  110. package/coverage/lib/directives/wallet-events.directive.ts.html +1 -1
  111. package/coverage/lib/hsuite-wallet.module.ts.html +1 -1
  112. package/coverage/lib/index.html +1 -1
  113. package/coverage/lib/models/connection-config.model.ts.html +1 -1
  114. package/coverage/lib/models/index.html +1 -1
  115. package/coverage/lib/models/provider-types.ts.html +1 -1
  116. package/coverage/lib/providers/base-wallet-provider.ts.html +20 -20
  117. package/coverage/lib/providers/hsuite-native/channel-client.service.ts.html +637 -637
  118. package/coverage/lib/providers/hsuite-native/index.html +19 -19
  119. package/coverage/lib/providers/hsuite-native-provider.ts.html +1 -1
  120. package/coverage/lib/providers/index.html +18 -18
  121. package/coverage/lib/providers/p2p-native/index.html +20 -20
  122. package/coverage/lib/providers/p2p-native/p2p-native.provider.ts.html +993 -993
  123. package/coverage/lib/providers/p2p-native/p2p-session-manager.ts.html +1 -1
  124. package/coverage/lib/providers/wallet-error-handler.ts.html +1 -1
  125. package/coverage/lib/providers/walletconnect/core/index.html +65 -65
  126. package/coverage/lib/providers/walletconnect/core/session-health.ts.html +240 -240
  127. package/coverage/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +559 -559
  128. package/coverage/lib/providers/walletconnect/core/walletconnect-provider.ts.html +1104 -1104
  129. package/coverage/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +493 -493
  130. package/coverage/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +366 -366
  131. package/coverage/lib/providers/walletconnect/signers/hedera-signer.ts.html +730 -730
  132. package/coverage/lib/providers/walletconnect/signers/index.html +43 -43
  133. package/coverage/lib/providers/walletconnect/signers/signer-factory.ts.html +234 -234
  134. package/coverage/lib/providers/walletconnect/signers/xrpl-signer.ts.html +650 -650
  135. package/coverage/lib/services/index.html +31 -31
  136. package/coverage/lib/services/logger.service.ts.html +4 -4
  137. package/coverage/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1 -1
  138. package/coverage/lib/services/transaction-builders/hedera-amount-utils.ts.html +155 -155
  139. package/coverage/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +2156 -2156
  140. package/coverage/lib/services/transaction-builders/index.html +43 -43
  141. package/coverage/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +1674 -1674
  142. package/coverage/lib/services/transaction.service.ts.html +4 -7
  143. package/coverage/lib/services/unified-wallet.service.ts.html +7 -10
  144. package/coverage/lib/services/wallet-context.service.ts.html +1 -1
  145. package/coverage/lib/services/wallet-event-bus.service.ts.html +249 -249
  146. package/coverage/lib/services/wallet-providers.service.ts.html +4 -7
  147. package/coverage/lib/transports/chrome-extension-transport.ts.html +1 -1
  148. package/coverage/lib/transports/index.html +1 -1
  149. package/coverage/lib/utils/index.html +1 -1
  150. package/coverage/lib/utils/ledger-icons.util.ts.html +1 -1
  151. package/dist/fesm2022/hsuite-native-connect-angular.mjs +85 -20
  152. package/dist/fesm2022/hsuite-native-connect-angular.mjs.map +1 -1
  153. package/dist/index.d.ts +33 -3
  154. package/package.json +4 -4
  155. package/src/lib/components/wallet-connect-button/wallet-connect-button.component.spec.ts +89 -0
  156. package/src/lib/components/wallet-connect-button/wallet-connect-button.component.ts +8 -0
  157. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.html +1 -6
  158. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.spec.ts +173 -0
  159. package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts +84 -19
  160. package/src/lib/services/transaction.service.ts +0 -1
  161. package/src/lib/services/unified-wallet.service.ts +0 -1
  162. package/src/lib/services/wallet-providers.service.ts +0 -1
package/dist/index.d.ts CHANGED
@@ -2021,6 +2021,12 @@ declare class WalletConnectButtonComponent {
2021
2021
  * Wallet URL for targeting the wallet window
2022
2022
  */
2023
2023
  walletUrl: string;
2024
+ /**
2025
+ * Pins the connection network and hides the network-selection step in the
2026
+ * modal. When set to `'mainnet'` or `'testnet'`, the dApp decides the network
2027
+ * and the user never sees the picker. When omitted, the user chooses.
2028
+ */
2029
+ network?: 'mainnet' | 'testnet';
2024
2030
  /**
2025
2031
  * Whether to show session information when connected
2026
2032
  * @default true
@@ -2104,7 +2110,7 @@ declare class WalletConnectButtonComponent {
2104
2110
  */
2105
2111
  getConnectedAccounts(): any[];
2106
2112
  static ɵfac: i0.ɵɵFactoryDeclaration<WalletConnectButtonComponent, never>;
2107
- static ɵcmp: i0.ɵɵComponentDeclaration<WalletConnectButtonComponent, "wallet-connect-button", never, { "walletConnectProjectId": { "alias": "walletConnectProjectId"; "required": false; }; "appName": { "alias": "appName"; "required": false; }; "appDescription": { "alias": "appDescription"; "required": false; }; "walletUrl": { "alias": "walletUrl"; "required": false; }; "showSessionInfo": { "alias": "showSessionInfo"; "required": false; }; "buttonColor": { "alias": "buttonColor"; "required": false; }; "size": { "alias": "size"; "required": false; }; "connectText": { "alias": "connectText"; "required": false; }; "connectedText": { "alias": "connectedText"; "required": false; }; "multiSessionMode": { "alias": "multiSessionMode"; "required": false; }; }, { "connected": "connected"; "disconnected": "disconnected"; "error": "error"; }, never, never, true, never>;
2113
+ static ɵcmp: i0.ɵɵComponentDeclaration<WalletConnectButtonComponent, "wallet-connect-button", never, { "walletConnectProjectId": { "alias": "walletConnectProjectId"; "required": false; }; "appName": { "alias": "appName"; "required": false; }; "appDescription": { "alias": "appDescription"; "required": false; }; "walletUrl": { "alias": "walletUrl"; "required": false; }; "network": { "alias": "network"; "required": false; }; "showSessionInfo": { "alias": "showSessionInfo"; "required": false; }; "buttonColor": { "alias": "buttonColor"; "required": false; }; "size": { "alias": "size"; "required": false; }; "connectText": { "alias": "connectText"; "required": false; }; "connectedText": { "alias": "connectedText"; "required": false; }; "multiSessionMode": { "alias": "multiSessionMode"; "required": false; }; }, { "connected": "connected"; "disconnected": "disconnected"; "error": "error"; }, never, never, true, never>;
2108
2114
  }
2109
2115
 
2110
2116
  /**
@@ -3298,13 +3304,22 @@ interface StepConfig {
3298
3304
  * Main wallet connection modal component.
3299
3305
  * Orchestrates the multi-step connection flow.
3300
3306
  */
3301
- declare class WalletConnectionModalComponent {
3307
+ declare class WalletConnectionModalComponent implements OnInit {
3302
3308
  private modalController;
3303
3309
  private unifiedWalletService;
3304
3310
  /**
3305
3311
  * WalletConnect project ID (required for WalletConnect)
3306
3312
  */
3307
3313
  projectId?: string;
3314
+ /**
3315
+ * Pins the connection network and hides the network-selection step.
3316
+ *
3317
+ * When set to `'mainnet'` or `'testnet'`, the host dApp decides the network
3318
+ * and the user is never shown the network picker — the modal opens directly
3319
+ * on protocol selection. When omitted (default), the user chooses the network
3320
+ * as the first step.
3321
+ */
3322
+ network?: 'mainnet' | 'testnet';
3308
3323
  /**
3309
3324
  * App name for WalletConnect metadata
3310
3325
  */
@@ -3372,12 +3387,27 @@ declare class WalletConnectionModalComponent {
3372
3387
  * Different protocol paths have different step mappings.
3373
3388
  */
3374
3389
  readonly displayStep: i0.Signal<number>;
3390
+ /**
3391
+ * Whether a back affordance should be offered for the current step.
3392
+ * The first reachable step has no back target — that is protocol selection
3393
+ * when the network is pinned, otherwise network selection. The connection
3394
+ * progress step manages its own retry navigation instead.
3395
+ */
3396
+ readonly canGoBack: i0.Signal<boolean>;
3375
3397
  /**
3376
3398
  *
3377
3399
  * @param modalController
3378
3400
  * @param unifiedWalletService
3379
3401
  */
3380
3402
  constructor(modalController: ModalController$1, unifiedWalletService: UnifiedWalletService);
3403
+ /**
3404
+ * Apply the pinned network (if any) before the first render.
3405
+ *
3406
+ * When the host dApp provides a {@link network}, lock the selection to it and
3407
+ * skip straight to protocol selection so the user never sees — and cannot
3408
+ * change — the network. With no input, the modal opens on network selection.
3409
+ */
3410
+ ngOnInit(): void;
3381
3411
  /**
3382
3412
  * Select a network option (internal, use selectNetworkAndProceed for UI)
3383
3413
  * @param networkId
@@ -3476,7 +3506,7 @@ declare class WalletConnectionModalComponent {
3476
3506
  */
3477
3507
  private detectExtension;
3478
3508
  static ɵfac: i0.ɵɵFactoryDeclaration<WalletConnectionModalComponent, never>;
3479
- static ɵcmp: i0.ɵɵComponentDeclaration<WalletConnectionModalComponent, "hsuite-wallet-connection-modal", never, { "projectId": { "alias": "projectId"; "required": false; }; "appName": { "alias": "appName"; "required": false; }; "appDescription": { "alias": "appDescription"; "required": false; }; "walletUrl": { "alias": "walletUrl"; "required": false; }; }, { "connected": "connected"; }, never, never, true, never>;
3509
+ static ɵcmp: i0.ɵɵComponentDeclaration<WalletConnectionModalComponent, "hsuite-wallet-connection-modal", never, { "projectId": { "alias": "projectId"; "required": false; }; "network": { "alias": "network"; "required": false; }; "appName": { "alias": "appName"; "required": false; }; "appDescription": { "alias": "appDescription"; "required": false; }; "walletUrl": { "alias": "walletUrl"; "required": false; }; }, { "connected": "connected"; }, never, never, true, never>;
3480
3510
  }
3481
3511
 
3482
3512
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hsuite/native-connect-angular",
3
- "version": "1.0.0",
3
+ "version": "2.1.0",
4
4
  "license": "PolyForm-Noncommercial-1.0.0",
5
5
  "description": "Angular integration SDK for HSuite Wallet - provides direct SDK integration without wrappers",
6
6
  "type": "module",
@@ -23,9 +23,9 @@
23
23
  "dependencies": {
24
24
  "@hashgraph/proto": "^2.25.0",
25
25
  "@hashgraph/sdk": "^2.76.0",
26
- "@hsuite/native-connect-sdk": "^1.0.0",
27
- "@hsuite/native-connect-types": "^1.0.0",
28
- "@hsuite/native-connect-ui": "^1.0.0",
26
+ "@hsuite/native-connect-sdk": "^2.1.0",
27
+ "@hsuite/native-connect-types": "^2.1.0",
28
+ "@hsuite/native-connect-ui": "^2.1.0",
29
29
  "@walletconnect/modal": "^2.7.0",
30
30
  "@walletconnect/sign-client": "^2.23.0",
31
31
  "@walletconnect/types": "^2.23.0",
@@ -0,0 +1,89 @@
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
+ * @fileoverview Unit tests for WalletConnectButtonComponent.
13
+ *
14
+ * Focused on threading the `network` pinning input through to the connection
15
+ * modal, so the convenience button exposes the same capability as opening the
16
+ * modal directly.
17
+ */
18
+
19
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
20
+ import { TestBed } from '@angular/core/testing';
21
+ import { ModalController } from '@ionic/angular/standalone';
22
+
23
+ // Mock the logger so the SDK does not need real configuration during tests.
24
+ vi.mock('@hsuite/native-connect-sdk', () => ({
25
+ getLogger: vi.fn(() => ({
26
+ debug: vi.fn(),
27
+ info: vi.fn(),
28
+ warn: vi.fn(),
29
+ error: vi.fn(),
30
+ scoped: vi.fn(() => ({
31
+ debug: vi.fn(),
32
+ info: vi.fn(),
33
+ warn: vi.fn(),
34
+ error: vi.fn(),
35
+ })),
36
+ })),
37
+ }));
38
+
39
+ import { UnifiedWalletService } from '../../services/unified-wallet.service';
40
+
41
+ import { WalletConnectButtonComponent } from './wallet-connect-button.component';
42
+
43
+ describe('WalletConnectButtonComponent — network pinning', () => {
44
+ let component: WalletConnectButtonComponent;
45
+ let modalController: { create: ReturnType<typeof vi.fn> };
46
+ let modal: { present: ReturnType<typeof vi.fn>; onDidDismiss: ReturnType<typeof vi.fn> };
47
+
48
+ beforeEach(() => {
49
+ modal = {
50
+ present: vi.fn().mockResolvedValue(undefined),
51
+ onDidDismiss: vi.fn().mockResolvedValue({ data: { connected: false } }),
52
+ };
53
+ modalController = { create: vi.fn().mockResolvedValue(modal) };
54
+ const wallet = {
55
+ allAccounts: vi.fn().mockReturnValue([]),
56
+ isAnyConnected: vi.fn().mockReturnValue(false),
57
+ };
58
+
59
+ TestBed.configureTestingModule({
60
+ providers: [
61
+ { provide: ModalController, useValue: modalController },
62
+ { provide: UnifiedWalletService, useValue: wallet },
63
+ ],
64
+ });
65
+
66
+ component = TestBed.runInInjectionContext(() => new WalletConnectButtonComponent());
67
+ });
68
+
69
+ it('forwards the pinned network to the connection modal', async () => {
70
+ component.network = 'mainnet';
71
+
72
+ await component.connect();
73
+
74
+ expect(modalController.create).toHaveBeenCalledWith(
75
+ expect.objectContaining({
76
+ componentProps: expect.objectContaining({ network: 'mainnet' }),
77
+ }),
78
+ );
79
+ });
80
+
81
+ it('passes no network by default so the user chooses it', async () => {
82
+ await component.connect();
83
+
84
+ const props = (
85
+ modalController.create.mock.calls[0][0] as { componentProps: { network?: string } }
86
+ ).componentProps;
87
+ expect(props.network).toBeUndefined();
88
+ });
89
+ });
@@ -69,6 +69,13 @@ export class WalletConnectButtonComponent {
69
69
  */
70
70
  @Input() walletUrl = DEFAULT_WALLET_URL;
71
71
 
72
+ /**
73
+ * Pins the connection network and hides the network-selection step in the
74
+ * modal. When set to `'mainnet'` or `'testnet'`, the dApp decides the network
75
+ * and the user never sees the picker. When omitted, the user chooses.
76
+ */
77
+ @Input() network?: 'mainnet' | 'testnet';
78
+
72
79
  /**
73
80
  * Whether to show session information when connected
74
81
  * @default true
@@ -160,6 +167,7 @@ export class WalletConnectButtonComponent {
160
167
  appName: this.appName,
161
168
  appDescription: this.appDescription,
162
169
  walletUrl: this.walletUrl,
170
+ network: this.network,
163
171
  },
164
172
  });
165
173
 
@@ -2,12 +2,7 @@
2
2
  <div class="modal-inner-content wallet-connection-modal">
3
3
  <div class="header">
4
4
  <div class="title">
5
- <ion-button
6
- *ngIf="currentStep() > 1 && currentStep() !== ConnectionStep.ConnectionProgress"
7
- (click)="back()"
8
- fill="clear"
9
- class="back-btn"
10
- >
5
+ <ion-button *ngIf="canGoBack()" (click)="back()" fill="clear" class="back-btn">
11
6
  <ion-icon slot="icon-only" name="arrow-back-outline"></ion-icon>
12
7
  </ion-button>
13
8
  <p>{{ stepTitle() }}</p>
@@ -0,0 +1,173 @@
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
+ * @fileoverview Unit tests for WalletConnectionModalComponent.
13
+ *
14
+ * Focused on the `network` pinning capability: a host dApp can fix the
15
+ * connection network ('mainnet' | 'testnet') so the user is never shown the
16
+ * network-selection step. When the input is absent the modal behaves exactly
17
+ * as before (user picks the network as step 1).
18
+ */
19
+
20
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
21
+ import { TestBed } from '@angular/core/testing';
22
+ import { ModalController, Platform } from '@ionic/angular';
23
+
24
+ // Mock the logger so the SDK does not need real configuration during tests.
25
+ vi.mock('@hsuite/native-connect-sdk', () => ({
26
+ getLogger: vi.fn(() => ({
27
+ debug: vi.fn(),
28
+ info: vi.fn(),
29
+ warn: vi.fn(),
30
+ error: vi.fn(),
31
+ scoped: vi.fn(() => ({
32
+ debug: vi.fn(),
33
+ info: vi.fn(),
34
+ warn: vi.fn(),
35
+ error: vi.fn(),
36
+ })),
37
+ })),
38
+ }));
39
+
40
+ import { P2PNativeProvider } from '../../providers/p2p-native/p2p-native.provider';
41
+ import { UnifiedWalletService } from '../../services/unified-wallet.service';
42
+
43
+ import { WalletConnectionModalComponent } from './wallet-connection-modal.component';
44
+
45
+ /** ConnectionStep display values mirrored from the component (1-based). */
46
+ const NETWORK_SELECTION_STEP = 1;
47
+ const PROTOCOL_SELECTION_STEP = 2;
48
+
49
+ describe('WalletConnectionModalComponent — network pinning', () => {
50
+ let component: WalletConnectionModalComponent;
51
+ let modalController: { dismiss: ReturnType<typeof vi.fn>; create: ReturnType<typeof vi.fn> };
52
+ let unifiedWalletService: { connect: ReturnType<typeof vi.fn> };
53
+
54
+ beforeEach(() => {
55
+ modalController = {
56
+ dismiss: vi.fn().mockResolvedValue(undefined),
57
+ create: vi.fn(),
58
+ };
59
+ unifiedWalletService = {
60
+ connect: vi.fn().mockResolvedValue(undefined),
61
+ };
62
+ const platform = { is: vi.fn().mockReturnValue(false) };
63
+ const p2pNativeProvider = {
64
+ onPeerConnected: vi.fn(),
65
+ createPairingOffer: vi.fn(),
66
+ waitForSessionApproval: vi.fn(),
67
+ };
68
+
69
+ TestBed.configureTestingModule({
70
+ providers: [
71
+ { provide: Platform, useValue: platform },
72
+ { provide: P2PNativeProvider, useValue: p2pNativeProvider },
73
+ ],
74
+ });
75
+
76
+ // Construct directly inside an injection context so the component's
77
+ // `inject(Platform)` / `inject(P2PNativeProvider)` field initializers
78
+ // resolve, without compiling the external template/styles (this package
79
+ // has no Angular template-resolving test plugin configured).
80
+ component = TestBed.runInInjectionContext(
81
+ () =>
82
+ new WalletConnectionModalComponent(
83
+ modalController as unknown as ModalController,
84
+ unifiedWalletService as unknown as UnifiedWalletService,
85
+ ),
86
+ );
87
+ });
88
+
89
+ describe('default behavior (no network input)', () => {
90
+ it('starts on the network-selection step so the user chooses the network', () => {
91
+ component.ngOnInit();
92
+
93
+ expect(component.currentStep()).toBe(NETWORK_SELECTION_STEP);
94
+ expect(component.selectedNetwork()).toBe('testnet');
95
+ });
96
+
97
+ it('allows going back from protocol selection to network selection', () => {
98
+ component.ngOnInit();
99
+ // Advance from network selection to protocol selection the way the UI does.
100
+ component.selectNetworkAndProceed('testnet');
101
+ expect(component.currentStep()).toBe(PROTOCOL_SELECTION_STEP);
102
+
103
+ component.back();
104
+
105
+ expect(component.currentStep()).toBe(NETWORK_SELECTION_STEP);
106
+ });
107
+
108
+ it('keeps "Network" as the first step in the progress indicator', () => {
109
+ component.ngOnInit();
110
+ component.selectProtocol('hsuite-native');
111
+ component.selectConnectionMethod('desktop');
112
+
113
+ expect(component.stepConfig().labels).toEqual(['Network', 'Protocol', 'Method']);
114
+ expect(component.stepConfig().total).toBe(3);
115
+ });
116
+ });
117
+
118
+ describe('pinned network (network = "mainnet")', () => {
119
+ beforeEach(() => {
120
+ component.network = 'mainnet';
121
+ component.ngOnInit();
122
+ });
123
+
124
+ it('skips the network-selection step and starts on protocol selection', () => {
125
+ expect(component.currentStep()).toBe(PROTOCOL_SELECTION_STEP);
126
+ });
127
+
128
+ it('pins the selected network to the provided value', () => {
129
+ expect(component.selectedNetwork()).toBe('mainnet');
130
+ });
131
+
132
+ it('does not allow navigating back to the network-selection step', () => {
133
+ component.back();
134
+
135
+ expect(component.currentStep()).toBe(PROTOCOL_SELECTION_STEP);
136
+ });
137
+
138
+ it('hides the back affordance on the first reachable step', () => {
139
+ expect(component.canGoBack()).toBe(false);
140
+ });
141
+
142
+ it('drops "Network" from the progress indicator and renumbers', () => {
143
+ component.selectProtocol('hsuite-native');
144
+ component.selectConnectionMethod('desktop');
145
+
146
+ expect(component.stepConfig().labels).toEqual(['Protocol', 'Method']);
147
+ expect(component.stepConfig().total).toBe(2);
148
+ expect(component.displayStep()).toBe(1);
149
+ });
150
+
151
+ it('forwards the pinned network to the SDK connect call', async () => {
152
+ component.selectProtocolAndProceed('hsuite-native');
153
+ component.selectConnectionMethod('desktop');
154
+
155
+ await component.next();
156
+
157
+ expect(unifiedWalletService.connect).toHaveBeenCalledWith(
158
+ 'hsuite-native',
159
+ expect.objectContaining({ networkId: 'mainnet' }),
160
+ );
161
+ });
162
+ });
163
+
164
+ describe('pinned network (network = "testnet")', () => {
165
+ it('skips selection and pins testnet', () => {
166
+ component.network = 'testnet';
167
+ component.ngOnInit();
168
+
169
+ expect(component.currentStep()).toBe(PROTOCOL_SELECTION_STEP);
170
+ expect(component.selectedNetwork()).toBe('testnet');
171
+ });
172
+ });
173
+ });
@@ -22,7 +22,16 @@
22
22
  */
23
23
 
24
24
  import { CommonModule } from '@angular/common';
25
- import { Component, Input, Output, EventEmitter, signal, computed, inject } from '@angular/core';
25
+ import {
26
+ Component,
27
+ Input,
28
+ Output,
29
+ EventEmitter,
30
+ OnInit,
31
+ signal,
32
+ computed,
33
+ inject,
34
+ } from '@angular/core';
26
35
  import { getLogger } from '@hsuite/native-connect-sdk';
27
36
  import { IonicModule, ModalController, Platform } from '@ionic/angular';
28
37
 
@@ -112,12 +121,22 @@ interface StepConfig {
112
121
  templateUrl: './wallet-connection-modal.component.html',
113
122
  styleUrls: ['./wallet-connection-modal.component.scss'],
114
123
  })
115
- export class WalletConnectionModalComponent {
124
+ export class WalletConnectionModalComponent implements OnInit {
116
125
  /**
117
126
  * WalletConnect project ID (required for WalletConnect)
118
127
  */
119
128
  @Input() projectId?: string;
120
129
 
130
+ /**
131
+ * Pins the connection network and hides the network-selection step.
132
+ *
133
+ * When set to `'mainnet'` or `'testnet'`, the host dApp decides the network
134
+ * and the user is never shown the network picker — the modal opens directly
135
+ * on protocol selection. When omitted (default), the user chooses the network
136
+ * as the first step.
137
+ */
138
+ @Input() network?: 'mainnet' | 'testnet';
139
+
121
140
  /**
122
141
  * App name for WalletConnect metadata
123
142
  */
@@ -325,23 +344,30 @@ export class WalletConnectionModalComponent {
325
344
  const protocol = this.selectedProtocol();
326
345
  const method = this.selectedConnectionMethod();
327
346
 
347
+ let base: StepConfig;
348
+
328
349
  // Initial state: show 3 placeholder steps until protocol is selected
329
350
  if (!protocol) {
330
- return { total: 3, labels: ['Network', 'Protocol', '...'] };
351
+ base = { total: 3, labels: ['Network', 'Protocol', '...'] };
352
+ } else if (protocol === 'hsuite-native') {
353
+ // HSuite Native path
354
+ base =
355
+ method === 'mobile-qr'
356
+ ? // Mobile QR needs 4 steps
357
+ { total: 4, labels: ['Network', 'Protocol', 'Method', 'Pair'] }
358
+ : // Desktop connects immediately after method selection (3 steps)
359
+ { total: 3, labels: ['Network', 'Protocol', 'Method'] };
360
+ } else {
361
+ // WalletConnect path: 4 steps
362
+ base = { total: 4, labels: ['Network', 'Protocol', 'Ledger', 'Connect'] };
331
363
  }
332
364
 
333
- // HSuite Native path
334
- if (protocol === 'hsuite-native') {
335
- // If mobile QR is selected, we need 4 steps
336
- if (method === 'mobile-qr') {
337
- return { total: 4, labels: ['Network', 'Protocol', 'Method', 'Pair'] };
338
- }
339
- // Desktop connection is 3 steps (connects immediately after method selection)
340
- return { total: 3, labels: ['Network', 'Protocol', 'Method'] };
365
+ // When the network is pinned by the host dApp the network step is never
366
+ // shown drop it from the indicator so the numbering stays accurate.
367
+ if (this.network) {
368
+ return { total: base.total - 1, labels: base.labels.slice(1) };
341
369
  }
342
-
343
- // WalletConnect path: 4 steps
344
- return { total: 4, labels: ['Network', 'Protocol', 'Ledger', 'Connect'] };
370
+ return base;
345
371
  });
346
372
 
347
373
  /**
@@ -353,20 +379,24 @@ export class WalletConnectionModalComponent {
353
379
  // Protocol could be used for protocol-specific step mapping in the future
354
380
  const _protocol = this.selectedProtocol();
355
381
 
382
+ // When the network is pinned the network step is removed, so every
383
+ // subsequent step shifts down one position in the indicator.
384
+ const networkOffset = this.network ? 1 : 0;
385
+
356
386
  // Map internal step to display position based on protocol path
357
387
  switch (step) {
358
388
  case ConnectionStep.NetworkSelection:
359
389
  return 1;
360
390
  case ConnectionStep.ProtocolSelection:
361
- return 2;
391
+ return 2 - networkOffset;
362
392
  case ConnectionStep.ConnectionMethodSelection:
363
- return 3;
393
+ return 3 - networkOffset;
364
394
  case ConnectionStep.LedgerSelection:
365
395
  // WalletConnect ledger selection is step 3
366
- return 3;
396
+ return 3 - networkOffset;
367
397
  case ConnectionStep.QrPairing:
368
398
  // QR pairing is step 4 for both paths that use it
369
- return 4;
399
+ return 4 - networkOffset;
370
400
  case ConnectionStep.ConnectionProgress:
371
401
  // Connection progress is always the last step
372
402
  return this.stepConfig().total;
@@ -375,6 +405,23 @@ export class WalletConnectionModalComponent {
375
405
  }
376
406
  });
377
407
 
408
+ /**
409
+ * Whether a back affordance should be offered for the current step.
410
+ * The first reachable step has no back target — that is protocol selection
411
+ * when the network is pinned, otherwise network selection. The connection
412
+ * progress step manages its own retry navigation instead.
413
+ */
414
+ readonly canGoBack = computed<boolean>(() => {
415
+ const step = this.currentStep();
416
+ if (step === ConnectionStep.ConnectionProgress) {
417
+ return false;
418
+ }
419
+ const firstStep = this.network
420
+ ? ConnectionStep.ProtocolSelection
421
+ : ConnectionStep.NetworkSelection;
422
+ return step > firstStep;
423
+ });
424
+
378
425
  /**
379
426
  *
380
427
  * @param modalController
@@ -390,6 +437,20 @@ export class WalletConnectionModalComponent {
390
437
  });
391
438
  }
392
439
 
440
+ /**
441
+ * Apply the pinned network (if any) before the first render.
442
+ *
443
+ * When the host dApp provides a {@link network}, lock the selection to it and
444
+ * skip straight to protocol selection so the user never sees — and cannot
445
+ * change — the network. With no input, the modal opens on network selection.
446
+ */
447
+ ngOnInit(): void {
448
+ if (this.network) {
449
+ this.selectedNetwork.set(this.network);
450
+ this.currentStep.set(ConnectionStep.ProtocolSelection);
451
+ }
452
+ }
453
+
393
454
  /**
394
455
  * Select a network option (internal, use selectNetworkAndProceed for UI)
395
456
  * @param networkId
@@ -510,7 +571,11 @@ export class WalletConnectionModalComponent {
510
571
  back(): void {
511
572
  const currentStep = this.currentStep();
512
573
  if (currentStep === ConnectionStep.ProtocolSelection) {
513
- this.currentStep.set(ConnectionStep.NetworkSelection);
574
+ // When the network is pinned, protocol selection is the first reachable
575
+ // step — there is no network step to return to.
576
+ if (!this.network) {
577
+ this.currentStep.set(ConnectionStep.NetworkSelection);
578
+ }
514
579
  } else if (currentStep === ConnectionStep.ConnectionMethodSelection) {
515
580
  this.currentStep.set(ConnectionStep.ProtocolSelection);
516
581
  } else if (currentStep === ConnectionStep.LedgerSelection) {
@@ -57,7 +57,6 @@ import type { SignResult, SubmitResult } from '../providers/base-wallet-provider
57
57
  import { UnifiedWalletService } from './unified-wallet.service';
58
58
  import { WalletEventBus } from './wallet-event-bus.service';
59
59
 
60
-
61
60
  const logger = getLogger().scoped?.('TransactionService') ?? getLogger();
62
61
 
63
62
  /**
@@ -56,7 +56,6 @@ import { WalletConnectV2Provider } from '../providers/walletconnect/core/walletc
56
56
 
57
57
  import { WalletEventBus } from './wallet-event-bus.service';
58
58
 
59
-
60
59
  const logger = getLogger().scoped?.('UnifiedWalletService') ?? getLogger();
61
60
 
62
61
  interface ProviderSummary {
@@ -44,7 +44,6 @@ import { WalletConnectV2Provider } from '../providers/walletconnect/core/walletc
44
44
 
45
45
  import { UnifiedWalletService } from './unified-wallet.service';
46
46
 
47
-
48
47
  const logger = getLogger().scoped?.('WalletProvidersService') ?? getLogger();
49
48
 
50
49
  /**