@meshconnect/uwc-react 0.11.18 → 0.12.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.
@@ -9,9 +9,9 @@ import type { UseSignMessageReturn } from '@meshconnect/uwc-types';
9
9
  *
10
10
  * const handleSign = async () => {
11
11
  * try {
12
- * const sig = await signMessage('Hello World')
13
- * console.log('Signature:', sig)
14
- * // signature state will also be updated with the result
12
+ * const { signature, address } = await signMessage('Hello World')
13
+ * console.log('Signature:', signature, 'signed by', address)
14
+ * // The `signature` state also holds result.signature after the call.
15
15
  * } catch (error) {
16
16
  * console.error('Failed to sign:', error)
17
17
  * }
@@ -1 +1 @@
1
- {"version":3,"file":"useSignMessage.d.ts","sourceRoot":"","sources":["../../src/hooks/useSignMessage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,oBAAoB,EAErB,MAAM,wBAAwB,CAAA;AAE/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,CAwCrD"}
1
+ {"version":3,"file":"useSignMessage.d.ts","sourceRoot":"","sources":["../../src/hooks/useSignMessage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,oBAAoB,EAErB,MAAM,wBAAwB,CAAA;AAE/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,CA0CrD"}
@@ -10,9 +10,9 @@ import { useConnectionContext } from './useConnectionContext';
10
10
  *
11
11
  * const handleSign = async () => {
12
12
  * try {
13
- * const sig = await signMessage('Hello World')
14
- * console.log('Signature:', sig)
15
- * // signature state will also be updated with the result
13
+ * const { signature, address } = await signMessage('Hello World')
14
+ * console.log('Signature:', signature, 'signed by', address)
15
+ * // The `signature` state also holds result.signature after the call.
16
16
  * } catch (error) {
17
17
  * console.error('Failed to sign:', error)
18
18
  * }
@@ -35,9 +35,11 @@ export function useSignMessage() {
35
35
  setIsLoading(true);
36
36
  setError(undefined);
37
37
  try {
38
- const sig = await connector.signMessage(message);
39
- setSignature(sig);
40
- return sig;
38
+ const result = await connector.signMessage(message);
39
+ // Keep the `signature` state as the SignatureType for backward-compat
40
+ // display; callers needing the exact signer read `result.address`.
41
+ setSignature(result.signature);
42
+ return result;
41
43
  }
42
44
  catch (err) {
43
45
  const walletError = err;
@@ -1 +1 @@
1
- {"version":3,"file":"useSignMessage.js","sourceRoot":"","sources":["../../src/hooks/useSignMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAO7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,CAAA;IACtD,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IACtC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,EAA6B,CAAA;IACvE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAA2B,CAAA;IAE7D,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,OAAe,EAA0B,EAAE;QAChD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAA;QAClB,QAAQ,CAAC,SAAS,CAAC,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YAChD,YAAY,CAAC,GAAG,CAAC,CAAA;YACjB,OAAO,GAAG,CAAA;QACZ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,GAAkB,CAAA;YACtC,QAAQ,CAAC,WAAW,CAAC,CAAA;YACrB,MAAM,GAAG,CAAA;QACX,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,CACnC,CAAA;IAED,OAAO;QACL,WAAW;QACX,SAAS;QACT,SAAS;QACT,KAAK;KACN,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"useSignMessage.js","sourceRoot":"","sources":["../../src/hooks/useSignMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAQ7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,CAAA;IACtD,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IACtC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,EAA6B,CAAA;IACvE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAA2B,CAAA;IAE7D,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,OAAe,EAA4B,EAAE;QAClD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAA;QAClB,QAAQ,CAAC,SAAS,CAAC,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YACnD,sEAAsE;YACtE,mEAAmE;YACnE,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAC9B,OAAO,MAAM,CAAA;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,GAAkB,CAAA;YACtC,QAAQ,CAAC,WAAW,CAAC,CAAA;YACrB,MAAM,GAAG,CAAA;QACX,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,CACnC,CAAA;IAED,OAAO;QACL,WAAW;QACX,SAAS;QACT,SAAS;QACT,KAAK;KACN,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshconnect/uwc-react",
3
- "version": "0.11.18",
3
+ "version": "0.12.0",
4
4
  "description": "React hooks and components for Universal Wallet Connector",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,8 +16,8 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@meshconnect/uwc-core": "1.10.3",
20
- "@meshconnect/uwc-types": "0.23.0"
19
+ "@meshconnect/uwc-core": "2.0.0",
20
+ "@meshconnect/uwc-types": "0.25.0"
21
21
  },
22
22
  "peerDependencies": {
23
23
  "react": "^18.0.0",
@@ -0,0 +1,177 @@
1
+ import React, { act } from 'react'
2
+ import { describe, it, expect, vi } from 'vitest'
3
+ import { createRoot } from 'react-dom/client'
4
+ import { ConnectionContext } from '../providers/ConnectionProvider'
5
+ import { useSignMessage } from './useSignMessage'
6
+ import type {
7
+ SignatureResult,
8
+ UseSignMessageReturn
9
+ } from '@meshconnect/uwc-types'
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Fixtures + helpers
13
+ // ---------------------------------------------------------------------------
14
+
15
+ const SIGNER_ADDRESS = '0xSignerAddress'
16
+
17
+ const RESULT: SignatureResult = {
18
+ signature: { type: 'standard', signature: '0xdeadbeef' },
19
+ address: SIGNER_ADDRESS
20
+ }
21
+
22
+ /** Minimal stub that satisfies ConnectionContextValue's connector shape. */
23
+ function makeConnector(
24
+ signMessage: (message: string) => Promise<SignatureResult>
25
+ ) {
26
+ return {
27
+ signMessage,
28
+ getSession: () => ({ isConnected: false }),
29
+ isReady: () => true,
30
+ subscribe: () => () => {},
31
+ getWallets: () => [],
32
+ getNetworks: () => []
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Minimal context value that wraps a connector stub. Pass `{ activeAddress }`
38
+ * as an object (not a bare arg) so an explicit `undefined` survives.
39
+ */
40
+ function makeContextValue(
41
+ connector: ReturnType<typeof makeConnector>,
42
+ { activeAddress }: { activeAddress: string | undefined } = {
43
+ activeAddress: '0xUserAddress'
44
+ }
45
+ ) {
46
+ return {
47
+ connector,
48
+ session: {
49
+ isConnected: activeAddress !== undefined,
50
+ walletId: undefined,
51
+ networkId: undefined,
52
+ activeAddress
53
+ },
54
+ wallets: [],
55
+ networks: [],
56
+ isReady: true
57
+ }
58
+ }
59
+
60
+ function renderHookInContext(
61
+ contextValue: ReturnType<typeof makeContextValue>
62
+ ) {
63
+ const captured: { current: UseSignMessageReturn | null } = { current: null }
64
+
65
+ function Capture() {
66
+ captured.current = useSignMessage()
67
+ return null
68
+ }
69
+
70
+ const container = document.createElement('div')
71
+ document.body.appendChild(container)
72
+ const root = createRoot(container)
73
+
74
+ async function render() {
75
+ await act(async () => {
76
+ root.render(
77
+ <ConnectionContext.Provider value={contextValue as never}>
78
+ <Capture />
79
+ </ConnectionContext.Provider>
80
+ )
81
+ })
82
+ }
83
+
84
+ async function unmount() {
85
+ await act(async () => {
86
+ root.unmount()
87
+ })
88
+ document.body.removeChild(container)
89
+ }
90
+
91
+ return { captured, render, unmount }
92
+ }
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // Tests
96
+ // ---------------------------------------------------------------------------
97
+
98
+ describe('useSignMessage', () => {
99
+ it('resolves to the full SignatureResult { signature, address }', async () => {
100
+ const mockSign = vi.fn().mockResolvedValue(RESULT)
101
+ const ctxValue = makeContextValue(makeConnector(mockSign))
102
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
103
+
104
+ await render()
105
+ expect(captured.current).not.toBeNull()
106
+
107
+ let result: SignatureResult | undefined
108
+ await act(async () => {
109
+ result = await captured.current!.signMessage('Hello World')
110
+ })
111
+
112
+ expect(mockSign).toHaveBeenCalledOnce()
113
+ expect(mockSign).toHaveBeenCalledWith('Hello World')
114
+ expect(result).toEqual(RESULT)
115
+ await unmount()
116
+ })
117
+
118
+ it('stores result.signature (the SignatureType) in the signature state', async () => {
119
+ const mockSign = vi.fn().mockResolvedValue(RESULT)
120
+ const ctxValue = makeContextValue(makeConnector(mockSign))
121
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
122
+
123
+ await render()
124
+
125
+ await act(async () => {
126
+ await captured.current!.signMessage('Hello World')
127
+ })
128
+
129
+ expect(captured.current!.signature).toEqual(RESULT.signature)
130
+ await unmount()
131
+ })
132
+
133
+ it('sets error state and re-throws when connector rejects', async () => {
134
+ const walletError = { code: 4001, message: 'User rejected' }
135
+ const mockSign = vi.fn().mockRejectedValue(walletError)
136
+ const ctxValue = makeContextValue(makeConnector(mockSign))
137
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
138
+
139
+ await render()
140
+
141
+ let thrownError: unknown
142
+ await act(async () => {
143
+ try {
144
+ await captured.current!.signMessage('Hello World')
145
+ } catch (err) {
146
+ thrownError = err
147
+ }
148
+ })
149
+
150
+ expect(thrownError).toBe(walletError)
151
+ expect(captured.current!.error).toBe(walletError)
152
+ await unmount()
153
+ })
154
+
155
+ it('throws "No wallet connected" when there is no active address', async () => {
156
+ const mockSign = vi.fn()
157
+ const ctxValue = makeContextValue(makeConnector(mockSign), {
158
+ activeAddress: undefined
159
+ })
160
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
161
+
162
+ await render()
163
+
164
+ let thrownError: unknown
165
+ await act(async () => {
166
+ try {
167
+ await captured.current!.signMessage('Hello World')
168
+ } catch (err) {
169
+ thrownError = err
170
+ }
171
+ })
172
+
173
+ expect((thrownError as Error).message).toBe('No wallet connected')
174
+ expect(mockSign).not.toHaveBeenCalled()
175
+ await unmount()
176
+ })
177
+ })
@@ -2,6 +2,7 @@ import { useCallback, useState } from 'react'
2
2
  import { useConnectionContext } from './useConnectionContext'
3
3
  import type {
4
4
  SignatureType,
5
+ SignatureResult,
5
6
  UseSignMessageReturn,
6
7
  WalletError
7
8
  } from '@meshconnect/uwc-types'
@@ -16,9 +17,9 @@ import type {
16
17
  *
17
18
  * const handleSign = async () => {
18
19
  * try {
19
- * const sig = await signMessage('Hello World')
20
- * console.log('Signature:', sig)
21
- * // signature state will also be updated with the result
20
+ * const { signature, address } = await signMessage('Hello World')
21
+ * console.log('Signature:', signature, 'signed by', address)
22
+ * // The `signature` state also holds result.signature after the call.
22
23
  * } catch (error) {
23
24
  * console.error('Failed to sign:', error)
24
25
  * }
@@ -33,7 +34,7 @@ export function useSignMessage(): UseSignMessageReturn {
33
34
  const [error, setError] = useState<WalletError | undefined>()
34
35
 
35
36
  const signMessage = useCallback(
36
- async (message: string): Promise<SignatureType> => {
37
+ async (message: string): Promise<SignatureResult> => {
37
38
  if (!connector || !session.activeAddress) {
38
39
  throw new Error('No wallet connected')
39
40
  }
@@ -45,9 +46,11 @@ export function useSignMessage(): UseSignMessageReturn {
45
46
  setIsLoading(true)
46
47
  setError(undefined)
47
48
  try {
48
- const sig = await connector.signMessage(message)
49
- setSignature(sig)
50
- return sig
49
+ const result = await connector.signMessage(message)
50
+ // Keep the `signature` state as the SignatureType for backward-compat
51
+ // display; callers needing the exact signer read `result.address`.
52
+ setSignature(result.signature)
53
+ return result
51
54
  } catch (err) {
52
55
  const walletError = err as WalletError
53
56
  setError(walletError)