@meshconnect/uwc-react 0.6.10-snapshot.bcb597e → 0.6.11-snapshot.3776809

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/README.md CHANGED
@@ -199,6 +199,34 @@ function WalletList() {
199
199
  }
200
200
  ```
201
201
 
202
+ #### useSignSolanaTransaction
203
+
204
+ Sign a Solana transaction **without broadcasting it** — for fee-payer relay flows where a relay (e.g. your backend) pays the network fee and submits the transaction. Raw bytes in, signed bytes out, so callers don't need `@solana/web3.js`:
205
+
206
+ ```tsx
207
+ import { useSignSolanaTransaction } from '@meshconnect/uwc-react'
208
+
209
+ function SignButton({ unsignedTx }: { unsignedTx: Uint8Array }) {
210
+ const { signSolanaTransaction, isLoading, error } = useSignSolanaTransaction()
211
+
212
+ const onSign = async () => {
213
+ const signedTx = await signSolanaTransaction(unsignedTx)
214
+ // Hand signedTx to your relay to broadcast — UWC never sends it.
215
+ }
216
+
217
+ return (
218
+ <div>
219
+ <button onClick={onSign} disabled={isLoading}>
220
+ {isLoading ? 'Signing...' : 'Sign Transaction'}
221
+ </button>
222
+ {error && <p>{error.message}</p>}
223
+ </div>
224
+ )
225
+ }
226
+ ```
227
+
228
+ Works with injected wallets, WalletConnect, and through the iframe bridge.
229
+
202
230
  ## API Reference
203
231
 
204
232
  ### ConnectionProvider
@@ -230,4 +258,7 @@ Returns the current session state.
230
258
  Returns the list of available wallets.
231
259
 
232
260
  #### useNetworks()
233
- Returns the list of available networks.
261
+ Returns the list of available networks.
262
+
263
+ #### useSignSolanaTransaction()
264
+ Returns a sign-only `signSolanaTransaction(bytes: Uint8Array) => Promise<Uint8Array>` for Solana fee-payer relay flows, plus `isLoading` and `error` state. Never broadcasts — the relay owns submission.
@@ -1,8 +1,3 @@
1
- import type { WalletError } from '@meshconnect/uwc-types';
2
- export interface UseSignSolanaTransactionReturn {
3
- signSolanaTransaction: (serializedTx: Uint8Array) => Promise<Uint8Array>;
4
- isLoading: boolean;
5
- error: WalletError | undefined;
6
- }
1
+ import type { UseSignSolanaTransactionReturn } from '@meshconnect/uwc-types';
7
2
  export declare function useSignSolanaTransaction(): UseSignSolanaTransactionReturn;
8
3
  //# sourceMappingURL=useSignSolanaTransaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSignSolanaTransaction.d.ts","sourceRoot":"","sources":["../../src/hooks/useSignSolanaTransaction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEzD,MAAM,WAAW,8BAA8B;IAC7C,qBAAqB,EAAE,CAAC,YAAY,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IACxE,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,WAAW,GAAG,SAAS,CAAA;CAC/B;AAED,wBAAgB,wBAAwB,IAAI,8BAA8B,CA2CzE"}
1
+ {"version":3,"file":"useSignSolanaTransaction.d.ts","sourceRoot":"","sources":["../../src/hooks/useSignSolanaTransaction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,8BAA8B,EAE/B,MAAM,wBAAwB,CAAA;AAE/B,wBAAgB,wBAAwB,IAAI,8BAA8B,CAuCzE"}
@@ -5,20 +5,20 @@ export function useSignSolanaTransaction() {
5
5
  if (!context) {
6
6
  throw new Error('useSignSolanaTransaction must be used within a ConnectionProvider');
7
7
  }
8
- const { connector } = context;
8
+ const { connector, session } = context;
9
9
  const [isLoading, setIsLoading] = useState(false);
10
10
  const [error, setError] = useState();
11
11
  const signSolanaTransaction = useCallback(async (serializedTx) => {
12
+ if (!session.activeAddress) {
13
+ throw new Error('No wallet connected');
14
+ }
15
+ if (!serializedTx?.length) {
16
+ throw new Error('Transaction bytes are required');
17
+ }
12
18
  setIsLoading(true);
13
19
  setError(undefined);
14
20
  try {
15
- // [UWC ONC-3267] TEMP — revert before merge
16
- // eslint-disable-next-line no-console
17
- console.log('[UWC ONC-3267] hook.useSignSolanaTransaction entry, bytes=', serializedTx.length);
18
- const result = await connector.signSolanaTransaction(serializedTx);
19
- // eslint-disable-next-line no-console
20
- console.log('[UWC ONC-3267] hook.useSignSolanaTransaction returned, bytes=', result.length);
21
- return result;
21
+ return await connector.signSolanaTransaction(serializedTx);
22
22
  }
23
23
  catch (err) {
24
24
  const walletError = err;
@@ -28,7 +28,7 @@ export function useSignSolanaTransaction() {
28
28
  finally {
29
29
  setIsLoading(false);
30
30
  }
31
- }, [connector]);
31
+ }, [connector, session.activeAddress]);
32
32
  return { signSolanaTransaction, isLoading, error };
33
33
  }
34
34
  //# sourceMappingURL=useSignSolanaTransaction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSignSolanaTransaction.js","sourceRoot":"","sources":["../../src/hooks/useSignSolanaTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AASnE,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAE7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAA;IACH,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAC7B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAA2B,CAAA;IAE7D,MAAM,qBAAqB,GAAG,WAAW,CACvC,KAAK,EAAE,YAAwB,EAAuB,EAAE;QACtD,YAAY,CAAC,IAAI,CAAC,CAAA;QAClB,QAAQ,CAAC,SAAS,CAAC,CAAA;QACnB,IAAI,CAAC;YACH,4CAA4C;YAC5C,sCAAsC;YACtC,OAAO,CAAC,GAAG,CACT,4DAA4D,EAC5D,YAAY,CAAC,MAAM,CACpB,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAA;YAClE,sCAAsC;YACtC,OAAO,CAAC,GAAG,CACT,+DAA+D,EAC/D,MAAM,CAAC,MAAM,CACd,CAAA;YACD,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,CAAC,CACZ,CAAA;IAED,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AACpD,CAAC"}
1
+ {"version":3,"file":"useSignSolanaTransaction.js","sourceRoot":"","sources":["../../src/hooks/useSignSolanaTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAMnE,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAE7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAA;IACH,CAAC;IAED,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,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAA2B,CAAA;IAE7D,MAAM,qBAAqB,GAAG,WAAW,CACvC,KAAK,EAAE,YAAwB,EAAuB,EAAE;QACtD,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAA;QAClB,QAAQ,CAAC,SAAS,CAAC,CAAA;QACnB,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAA;QAC5D,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,EAAE,qBAAqB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AACpD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshconnect/uwc-react",
3
- "version": "0.6.10-snapshot.bcb597e",
3
+ "version": "0.6.11-snapshot.3776809",
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": "0.7.10-snapshot.bcb597e",
20
- "@meshconnect/uwc-types": "0.12.1-snapshot.bcb597e"
19
+ "@meshconnect/uwc-types": "0.13.0-snapshot.3776809",
20
+ "@meshconnect/uwc-core": "0.7.11-snapshot.3776809"
21
21
  },
22
22
  "peerDependencies": {
23
23
  "react": "^18.0.0",
@@ -3,7 +3,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
3
3
  import { createRoot } from 'react-dom/client'
4
4
  import { ConnectionContext } from '../providers/ConnectionProvider'
5
5
  import { useSignSolanaTransaction } from './useSignSolanaTransaction'
6
- import type { UseSignSolanaTransactionReturn } from './useSignSolanaTransaction'
6
+ import type { UseSignSolanaTransactionReturn } from '@meshconnect/uwc-types'
7
7
 
8
8
  // ---------------------------------------------------------------------------
9
9
  // Helpers
@@ -24,15 +24,24 @@ function makeConnector(
24
24
  }
25
25
  }
26
26
 
27
- /** Minimal context value that wraps a connector stub. */
28
- function makeContextValue(connector: ReturnType<typeof makeConnector>) {
27
+ /**
28
+ * Minimal context value that wraps a connector stub. Pass `{ activeAddress }`
29
+ * as an object (not a bare arg) so an explicit `undefined` survives — a default
30
+ * parameter would otherwise replace `undefined` with the connected address.
31
+ */
32
+ function makeContextValue(
33
+ connector: ReturnType<typeof makeConnector>,
34
+ { activeAddress }: { activeAddress: string | undefined } = {
35
+ activeAddress: 'SoLanaTestAddr1111111111111111111111111111'
36
+ }
37
+ ) {
29
38
  return {
30
39
  connector,
31
40
  session: {
32
- isConnected: false,
41
+ isConnected: activeAddress !== undefined,
33
42
  walletId: undefined,
34
43
  networkId: undefined,
35
- activeAddress: undefined
44
+ activeAddress
36
45
  },
37
46
  wallets: [],
38
47
  networks: [],
@@ -115,15 +124,14 @@ describe('useSignSolanaTransaction', () => {
115
124
 
116
125
  expect(() => {
117
126
  // Synchronous render — React will throw during render, caught here.
118
- // Suppress the React error boundary console.error noise.
119
- const originalError = console.error
120
- console.error = () => {}
127
+ // Suppress the React error-boundary noise this logs on the way out.
128
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
121
129
  try {
122
130
  act(() => {
123
131
  root.render(<BareHook />)
124
132
  })
125
133
  } finally {
126
- console.error = originalError
134
+ errorSpy.mockRestore()
127
135
  }
128
136
  }).toThrowError(
129
137
  'useSignSolanaTransaction must be used within a ConnectionProvider'
@@ -238,4 +246,52 @@ describe('useSignSolanaTransaction', () => {
238
246
  expect(captured.current!.isLoading).toBe(false)
239
247
  await unmount()
240
248
  })
249
+
250
+ // (e) throws "No wallet connected" before touching the connector when no active address
251
+ it('throws "No wallet connected" when there is no active address', async () => {
252
+ const mockSign = vi.fn()
253
+ const ctxValue = makeContextValue(makeConnector(mockSign), {
254
+ activeAddress: undefined
255
+ })
256
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
257
+
258
+ await render()
259
+
260
+ let thrownError: unknown
261
+ await act(async () => {
262
+ try {
263
+ await captured.current!.signSolanaTransaction(new Uint8Array([1]))
264
+ } catch (err) {
265
+ thrownError = err
266
+ }
267
+ })
268
+
269
+ expect((thrownError as Error).message).toBe('No wallet connected')
270
+ expect(mockSign).not.toHaveBeenCalled()
271
+ await unmount()
272
+ })
273
+
274
+ // (f) rejects empty input before touching the connector
275
+ it('throws "Transaction bytes are required" for empty bytes', async () => {
276
+ const mockSign = vi.fn()
277
+ const ctxValue = makeContextValue(makeConnector(mockSign))
278
+ const { captured, render, unmount } = renderHookInContext(ctxValue)
279
+
280
+ await render()
281
+
282
+ let thrownError: unknown
283
+ await act(async () => {
284
+ try {
285
+ await captured.current!.signSolanaTransaction(new Uint8Array(0))
286
+ } catch (err) {
287
+ thrownError = err
288
+ }
289
+ })
290
+
291
+ expect((thrownError as Error).message).toBe(
292
+ 'Transaction bytes are required'
293
+ )
294
+ expect(mockSign).not.toHaveBeenCalled()
295
+ await unmount()
296
+ })
241
297
  })
@@ -1,12 +1,9 @@
1
1
  import { useContext, useCallback, useState } from 'react'
2
2
  import { ConnectionContext } from '../providers/ConnectionProvider'
3
- import type { WalletError } from '@meshconnect/uwc-types'
4
-
5
- export interface UseSignSolanaTransactionReturn {
6
- signSolanaTransaction: (serializedTx: Uint8Array) => Promise<Uint8Array>
7
- isLoading: boolean
8
- error: WalletError | undefined
9
- }
3
+ import type {
4
+ UseSignSolanaTransactionReturn,
5
+ WalletError
6
+ } from '@meshconnect/uwc-types'
10
7
 
11
8
  export function useSignSolanaTransaction(): UseSignSolanaTransactionReturn {
12
9
  const context = useContext(ConnectionContext)
@@ -17,28 +14,24 @@ export function useSignSolanaTransaction(): UseSignSolanaTransactionReturn {
17
14
  )
18
15
  }
19
16
 
20
- const { connector } = context
17
+ const { connector, session } = context
21
18
  const [isLoading, setIsLoading] = useState(false)
22
19
  const [error, setError] = useState<WalletError | undefined>()
23
20
 
24
21
  const signSolanaTransaction = useCallback(
25
22
  async (serializedTx: Uint8Array): Promise<Uint8Array> => {
23
+ if (!session.activeAddress) {
24
+ throw new Error('No wallet connected')
25
+ }
26
+
27
+ if (!serializedTx?.length) {
28
+ throw new Error('Transaction bytes are required')
29
+ }
30
+
26
31
  setIsLoading(true)
27
32
  setError(undefined)
28
33
  try {
29
- // [UWC ONC-3267] TEMP — revert before merge
30
- // eslint-disable-next-line no-console
31
- console.log(
32
- '[UWC ONC-3267] hook.useSignSolanaTransaction entry, bytes=',
33
- serializedTx.length
34
- )
35
- const result = await connector.signSolanaTransaction(serializedTx)
36
- // eslint-disable-next-line no-console
37
- console.log(
38
- '[UWC ONC-3267] hook.useSignSolanaTransaction returned, bytes=',
39
- result.length
40
- )
41
- return result
34
+ return await connector.signSolanaTransaction(serializedTx)
42
35
  } catch (err) {
43
36
  const walletError = err as WalletError
44
37
  setError(walletError)
@@ -47,7 +40,7 @@ export function useSignSolanaTransaction(): UseSignSolanaTransactionReturn {
47
40
  setIsLoading(false)
48
41
  }
49
42
  },
50
- [connector]
43
+ [connector, session.activeAddress]
51
44
  )
52
45
 
53
46
  return { signSolanaTransaction, isLoading, error }