@meshconnect/uwc-core 0.7.4 → 0.7.5-snapshot.c90b3e8

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 (50) hide show
  1. package/README.md +924 -0
  2. package/dist/events.d.ts +71 -0
  3. package/dist/events.d.ts.map +1 -0
  4. package/dist/events.js +2 -0
  5. package/dist/events.js.map +1 -0
  6. package/dist/index.d.ts +2 -3
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/managers/event-manager.d.ts +22 -3
  11. package/dist/managers/event-manager.d.ts.map +1 -1
  12. package/dist/managers/event-manager.js +63 -7
  13. package/dist/managers/event-manager.js.map +1 -1
  14. package/dist/services/connection-service.d.ts +5 -2
  15. package/dist/services/connection-service.d.ts.map +1 -1
  16. package/dist/services/connection-service.js +19 -7
  17. package/dist/services/connection-service.js.map +1 -1
  18. package/dist/services/network-switch-service.d.ts +2 -1
  19. package/dist/services/network-switch-service.d.ts.map +1 -1
  20. package/dist/services/network-switch-service.js +15 -3
  21. package/dist/services/network-switch-service.js.map +1 -1
  22. package/dist/services/signature-service.d.ts +3 -1
  23. package/dist/services/signature-service.d.ts.map +1 -1
  24. package/dist/services/signature-service.js +10 -5
  25. package/dist/services/signature-service.js.map +1 -1
  26. package/dist/services/transaction-service.d.ts +3 -1
  27. package/dist/services/transaction-service.d.ts.map +1 -1
  28. package/dist/services/transaction-service.js +10 -5
  29. package/dist/services/transaction-service.js.map +1 -1
  30. package/dist/services/wallet-capabilities-service.d.ts +2 -1
  31. package/dist/services/wallet-capabilities-service.d.ts.map +1 -1
  32. package/dist/services/wallet-capabilities-service.js +9 -2
  33. package/dist/services/wallet-capabilities-service.js.map +1 -1
  34. package/dist/universal-wallet-connector.d.ts +52 -6
  35. package/dist/universal-wallet-connector.d.ts.map +1 -1
  36. package/dist/universal-wallet-connector.js +271 -177
  37. package/dist/universal-wallet-connector.js.map +1 -1
  38. package/package.json +5 -5
  39. package/src/events.ts +73 -0
  40. package/src/index.ts +11 -3
  41. package/src/managers/event-manager.test.ts +70 -0
  42. package/src/managers/event-manager.ts +80 -9
  43. package/src/services/connection-service.test.ts +11 -3
  44. package/src/services/connection-service.ts +34 -7
  45. package/src/services/network-switch-service.ts +22 -3
  46. package/src/services/signature-service.ts +13 -5
  47. package/src/services/transaction-service.ts +13 -5
  48. package/src/services/wallet-capabilities-service.ts +14 -2
  49. package/src/universal-wallet-connector.test.ts +87 -3
  50. package/src/universal-wallet-connector.ts +395 -204
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshconnect/uwc-core",
3
- "version": "0.7.4",
3
+ "version": "0.7.5-snapshot.c90b3e8",
4
4
  "description": "Core functionality for Universal Wallet Connector",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,10 +16,10 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@meshconnect/uwc-injected-connector": "0.10.4",
20
- "@meshconnect/uwc-ton-connector": "0.5.2",
21
- "@meshconnect/uwc-types": "0.11.1",
22
- "@meshconnect/uwc-wallet-connect-connector": "0.4.13"
19
+ "@meshconnect/uwc-wallet-connect-connector": "0.4.13-snapshot.c90b3e8",
20
+ "@meshconnect/uwc-injected-connector": "0.10.5-snapshot.c90b3e8",
21
+ "@meshconnect/uwc-ton-connector": "0.5.3-snapshot.c90b3e8",
22
+ "@meshconnect/uwc-types": "0.11.1-snapshot.c90b3e8"
23
23
  },
24
24
  "devDependencies": {
25
25
  "typescript": "^5.9.3"
package/src/events.ts ADDED
@@ -0,0 +1,73 @@
1
+ import type {
2
+ Session,
3
+ Network,
4
+ WalletMetadata,
5
+ ConnectionMode,
6
+ WalletError,
7
+ EVMCapabilities
8
+ } from '@meshconnect/uwc-types'
9
+
10
+ /**
11
+ * User-initiated operations that can surface through the `error` event.
12
+ */
13
+ export type UWCOperation =
14
+ | 'connect'
15
+ | 'disconnect'
16
+ | 'switchNetwork'
17
+ | 'signMessage'
18
+ | 'sendTransaction'
19
+ | 'getWalletCapabilities'
20
+ | 'initialize'
21
+
22
+ /**
23
+ * Typed event map emitted by UniversalWalletConnector.
24
+ *
25
+ * Subscribe with `on(event, listener)` to react to a single kind of change
26
+ * instead of re-reading `getSession()` on every notification.
27
+ *
28
+ * Every typed event also triggers the `change` event, so legacy
29
+ * `subscribe(listener)` callers continue to fire.
30
+ */
31
+ export interface UWCEventMap {
32
+ /** Wallet detection finished; `getWallets()` now reflects which are installed. */
33
+ ready: void
34
+ /** Emitted once detection finishes, with the final wallet list. */
35
+ walletsDetected: { wallets: WalletMetadata[] }
36
+
37
+ /** `connect()` has started. */
38
+ connecting: { connectionMode: ConnectionMode; walletId: string }
39
+ /** `connect()` completed successfully. */
40
+ connected: { session: Session }
41
+ /** `disconnect()` completed and the session was cleared. */
42
+ disconnected: void
43
+ /**
44
+ * A pairing URI became available for WalletConnect / TonConnect flows.
45
+ * Prefer this over polling `getConnectionURI()`.
46
+ */
47
+ connectionUri: { uri: string; connectionMode: ConnectionMode }
48
+
49
+ /** The active session changed (address, network, capabilities, …). */
50
+ sessionChanged: { session: Session }
51
+
52
+ /** Network switching is in progress. Fires on start and end. */
53
+ networkSwitching: { isLoading: boolean; isWaitingForUserApproval: boolean }
54
+ /** Network switch succeeded. */
55
+ networkSwitched: { network: Network }
56
+
57
+ /** Wallet capabilities were refreshed. */
58
+ capabilitiesUpdated: { capabilities: Record<string, EVMCapabilities> }
59
+
60
+ /** A user-initiated operation failed. */
61
+ error: { error: WalletError; operation: UWCOperation }
62
+
63
+ /**
64
+ * Back-compat catch-all. Fires after every other event above.
65
+ * New code should prefer the specific events.
66
+ */
67
+ change: void
68
+ }
69
+
70
+ export type UWCEventName = keyof UWCEventMap
71
+ export type UWCEventListener<K extends UWCEventName> = (
72
+ data: UWCEventMap[K]
73
+ ) => void
package/src/index.ts CHANGED
@@ -1,3 +1,11 @@
1
- export * from './universal-wallet-connector'
2
- export * from './managers'
3
- export * from './services'
1
+ export {
2
+ UniversalWalletConnector,
3
+ type UWCConfig,
4
+ type OperationOptions
5
+ } from './universal-wallet-connector'
6
+ export type {
7
+ UWCEventMap,
8
+ UWCEventName,
9
+ UWCEventListener,
10
+ UWCOperation
11
+ } from './events'
@@ -71,4 +71,74 @@ describe('EventManager', () => {
71
71
  eventManager.clearAllListeners()
72
72
  expect(eventManager.getListenerCount()).toBe(0)
73
73
  })
74
+
75
+ describe('typed events', () => {
76
+ it('dispatches typed event data only to on() listeners of that event', () => {
77
+ const disconnected: unknown[] = []
78
+ const networkSwitched: unknown[] = []
79
+
80
+ eventManager.on('disconnected', data => disconnected.push(data))
81
+ eventManager.on('networkSwitched', data => networkSwitched.push(data))
82
+
83
+ eventManager.emit('disconnected', undefined)
84
+
85
+ expect(disconnected).toHaveLength(1)
86
+ expect(networkSwitched).toHaveLength(0)
87
+ })
88
+
89
+ it('cascades every typed event to the legacy change channel', () => {
90
+ let changeCount = 0
91
+ eventManager.subscribe(() => {
92
+ changeCount++
93
+ })
94
+
95
+ eventManager.emit('connectionUri', {
96
+ uri: 'wc://x',
97
+ connectionMode: 'walletConnect'
98
+ })
99
+ eventManager.emit('disconnected', undefined)
100
+
101
+ expect(changeCount).toBe(2)
102
+ })
103
+
104
+ it('off() removes a listener from the typed set', () => {
105
+ const calls: unknown[] = []
106
+ const listener = (d: unknown) => calls.push(d)
107
+ eventManager.on('ready', listener)
108
+ eventManager.off('ready', listener)
109
+ eventManager.emit('ready', undefined)
110
+ expect(calls).toHaveLength(0)
111
+ })
112
+
113
+ it('once() removes the listener after a single dispatch', () => {
114
+ let calls = 0
115
+ eventManager.once('ready', () => {
116
+ calls++
117
+ })
118
+ eventManager.emit('ready', undefined)
119
+ eventManager.emit('ready', undefined)
120
+ expect(calls).toBe(1)
121
+ })
122
+
123
+ it('a throwing listener does not stop other listeners', () => {
124
+ const calls: string[] = []
125
+ eventManager.on('ready', () => {
126
+ throw new Error('boom')
127
+ })
128
+ eventManager.on('ready', () => {
129
+ calls.push('second')
130
+ })
131
+ eventManager.emit('ready', undefined)
132
+ expect(calls).toEqual(['second'])
133
+ })
134
+
135
+ it('emit("change") does not recurse into itself', () => {
136
+ let count = 0
137
+ eventManager.on('change', () => {
138
+ count++
139
+ })
140
+ eventManager.emit('change', undefined)
141
+ expect(count).toBe(1)
142
+ })
143
+ })
74
144
  })
@@ -1,22 +1,93 @@
1
- type Listener = () => void
2
- type Unsubscribe = () => void
1
+ import type { UWCEventMap, UWCEventName, UWCEventListener } from '../events'
3
2
 
3
+ type LegacyListener = () => void
4
+ type UntypedListener = (data: unknown) => void
5
+
6
+ /**
7
+ * Typed event emitter used by UniversalWalletConnector.
8
+ *
9
+ * Each event has its own listener set. Emitting any typed event also
10
+ * dispatches the legacy `change` event, so `subscribe()` callers keep
11
+ * receiving a notification on every state change.
12
+ */
4
13
  export class EventManager {
5
- private listeners: Set<Listener> = new Set()
14
+ private listeners: Map<UWCEventName, Set<UntypedListener>> = new Map()
15
+
16
+ /** Subscribe to a typed event. Returns an unsubscribe function. */
17
+ on<K extends UWCEventName>(
18
+ event: K,
19
+ listener: UWCEventListener<K>
20
+ ): () => void {
21
+ let set = this.listeners.get(event)
22
+ if (!set) {
23
+ set = new Set()
24
+ this.listeners.set(event, set)
25
+ }
26
+ set.add(listener as UntypedListener)
27
+ return () => this.off(event, listener)
28
+ }
29
+
30
+ /** Subscribe once; the listener is removed after the first dispatch. */
31
+ once<K extends UWCEventName>(
32
+ event: K,
33
+ listener: UWCEventListener<K>
34
+ ): () => void {
35
+ const wrapper: UWCEventListener<K> = data => {
36
+ this.off(event, wrapper)
37
+ listener(data)
38
+ }
39
+ return this.on(event, wrapper)
40
+ }
41
+
42
+ off<K extends UWCEventName>(event: K, listener: UWCEventListener<K>): void {
43
+ const set = this.listeners.get(event)
44
+ set?.delete(listener as UntypedListener)
45
+ }
46
+
47
+ emit<K extends UWCEventName>(event: K, data: UWCEventMap[K]): void {
48
+ this.dispatch(event, data)
49
+ if (event !== 'change') {
50
+ this.dispatch('change', undefined as UWCEventMap['change'])
51
+ }
52
+ }
6
53
 
7
- subscribe(listener: Listener): Unsubscribe {
8
- this.listeners.add(listener)
9
- return () => {
10
- this.listeners.delete(listener)
54
+ private dispatch<K extends UWCEventName>(
55
+ event: K,
56
+ data: UWCEventMap[K]
57
+ ): void {
58
+ const set = this.listeners.get(event)
59
+ if (!set || set.size === 0) return
60
+ // Clone to guard against mutation during dispatch.
61
+ for (const listener of [...set]) {
62
+ try {
63
+ listener(data)
64
+ } catch {
65
+ // A bad listener shouldn't break the rest of the dispatch chain.
66
+ }
11
67
  }
12
68
  }
13
69
 
70
+ // ---- legacy API (still used by the React ConnectionProvider) ----
71
+
72
+ /**
73
+ * @deprecated Prefer `on(eventName, listener)` for targeted updates.
74
+ * Subscribes to the catch-all `change` event.
75
+ */
76
+ subscribe(listener: LegacyListener): () => void {
77
+ return this.on('change', listener)
78
+ }
79
+
80
+ /** @deprecated Prefer `emit(eventName, data)`. Emits `change` with no payload. */
14
81
  notify(): void {
15
- this.listeners.forEach(listener => listener())
82
+ this.dispatch('change', undefined as UWCEventMap['change'])
16
83
  }
17
84
 
18
85
  getListenerCount(): number {
19
- return this.listeners.size
86
+ let count = 0
87
+ for (const set of this.listeners.values()) {
88
+ count += set.size
89
+ }
90
+ return count
20
91
  }
21
92
 
22
93
  clearAllListeners(): void {
@@ -249,8 +249,12 @@ describe('ConnectionService', () => {
249
249
  })
250
250
  })
251
251
 
252
- it('polls for URI and notifies eventManager when available', async () => {
253
- const notifySpy = vi.spyOn(eventManager, 'notify')
252
+ it('emits connectionUri and change events when URI becomes available', async () => {
253
+ const uriListener = vi.fn()
254
+ const changeListener = vi.fn()
255
+ eventManager.on('connectionUri', uriListener)
256
+ eventManager.on('change', changeListener)
257
+
254
258
  let connectResolve: (v: any) => void
255
259
 
256
260
  tonConnector.connect = vi.fn().mockReturnValue(
@@ -275,7 +279,11 @@ describe('ConnectionService', () => {
275
279
  // Wait for polling to detect URI
276
280
  await new Promise(r => setTimeout(r, 250))
277
281
 
278
- expect(notifySpy).toHaveBeenCalled()
282
+ expect(uriListener).toHaveBeenCalledWith({
283
+ uri: 'tc://some-uri',
284
+ connectionMode: 'tonConnect'
285
+ })
286
+ expect(changeListener).toHaveBeenCalled()
279
287
 
280
288
  // Resolve the connection to let the test finish
281
289
  connectResolve!({
@@ -13,6 +13,10 @@ import type {
13
13
  import type { SessionManager } from '../managers/session-manager'
14
14
  import type { EventManager } from '../managers/event-manager'
15
15
 
16
+ export interface ServiceOptions {
17
+ signal?: AbortSignal
18
+ }
19
+
16
20
  export class ConnectionService {
17
21
  private activeConnector: Connector | null = null
18
22
 
@@ -28,8 +32,13 @@ export class ConnectionService {
28
32
  async connect(
29
33
  connectionMode: ConnectionMode,
30
34
  walletId: string,
31
- networkId?: NetworkId
35
+ networkId?: NetworkId,
36
+ options?: ServiceOptions
32
37
  ): Promise<void> {
38
+ options?.signal?.throwIfAborted()
39
+
40
+ this.eventManager.emit('connecting', { connectionMode, walletId })
41
+
33
42
  // Find the wallet
34
43
  const wallet = this.findWallet(walletId)
35
44
 
@@ -59,7 +68,12 @@ export class ConnectionService {
59
68
  connectionMode === 'tonConnect' ||
60
69
  connectionMode === 'walletConnect'
61
70
  ) {
62
- result = await this.connectWithURIPoll(connector, network, provider)
71
+ result = await this.connectWithURIPoll(
72
+ connector,
73
+ network,
74
+ provider,
75
+ connectionMode
76
+ )
63
77
  } else {
64
78
  throw new Error(`Unsupported connection mode: ${connectionMode}`)
65
79
  }
@@ -68,6 +82,9 @@ export class ConnectionService {
68
82
  throw error
69
83
  }
70
84
 
85
+ // If the caller aborted during the await, bail before mutating session
86
+ options?.signal?.throwIfAborted()
87
+
71
88
  // Filter available addresses to only include those for configured networks
72
89
  const filteredAvailableAddresses = result.availableAddresses.filter(addr =>
73
90
  this.networks.some(n => n.id === addr.networkId)
@@ -84,20 +101,26 @@ export class ConnectionService {
84
101
  ),
85
102
  availableAddresses: filteredAvailableAddresses
86
103
  })
104
+
105
+ const session = this.sessionManager.getSession()
106
+ this.eventManager.emit('connected', { session })
107
+ this.eventManager.emit('sessionChanged', { session })
87
108
  }
88
109
 
89
110
  private async connectWithURIPoll(
90
111
  connector: Connector,
91
112
  network: Network,
92
- provider: SupportedProvider
113
+ provider: SupportedProvider,
114
+ connectionMode: ConnectionMode
93
115
  ): Promise<ConnectorResult> {
94
116
  const connectPromise = connector.connect(network, provider)
95
117
 
118
+ let emittedUri: string | undefined
96
119
  const pollForURI = setInterval(() => {
97
120
  const uri = this.getConnectionURI()
98
- if (uri) {
99
- clearInterval(pollForURI)
100
- this.eventManager.notify()
121
+ if (uri && uri !== emittedUri) {
122
+ emittedUri = uri
123
+ this.eventManager.emit('connectionUri', { uri, connectionMode })
101
124
  }
102
125
  }, 100)
103
126
 
@@ -219,7 +242,8 @@ export class ConnectionService {
219
242
  return network
220
243
  }
221
244
 
222
- async disconnect(): Promise<void> {
245
+ async disconnect(options?: ServiceOptions): Promise<void> {
246
+ options?.signal?.throwIfAborted()
223
247
  try {
224
248
  if (
225
249
  this.activeConnector &&
@@ -230,6 +254,9 @@ export class ConnectionService {
230
254
  } finally {
231
255
  this.activeConnector = null
232
256
  this.sessionManager.clearSession()
257
+ const session = this.sessionManager.getSession()
258
+ this.eventManager.emit('disconnected', undefined)
259
+ this.eventManager.emit('sessionChanged', { session })
233
260
  }
234
261
  }
235
262
 
@@ -11,6 +11,7 @@ import type {
11
11
  } from '@meshconnect/uwc-types'
12
12
  import type { SessionManager } from '../managers/session-manager'
13
13
  import type { EventManager } from '../managers/event-manager'
14
+ import type { ServiceOptions } from './connection-service'
14
15
 
15
16
  export class NetworkSwitchService {
16
17
  private isLoading = false
@@ -31,7 +32,12 @@ export class NetworkSwitchService {
31
32
  }
32
33
  }
33
34
 
34
- async switchNetwork(networkId: NetworkId): Promise<void> {
35
+ async switchNetwork(
36
+ networkId: NetworkId,
37
+ options?: ServiceOptions
38
+ ): Promise<void> {
39
+ options?.signal?.throwIfAborted()
40
+
35
41
  // Check if there's an active connection
36
42
  const session = this.sessionManager.getSession()
37
43
  if (!session) {
@@ -104,7 +110,10 @@ export class NetworkSwitchService {
104
110
  // Set loading states
105
111
  this.isLoading = true
106
112
  this.isWaitingForUserApproval = requiresApproval
107
- this.eventManager.notify()
113
+ this.eventManager.emit('networkSwitching', {
114
+ isLoading: true,
115
+ isWaitingForUserApproval: requiresApproval
116
+ })
108
117
 
109
118
  // Perform the network switch and get the new address
110
119
  // Pass the appropriate provider based on connection mode
@@ -129,6 +138,8 @@ export class NetworkSwitchService {
129
138
  result = await activeConnector.switchNetwork(network)
130
139
  }
131
140
 
141
+ options?.signal?.throwIfAborted()
142
+
132
143
  // Filter available addresses to only include those for configured networks
133
144
  const filteredAvailableAddresses = result.availableAddresses
134
145
  ? result.availableAddresses.filter(addr =>
@@ -144,11 +155,19 @@ export class NetworkSwitchService {
144
155
  availableAddresses: filteredAvailableAddresses
145
156
  })
146
157
  })
158
+
159
+ this.eventManager.emit('networkSwitched', { network })
160
+ this.eventManager.emit('sessionChanged', {
161
+ session: this.sessionManager.getSession()
162
+ })
147
163
  } finally {
148
164
  // Clear loading states
149
165
  this.isLoading = false
150
166
  this.isWaitingForUserApproval = false
151
- this.eventManager.notify()
167
+ this.eventManager.emit('networkSwitching', {
168
+ isLoading: false,
169
+ isWaitingForUserApproval: false
170
+ })
152
171
  }
153
172
  }
154
173
 
@@ -8,6 +8,7 @@ import type {
8
8
  SignatureType
9
9
  } from '@meshconnect/uwc-types'
10
10
  import type { SessionManager } from '../managers/session-manager'
11
+ import type { ServiceOptions } from './connection-service'
11
12
 
12
13
  /**
13
14
  * Service for handling signature operations across different connector types
@@ -22,12 +23,15 @@ export class SignatureService {
22
23
  * Sign a message with the currently connected wallet
23
24
  * @param message The message to sign
24
25
  * @param provider The wallet provider to use for signing (required for injected connector)
26
+ * @param options Optional cancellation signal
25
27
  * @returns A promise that resolves to the signature
26
28
  */
27
29
  async signMessage(
28
30
  message: string,
29
- provider?: SupportedProvider
31
+ provider?: SupportedProvider,
32
+ options?: ServiceOptions
30
33
  ): Promise<SignatureType> {
34
+ options?.signal?.throwIfAborted()
31
35
  const session = this.sessionManager.getSession()
32
36
 
33
37
  if (!session.connectionMode) {
@@ -52,29 +56,33 @@ export class SignatureService {
52
56
  }
53
57
 
54
58
  // Call the connector's signMessage method with the appropriate provider
59
+ let signature: SignatureType
55
60
  if (session.connectionMode === 'injected') {
56
61
  if (!provider) {
57
62
  throw new Error('Provider is required for injected connector')
58
63
  }
59
- return await connector.signMessage(
64
+ signature = await connector.signMessage(
60
65
  message,
61
66
  provider as
62
67
  | ExtensionInjectedProvider
63
68
  | IntegratedBrowserInjectedProvider
64
69
  )
65
70
  } else if (session.connectionMode === 'tonConnect') {
66
- return await connector.signMessage(message)
71
+ signature = await connector.signMessage(message)
67
72
  } else if (session.connectionMode === 'walletConnect') {
68
73
  if (!provider) {
69
74
  throw new Error('Provider is required for WalletConnect connector')
70
75
  }
71
- return await connector.signMessage(
76
+ signature = await connector.signMessage(
72
77
  message,
73
78
  provider as WalletConnectProvider
74
79
  )
75
80
  } else {
76
81
  // For other connectors that might not need the provider
77
- return await connector.signMessage(message)
82
+ signature = await connector.signMessage(message)
78
83
  }
84
+
85
+ options?.signal?.throwIfAborted()
86
+ return signature
79
87
  }
80
88
  }
@@ -9,6 +9,7 @@ import type {
9
9
  TransactionResult
10
10
  } from '@meshconnect/uwc-types'
11
11
  import type { SessionManager } from '../managers/session-manager'
12
+ import type { ServiceOptions } from './connection-service'
12
13
 
13
14
  /**
14
15
  * Service for handling transaction operations across different connector types
@@ -23,12 +24,15 @@ export class TransactionService {
23
24
  * Send a transaction with the currently connected wallet
24
25
  * @param request The transaction request parameters
25
26
  * @param provider The wallet provider to use for sending (required for injected connector)
27
+ * @param options Optional cancellation signal
26
28
  * @returns A promise that resolves to the transaction result
27
29
  */
28
30
  async sendTransaction(
29
31
  request: TransactionRequest,
30
- provider?: SupportedProvider
32
+ provider?: SupportedProvider,
33
+ options?: ServiceOptions
31
34
  ): Promise<TransactionResult> {
35
+ options?.signal?.throwIfAborted()
32
36
  const session = this.sessionManager.getSession()
33
37
 
34
38
  if (!session.connectionMode) {
@@ -53,29 +57,33 @@ export class TransactionService {
53
57
  }
54
58
 
55
59
  // Call the connector's sendTransaction method with the appropriate provider
60
+ let result: TransactionResult
56
61
  if (session.connectionMode === 'injected') {
57
62
  if (!provider) {
58
63
  throw new Error('Provider is required for injected connector')
59
64
  }
60
- return await connector.sendTransaction(
65
+ result = await connector.sendTransaction(
61
66
  request,
62
67
  provider as
63
68
  | ExtensionInjectedProvider
64
69
  | IntegratedBrowserInjectedProvider
65
70
  )
66
71
  } else if (session.connectionMode === 'tonConnect') {
67
- return await connector.sendTransaction(request)
72
+ result = await connector.sendTransaction(request)
68
73
  } else if (session.connectionMode === 'walletConnect') {
69
74
  if (!provider) {
70
75
  throw new Error('Provider is required for WalletConnect connector')
71
76
  }
72
- return await connector.sendTransaction(
77
+ result = await connector.sendTransaction(
73
78
  request,
74
79
  provider as WalletConnectProvider
75
80
  )
76
81
  } else {
77
82
  // For other connectors that might not need the provider
78
- return await connector.sendTransaction(request)
83
+ result = await connector.sendTransaction(request)
79
84
  }
85
+
86
+ options?.signal?.throwIfAborted()
87
+ return result
80
88
  }
81
89
  }
@@ -6,6 +6,7 @@ import type {
6
6
  } from '@meshconnect/uwc-types'
7
7
  import type { SessionManager } from '../managers/session-manager'
8
8
  import type { EventManager } from '../managers/event-manager'
9
+ import type { ServiceOptions } from './connection-service'
9
10
 
10
11
  export class WalletCapabilitiesService {
11
12
  constructor(
@@ -17,8 +18,11 @@ export class WalletCapabilitiesService {
17
18
 
18
19
  async getWalletCapabilities(
19
20
  address: string,
20
- activeNetwork?: Network
21
+ activeNetwork?: Network,
22
+ options?: ServiceOptions
21
23
  ): Promise<void> {
24
+ options?.signal?.throwIfAborted()
25
+
22
26
  let activeWalletCapabilities: Record<string, EVMCapabilities> = {}
23
27
  let activeNetworkWalletCapabilities: EVMCapabilities = {}
24
28
 
@@ -49,6 +53,8 @@ export class WalletCapabilitiesService {
49
53
  capabilities = {}
50
54
  }
51
55
 
56
+ options?.signal?.throwIfAborted()
57
+
52
58
  // keep only supported networks
53
59
  activeWalletCapabilities = Object.fromEntries(
54
60
  Object.entries(capabilities).filter(([networkId, _]) =>
@@ -71,7 +77,13 @@ export class WalletCapabilitiesService {
71
77
  activeNetworkWalletCapabilities: null
72
78
  })
73
79
  }
74
- this.eventManager.notify()
80
+
81
+ this.eventManager.emit('capabilitiesUpdated', {
82
+ capabilities: activeWalletCapabilities
83
+ })
84
+ this.eventManager.emit('sessionChanged', {
85
+ session: this.sessionManager.getSession()
86
+ })
75
87
  }
76
88
  }
77
89
  }