@hsuite/native-connect-angular 1.0.0 → 2.1.1
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.
- package/coverage/coverage-summary.json +53 -49
- package/coverage/index.html +100 -100
- package/coverage/lcov-report/index.html +100 -100
- package/coverage/lcov-report/lib/components/account-selector/account-actions/account-actions.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-actions/index.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-filter/account-filter.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-filter/index.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-formatting.service.ts.html +13 -19
- package/coverage/lcov-report/lib/components/account-selector/account-grouping.service.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-list/account-list.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-list/index.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-selector.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/account-selector.service.ts.html +1 -1
- package/coverage/lcov-report/lib/components/account-selector/index.html +5 -5
- package/coverage/lcov-report/lib/components/wallet-account-display/index.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-account-display/wallet-account-display.component.ts.html +10 -10
- package/coverage/lcov-report/lib/components/wallet-connect-button/index.html +21 -21
- package/coverage/lcov-report/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +475 -451
- package/coverage/lcov-report/lib/components/wallet-connect-prompt/index.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-connected-guard/index.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +148 -148
- package/coverage/lcov-report/lib/components/wallet-connection-modal/connection-method-step/index.html +17 -17
- package/coverage/lcov-report/lib/components/wallet-connection-modal/index.html +21 -21
- package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/index.html +17 -17
- package/coverage/lcov-report/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +838 -838
- package/coverage/lcov-report/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +1230 -987
- package/coverage/lcov-report/lib/components/wallet-session-display/index.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-session-display/wallet-session-display.component.ts.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-transaction-status/index.html +1 -1
- package/coverage/lcov-report/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +1 -1
- package/coverage/lcov-report/lib/directives/index.html +1 -1
- package/coverage/lcov-report/lib/directives/wallet-connected.directive.ts.html +1 -1
- package/coverage/lcov-report/lib/directives/wallet-context.directive.ts.html +1 -1
- package/coverage/lcov-report/lib/directives/wallet-events.directive.ts.html +1 -1
- package/coverage/lcov-report/lib/hsuite-wallet.module.ts.html +1 -1
- package/coverage/lcov-report/lib/index.html +1 -1
- package/coverage/lcov-report/lib/models/connection-config.model.ts.html +1 -1
- package/coverage/lcov-report/lib/models/index.html +7 -7
- package/coverage/lcov-report/lib/models/provider-types.ts.html +11 -5
- package/coverage/lcov-report/lib/providers/base-wallet-provider.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/hsuite-native/channel-client.service.ts.html +9 -6
- package/coverage/lcov-report/lib/providers/hsuite-native/index.html +10 -10
- package/coverage/lcov-report/lib/providers/hsuite-native-provider.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/index.html +1 -1
- package/coverage/lcov-report/lib/providers/p2p-native/index.html +7 -7
- package/coverage/lcov-report/lib/providers/p2p-native/p2p-native.provider.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/p2p-native/p2p-session-manager.ts.html +7 -4
- package/coverage/lcov-report/lib/providers/wallet-error-handler.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/core/index.html +10 -10
- package/coverage/lcov-report/lib/providers/walletconnect/core/session-health.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-provider.ts.html +10 -7
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/signers/hedera-signer.ts.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/signers/index.html +1 -1
- package/coverage/lcov-report/lib/providers/walletconnect/signers/signer-factory.ts.html +49 -49
- package/coverage/lcov-report/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1 -1
- package/coverage/lcov-report/lib/services/hsuite-auth.interceptor.ts.html +568 -0
- package/coverage/lcov-report/lib/services/index.html +50 -20
- package/coverage/lcov-report/lib/services/logger.service.ts.html +4 -4
- package/coverage/lcov-report/lib/services/smart-session.service.ts.html +1264 -0
- package/coverage/lcov-report/lib/services/transaction-builders/active-account-source.ts.html +250 -0
- package/coverage/lcov-report/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1 -1
- package/coverage/lcov-report/lib/services/transaction-builders/hedera-amount-utils.ts.html +1 -1
- package/coverage/lcov-report/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +318 -318
- package/coverage/lcov-report/lib/services/transaction-builders/index.html +24 -9
- package/coverage/lcov-report/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +1 -1
- package/coverage/lcov-report/lib/services/transaction.service.ts.html +7 -10
- package/coverage/lcov-report/lib/services/unified-wallet.service.ts.html +9 -12
- package/coverage/lcov-report/lib/services/wallet-context.service.ts.html +1 -1
- package/coverage/lcov-report/lib/services/wallet-event-bus.service.ts.html +1 -1
- package/coverage/lcov-report/lib/services/wallet-providers.service.ts.html +4 -7
- package/coverage/lcov-report/lib/transports/chrome-extension-transport.ts.html +1 -1
- package/coverage/lcov-report/lib/transports/index.html +1 -1
- package/coverage/lcov-report/lib/utils/index.html +36 -21
- package/coverage/lcov-report/lib/utils/ledger-icons.util.ts.html +254 -161
- package/coverage/lcov-report/lib/utils/ledger-ui-registry.ts.html +676 -0
- package/coverage/lcov.info +3236 -2122
- package/coverage/lib/components/account-selector/account-actions/account-actions.component.ts.html +1 -1
- package/coverage/lib/components/account-selector/account-actions/index.html +1 -1
- package/coverage/lib/components/account-selector/account-filter/account-filter.component.ts.html +1 -1
- package/coverage/lib/components/account-selector/account-filter/index.html +1 -1
- package/coverage/lib/components/account-selector/account-formatting.service.ts.html +13 -19
- package/coverage/lib/components/account-selector/account-grouping.service.ts.html +1 -1
- package/coverage/lib/components/account-selector/account-list/account-list.component.ts.html +1 -1
- package/coverage/lib/components/account-selector/account-list/index.html +1 -1
- package/coverage/lib/components/account-selector/account-selector.component.ts.html +1 -1
- package/coverage/lib/components/account-selector/account-selector.service.ts.html +1 -1
- package/coverage/lib/components/account-selector/index.html +5 -5
- package/coverage/lib/components/wallet-account-display/index.html +1 -1
- package/coverage/lib/components/wallet-account-display/wallet-account-display.component.ts.html +10 -10
- package/coverage/lib/components/wallet-connect-button/index.html +21 -21
- package/coverage/lib/components/wallet-connect-button/wallet-connect-button.component.ts.html +475 -451
- package/coverage/lib/components/wallet-connect-prompt/index.html +1 -1
- package/coverage/lib/components/wallet-connect-prompt/wallet-connect-prompt.component.ts.html +1 -1
- package/coverage/lib/components/wallet-connected-guard/index.html +1 -1
- package/coverage/lib/components/wallet-connected-guard/wallet-connected-guard.component.ts.html +1 -1
- package/coverage/lib/components/wallet-connection-modal/connection-method-step/connection-method-step.component.ts.html +148 -148
- package/coverage/lib/components/wallet-connection-modal/connection-method-step/index.html +17 -17
- package/coverage/lib/components/wallet-connection-modal/index.html +21 -21
- package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/index.html +17 -17
- package/coverage/lib/components/wallet-connection-modal/qr-pairing-step/qr-pairing-step.component.ts.html +838 -838
- package/coverage/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts.html +1230 -987
- package/coverage/lib/components/wallet-session-display/index.html +1 -1
- package/coverage/lib/components/wallet-session-display/wallet-session-display.component.ts.html +1 -1
- package/coverage/lib/components/wallet-transaction-status/index.html +1 -1
- package/coverage/lib/components/wallet-transaction-status/wallet-transaction-status.component.ts.html +1 -1
- package/coverage/lib/directives/index.html +1 -1
- package/coverage/lib/directives/wallet-connected.directive.ts.html +1 -1
- package/coverage/lib/directives/wallet-context.directive.ts.html +1 -1
- package/coverage/lib/directives/wallet-events.directive.ts.html +1 -1
- package/coverage/lib/hsuite-wallet.module.ts.html +1 -1
- package/coverage/lib/index.html +1 -1
- package/coverage/lib/models/connection-config.model.ts.html +1 -1
- package/coverage/lib/models/index.html +7 -7
- package/coverage/lib/models/provider-types.ts.html +11 -5
- package/coverage/lib/providers/base-wallet-provider.ts.html +1 -1
- package/coverage/lib/providers/hsuite-native/channel-client.service.ts.html +9 -6
- package/coverage/lib/providers/hsuite-native/index.html +10 -10
- package/coverage/lib/providers/hsuite-native-provider.ts.html +1 -1
- package/coverage/lib/providers/index.html +1 -1
- package/coverage/lib/providers/p2p-native/index.html +7 -7
- package/coverage/lib/providers/p2p-native/p2p-native.provider.ts.html +1 -1
- package/coverage/lib/providers/p2p-native/p2p-session-manager.ts.html +7 -4
- package/coverage/lib/providers/wallet-error-handler.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/core/index.html +10 -10
- package/coverage/lib/providers/walletconnect/core/session-health.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/core/walletconnect-client-manager.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/core/walletconnect-provider.ts.html +10 -7
- package/coverage/lib/providers/walletconnect/core/walletconnect-session-store.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/core/walletconnect-signing-orchestrator.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/signers/hedera-signer.ts.html +1 -1
- package/coverage/lib/providers/walletconnect/signers/index.html +1 -1
- package/coverage/lib/providers/walletconnect/signers/signer-factory.ts.html +49 -49
- package/coverage/lib/providers/walletconnect/signers/xrpl-signer.ts.html +1 -1
- package/coverage/lib/services/hsuite-auth.interceptor.ts.html +568 -0
- package/coverage/lib/services/index.html +50 -20
- package/coverage/lib/services/logger.service.ts.html +4 -4
- package/coverage/lib/services/smart-session.service.ts.html +1264 -0
- package/coverage/lib/services/transaction-builders/active-account-source.ts.html +250 -0
- package/coverage/lib/services/transaction-builders/base-transaction-builder.service.ts.html +1 -1
- package/coverage/lib/services/transaction-builders/hedera-amount-utils.ts.html +1 -1
- package/coverage/lib/services/transaction-builders/hedera-transaction-builder.service.ts.html +318 -318
- package/coverage/lib/services/transaction-builders/index.html +24 -9
- package/coverage/lib/services/transaction-builders/xrpl-transaction-builder.service.ts.html +1 -1
- package/coverage/lib/services/transaction.service.ts.html +7 -10
- package/coverage/lib/services/unified-wallet.service.ts.html +9 -12
- package/coverage/lib/services/wallet-context.service.ts.html +1 -1
- package/coverage/lib/services/wallet-event-bus.service.ts.html +1 -1
- package/coverage/lib/services/wallet-providers.service.ts.html +4 -7
- package/coverage/lib/transports/chrome-extension-transport.ts.html +1 -1
- package/coverage/lib/transports/index.html +1 -1
- package/coverage/lib/utils/index.html +36 -21
- package/coverage/lib/utils/ledger-icons.util.ts.html +254 -161
- package/coverage/lib/utils/ledger-ui-registry.ts.html +676 -0
- package/dist/fesm2022/hsuite-native-connect-angular.mjs +939 -328
- package/dist/fesm2022/hsuite-native-connect-angular.mjs.map +1 -1
- package/dist/index.d.ts +489 -33
- package/package.json +4 -4
- package/src/index.ts +26 -0
- package/src/lib/components/account-selector/account-formatting.service.ts +8 -10
- package/src/lib/components/wallet-account-display/wallet-account-display.component.ts +9 -9
- package/src/lib/components/wallet-connect-button/wallet-connect-button.component.spec.ts +89 -0
- package/src/lib/components/wallet-connect-button/wallet-connect-button.component.ts +8 -0
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.html +1 -6
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.spec.ts +173 -0
- package/src/lib/components/wallet-connection-modal/wallet-connection-modal.component.ts +118 -37
- package/src/lib/models/provider-types.ts +3 -1
- package/src/lib/models/unified-account.model.ts +4 -1
- package/src/lib/providers/hsuite-native/channel-client.service.ts +1 -0
- package/src/lib/providers/p2p-native/p2p-session-manager.ts +1 -0
- package/src/lib/providers/walletconnect/core/walletconnect-provider.ts +2 -1
- package/src/lib/services/hsuite-auth.interceptor.ts +159 -0
- package/src/lib/services/smart-session.service.ts +378 -0
- package/src/lib/services/transaction-builders/active-account-source.spec.ts +75 -0
- package/src/lib/services/transaction-builders/active-account-source.ts +55 -0
- package/src/lib/services/transaction-builders/hedera-transaction-builder.service.ts +4 -4
- package/src/lib/services/transaction-builders/index.ts +1 -0
- package/src/lib/services/transaction.service.ts +7 -4
- package/src/lib/services/unified-wallet.service.spec.ts +1 -1
- package/src/lib/services/unified-wallet.service.ts +2 -3
- package/src/lib/services/wallet-providers.service.ts +0 -1
- package/src/lib/utils/index.ts +1 -0
- package/src/lib/utils/ledger-icons.util.ts +61 -30
- package/src/lib/utils/ledger-ui-registry.ts +197 -0
|
@@ -0,0 +1,378 @@
|
|
|
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 Smart-host customer session helper.
|
|
13
|
+
*
|
|
14
|
+
* @module services/smart-session
|
|
15
|
+
*
|
|
16
|
+
* @description
|
|
17
|
+
* SmartSessionService automates the smart-host authentication handshake for
|
|
18
|
+
* HSuite dApps. It discovers the host's `appId`, requests a challenge, signs it
|
|
19
|
+
* with the active wallet account, and exchanges the signed challenge for a
|
|
20
|
+
* short-lived bearer token.
|
|
21
|
+
*
|
|
22
|
+
* **Typical flow:**
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const session = inject(SmartSessionService);
|
|
25
|
+
* await session.login();
|
|
26
|
+
* const bearer = session.getBearer();
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* The service also exposes {@link withSession} for automatic 401 recovery:
|
|
30
|
+
* operations that fail with HTTP 401 are retried once after a fresh login.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { HttpClient } from '@angular/common/http';
|
|
34
|
+
import { Injectable, inject, InjectionToken } from '@angular/core';
|
|
35
|
+
import { getLogger } from '@hsuite/native-connect-sdk';
|
|
36
|
+
import { firstValueFrom } from 'rxjs';
|
|
37
|
+
|
|
38
|
+
import type { SignMessageResult } from '../providers/base-wallet-provider';
|
|
39
|
+
|
|
40
|
+
import { TransactionService } from './transaction.service';
|
|
41
|
+
import { UnifiedWalletService } from './unified-wallet.service';
|
|
42
|
+
|
|
43
|
+
const logger = getLogger().scoped?.('SmartSessionService') ?? getLogger();
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Configuration token for {@link SmartSessionService}.
|
|
47
|
+
*/
|
|
48
|
+
export const SMART_SESSION_CONFIG = new InjectionToken<SmartSessionConfig>('SMART_SESSION_CONFIG', {
|
|
49
|
+
factory: () => ({}),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Configuration for the smart-host session handshake.
|
|
54
|
+
*/
|
|
55
|
+
export interface SmartSessionConfig {
|
|
56
|
+
/**
|
|
57
|
+
* Base URL for the smart-host API.
|
|
58
|
+
* @default '' (relative to the current origin)
|
|
59
|
+
*/
|
|
60
|
+
baseUrl?: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Health endpoint used to discover the host `appId`.
|
|
64
|
+
* @default '/api/health'
|
|
65
|
+
*/
|
|
66
|
+
healthEndpoint?: string;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Challenge endpoint used to obtain a message to sign.
|
|
70
|
+
* @default '/api/auth/challenge'
|
|
71
|
+
*/
|
|
72
|
+
challengeEndpoint?: string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Verify endpoint used to exchange the signed challenge for a bearer token.
|
|
76
|
+
* @default '/api/auth/verify'
|
|
77
|
+
*/
|
|
78
|
+
verifyEndpoint?: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* sessionStorage key used to persist the session token and expiry.
|
|
82
|
+
* @default 'hsuite.smart-session'
|
|
83
|
+
*/
|
|
84
|
+
storageKey?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Health response shape expected from the smart host.
|
|
89
|
+
*/
|
|
90
|
+
export interface SmartHostHealth {
|
|
91
|
+
appId: string;
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Challenge response shape expected from the smart host.
|
|
97
|
+
*/
|
|
98
|
+
export interface SmartHostChallenge {
|
|
99
|
+
challenge: string;
|
|
100
|
+
[key: string]: unknown;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Verify request payload sent to the smart host.
|
|
105
|
+
*/
|
|
106
|
+
export interface SmartHostVerifyRequest {
|
|
107
|
+
appId: string;
|
|
108
|
+
accountAddress: string;
|
|
109
|
+
publicKey?: string;
|
|
110
|
+
signature: string;
|
|
111
|
+
algorithm?: string;
|
|
112
|
+
message: string;
|
|
113
|
+
caipChainId?: string;
|
|
114
|
+
ledgerId?: string;
|
|
115
|
+
networkId?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Verify response shape expected from the smart host.
|
|
120
|
+
*/
|
|
121
|
+
export interface SmartHostVerifyResponse {
|
|
122
|
+
bearer: string;
|
|
123
|
+
expiresAt?: number;
|
|
124
|
+
expiresIn?: number;
|
|
125
|
+
[key: string]: unknown;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Persisted smart session.
|
|
130
|
+
*/
|
|
131
|
+
interface StoredSession {
|
|
132
|
+
bearer: string;
|
|
133
|
+
expiresAt: number;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Smart-host customer session helper.
|
|
138
|
+
*
|
|
139
|
+
* @service SmartSessionService
|
|
140
|
+
*
|
|
141
|
+
* @description
|
|
142
|
+
* Encapsulates the full challenge → sign → verify → store JWT flow required by
|
|
143
|
+
* HSuite smart hosts. The service is intentionally thin: it delegates signing to
|
|
144
|
+
* {@link TransactionService} and relies on standard Angular `HttpClient` for the
|
|
145
|
+
* host HTTP calls.
|
|
146
|
+
*
|
|
147
|
+
* @providedIn root
|
|
148
|
+
*/
|
|
149
|
+
@Injectable({ providedIn: 'root' })
|
|
150
|
+
export class SmartSessionService {
|
|
151
|
+
private readonly http = inject(HttpClient);
|
|
152
|
+
private readonly walletService = inject(UnifiedWalletService);
|
|
153
|
+
private readonly transactionService = inject(TransactionService);
|
|
154
|
+
private readonly config = inject(SMART_SESSION_CONFIG);
|
|
155
|
+
|
|
156
|
+
private get baseUrl(): string {
|
|
157
|
+
return this.config.baseUrl ?? '';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private get healthEndpoint(): string {
|
|
161
|
+
return this.config.healthEndpoint ?? '/api/health';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private get challengeEndpoint(): string {
|
|
165
|
+
return this.config.challengeEndpoint ?? '/api/auth/challenge';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private get verifyEndpoint(): string {
|
|
169
|
+
return this.config.verifyEndpoint ?? '/api/auth/verify';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private get storageKey(): string {
|
|
173
|
+
return this.config.storageKey ?? 'hsuite.smart-session';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Returns the currently stored bearer token, or `null` if there is no session.
|
|
178
|
+
*
|
|
179
|
+
* @returns Bearer token string or null
|
|
180
|
+
*/
|
|
181
|
+
getBearer(): string | null {
|
|
182
|
+
const stored = this.readStoredSession();
|
|
183
|
+
return stored && stored.expiresAt > Date.now() ? stored.bearer : null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Checks whether a non-expired session is available.
|
|
188
|
+
*
|
|
189
|
+
* @returns true if logged in and the bearer has not expired
|
|
190
|
+
*/
|
|
191
|
+
isLoggedIn(): boolean {
|
|
192
|
+
return this.getBearer() !== null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Performs the full smart-host login handshake.
|
|
197
|
+
*
|
|
198
|
+
* @description
|
|
199
|
+
* 1. Discovers `appId` from the health endpoint.
|
|
200
|
+
* 2. Fetches a challenge from the challenge endpoint.
|
|
201
|
+
* 3. Signs the challenge with the active wallet account.
|
|
202
|
+
* 4. Exchanges the signed challenge for a bearer token.
|
|
203
|
+
* 5. Stores the bearer and expiry in `sessionStorage`.
|
|
204
|
+
*
|
|
205
|
+
* @returns The verify response from the host
|
|
206
|
+
*
|
|
207
|
+
* @throws {Error} If no active account is available
|
|
208
|
+
* @throws {Error} If the health endpoint does not return an `appId`
|
|
209
|
+
* @throws {Error} If the challenge endpoint does not return a `challenge`
|
|
210
|
+
* @throws {Error} If the verify call fails
|
|
211
|
+
*/
|
|
212
|
+
async login(): Promise<SmartHostVerifyResponse> {
|
|
213
|
+
const account = this.walletService.activeAccount();
|
|
214
|
+
if (!account) {
|
|
215
|
+
throw new Error('No active account');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
logger.info('Starting smart-host login handshake', {
|
|
219
|
+
accountAddress: account.address,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const health = await this.fetchHealth();
|
|
223
|
+
if (!health.appId) {
|
|
224
|
+
throw new Error('Smart host health endpoint did not return appId');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const challengeResponse = await this.fetchChallenge(health.appId);
|
|
228
|
+
if (!challengeResponse.challenge) {
|
|
229
|
+
throw new Error('Smart host challenge endpoint did not return challenge');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const signResult = await this.transactionService.signMessage(challengeResponse.challenge);
|
|
233
|
+
|
|
234
|
+
const verifyResponse = await this.verifyChallenge(
|
|
235
|
+
health.appId,
|
|
236
|
+
account,
|
|
237
|
+
challengeResponse.challenge,
|
|
238
|
+
signResult,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
if (!verifyResponse.bearer) {
|
|
242
|
+
throw new Error('Smart host verify endpoint did not return bearer');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const expiresAt = this.resolveExpiry(verifyResponse);
|
|
246
|
+
this.storeSession({ bearer: verifyResponse.bearer, expiresAt });
|
|
247
|
+
|
|
248
|
+
logger.info('Smart-host login successful', {
|
|
249
|
+
appId: health.appId,
|
|
250
|
+
expiresAt,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
return verifyResponse;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Clears the stored session.
|
|
258
|
+
*/
|
|
259
|
+
logout(): void {
|
|
260
|
+
this.clearStoredSession();
|
|
261
|
+
logger.info('Smart-host session cleared');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Runs an HTTP operation with automatic 401 recovery.
|
|
266
|
+
*
|
|
267
|
+
* @description
|
|
268
|
+
* Executes the provided operation. If it rejects with an HTTP 401 error,
|
|
269
|
+
* the service clears the current bearer, performs a fresh login, and retries
|
|
270
|
+
* the operation once. Any other error is propagated immediately.
|
|
271
|
+
*
|
|
272
|
+
* @param operation - Async operation that needs a valid session
|
|
273
|
+
* @returns The result of the operation
|
|
274
|
+
*
|
|
275
|
+
* @throws {Error} The original error if retry is not possible or fails
|
|
276
|
+
*/
|
|
277
|
+
async withSession<T>(operation: () => Promise<T>): Promise<T> {
|
|
278
|
+
try {
|
|
279
|
+
return await operation();
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (this.isUnauthorizedError(error)) {
|
|
282
|
+
logger.warn('Operation received 401; attempting single session refresh');
|
|
283
|
+
this.logout();
|
|
284
|
+
await this.login();
|
|
285
|
+
return await operation();
|
|
286
|
+
}
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private async fetchHealth(): Promise<SmartHostHealth> {
|
|
292
|
+
return firstValueFrom(this.http.get<SmartHostHealth>(`${this.baseUrl}${this.healthEndpoint}`));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private async fetchChallenge(appId: string): Promise<SmartHostChallenge> {
|
|
296
|
+
return firstValueFrom(
|
|
297
|
+
this.http.post<SmartHostChallenge>(`${this.baseUrl}${this.challengeEndpoint}`, { appId }),
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private async verifyChallenge(
|
|
302
|
+
appId: string,
|
|
303
|
+
account: import('../models/unified-account.model').UnifiedAccount,
|
|
304
|
+
challenge: string,
|
|
305
|
+
signResult: SignMessageResult,
|
|
306
|
+
): Promise<SmartHostVerifyResponse> {
|
|
307
|
+
const payload: SmartHostVerifyRequest = {
|
|
308
|
+
appId,
|
|
309
|
+
accountAddress: account.address,
|
|
310
|
+
publicKey: signResult.publicKey ?? account.publicKey,
|
|
311
|
+
signature: signResult.signature,
|
|
312
|
+
algorithm: signResult.algorithm,
|
|
313
|
+
message: challenge,
|
|
314
|
+
caipChainId: signResult.caipChainId,
|
|
315
|
+
ledgerId: account.ledgerId,
|
|
316
|
+
networkId: account.networkId,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
return firstValueFrom(
|
|
320
|
+
this.http.post<SmartHostVerifyResponse>(`${this.baseUrl}${this.verifyEndpoint}`, payload),
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private resolveExpiry(response: SmartHostVerifyResponse): number {
|
|
325
|
+
if (response.expiresAt) {
|
|
326
|
+
return response.expiresAt;
|
|
327
|
+
}
|
|
328
|
+
if (response.expiresIn) {
|
|
329
|
+
return Date.now() + response.expiresIn * 1000;
|
|
330
|
+
}
|
|
331
|
+
// Default to 5 minutes if no expiry is provided
|
|
332
|
+
return Date.now() + 5 * 60 * 1000;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private readStoredSession(): StoredSession | null {
|
|
336
|
+
try {
|
|
337
|
+
const raw = sessionStorage.getItem(this.storageKey);
|
|
338
|
+
if (!raw) {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
const parsed = JSON.parse(raw) as StoredSession;
|
|
342
|
+
if (!parsed.bearer || typeof parsed.expiresAt !== 'number') {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
return parsed;
|
|
346
|
+
} catch {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private storeSession(session: StoredSession): void {
|
|
352
|
+
try {
|
|
353
|
+
sessionStorage.setItem(this.storageKey, JSON.stringify(session));
|
|
354
|
+
} catch (error) {
|
|
355
|
+
logger.warn('Failed to store smart session', { error });
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private clearStoredSession(): void {
|
|
360
|
+
try {
|
|
361
|
+
sessionStorage.removeItem(this.storageKey);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
logger.warn('Failed to clear smart session', { error });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private isUnauthorizedError(error: unknown): boolean {
|
|
368
|
+
if (!error || typeof error !== 'object') {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
const status = (error as { status?: number }).status;
|
|
372
|
+
if (typeof status === 'number') {
|
|
373
|
+
return status === 401;
|
|
374
|
+
}
|
|
375
|
+
const message = String((error as { message?: unknown }).message ?? '');
|
|
376
|
+
return /\b401\b|unauthorized/i.test(message);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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 #5 decoupling. The Hedera transaction builder must resolve the
|
|
13
|
+
* active account through the ACTIVE_ACCOUNT_SOURCE token, NOT by injecting
|
|
14
|
+
* UnifiedWalletService directly. A default root provider keeps the token
|
|
15
|
+
* pointing at UnifiedWalletService, so existing SDK consumers are unaffected
|
|
16
|
+
* (the comprehensive hedera-transaction-builder.service.spec, which provides a
|
|
17
|
+
* UnifiedWalletService mock, is the backward-compatibility proof). The embedded
|
|
18
|
+
* shell overrides the token with a one-member account context, which is why the
|
|
19
|
+
* stub-of-UnifiedWalletService and its Proxy guard can be deleted.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { TestBed } from '@angular/core/testing';
|
|
23
|
+
import { describe, it, expect } from 'vitest';
|
|
24
|
+
import { signal } from '@angular/core';
|
|
25
|
+
|
|
26
|
+
import { HederaTransactionBuilderService } from './hedera-transaction-builder.service';
|
|
27
|
+
import { ACTIVE_ACCOUNT_SOURCE, type ActiveAccountSource } from './active-account-source';
|
|
28
|
+
import { LoggerService } from '../logger.service';
|
|
29
|
+
import { UnifiedWalletService } from '../unified-wallet.service';
|
|
30
|
+
import type { UnifiedAccount } from '../../models/unified-account.model';
|
|
31
|
+
|
|
32
|
+
const mockLogger = {
|
|
33
|
+
scoped: () => ({ debug() {}, info() {}, warn() {}, error() {} }),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function testnetSource(networkId = 'hedera:testnet'): ActiveAccountSource {
|
|
37
|
+
const account: UnifiedAccount = {
|
|
38
|
+
id: `embedded:hedera:${networkId}:0.0.2193470`,
|
|
39
|
+
address: '0.0.2193470',
|
|
40
|
+
ledgerId: 'hedera',
|
|
41
|
+
networkId,
|
|
42
|
+
providerId: 'test',
|
|
43
|
+
providerType: 'hsuite-native',
|
|
44
|
+
metadata: {},
|
|
45
|
+
};
|
|
46
|
+
return { activeAccount: signal<UnifiedAccount | null>(account) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe('ACTIVE_ACCOUNT_SOURCE (Hedera builder decoupling, #5)', () => {
|
|
50
|
+
it('builds a Hedera transaction from ACTIVE_ACCOUNT_SOURCE with NO UnifiedWalletService provided', async () => {
|
|
51
|
+
TestBed.configureTestingModule({
|
|
52
|
+
providers: [
|
|
53
|
+
{ provide: ACTIVE_ACCOUNT_SOURCE, useValue: testnetSource() },
|
|
54
|
+
{ provide: LoggerService, useValue: mockLogger },
|
|
55
|
+
// UnifiedWalletService is deliberately NOT provided: the builder must
|
|
56
|
+
// resolve its network purely from the account source.
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const builder = TestBed.inject(HederaTransactionBuilderService);
|
|
61
|
+
const payload = await builder.buildSendHbar('0.0.123', '0.0.456', 1);
|
|
62
|
+
|
|
63
|
+
expect(typeof payload).toBe('string');
|
|
64
|
+
expect(payload.length).toBeGreaterThan(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('default provider falls back to UnifiedWalletService (backward compatible)', () => {
|
|
68
|
+
const fakeUnified = { activeAccount: signal<UnifiedAccount | null>(null) };
|
|
69
|
+
TestBed.configureTestingModule({
|
|
70
|
+
providers: [{ provide: UnifiedWalletService, useValue: fakeUnified }],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(TestBed.inject(ACTIVE_ACCOUNT_SOURCE)).toBe(fakeUnified);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
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 ACTIVE_ACCOUNT_SOURCE: the minimal active-account read surface the
|
|
13
|
+
* transaction builders need.
|
|
14
|
+
*
|
|
15
|
+
* @description
|
|
16
|
+
* The Hedera transaction builder only reads `activeAccount()` from the wallet
|
|
17
|
+
* (to pick the network and the entity key config). Injecting the whole
|
|
18
|
+
* {@link UnifiedWalletService} couples the builder to a heavy root service that
|
|
19
|
+
* also runs the dApp connect stack on construction. This token narrows that
|
|
20
|
+
* dependency to a single member.
|
|
21
|
+
*
|
|
22
|
+
* The default provider points at {@link UnifiedWalletService}, so existing SDK
|
|
23
|
+
* consumers that already provide it need NO wiring change (backward
|
|
24
|
+
* compatible). The embedded widget shell overrides this token with a one-member
|
|
25
|
+
* account context, which keeps the heavy root service from ever being
|
|
26
|
+
* constructed inside the wallet.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { InjectionToken, inject, type Signal } from '@angular/core';
|
|
30
|
+
|
|
31
|
+
import type { UnifiedAccount } from '../../models/unified-account.model';
|
|
32
|
+
import { UnifiedWalletService } from '../unified-wallet.service';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The only member the transaction builders read from the active wallet account.
|
|
36
|
+
* Implemented by {@link UnifiedWalletService} (the default) and by the embedded
|
|
37
|
+
* shell's one-member account context.
|
|
38
|
+
*/
|
|
39
|
+
export interface ActiveAccountSource {
|
|
40
|
+
readonly activeAccount: Signal<UnifiedAccount | null>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Injection token for the active-account read surface. Defaults to
|
|
45
|
+
* {@link UnifiedWalletService} so consumers that already provide it need no
|
|
46
|
+
* extra wiring; override it to supply a narrower source (the embedded shell
|
|
47
|
+
* does this to avoid constructing the root service inside the wallet).
|
|
48
|
+
*/
|
|
49
|
+
export const ACTIVE_ACCOUNT_SOURCE = new InjectionToken<ActiveAccountSource>(
|
|
50
|
+
'ACTIVE_ACCOUNT_SOURCE',
|
|
51
|
+
{
|
|
52
|
+
providedIn: 'root',
|
|
53
|
+
factory: () => inject(UnifiedWalletService),
|
|
54
|
+
},
|
|
55
|
+
);
|
|
@@ -69,8 +69,8 @@ import {
|
|
|
69
69
|
} from '@hashgraph/sdk';
|
|
70
70
|
|
|
71
71
|
import { LoggerService } from '../logger.service';
|
|
72
|
-
import { UnifiedWalletService } from '../unified-wallet.service';
|
|
73
72
|
|
|
73
|
+
import { ACTIVE_ACCOUNT_SOURCE } from './active-account-source';
|
|
74
74
|
import { scaleHederaAmountToBaseUnits, assertSafeInteger } from './hedera-amount-utils';
|
|
75
75
|
|
|
76
76
|
/**
|
|
@@ -270,7 +270,7 @@ export interface AccountCreateOptions {
|
|
|
270
270
|
providedIn: 'root',
|
|
271
271
|
})
|
|
272
272
|
export class HederaTransactionBuilderService {
|
|
273
|
-
private readonly
|
|
273
|
+
private readonly accountSource = inject(ACTIVE_ACCOUNT_SOURCE);
|
|
274
274
|
private readonly logger = inject(LoggerService).scoped('HederaTransactionBuilder');
|
|
275
275
|
|
|
276
276
|
/**
|
|
@@ -286,7 +286,7 @@ export class HederaTransactionBuilderService {
|
|
|
286
286
|
* @throws {Error} When used in methods that require a network, if no account is active
|
|
287
287
|
*/
|
|
288
288
|
private getNetworkId(): string | undefined {
|
|
289
|
-
const activeAccount = this.
|
|
289
|
+
const activeAccount = this.accountSource.activeAccount();
|
|
290
290
|
return activeAccount?.networkId;
|
|
291
291
|
}
|
|
292
292
|
|
|
@@ -337,7 +337,7 @@ export class HederaTransactionBuilderService {
|
|
|
337
337
|
* @returns Key configuration or undefined if no active account
|
|
338
338
|
*/
|
|
339
339
|
private getActiveAccountKeyConfig(): HederaKeyConfig | undefined {
|
|
340
|
-
const activeAccount = this.
|
|
340
|
+
const activeAccount = this.accountSource.activeAccount();
|
|
341
341
|
if (!activeAccount) {
|
|
342
342
|
this.logger.debug('No active account for key config');
|
|
343
343
|
return undefined;
|
|
@@ -52,3 +52,4 @@ export {
|
|
|
52
52
|
} from './hedera-transaction-builder.service';
|
|
53
53
|
export { XrplTransactionBuilderService } from './xrpl-transaction-builder.service';
|
|
54
54
|
export { scaleHederaAmountToBaseUnits, assertSafeInteger } from './hedera-amount-utils';
|
|
55
|
+
export { ACTIVE_ACCOUNT_SOURCE, type ActiveAccountSource } from './active-account-source';
|
|
@@ -52,12 +52,15 @@ import { Injectable, inject, signal, type Signal, type WritableSignal } from '@a
|
|
|
52
52
|
import { getLogger } from '@hsuite/native-connect-sdk';
|
|
53
53
|
import { ToastController } from '@ionic/angular/standalone';
|
|
54
54
|
|
|
55
|
-
import type {
|
|
55
|
+
import type {
|
|
56
|
+
SignMessageResult,
|
|
57
|
+
SignResult,
|
|
58
|
+
SubmitResult,
|
|
59
|
+
} from '../providers/base-wallet-provider';
|
|
56
60
|
|
|
57
61
|
import { UnifiedWalletService } from './unified-wallet.service';
|
|
58
62
|
import { WalletEventBus } from './wallet-event-bus.service';
|
|
59
63
|
|
|
60
|
-
|
|
61
64
|
const logger = getLogger().scoped?.('TransactionService') ?? getLogger();
|
|
62
65
|
|
|
63
66
|
/**
|
|
@@ -211,9 +214,9 @@ export class TransactionService {
|
|
|
211
214
|
* @param message - Message to sign
|
|
212
215
|
* @returns Sign result with signature
|
|
213
216
|
*/
|
|
214
|
-
async signMessage(message: string): Promise<
|
|
217
|
+
async signMessage(message: string): Promise<SignMessageResult> {
|
|
215
218
|
return this.executeTransaction(async () => {
|
|
216
|
-
const result =
|
|
219
|
+
const result = await this.walletService.signMessage(message);
|
|
217
220
|
logger.info('Message signed', { hasSignature: !!result.signature });
|
|
218
221
|
await this.showSuccessToast('Message Signed', 'Your message has been signed successfully.');
|
|
219
222
|
return result;
|
|
@@ -409,7 +409,7 @@ class TestableUnifiedWalletService {
|
|
|
409
409
|
});
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
-
async signMessage(message: string, encoding?: 'utf-8' | 'base64'): Promise<
|
|
412
|
+
async signMessage(message: string, encoding?: 'utf-8' | 'base64'): Promise<SignMessageResult> {
|
|
413
413
|
const account = this._activeAccount();
|
|
414
414
|
if (!account) {
|
|
415
415
|
throw new Error('No active account');
|
|
@@ -49,14 +49,13 @@ import { getLogger } from '@hsuite/native-connect-sdk';
|
|
|
49
49
|
import type { ConnectionConfig } from '../models/connection-config.model';
|
|
50
50
|
import type { ProviderType, ConnectionStatus } from '../models/provider-types';
|
|
51
51
|
import type { UnifiedAccount } from '../models/unified-account.model';
|
|
52
|
-
import { BaseWalletProvider } from '../providers/base-wallet-provider';
|
|
52
|
+
import { BaseWalletProvider, SignMessageResult } from '../providers/base-wallet-provider';
|
|
53
53
|
import { HsuiteNativeProvider } from '../providers/hsuite-native-provider';
|
|
54
54
|
import { P2PNativeProvider } from '../providers/p2p-native/p2p-native.provider';
|
|
55
55
|
import { WalletConnectV2Provider } from '../providers/walletconnect/core/walletconnect-provider';
|
|
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 {
|
|
@@ -564,7 +563,7 @@ export class UnifiedWalletService {
|
|
|
564
563
|
* @throws {Error} If provider is not found
|
|
565
564
|
* @throws {Error} If user rejects the signing request
|
|
566
565
|
*/
|
|
567
|
-
async signMessage(message: string, encoding?: 'utf-8' | 'base64'): Promise<
|
|
566
|
+
async signMessage(message: string, encoding?: 'utf-8' | 'base64'): Promise<SignMessageResult> {
|
|
568
567
|
const account = this._activeAccount();
|
|
569
568
|
if (!account) {
|
|
570
569
|
throw new Error('No active account');
|