@miden-sdk/use-miden-para-react 0.13.1 → 0.13.3
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/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/ParaSignerProvider.tsx +57 -17
package/dist/index.d.mts
CHANGED
|
@@ -7,6 +7,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
7
7
|
import { ReactNode } from 'react';
|
|
8
8
|
import { ParaWeb, Wallet } from '@getpara/web-sdk';
|
|
9
9
|
import { QueryClient } from '@tanstack/react-query';
|
|
10
|
+
import { SignerAccountConfig } from '@miden-sdk/react';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* React hook that converts Para React SDK context into a ready-to-use Miden WebClient.
|
|
@@ -55,6 +56,8 @@ interface ParaSignerProviderProps {
|
|
|
55
56
|
* Use this for customizing OAuth methods, external wallets, etc.
|
|
56
57
|
*/
|
|
57
58
|
paraProviderConfig?: Partial<Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>>;
|
|
59
|
+
/** Optional custom account components to include in the account (e.g. from a compiled .masp package) */
|
|
60
|
+
customComponents?: SignerAccountConfig['customComponents'];
|
|
58
61
|
}
|
|
59
62
|
/**
|
|
60
63
|
* Para-specific extras exposed via useParaSigner hook.
|
|
@@ -78,7 +81,7 @@ interface ParaSignerExtras {
|
|
|
78
81
|
* </ParaSignerProvider>
|
|
79
82
|
* ```
|
|
80
83
|
*/
|
|
81
|
-
declare function ParaSignerProvider({ children, apiKey, environment, appName, showSigningModal, customSignConfirmStep, queryClient, paraProviderConfig, }: ParaSignerProviderProps): react_jsx_runtime.JSX.Element;
|
|
84
|
+
declare function ParaSignerProvider({ children, apiKey, environment, appName, showSigningModal, customSignConfirmStep, queryClient, paraProviderConfig, customComponents, }: ParaSignerProviderProps): react_jsx_runtime.JSX.Element;
|
|
82
85
|
/**
|
|
83
86
|
* Hook for Para-specific extras beyond the unified useSigner interface.
|
|
84
87
|
* Use this to access the Para client or wallet details directly.
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
7
7
|
import { ReactNode } from 'react';
|
|
8
8
|
import { ParaWeb, Wallet } from '@getpara/web-sdk';
|
|
9
9
|
import { QueryClient } from '@tanstack/react-query';
|
|
10
|
+
import { SignerAccountConfig } from '@miden-sdk/react';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* React hook that converts Para React SDK context into a ready-to-use Miden WebClient.
|
|
@@ -55,6 +56,8 @@ interface ParaSignerProviderProps {
|
|
|
55
56
|
* Use this for customizing OAuth methods, external wallets, etc.
|
|
56
57
|
*/
|
|
57
58
|
paraProviderConfig?: Partial<Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>>;
|
|
59
|
+
/** Optional custom account components to include in the account (e.g. from a compiled .masp package) */
|
|
60
|
+
customComponents?: SignerAccountConfig['customComponents'];
|
|
58
61
|
}
|
|
59
62
|
/**
|
|
60
63
|
* Para-specific extras exposed via useParaSigner hook.
|
|
@@ -78,7 +81,7 @@ interface ParaSignerExtras {
|
|
|
78
81
|
* </ParaSignerProvider>
|
|
79
82
|
* ```
|
|
80
83
|
*/
|
|
81
|
-
declare function ParaSignerProvider({ children, apiKey, environment, appName, showSigningModal, customSignConfirmStep, queryClient, paraProviderConfig, }: ParaSignerProviderProps): react_jsx_runtime.JSX.Element;
|
|
84
|
+
declare function ParaSignerProvider({ children, apiKey, environment, appName, showSigningModal, customSignConfirmStep, queryClient, paraProviderConfig, customComponents, }: ParaSignerProviderProps): react_jsx_runtime.JSX.Element;
|
|
82
85
|
/**
|
|
83
86
|
* Hook for Para-specific extras beyond the unified useSigner interface.
|
|
84
87
|
* Use this to access the Para client or wallet details directly.
|
package/dist/index.js
CHANGED
|
@@ -132,7 +132,8 @@ function ParaSignerProvider({
|
|
|
132
132
|
showSigningModal = true,
|
|
133
133
|
customSignConfirmStep,
|
|
134
134
|
queryClient,
|
|
135
|
-
paraProviderConfig
|
|
135
|
+
paraProviderConfig,
|
|
136
|
+
customComponents
|
|
136
137
|
}) {
|
|
137
138
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_query.QueryClientProvider, { client: queryClient != null ? queryClient : defaultQueryClient, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
138
139
|
import_react_sdk_lite2.ParaProvider,
|
|
@@ -148,6 +149,7 @@ function ParaSignerProvider({
|
|
|
148
149
|
{
|
|
149
150
|
showSigningModal,
|
|
150
151
|
customSignConfirmStep,
|
|
152
|
+
customComponents,
|
|
151
153
|
children
|
|
152
154
|
}
|
|
153
155
|
)
|
|
@@ -157,7 +159,8 @@ function ParaSignerProvider({
|
|
|
157
159
|
function ParaSignerProviderInner({
|
|
158
160
|
children,
|
|
159
161
|
showSigningModal = true,
|
|
160
|
-
customSignConfirmStep
|
|
162
|
+
customSignConfirmStep,
|
|
163
|
+
customComponents
|
|
161
164
|
}) {
|
|
162
165
|
const { openModal } = (0, import_react_sdk_lite2.useModal)();
|
|
163
166
|
const { logoutAsync } = (0, import_react_sdk_lite2.useLogout)();
|
|
@@ -197,7 +200,9 @@ function ParaSignerProviderInner({
|
|
|
197
200
|
const wallets = Object.values(await paraRef.current.getWallets());
|
|
198
201
|
const evmWallets = wallets.filter((w) => w.type === "EVM");
|
|
199
202
|
if (evmWallets.length > 0 && !cancelled) {
|
|
200
|
-
setWallet(
|
|
203
|
+
setWallet(
|
|
204
|
+
(prev) => (prev == null ? void 0 : prev.id) === evmWallets[0].id ? prev : evmWallets[0]
|
|
205
|
+
);
|
|
201
206
|
setIsConnected(true);
|
|
202
207
|
} else if (!cancelled) {
|
|
203
208
|
setIsConnected(false);
|
|
@@ -266,7 +271,8 @@ function ParaSignerProviderInner({
|
|
|
266
271
|
accountConfig: {
|
|
267
272
|
publicKeyCommitment: commitmentBytes,
|
|
268
273
|
accountType: "RegularAccountImmutableCode",
|
|
269
|
-
storageMode: AccountStorageMode.public()
|
|
274
|
+
storageMode: AccountStorageMode.public(),
|
|
275
|
+
...(customComponents == null ? void 0 : customComponents.length) ? { customComponents } : {}
|
|
270
276
|
},
|
|
271
277
|
storeName: `para_${wallet.id}`,
|
|
272
278
|
name: "Para",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/useParaMiden.ts","../src/ParaSignerProvider.tsx"],"sourcesContent":["export { useParaMiden } from './useParaMiden';\nexport {\n ParaSignerProvider,\n useParaSigner,\n useModal,\n useLogout,\n type ParaSignerProviderProps,\n type ParaSignerExtras,\n} from './ParaSignerProvider';\n","'use client';\n\nimport { useClient, useAccount, type Wallet } from '@getpara/react-sdk-lite';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n createParaMidenClient,\n type Opts,\n type MidenAccountStorageMode,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\n\n/**\n * React hook that converts Para React SDK context into a ready-to-use Miden WebClient.\n * Spawns the client once a Para session with at least one EVM wallet is active.\n *\n * Returns:\n * - client: WebClient instance backed by the active Para session (or null while loading)\n * - accountId: Miden account id derived for the selected EVM wallet\n * - para: Para client instance from context\n * - evmWallets: filtered list of Para wallets with type === 'EVM'\n * - nodeUrl: Miden node endpoint used for the client\n * - opts: forwarded options used when creating the client\n * - showSigningModal: toggles the built-in signing modal\n * - customSignConfirmStep: optional callback for custom transaction confirmation flows\n */\nexport function useParaMiden(\n nodeUrl: string,\n storageMode: MidenAccountStorageMode = 'public',\n opts: Omit<Opts, 'endpoint' | 'type' | 'storageMode'> = {},\n showSigningModal: boolean = true,\n customSignConfirmStep?: CustomSignConfirmStep\n) {\n const para = useClient();\n const { isConnected, embedded } = useAccount();\n const clientRef = useRef<import('@miden-sdk/miden-sdk').WebClient | null>(\n null\n );\n const [accountId, setAccountId] = useState<string>('');\n\n const evmWallets = useMemo(\n () => embedded.wallets?.filter((wallet) => wallet.type === 'EVM'),\n [embedded.wallets]\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function setupClient() {\n if (\n !isConnected ||\n !para ||\n !embedded.wallets?.length ||\n clientRef.current\n ) {\n return;\n }\n\n const { AccountType } = await import('@miden-sdk/miden-sdk');\n\n const { client: midenParaClient, accountId: aId } =\n await createParaMidenClient(\n para,\n evmWallets as Wallet[],\n {\n ...opts,\n endpoint: nodeUrl,\n type: AccountType.RegularAccountImmutableCode,\n storageMode,\n },\n showSigningModal,\n customSignConfirmStep\n );\n\n if (cancelled) {\n return;\n }\n\n clientRef.current = midenParaClient;\n setAccountId(aId);\n }\n\n setupClient();\n\n return () => {\n cancelled = true;\n };\n }, [\n isConnected,\n evmWallets,\n para,\n nodeUrl,\n showSigningModal,\n customSignConfirmStep,\n ]);\n\n return {\n client: clientRef.current,\n accountId,\n para,\n evmWallets,\n nodeUrl,\n opts,\n };\n}\n","import {\n useState,\n useEffect,\n useCallback,\n useRef,\n createContext,\n useContext,\n type ReactNode,\n} from 'react';\nimport { ParaWeb, Environment, type Wallet } from '@getpara/web-sdk';\nimport {\n ParaProvider,\n useClient,\n useModal,\n useLogout,\n type ParaProviderProps,\n} from '@getpara/react-sdk-lite';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { SignerContext, type SignerContextValue } from '@miden-sdk/react';\nimport { signCb as createSignCb, type CustomSignConfirmStep } from '@miden-sdk/miden-para';\nimport { evmPkToCommitment, getUncompressedPublicKeyFromWallet } from '@miden-sdk/miden-para';\n\n// Re-export Para hooks for convenience\nexport { useModal, useLogout } from '@getpara/react-sdk-lite';\n\nconst defaultQueryClient = new QueryClient();\n\n// PARA SIGNER PROVIDER\n// ================================================================================================\n\n/** Environment string values accepted by ParaSignerProvider */\nexport type ParaEnvironment = 'BETA' | 'PROD' | 'SANDBOX' | 'DEV' | 'DEVELOPMENT' | 'PRODUCTION';\n\n/**\n * Convert environment string to Environment enum value.\n * Handles the mapping safely for both ESM and CJS environments.\n */\nfunction getEnvironmentValue(env: ParaEnvironment): Environment {\n // Handle aliases\n const normalizedEnv = env === 'DEVELOPMENT' ? 'BETA' : env === 'PRODUCTION' ? 'PROD' : env;\n\n // Try accessing the enum - Environment may be undefined in some test environments\n if (Environment && typeof Environment === 'object') {\n const value = Environment[normalizedEnv as keyof typeof Environment];\n if (value !== undefined) return value;\n }\n\n // Fallback: return the string directly (Para SDK may accept string values)\n return normalizedEnv as unknown as Environment;\n}\n\nexport interface ParaSignerProviderProps {\n children: ReactNode;\n /** Para API key */\n apiKey: string;\n /** Para environment (BETA, PROD, SANDBOX, DEV, DEVELOPMENT, PRODUCTION) */\n environment: ParaEnvironment;\n /** App name displayed in Para modal */\n appName?: string;\n /** Whether to show the signing modal for transaction confirmation */\n showSigningModal?: boolean;\n /** Custom sign confirmation step callback */\n customSignConfirmStep?: CustomSignConfirmStep;\n /**\n * Optional custom QueryClient instance for React Query.\n * If not provided, a default instance is used internally.\n */\n queryClient?: QueryClient;\n /**\n * Advanced: Additional config to pass to ParaProvider.\n * Use this for customizing OAuth methods, external wallets, etc.\n */\n paraProviderConfig?: Partial<Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>>;\n}\n\n/**\n * Para-specific extras exposed via useParaSigner hook.\n */\nexport interface ParaSignerExtras {\n /** Para client instance */\n para: ParaWeb;\n /** Connected wallet (null if not connected) */\n wallet: Wallet | null;\n}\n\nconst ParaSignerExtrasContext = createContext<ParaSignerExtras | null>(null);\n\n/**\n * ParaSignerProvider wraps MidenProvider to enable Para wallet signing.\n * Includes ParaProvider internally, so you don't need to wrap with it separately.\n *\n * @example\n * ```tsx\n * <ParaSignerProvider apiKey=\"your-api-key\" environment=\"BETA\" appName=\"My App\">\n * <MidenProvider config={{ rpcUrl: \"testnet\" }}>\n * <App />\n * </MidenProvider>\n * </ParaSignerProvider>\n * ```\n */\nexport function ParaSignerProvider({\n children,\n apiKey,\n environment,\n appName = 'Miden App',\n showSigningModal = true,\n customSignConfirmStep,\n queryClient,\n paraProviderConfig,\n}: ParaSignerProviderProps) {\n return (\n <QueryClientProvider client={queryClient ?? defaultQueryClient}>\n <ParaProvider\n paraClientConfig={{\n env: getEnvironmentValue(environment),\n apiKey,\n }}\n config={{ appName }}\n {...paraProviderConfig}\n >\n <ParaSignerProviderInner\n showSigningModal={showSigningModal}\n customSignConfirmStep={customSignConfirmStep}\n >\n {children}\n </ParaSignerProviderInner>\n </ParaProvider>\n </QueryClientProvider>\n );\n}\n\n/**\n * Inner component that has access to ParaProvider context (useModal, etc.)\n */\nfunction ParaSignerProviderInner({\n children,\n showSigningModal = true,\n customSignConfirmStep,\n}: Pick<ParaSignerProviderProps, 'children' | 'showSigningModal' | 'customSignConfirmStep'>) {\n // Access Para modal from ParaProvider.\n // Store in refs to avoid re-render loops (these hooks return new objects each render).\n const { openModal } = useModal();\n const { logoutAsync } = useLogout();\n const openModalRef = useRef(openModal);\n const logoutAsyncRef = useRef(logoutAsync);\n useEffect(() => { openModalRef.current = openModal; }, [openModal]);\n useEffect(() => { logoutAsyncRef.current = logoutAsync; }, [logoutAsync]);\n\n // Get the Para client from ParaProvider context (avoids creating a duplicate instance).\n // Store in a ref so downstream effects don't re-fire when the hook returns a new wrapper.\n const para = useClient()!;\n const paraRef = useRef(para);\n useEffect(() => { paraRef.current = para; }, [para]);\n\n // Keep props in refs so buildContext doesn't re-run when parent re-renders with new closures.\n const showSigningModalRef = useRef(showSigningModal);\n const customSignConfirmStepRef = useRef(customSignConfirmStep);\n useEffect(() => { showSigningModalRef.current = showSigningModal; }, [showSigningModal]);\n useEffect(() => { customSignConfirmStepRef.current = customSignConfirmStep; }, [customSignConfirmStep]);\n\n const [wallet, setWallet] = useState<Wallet | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n // Check connection status on mount and periodically\n useEffect(() => {\n let cancelled = false;\n\n async function checkConnection() {\n try {\n const isLoggedIn = await paraRef.current.isFullyLoggedIn();\n if (!isLoggedIn || cancelled) {\n setIsConnected(false);\n setWallet(null);\n return;\n }\n\n const wallets = Object.values(await paraRef.current.getWallets());\n const evmWallets = wallets.filter((w) => w.type === 'EVM');\n\n if (evmWallets.length > 0 && !cancelled) {\n setWallet((prev) => prev?.id === evmWallets[0].id ? prev : evmWallets[0]);\n setIsConnected(true);\n } else if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n } catch {\n if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n }\n }\n\n checkConnection();\n const interval = setInterval(checkConnection, 2000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, []);\n\n // Connect opens the Para modal\n const connect = useCallback(async () => {\n openModalRef.current();\n }, []);\n\n // Disconnect logs out from Para\n const disconnect = useCallback(async () => {\n await logoutAsyncRef.current();\n await paraRef.current.logout();\n setIsConnected(false);\n setWallet(null);\n }, []);\n\n // Build signer context (includes connect/disconnect for unified useSigner hook).\n // Only depends on isConnected and wallet — everything else is accessed via refs\n // so that MidenProvider doesn't see a new context object on every poll cycle.\n //\n // IMPORTANT: initialise with a disconnected placeholder (isConnected:false) rather\n // than null. When signerContext is null MidenProvider creates a local-keystore\n // client whose auto-sync accesses the WASM module; our buildContext also touches\n // WASM (evmPkToCommitment / AccountStorageMode) → concurrent WASM access → crash.\n // A {isConnected:false} context makes MidenProvider's init effect return early\n // without creating any client, keeping the WASM module free for buildContext.\n const disconnectedCtx = useRef<SignerContextValue>({\n signCb: async () => { throw new Error('Para wallet not connected'); },\n accountConfig: null as any,\n storeName: '',\n name: 'Para',\n isConnected: false,\n connect,\n disconnect,\n });\n const [signerContext, setSignerContext] = useState<SignerContextValue>(\n disconnectedCtx.current\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function buildContext() {\n if (!isConnected || !wallet) {\n setSignerContext(disconnectedCtx.current);\n return;\n }\n\n try {\n // Connected - build full context with signing capability\n const p = paraRef.current;\n const publicKey = await getUncompressedPublicKeyFromWallet(p, wallet);\n if (!publicKey) throw new Error('Failed to get public key from wallet');\n const commitment = await evmPkToCommitment(publicKey);\n\n // Serialize the commitment Word to Uint8Array for SignerAccountConfig\n const commitmentBytes = commitment.serialize();\n\n const signCallback = createSignCb(\n p,\n wallet,\n showSigningModalRef.current,\n customSignConfirmStepRef.current\n );\n\n if (!cancelled) {\n const { AccountStorageMode } = await import(\n '@miden-sdk/miden-sdk'\n );\n\n setSignerContext({\n signCb: signCallback,\n accountConfig: {\n publicKeyCommitment: commitmentBytes,\n accountType: 'RegularAccountImmutableCode',\n storageMode: AccountStorageMode.public(),\n },\n storeName: `para_${wallet.id}`,\n name: 'Para',\n isConnected: true,\n connect,\n disconnect,\n });\n }\n } catch (error) {\n console.error('Failed to build Para signer context:', error);\n if (!cancelled) {\n setSignerContext(disconnectedCtx.current);\n }\n }\n }\n\n buildContext();\n return () => {\n cancelled = true;\n };\n }, [isConnected, wallet, connect, disconnect]);\n\n return (\n <ParaSignerExtrasContext.Provider value={{ para, wallet }}>\n <SignerContext.Provider value={signerContext}>\n {children}\n </SignerContext.Provider>\n </ParaSignerExtrasContext.Provider>\n );\n}\n\n/**\n * Hook for Para-specific extras beyond the unified useSigner interface.\n * Use this to access the Para client or wallet details directly.\n *\n * @example\n * ```tsx\n * const { para, wallet, isConnected } = useParaSigner();\n * ```\n */\nexport function useParaSigner(): ParaSignerExtras & { isConnected: boolean } {\n const extras = useContext(ParaSignerExtrasContext);\n const signer = useContext(SignerContext);\n if (!extras) {\n throw new Error('useParaSigner must be used within ParaSignerProvider');\n }\n return { ...extras, isConnected: signer?.isConnected ?? false };\n}\n"],"mappings":"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","names":["import_react","import_react_sdk_lite","import_miden_para","createSignCb"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/useParaMiden.ts","../src/ParaSignerProvider.tsx"],"sourcesContent":["export { useParaMiden } from './useParaMiden';\nexport {\n ParaSignerProvider,\n useParaSigner,\n useModal,\n useLogout,\n type ParaSignerProviderProps,\n type ParaSignerExtras,\n} from './ParaSignerProvider';\n","'use client';\n\nimport { useClient, useAccount, type Wallet } from '@getpara/react-sdk-lite';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n createParaMidenClient,\n type Opts,\n type MidenAccountStorageMode,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\n\n/**\n * React hook that converts Para React SDK context into a ready-to-use Miden WebClient.\n * Spawns the client once a Para session with at least one EVM wallet is active.\n *\n * Returns:\n * - client: WebClient instance backed by the active Para session (or null while loading)\n * - accountId: Miden account id derived for the selected EVM wallet\n * - para: Para client instance from context\n * - evmWallets: filtered list of Para wallets with type === 'EVM'\n * - nodeUrl: Miden node endpoint used for the client\n * - opts: forwarded options used when creating the client\n * - showSigningModal: toggles the built-in signing modal\n * - customSignConfirmStep: optional callback for custom transaction confirmation flows\n */\nexport function useParaMiden(\n nodeUrl: string,\n storageMode: MidenAccountStorageMode = 'public',\n opts: Omit<Opts, 'endpoint' | 'type' | 'storageMode'> = {},\n showSigningModal: boolean = true,\n customSignConfirmStep?: CustomSignConfirmStep\n) {\n const para = useClient();\n const { isConnected, embedded } = useAccount();\n const clientRef = useRef<import('@miden-sdk/miden-sdk').WebClient | null>(\n null\n );\n const [accountId, setAccountId] = useState<string>('');\n\n const evmWallets = useMemo(\n () => embedded.wallets?.filter((wallet) => wallet.type === 'EVM'),\n [embedded.wallets]\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function setupClient() {\n if (\n !isConnected ||\n !para ||\n !embedded.wallets?.length ||\n clientRef.current\n ) {\n return;\n }\n\n const { AccountType } = await import('@miden-sdk/miden-sdk');\n\n const { client: midenParaClient, accountId: aId } =\n await createParaMidenClient(\n para,\n evmWallets as Wallet[],\n {\n ...opts,\n endpoint: nodeUrl,\n type: AccountType.RegularAccountImmutableCode,\n storageMode,\n },\n showSigningModal,\n customSignConfirmStep\n );\n\n if (cancelled) {\n return;\n }\n\n clientRef.current = midenParaClient;\n setAccountId(aId);\n }\n\n setupClient();\n\n return () => {\n cancelled = true;\n };\n }, [\n isConnected,\n evmWallets,\n para,\n nodeUrl,\n showSigningModal,\n customSignConfirmStep,\n ]);\n\n return {\n client: clientRef.current,\n accountId,\n para,\n evmWallets,\n nodeUrl,\n opts,\n };\n}\n","import {\n useState,\n useEffect,\n useCallback,\n useRef,\n createContext,\n useContext,\n type ReactNode,\n} from 'react';\nimport { ParaWeb, Environment, type Wallet } from '@getpara/web-sdk';\nimport {\n ParaProvider,\n useClient,\n useModal,\n useLogout,\n type ParaProviderProps,\n} from '@getpara/react-sdk-lite';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport {\n SignerContext,\n type SignerContextValue,\n type SignerAccountConfig,\n} from '@miden-sdk/react';\nimport {\n signCb as createSignCb,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\nimport {\n evmPkToCommitment,\n getUncompressedPublicKeyFromWallet,\n} from '@miden-sdk/miden-para';\n\n// Re-export Para hooks for convenience\nexport { useModal, useLogout } from '@getpara/react-sdk-lite';\n\nconst defaultQueryClient = new QueryClient();\n\n// PARA SIGNER PROVIDER\n// ================================================================================================\n\n/** Environment string values accepted by ParaSignerProvider */\nexport type ParaEnvironment =\n | 'BETA'\n | 'PROD'\n | 'SANDBOX'\n | 'DEV'\n | 'DEVELOPMENT'\n | 'PRODUCTION';\n\n/**\n * Convert environment string to Environment enum value.\n * Handles the mapping safely for both ESM and CJS environments.\n */\nfunction getEnvironmentValue(env: ParaEnvironment): Environment {\n // Handle aliases\n const normalizedEnv =\n env === 'DEVELOPMENT' ? 'BETA' : env === 'PRODUCTION' ? 'PROD' : env;\n\n // Try accessing the enum - Environment may be undefined in some test environments\n if (Environment && typeof Environment === 'object') {\n const value = Environment[normalizedEnv as keyof typeof Environment];\n if (value !== undefined) return value;\n }\n\n // Fallback: return the string directly (Para SDK may accept string values)\n return normalizedEnv as unknown as Environment;\n}\n\nexport interface ParaSignerProviderProps {\n children: ReactNode;\n /** Para API key */\n apiKey: string;\n /** Para environment (BETA, PROD, SANDBOX, DEV, DEVELOPMENT, PRODUCTION) */\n environment: ParaEnvironment;\n /** App name displayed in Para modal */\n appName?: string;\n /** Whether to show the signing modal for transaction confirmation */\n showSigningModal?: boolean;\n /** Custom sign confirmation step callback */\n customSignConfirmStep?: CustomSignConfirmStep;\n /**\n * Optional custom QueryClient instance for React Query.\n * If not provided, a default instance is used internally.\n */\n queryClient?: QueryClient;\n /**\n * Advanced: Additional config to pass to ParaProvider.\n * Use this for customizing OAuth methods, external wallets, etc.\n */\n paraProviderConfig?: Partial<\n Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>\n >;\n /** Optional custom account components to include in the account (e.g. from a compiled .masp package) */\n customComponents?: SignerAccountConfig['customComponents'];\n}\n\n/**\n * Para-specific extras exposed via useParaSigner hook.\n */\nexport interface ParaSignerExtras {\n /** Para client instance */\n para: ParaWeb;\n /** Connected wallet (null if not connected) */\n wallet: Wallet | null;\n}\n\nconst ParaSignerExtrasContext = createContext<ParaSignerExtras | null>(null);\n\n/**\n * ParaSignerProvider wraps MidenProvider to enable Para wallet signing.\n * Includes ParaProvider internally, so you don't need to wrap with it separately.\n *\n * @example\n * ```tsx\n * <ParaSignerProvider apiKey=\"your-api-key\" environment=\"BETA\" appName=\"My App\">\n * <MidenProvider config={{ rpcUrl: \"testnet\" }}>\n * <App />\n * </MidenProvider>\n * </ParaSignerProvider>\n * ```\n */\nexport function ParaSignerProvider({\n children,\n apiKey,\n environment,\n appName = 'Miden App',\n showSigningModal = true,\n customSignConfirmStep,\n queryClient,\n paraProviderConfig,\n customComponents,\n}: ParaSignerProviderProps) {\n return (\n <QueryClientProvider client={queryClient ?? defaultQueryClient}>\n <ParaProvider\n paraClientConfig={{\n env: getEnvironmentValue(environment),\n apiKey,\n }}\n config={{ appName }}\n {...paraProviderConfig}\n >\n <ParaSignerProviderInner\n showSigningModal={showSigningModal}\n customSignConfirmStep={customSignConfirmStep}\n customComponents={customComponents}\n >\n {children}\n </ParaSignerProviderInner>\n </ParaProvider>\n </QueryClientProvider>\n );\n}\n\n/**\n * Inner component that has access to ParaProvider context (useModal, etc.)\n */\nfunction ParaSignerProviderInner({\n children,\n showSigningModal = true,\n customSignConfirmStep,\n customComponents,\n}: Pick<\n ParaSignerProviderProps,\n 'children' | 'showSigningModal' | 'customSignConfirmStep' | 'customComponents'\n>) {\n // Access Para modal from ParaProvider.\n // Store in refs to avoid re-render loops (these hooks return new objects each render).\n const { openModal } = useModal();\n const { logoutAsync } = useLogout();\n const openModalRef = useRef(openModal);\n const logoutAsyncRef = useRef(logoutAsync);\n useEffect(() => {\n openModalRef.current = openModal;\n }, [openModal]);\n useEffect(() => {\n logoutAsyncRef.current = logoutAsync;\n }, [logoutAsync]);\n\n // Get the Para client from ParaProvider context (avoids creating a duplicate instance).\n // Store in a ref so downstream effects don't re-fire when the hook returns a new wrapper.\n const para = useClient()!;\n const paraRef = useRef(para);\n useEffect(() => {\n paraRef.current = para;\n }, [para]);\n\n // Keep props in refs so buildContext doesn't re-run when parent re-renders with new closures.\n const showSigningModalRef = useRef(showSigningModal);\n const customSignConfirmStepRef = useRef(customSignConfirmStep);\n useEffect(() => {\n showSigningModalRef.current = showSigningModal;\n }, [showSigningModal]);\n useEffect(() => {\n customSignConfirmStepRef.current = customSignConfirmStep;\n }, [customSignConfirmStep]);\n\n const [wallet, setWallet] = useState<Wallet | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n // Check connection status on mount and periodically\n useEffect(() => {\n let cancelled = false;\n\n async function checkConnection() {\n try {\n const isLoggedIn = await paraRef.current.isFullyLoggedIn();\n if (!isLoggedIn || cancelled) {\n setIsConnected(false);\n setWallet(null);\n return;\n }\n\n const wallets = Object.values(await paraRef.current.getWallets());\n const evmWallets = wallets.filter((w) => w.type === 'EVM');\n\n if (evmWallets.length > 0 && !cancelled) {\n setWallet((prev) =>\n prev?.id === evmWallets[0].id ? prev : evmWallets[0]\n );\n setIsConnected(true);\n } else if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n } catch {\n if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n }\n }\n\n checkConnection();\n const interval = setInterval(checkConnection, 2000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, []);\n\n // Connect opens the Para modal\n const connect = useCallback(async () => {\n openModalRef.current();\n }, []);\n\n // Disconnect logs out from Para\n const disconnect = useCallback(async () => {\n await logoutAsyncRef.current();\n await paraRef.current.logout();\n setIsConnected(false);\n setWallet(null);\n }, []);\n\n // Build signer context (includes connect/disconnect for unified useSigner hook).\n // Only depends on isConnected and wallet — everything else is accessed via refs\n // so that MidenProvider doesn't see a new context object on every poll cycle.\n //\n // IMPORTANT: initialise with a disconnected placeholder (isConnected:false) rather\n // than null. When signerContext is null MidenProvider creates a local-keystore\n // client whose auto-sync accesses the WASM module; our buildContext also touches\n // WASM (evmPkToCommitment / AccountStorageMode) → concurrent WASM access → crash.\n // A {isConnected:false} context makes MidenProvider's init effect return early\n // without creating any client, keeping the WASM module free for buildContext.\n const disconnectedCtx = useRef<SignerContextValue>({\n signCb: async () => {\n throw new Error('Para wallet not connected');\n },\n accountConfig: null as any,\n storeName: '',\n name: 'Para',\n isConnected: false,\n connect,\n disconnect,\n });\n const [signerContext, setSignerContext] = useState<SignerContextValue>(\n disconnectedCtx.current\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function buildContext() {\n if (!isConnected || !wallet) {\n setSignerContext(disconnectedCtx.current);\n return;\n }\n\n try {\n // Connected - build full context with signing capability\n const p = paraRef.current;\n const publicKey = await getUncompressedPublicKeyFromWallet(p, wallet);\n if (!publicKey) throw new Error('Failed to get public key from wallet');\n const commitment = await evmPkToCommitment(publicKey);\n\n // Serialize the commitment Word to Uint8Array for SignerAccountConfig\n const commitmentBytes = commitment.serialize();\n\n const signCallback = createSignCb(\n p,\n wallet,\n showSigningModalRef.current,\n customSignConfirmStepRef.current\n );\n\n if (!cancelled) {\n const { AccountStorageMode } = await import('@miden-sdk/miden-sdk');\n\n setSignerContext({\n signCb: signCallback,\n accountConfig: {\n publicKeyCommitment: commitmentBytes,\n accountType: 'RegularAccountImmutableCode',\n storageMode: AccountStorageMode.public(),\n ...(customComponents?.length ? { customComponents } : {}),\n },\n storeName: `para_${wallet.id}`,\n name: 'Para',\n isConnected: true,\n connect,\n disconnect,\n });\n }\n } catch (error) {\n console.error('Failed to build Para signer context:', error);\n if (!cancelled) {\n setSignerContext(disconnectedCtx.current);\n }\n }\n }\n\n buildContext();\n return () => {\n cancelled = true;\n };\n }, [isConnected, wallet, connect, disconnect]);\n\n return (\n <ParaSignerExtrasContext.Provider value={{ para, wallet }}>\n <SignerContext.Provider value={signerContext}>\n {children}\n </SignerContext.Provider>\n </ParaSignerExtrasContext.Provider>\n );\n}\n\n/**\n * Hook for Para-specific extras beyond the unified useSigner interface.\n * Use this to access the Para client or wallet details directly.\n *\n * @example\n * ```tsx\n * const { para, wallet, isConnected } = useParaSigner();\n * ```\n */\nexport function useParaSigner(): ParaSignerExtras & { isConnected: boolean } {\n const extras = useContext(ParaSignerExtrasContext);\n const signer = useContext(SignerContext);\n if (!extras) {\n throw new Error('useParaSigner must be used within ParaSignerProvider');\n }\n return { ...extras, isConnected: signer?.isConnected ?? false };\n}\n"],"mappings":"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","names":["import_react","import_react_sdk_lite","import_miden_para","createSignCb"]}
|
package/dist/index.mjs
CHANGED
|
@@ -83,9 +83,16 @@ import {
|
|
|
83
83
|
useLogout
|
|
84
84
|
} from "@getpara/react-sdk-lite";
|
|
85
85
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
86
|
-
import {
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
import {
|
|
87
|
+
SignerContext
|
|
88
|
+
} from "@miden-sdk/react";
|
|
89
|
+
import {
|
|
90
|
+
signCb as createSignCb
|
|
91
|
+
} from "@miden-sdk/miden-para";
|
|
92
|
+
import {
|
|
93
|
+
evmPkToCommitment,
|
|
94
|
+
getUncompressedPublicKeyFromWallet
|
|
95
|
+
} from "@miden-sdk/miden-para";
|
|
89
96
|
import { useModal as useModal2, useLogout as useLogout2 } from "@getpara/react-sdk-lite";
|
|
90
97
|
import { jsx } from "react/jsx-runtime";
|
|
91
98
|
var defaultQueryClient = new QueryClient();
|
|
@@ -106,7 +113,8 @@ function ParaSignerProvider({
|
|
|
106
113
|
showSigningModal = true,
|
|
107
114
|
customSignConfirmStep,
|
|
108
115
|
queryClient,
|
|
109
|
-
paraProviderConfig
|
|
116
|
+
paraProviderConfig,
|
|
117
|
+
customComponents
|
|
110
118
|
}) {
|
|
111
119
|
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient != null ? queryClient : defaultQueryClient, children: /* @__PURE__ */ jsx(
|
|
112
120
|
ParaProvider,
|
|
@@ -122,6 +130,7 @@ function ParaSignerProvider({
|
|
|
122
130
|
{
|
|
123
131
|
showSigningModal,
|
|
124
132
|
customSignConfirmStep,
|
|
133
|
+
customComponents,
|
|
125
134
|
children
|
|
126
135
|
}
|
|
127
136
|
)
|
|
@@ -131,7 +140,8 @@ function ParaSignerProvider({
|
|
|
131
140
|
function ParaSignerProviderInner({
|
|
132
141
|
children,
|
|
133
142
|
showSigningModal = true,
|
|
134
|
-
customSignConfirmStep
|
|
143
|
+
customSignConfirmStep,
|
|
144
|
+
customComponents
|
|
135
145
|
}) {
|
|
136
146
|
const { openModal } = useModal();
|
|
137
147
|
const { logoutAsync } = useLogout();
|
|
@@ -171,7 +181,9 @@ function ParaSignerProviderInner({
|
|
|
171
181
|
const wallets = Object.values(await paraRef.current.getWallets());
|
|
172
182
|
const evmWallets = wallets.filter((w) => w.type === "EVM");
|
|
173
183
|
if (evmWallets.length > 0 && !cancelled) {
|
|
174
|
-
setWallet(
|
|
184
|
+
setWallet(
|
|
185
|
+
(prev) => (prev == null ? void 0 : prev.id) === evmWallets[0].id ? prev : evmWallets[0]
|
|
186
|
+
);
|
|
175
187
|
setIsConnected(true);
|
|
176
188
|
} else if (!cancelled) {
|
|
177
189
|
setIsConnected(false);
|
|
@@ -240,7 +252,8 @@ function ParaSignerProviderInner({
|
|
|
240
252
|
accountConfig: {
|
|
241
253
|
publicKeyCommitment: commitmentBytes,
|
|
242
254
|
accountType: "RegularAccountImmutableCode",
|
|
243
|
-
storageMode: AccountStorageMode.public()
|
|
255
|
+
storageMode: AccountStorageMode.public(),
|
|
256
|
+
...(customComponents == null ? void 0 : customComponents.length) ? { customComponents } : {}
|
|
244
257
|
},
|
|
245
258
|
storeName: `para_${wallet.id}`,
|
|
246
259
|
name: "Para",
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useParaMiden.ts","../src/ParaSignerProvider.tsx"],"sourcesContent":["'use client';\n\nimport { useClient, useAccount, type Wallet } from '@getpara/react-sdk-lite';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n createParaMidenClient,\n type Opts,\n type MidenAccountStorageMode,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\n\n/**\n * React hook that converts Para React SDK context into a ready-to-use Miden WebClient.\n * Spawns the client once a Para session with at least one EVM wallet is active.\n *\n * Returns:\n * - client: WebClient instance backed by the active Para session (or null while loading)\n * - accountId: Miden account id derived for the selected EVM wallet\n * - para: Para client instance from context\n * - evmWallets: filtered list of Para wallets with type === 'EVM'\n * - nodeUrl: Miden node endpoint used for the client\n * - opts: forwarded options used when creating the client\n * - showSigningModal: toggles the built-in signing modal\n * - customSignConfirmStep: optional callback for custom transaction confirmation flows\n */\nexport function useParaMiden(\n nodeUrl: string,\n storageMode: MidenAccountStorageMode = 'public',\n opts: Omit<Opts, 'endpoint' | 'type' | 'storageMode'> = {},\n showSigningModal: boolean = true,\n customSignConfirmStep?: CustomSignConfirmStep\n) {\n const para = useClient();\n const { isConnected, embedded } = useAccount();\n const clientRef = useRef<import('@miden-sdk/miden-sdk').WebClient | null>(\n null\n );\n const [accountId, setAccountId] = useState<string>('');\n\n const evmWallets = useMemo(\n () => embedded.wallets?.filter((wallet) => wallet.type === 'EVM'),\n [embedded.wallets]\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function setupClient() {\n if (\n !isConnected ||\n !para ||\n !embedded.wallets?.length ||\n clientRef.current\n ) {\n return;\n }\n\n const { AccountType } = await import('@miden-sdk/miden-sdk');\n\n const { client: midenParaClient, accountId: aId } =\n await createParaMidenClient(\n para,\n evmWallets as Wallet[],\n {\n ...opts,\n endpoint: nodeUrl,\n type: AccountType.RegularAccountImmutableCode,\n storageMode,\n },\n showSigningModal,\n customSignConfirmStep\n );\n\n if (cancelled) {\n return;\n }\n\n clientRef.current = midenParaClient;\n setAccountId(aId);\n }\n\n setupClient();\n\n return () => {\n cancelled = true;\n };\n }, [\n isConnected,\n evmWallets,\n para,\n nodeUrl,\n showSigningModal,\n customSignConfirmStep,\n ]);\n\n return {\n client: clientRef.current,\n accountId,\n para,\n evmWallets,\n nodeUrl,\n opts,\n };\n}\n","import {\n useState,\n useEffect,\n useCallback,\n useRef,\n createContext,\n useContext,\n type ReactNode,\n} from 'react';\nimport { ParaWeb, Environment, type Wallet } from '@getpara/web-sdk';\nimport {\n ParaProvider,\n useClient,\n useModal,\n useLogout,\n type ParaProviderProps,\n} from '@getpara/react-sdk-lite';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { SignerContext, type SignerContextValue } from '@miden-sdk/react';\nimport { signCb as createSignCb, type CustomSignConfirmStep } from '@miden-sdk/miden-para';\nimport { evmPkToCommitment, getUncompressedPublicKeyFromWallet } from '@miden-sdk/miden-para';\n\n// Re-export Para hooks for convenience\nexport { useModal, useLogout } from '@getpara/react-sdk-lite';\n\nconst defaultQueryClient = new QueryClient();\n\n// PARA SIGNER PROVIDER\n// ================================================================================================\n\n/** Environment string values accepted by ParaSignerProvider */\nexport type ParaEnvironment = 'BETA' | 'PROD' | 'SANDBOX' | 'DEV' | 'DEVELOPMENT' | 'PRODUCTION';\n\n/**\n * Convert environment string to Environment enum value.\n * Handles the mapping safely for both ESM and CJS environments.\n */\nfunction getEnvironmentValue(env: ParaEnvironment): Environment {\n // Handle aliases\n const normalizedEnv = env === 'DEVELOPMENT' ? 'BETA' : env === 'PRODUCTION' ? 'PROD' : env;\n\n // Try accessing the enum - Environment may be undefined in some test environments\n if (Environment && typeof Environment === 'object') {\n const value = Environment[normalizedEnv as keyof typeof Environment];\n if (value !== undefined) return value;\n }\n\n // Fallback: return the string directly (Para SDK may accept string values)\n return normalizedEnv as unknown as Environment;\n}\n\nexport interface ParaSignerProviderProps {\n children: ReactNode;\n /** Para API key */\n apiKey: string;\n /** Para environment (BETA, PROD, SANDBOX, DEV, DEVELOPMENT, PRODUCTION) */\n environment: ParaEnvironment;\n /** App name displayed in Para modal */\n appName?: string;\n /** Whether to show the signing modal for transaction confirmation */\n showSigningModal?: boolean;\n /** Custom sign confirmation step callback */\n customSignConfirmStep?: CustomSignConfirmStep;\n /**\n * Optional custom QueryClient instance for React Query.\n * If not provided, a default instance is used internally.\n */\n queryClient?: QueryClient;\n /**\n * Advanced: Additional config to pass to ParaProvider.\n * Use this for customizing OAuth methods, external wallets, etc.\n */\n paraProviderConfig?: Partial<Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>>;\n}\n\n/**\n * Para-specific extras exposed via useParaSigner hook.\n */\nexport interface ParaSignerExtras {\n /** Para client instance */\n para: ParaWeb;\n /** Connected wallet (null if not connected) */\n wallet: Wallet | null;\n}\n\nconst ParaSignerExtrasContext = createContext<ParaSignerExtras | null>(null);\n\n/**\n * ParaSignerProvider wraps MidenProvider to enable Para wallet signing.\n * Includes ParaProvider internally, so you don't need to wrap with it separately.\n *\n * @example\n * ```tsx\n * <ParaSignerProvider apiKey=\"your-api-key\" environment=\"BETA\" appName=\"My App\">\n * <MidenProvider config={{ rpcUrl: \"testnet\" }}>\n * <App />\n * </MidenProvider>\n * </ParaSignerProvider>\n * ```\n */\nexport function ParaSignerProvider({\n children,\n apiKey,\n environment,\n appName = 'Miden App',\n showSigningModal = true,\n customSignConfirmStep,\n queryClient,\n paraProviderConfig,\n}: ParaSignerProviderProps) {\n return (\n <QueryClientProvider client={queryClient ?? defaultQueryClient}>\n <ParaProvider\n paraClientConfig={{\n env: getEnvironmentValue(environment),\n apiKey,\n }}\n config={{ appName }}\n {...paraProviderConfig}\n >\n <ParaSignerProviderInner\n showSigningModal={showSigningModal}\n customSignConfirmStep={customSignConfirmStep}\n >\n {children}\n </ParaSignerProviderInner>\n </ParaProvider>\n </QueryClientProvider>\n );\n}\n\n/**\n * Inner component that has access to ParaProvider context (useModal, etc.)\n */\nfunction ParaSignerProviderInner({\n children,\n showSigningModal = true,\n customSignConfirmStep,\n}: Pick<ParaSignerProviderProps, 'children' | 'showSigningModal' | 'customSignConfirmStep'>) {\n // Access Para modal from ParaProvider.\n // Store in refs to avoid re-render loops (these hooks return new objects each render).\n const { openModal } = useModal();\n const { logoutAsync } = useLogout();\n const openModalRef = useRef(openModal);\n const logoutAsyncRef = useRef(logoutAsync);\n useEffect(() => { openModalRef.current = openModal; }, [openModal]);\n useEffect(() => { logoutAsyncRef.current = logoutAsync; }, [logoutAsync]);\n\n // Get the Para client from ParaProvider context (avoids creating a duplicate instance).\n // Store in a ref so downstream effects don't re-fire when the hook returns a new wrapper.\n const para = useClient()!;\n const paraRef = useRef(para);\n useEffect(() => { paraRef.current = para; }, [para]);\n\n // Keep props in refs so buildContext doesn't re-run when parent re-renders with new closures.\n const showSigningModalRef = useRef(showSigningModal);\n const customSignConfirmStepRef = useRef(customSignConfirmStep);\n useEffect(() => { showSigningModalRef.current = showSigningModal; }, [showSigningModal]);\n useEffect(() => { customSignConfirmStepRef.current = customSignConfirmStep; }, [customSignConfirmStep]);\n\n const [wallet, setWallet] = useState<Wallet | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n // Check connection status on mount and periodically\n useEffect(() => {\n let cancelled = false;\n\n async function checkConnection() {\n try {\n const isLoggedIn = await paraRef.current.isFullyLoggedIn();\n if (!isLoggedIn || cancelled) {\n setIsConnected(false);\n setWallet(null);\n return;\n }\n\n const wallets = Object.values(await paraRef.current.getWallets());\n const evmWallets = wallets.filter((w) => w.type === 'EVM');\n\n if (evmWallets.length > 0 && !cancelled) {\n setWallet((prev) => prev?.id === evmWallets[0].id ? prev : evmWallets[0]);\n setIsConnected(true);\n } else if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n } catch {\n if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n }\n }\n\n checkConnection();\n const interval = setInterval(checkConnection, 2000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, []);\n\n // Connect opens the Para modal\n const connect = useCallback(async () => {\n openModalRef.current();\n }, []);\n\n // Disconnect logs out from Para\n const disconnect = useCallback(async () => {\n await logoutAsyncRef.current();\n await paraRef.current.logout();\n setIsConnected(false);\n setWallet(null);\n }, []);\n\n // Build signer context (includes connect/disconnect for unified useSigner hook).\n // Only depends on isConnected and wallet — everything else is accessed via refs\n // so that MidenProvider doesn't see a new context object on every poll cycle.\n //\n // IMPORTANT: initialise with a disconnected placeholder (isConnected:false) rather\n // than null. When signerContext is null MidenProvider creates a local-keystore\n // client whose auto-sync accesses the WASM module; our buildContext also touches\n // WASM (evmPkToCommitment / AccountStorageMode) → concurrent WASM access → crash.\n // A {isConnected:false} context makes MidenProvider's init effect return early\n // without creating any client, keeping the WASM module free for buildContext.\n const disconnectedCtx = useRef<SignerContextValue>({\n signCb: async () => { throw new Error('Para wallet not connected'); },\n accountConfig: null as any,\n storeName: '',\n name: 'Para',\n isConnected: false,\n connect,\n disconnect,\n });\n const [signerContext, setSignerContext] = useState<SignerContextValue>(\n disconnectedCtx.current\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function buildContext() {\n if (!isConnected || !wallet) {\n setSignerContext(disconnectedCtx.current);\n return;\n }\n\n try {\n // Connected - build full context with signing capability\n const p = paraRef.current;\n const publicKey = await getUncompressedPublicKeyFromWallet(p, wallet);\n if (!publicKey) throw new Error('Failed to get public key from wallet');\n const commitment = await evmPkToCommitment(publicKey);\n\n // Serialize the commitment Word to Uint8Array for SignerAccountConfig\n const commitmentBytes = commitment.serialize();\n\n const signCallback = createSignCb(\n p,\n wallet,\n showSigningModalRef.current,\n customSignConfirmStepRef.current\n );\n\n if (!cancelled) {\n const { AccountStorageMode } = await import(\n '@miden-sdk/miden-sdk'\n );\n\n setSignerContext({\n signCb: signCallback,\n accountConfig: {\n publicKeyCommitment: commitmentBytes,\n accountType: 'RegularAccountImmutableCode',\n storageMode: AccountStorageMode.public(),\n },\n storeName: `para_${wallet.id}`,\n name: 'Para',\n isConnected: true,\n connect,\n disconnect,\n });\n }\n } catch (error) {\n console.error('Failed to build Para signer context:', error);\n if (!cancelled) {\n setSignerContext(disconnectedCtx.current);\n }\n }\n }\n\n buildContext();\n return () => {\n cancelled = true;\n };\n }, [isConnected, wallet, connect, disconnect]);\n\n return (\n <ParaSignerExtrasContext.Provider value={{ para, wallet }}>\n <SignerContext.Provider value={signerContext}>\n {children}\n </SignerContext.Provider>\n </ParaSignerExtrasContext.Provider>\n );\n}\n\n/**\n * Hook for Para-specific extras beyond the unified useSigner interface.\n * Use this to access the Para client or wallet details directly.\n *\n * @example\n * ```tsx\n * const { para, wallet, isConnected } = useParaSigner();\n * ```\n */\nexport function useParaSigner(): ParaSignerExtras & { isConnected: boolean } {\n const extras = useContext(ParaSignerExtrasContext);\n const signer = useContext(SignerContext);\n if (!extras) {\n throw new Error('useParaSigner must be used within ParaSignerProvider');\n }\n return { ...extras, isConnected: signer?.isConnected ?? false };\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","useClient","useModal","useLogout"]}
|
|
1
|
+
{"version":3,"sources":["../src/useParaMiden.ts","../src/ParaSignerProvider.tsx"],"sourcesContent":["'use client';\n\nimport { useClient, useAccount, type Wallet } from '@getpara/react-sdk-lite';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n createParaMidenClient,\n type Opts,\n type MidenAccountStorageMode,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\n\n/**\n * React hook that converts Para React SDK context into a ready-to-use Miden WebClient.\n * Spawns the client once a Para session with at least one EVM wallet is active.\n *\n * Returns:\n * - client: WebClient instance backed by the active Para session (or null while loading)\n * - accountId: Miden account id derived for the selected EVM wallet\n * - para: Para client instance from context\n * - evmWallets: filtered list of Para wallets with type === 'EVM'\n * - nodeUrl: Miden node endpoint used for the client\n * - opts: forwarded options used when creating the client\n * - showSigningModal: toggles the built-in signing modal\n * - customSignConfirmStep: optional callback for custom transaction confirmation flows\n */\nexport function useParaMiden(\n nodeUrl: string,\n storageMode: MidenAccountStorageMode = 'public',\n opts: Omit<Opts, 'endpoint' | 'type' | 'storageMode'> = {},\n showSigningModal: boolean = true,\n customSignConfirmStep?: CustomSignConfirmStep\n) {\n const para = useClient();\n const { isConnected, embedded } = useAccount();\n const clientRef = useRef<import('@miden-sdk/miden-sdk').WebClient | null>(\n null\n );\n const [accountId, setAccountId] = useState<string>('');\n\n const evmWallets = useMemo(\n () => embedded.wallets?.filter((wallet) => wallet.type === 'EVM'),\n [embedded.wallets]\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function setupClient() {\n if (\n !isConnected ||\n !para ||\n !embedded.wallets?.length ||\n clientRef.current\n ) {\n return;\n }\n\n const { AccountType } = await import('@miden-sdk/miden-sdk');\n\n const { client: midenParaClient, accountId: aId } =\n await createParaMidenClient(\n para,\n evmWallets as Wallet[],\n {\n ...opts,\n endpoint: nodeUrl,\n type: AccountType.RegularAccountImmutableCode,\n storageMode,\n },\n showSigningModal,\n customSignConfirmStep\n );\n\n if (cancelled) {\n return;\n }\n\n clientRef.current = midenParaClient;\n setAccountId(aId);\n }\n\n setupClient();\n\n return () => {\n cancelled = true;\n };\n }, [\n isConnected,\n evmWallets,\n para,\n nodeUrl,\n showSigningModal,\n customSignConfirmStep,\n ]);\n\n return {\n client: clientRef.current,\n accountId,\n para,\n evmWallets,\n nodeUrl,\n opts,\n };\n}\n","import {\n useState,\n useEffect,\n useCallback,\n useRef,\n createContext,\n useContext,\n type ReactNode,\n} from 'react';\nimport { ParaWeb, Environment, type Wallet } from '@getpara/web-sdk';\nimport {\n ParaProvider,\n useClient,\n useModal,\n useLogout,\n type ParaProviderProps,\n} from '@getpara/react-sdk-lite';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport {\n SignerContext,\n type SignerContextValue,\n type SignerAccountConfig,\n} from '@miden-sdk/react';\nimport {\n signCb as createSignCb,\n type CustomSignConfirmStep,\n} from '@miden-sdk/miden-para';\nimport {\n evmPkToCommitment,\n getUncompressedPublicKeyFromWallet,\n} from '@miden-sdk/miden-para';\n\n// Re-export Para hooks for convenience\nexport { useModal, useLogout } from '@getpara/react-sdk-lite';\n\nconst defaultQueryClient = new QueryClient();\n\n// PARA SIGNER PROVIDER\n// ================================================================================================\n\n/** Environment string values accepted by ParaSignerProvider */\nexport type ParaEnvironment =\n | 'BETA'\n | 'PROD'\n | 'SANDBOX'\n | 'DEV'\n | 'DEVELOPMENT'\n | 'PRODUCTION';\n\n/**\n * Convert environment string to Environment enum value.\n * Handles the mapping safely for both ESM and CJS environments.\n */\nfunction getEnvironmentValue(env: ParaEnvironment): Environment {\n // Handle aliases\n const normalizedEnv =\n env === 'DEVELOPMENT' ? 'BETA' : env === 'PRODUCTION' ? 'PROD' : env;\n\n // Try accessing the enum - Environment may be undefined in some test environments\n if (Environment && typeof Environment === 'object') {\n const value = Environment[normalizedEnv as keyof typeof Environment];\n if (value !== undefined) return value;\n }\n\n // Fallback: return the string directly (Para SDK may accept string values)\n return normalizedEnv as unknown as Environment;\n}\n\nexport interface ParaSignerProviderProps {\n children: ReactNode;\n /** Para API key */\n apiKey: string;\n /** Para environment (BETA, PROD, SANDBOX, DEV, DEVELOPMENT, PRODUCTION) */\n environment: ParaEnvironment;\n /** App name displayed in Para modal */\n appName?: string;\n /** Whether to show the signing modal for transaction confirmation */\n showSigningModal?: boolean;\n /** Custom sign confirmation step callback */\n customSignConfirmStep?: CustomSignConfirmStep;\n /**\n * Optional custom QueryClient instance for React Query.\n * If not provided, a default instance is used internally.\n */\n queryClient?: QueryClient;\n /**\n * Advanced: Additional config to pass to ParaProvider.\n * Use this for customizing OAuth methods, external wallets, etc.\n */\n paraProviderConfig?: Partial<\n Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>\n >;\n /** Optional custom account components to include in the account (e.g. from a compiled .masp package) */\n customComponents?: SignerAccountConfig['customComponents'];\n}\n\n/**\n * Para-specific extras exposed via useParaSigner hook.\n */\nexport interface ParaSignerExtras {\n /** Para client instance */\n para: ParaWeb;\n /** Connected wallet (null if not connected) */\n wallet: Wallet | null;\n}\n\nconst ParaSignerExtrasContext = createContext<ParaSignerExtras | null>(null);\n\n/**\n * ParaSignerProvider wraps MidenProvider to enable Para wallet signing.\n * Includes ParaProvider internally, so you don't need to wrap with it separately.\n *\n * @example\n * ```tsx\n * <ParaSignerProvider apiKey=\"your-api-key\" environment=\"BETA\" appName=\"My App\">\n * <MidenProvider config={{ rpcUrl: \"testnet\" }}>\n * <App />\n * </MidenProvider>\n * </ParaSignerProvider>\n * ```\n */\nexport function ParaSignerProvider({\n children,\n apiKey,\n environment,\n appName = 'Miden App',\n showSigningModal = true,\n customSignConfirmStep,\n queryClient,\n paraProviderConfig,\n customComponents,\n}: ParaSignerProviderProps) {\n return (\n <QueryClientProvider client={queryClient ?? defaultQueryClient}>\n <ParaProvider\n paraClientConfig={{\n env: getEnvironmentValue(environment),\n apiKey,\n }}\n config={{ appName }}\n {...paraProviderConfig}\n >\n <ParaSignerProviderInner\n showSigningModal={showSigningModal}\n customSignConfirmStep={customSignConfirmStep}\n customComponents={customComponents}\n >\n {children}\n </ParaSignerProviderInner>\n </ParaProvider>\n </QueryClientProvider>\n );\n}\n\n/**\n * Inner component that has access to ParaProvider context (useModal, etc.)\n */\nfunction ParaSignerProviderInner({\n children,\n showSigningModal = true,\n customSignConfirmStep,\n customComponents,\n}: Pick<\n ParaSignerProviderProps,\n 'children' | 'showSigningModal' | 'customSignConfirmStep' | 'customComponents'\n>) {\n // Access Para modal from ParaProvider.\n // Store in refs to avoid re-render loops (these hooks return new objects each render).\n const { openModal } = useModal();\n const { logoutAsync } = useLogout();\n const openModalRef = useRef(openModal);\n const logoutAsyncRef = useRef(logoutAsync);\n useEffect(() => {\n openModalRef.current = openModal;\n }, [openModal]);\n useEffect(() => {\n logoutAsyncRef.current = logoutAsync;\n }, [logoutAsync]);\n\n // Get the Para client from ParaProvider context (avoids creating a duplicate instance).\n // Store in a ref so downstream effects don't re-fire when the hook returns a new wrapper.\n const para = useClient()!;\n const paraRef = useRef(para);\n useEffect(() => {\n paraRef.current = para;\n }, [para]);\n\n // Keep props in refs so buildContext doesn't re-run when parent re-renders with new closures.\n const showSigningModalRef = useRef(showSigningModal);\n const customSignConfirmStepRef = useRef(customSignConfirmStep);\n useEffect(() => {\n showSigningModalRef.current = showSigningModal;\n }, [showSigningModal]);\n useEffect(() => {\n customSignConfirmStepRef.current = customSignConfirmStep;\n }, [customSignConfirmStep]);\n\n const [wallet, setWallet] = useState<Wallet | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n // Check connection status on mount and periodically\n useEffect(() => {\n let cancelled = false;\n\n async function checkConnection() {\n try {\n const isLoggedIn = await paraRef.current.isFullyLoggedIn();\n if (!isLoggedIn || cancelled) {\n setIsConnected(false);\n setWallet(null);\n return;\n }\n\n const wallets = Object.values(await paraRef.current.getWallets());\n const evmWallets = wallets.filter((w) => w.type === 'EVM');\n\n if (evmWallets.length > 0 && !cancelled) {\n setWallet((prev) =>\n prev?.id === evmWallets[0].id ? prev : evmWallets[0]\n );\n setIsConnected(true);\n } else if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n } catch {\n if (!cancelled) {\n setIsConnected(false);\n setWallet(null);\n }\n }\n }\n\n checkConnection();\n const interval = setInterval(checkConnection, 2000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, []);\n\n // Connect opens the Para modal\n const connect = useCallback(async () => {\n openModalRef.current();\n }, []);\n\n // Disconnect logs out from Para\n const disconnect = useCallback(async () => {\n await logoutAsyncRef.current();\n await paraRef.current.logout();\n setIsConnected(false);\n setWallet(null);\n }, []);\n\n // Build signer context (includes connect/disconnect for unified useSigner hook).\n // Only depends on isConnected and wallet — everything else is accessed via refs\n // so that MidenProvider doesn't see a new context object on every poll cycle.\n //\n // IMPORTANT: initialise with a disconnected placeholder (isConnected:false) rather\n // than null. When signerContext is null MidenProvider creates a local-keystore\n // client whose auto-sync accesses the WASM module; our buildContext also touches\n // WASM (evmPkToCommitment / AccountStorageMode) → concurrent WASM access → crash.\n // A {isConnected:false} context makes MidenProvider's init effect return early\n // without creating any client, keeping the WASM module free for buildContext.\n const disconnectedCtx = useRef<SignerContextValue>({\n signCb: async () => {\n throw new Error('Para wallet not connected');\n },\n accountConfig: null as any,\n storeName: '',\n name: 'Para',\n isConnected: false,\n connect,\n disconnect,\n });\n const [signerContext, setSignerContext] = useState<SignerContextValue>(\n disconnectedCtx.current\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function buildContext() {\n if (!isConnected || !wallet) {\n setSignerContext(disconnectedCtx.current);\n return;\n }\n\n try {\n // Connected - build full context with signing capability\n const p = paraRef.current;\n const publicKey = await getUncompressedPublicKeyFromWallet(p, wallet);\n if (!publicKey) throw new Error('Failed to get public key from wallet');\n const commitment = await evmPkToCommitment(publicKey);\n\n // Serialize the commitment Word to Uint8Array for SignerAccountConfig\n const commitmentBytes = commitment.serialize();\n\n const signCallback = createSignCb(\n p,\n wallet,\n showSigningModalRef.current,\n customSignConfirmStepRef.current\n );\n\n if (!cancelled) {\n const { AccountStorageMode } = await import('@miden-sdk/miden-sdk');\n\n setSignerContext({\n signCb: signCallback,\n accountConfig: {\n publicKeyCommitment: commitmentBytes,\n accountType: 'RegularAccountImmutableCode',\n storageMode: AccountStorageMode.public(),\n ...(customComponents?.length ? { customComponents } : {}),\n },\n storeName: `para_${wallet.id}`,\n name: 'Para',\n isConnected: true,\n connect,\n disconnect,\n });\n }\n } catch (error) {\n console.error('Failed to build Para signer context:', error);\n if (!cancelled) {\n setSignerContext(disconnectedCtx.current);\n }\n }\n }\n\n buildContext();\n return () => {\n cancelled = true;\n };\n }, [isConnected, wallet, connect, disconnect]);\n\n return (\n <ParaSignerExtrasContext.Provider value={{ para, wallet }}>\n <SignerContext.Provider value={signerContext}>\n {children}\n </SignerContext.Provider>\n </ParaSignerExtrasContext.Provider>\n );\n}\n\n/**\n * Hook for Para-specific extras beyond the unified useSigner interface.\n * Use this to access the Para client or wallet details directly.\n *\n * @example\n * ```tsx\n * const { para, wallet, isConnected } = useParaSigner();\n * ```\n */\nexport function useParaSigner(): ParaSignerExtras & { isConnected: boolean } {\n const extras = useContext(ParaSignerExtrasContext);\n const signer = useContext(SignerContext);\n if (!extras) {\n throw new Error('useParaSigner must be used within ParaSignerProvider');\n }\n return { ...extras, isConnected: signer?.isConnected ?? false };\n}\n"],"mappings":"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","names":["useState","useEffect","useRef","useClient","useModal","useLogout"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miden-sdk/use-miden-para-react",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"description": "React hook that wires Para accounts into a Miden client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Miden Labs",
|
|
@@ -36,19 +36,19 @@
|
|
|
36
36
|
"publish": "npm run build && npm publish --access public"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@
|
|
40
|
-
"@getpara/
|
|
41
|
-
"@
|
|
42
|
-
"@miden-sdk/miden-
|
|
43
|
-
"@miden-sdk/react": "^0.13.
|
|
39
|
+
"@getpara/react-sdk-lite": "^2.11.0",
|
|
40
|
+
"@getpara/web-sdk": "^2.11.0",
|
|
41
|
+
"@miden-sdk/miden-para": "^0.13.2",
|
|
42
|
+
"@miden-sdk/miden-sdk": "^0.13.1",
|
|
43
|
+
"@miden-sdk/react": "^0.13.3",
|
|
44
44
|
"@tanstack/react-query": "^5.0.0",
|
|
45
45
|
"react": "^18.0.0 || ^19.0.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"@getpara/
|
|
50
|
-
"@
|
|
51
|
-
"@miden-sdk/react": "^0.13.
|
|
48
|
+
"@getpara/react-sdk-lite": "^2.11.0",
|
|
49
|
+
"@getpara/web-sdk": "^2.11.0",
|
|
50
|
+
"@miden-sdk/miden-sdk": "^0.13.1",
|
|
51
|
+
"@miden-sdk/react": "^0.13.3",
|
|
52
52
|
"@tanstack/react-query": "^5.90.12",
|
|
53
53
|
"@types/react": "^19.2.5",
|
|
54
54
|
"tsup": "^8.3.0",
|
|
@@ -16,9 +16,19 @@ import {
|
|
|
16
16
|
type ParaProviderProps,
|
|
17
17
|
} from '@getpara/react-sdk-lite';
|
|
18
18
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
import {
|
|
20
|
+
SignerContext,
|
|
21
|
+
type SignerContextValue,
|
|
22
|
+
type SignerAccountConfig,
|
|
23
|
+
} from '@miden-sdk/react';
|
|
24
|
+
import {
|
|
25
|
+
signCb as createSignCb,
|
|
26
|
+
type CustomSignConfirmStep,
|
|
27
|
+
} from '@miden-sdk/miden-para';
|
|
28
|
+
import {
|
|
29
|
+
evmPkToCommitment,
|
|
30
|
+
getUncompressedPublicKeyFromWallet,
|
|
31
|
+
} from '@miden-sdk/miden-para';
|
|
22
32
|
|
|
23
33
|
// Re-export Para hooks for convenience
|
|
24
34
|
export { useModal, useLogout } from '@getpara/react-sdk-lite';
|
|
@@ -29,7 +39,13 @@ const defaultQueryClient = new QueryClient();
|
|
|
29
39
|
// ================================================================================================
|
|
30
40
|
|
|
31
41
|
/** Environment string values accepted by ParaSignerProvider */
|
|
32
|
-
export type ParaEnvironment =
|
|
42
|
+
export type ParaEnvironment =
|
|
43
|
+
| 'BETA'
|
|
44
|
+
| 'PROD'
|
|
45
|
+
| 'SANDBOX'
|
|
46
|
+
| 'DEV'
|
|
47
|
+
| 'DEVELOPMENT'
|
|
48
|
+
| 'PRODUCTION';
|
|
33
49
|
|
|
34
50
|
/**
|
|
35
51
|
* Convert environment string to Environment enum value.
|
|
@@ -37,7 +53,8 @@ export type ParaEnvironment = 'BETA' | 'PROD' | 'SANDBOX' | 'DEV' | 'DEVELOPMENT
|
|
|
37
53
|
*/
|
|
38
54
|
function getEnvironmentValue(env: ParaEnvironment): Environment {
|
|
39
55
|
// Handle aliases
|
|
40
|
-
const normalizedEnv =
|
|
56
|
+
const normalizedEnv =
|
|
57
|
+
env === 'DEVELOPMENT' ? 'BETA' : env === 'PRODUCTION' ? 'PROD' : env;
|
|
41
58
|
|
|
42
59
|
// Try accessing the enum - Environment may be undefined in some test environments
|
|
43
60
|
if (Environment && typeof Environment === 'object') {
|
|
@@ -70,7 +87,11 @@ export interface ParaSignerProviderProps {
|
|
|
70
87
|
* Advanced: Additional config to pass to ParaProvider.
|
|
71
88
|
* Use this for customizing OAuth methods, external wallets, etc.
|
|
72
89
|
*/
|
|
73
|
-
paraProviderConfig?: Partial<
|
|
90
|
+
paraProviderConfig?: Partial<
|
|
91
|
+
Omit<ParaProviderProps<any, any>, 'children' | 'paraClientConfig'>
|
|
92
|
+
>;
|
|
93
|
+
/** Optional custom account components to include in the account (e.g. from a compiled .masp package) */
|
|
94
|
+
customComponents?: SignerAccountConfig['customComponents'];
|
|
74
95
|
}
|
|
75
96
|
|
|
76
97
|
/**
|
|
@@ -107,6 +128,7 @@ export function ParaSignerProvider({
|
|
|
107
128
|
customSignConfirmStep,
|
|
108
129
|
queryClient,
|
|
109
130
|
paraProviderConfig,
|
|
131
|
+
customComponents,
|
|
110
132
|
}: ParaSignerProviderProps) {
|
|
111
133
|
return (
|
|
112
134
|
<QueryClientProvider client={queryClient ?? defaultQueryClient}>
|
|
@@ -121,6 +143,7 @@ export function ParaSignerProvider({
|
|
|
121
143
|
<ParaSignerProviderInner
|
|
122
144
|
showSigningModal={showSigningModal}
|
|
123
145
|
customSignConfirmStep={customSignConfirmStep}
|
|
146
|
+
customComponents={customComponents}
|
|
124
147
|
>
|
|
125
148
|
{children}
|
|
126
149
|
</ParaSignerProviderInner>
|
|
@@ -136,27 +159,41 @@ function ParaSignerProviderInner({
|
|
|
136
159
|
children,
|
|
137
160
|
showSigningModal = true,
|
|
138
161
|
customSignConfirmStep,
|
|
139
|
-
|
|
162
|
+
customComponents,
|
|
163
|
+
}: Pick<
|
|
164
|
+
ParaSignerProviderProps,
|
|
165
|
+
'children' | 'showSigningModal' | 'customSignConfirmStep' | 'customComponents'
|
|
166
|
+
>) {
|
|
140
167
|
// Access Para modal from ParaProvider.
|
|
141
168
|
// Store in refs to avoid re-render loops (these hooks return new objects each render).
|
|
142
169
|
const { openModal } = useModal();
|
|
143
170
|
const { logoutAsync } = useLogout();
|
|
144
171
|
const openModalRef = useRef(openModal);
|
|
145
172
|
const logoutAsyncRef = useRef(logoutAsync);
|
|
146
|
-
useEffect(() => {
|
|
147
|
-
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
openModalRef.current = openModal;
|
|
175
|
+
}, [openModal]);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
logoutAsyncRef.current = logoutAsync;
|
|
178
|
+
}, [logoutAsync]);
|
|
148
179
|
|
|
149
180
|
// Get the Para client from ParaProvider context (avoids creating a duplicate instance).
|
|
150
181
|
// Store in a ref so downstream effects don't re-fire when the hook returns a new wrapper.
|
|
151
182
|
const para = useClient()!;
|
|
152
183
|
const paraRef = useRef(para);
|
|
153
|
-
useEffect(() => {
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
paraRef.current = para;
|
|
186
|
+
}, [para]);
|
|
154
187
|
|
|
155
188
|
// Keep props in refs so buildContext doesn't re-run when parent re-renders with new closures.
|
|
156
189
|
const showSigningModalRef = useRef(showSigningModal);
|
|
157
190
|
const customSignConfirmStepRef = useRef(customSignConfirmStep);
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
showSigningModalRef.current = showSigningModal;
|
|
193
|
+
}, [showSigningModal]);
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
customSignConfirmStepRef.current = customSignConfirmStep;
|
|
196
|
+
}, [customSignConfirmStep]);
|
|
160
197
|
|
|
161
198
|
const [wallet, setWallet] = useState<Wallet | null>(null);
|
|
162
199
|
const [isConnected, setIsConnected] = useState(false);
|
|
@@ -178,7 +215,9 @@ function ParaSignerProviderInner({
|
|
|
178
215
|
const evmWallets = wallets.filter((w) => w.type === 'EVM');
|
|
179
216
|
|
|
180
217
|
if (evmWallets.length > 0 && !cancelled) {
|
|
181
|
-
setWallet((prev) =>
|
|
218
|
+
setWallet((prev) =>
|
|
219
|
+
prev?.id === evmWallets[0].id ? prev : evmWallets[0]
|
|
220
|
+
);
|
|
182
221
|
setIsConnected(true);
|
|
183
222
|
} else if (!cancelled) {
|
|
184
223
|
setIsConnected(false);
|
|
@@ -224,7 +263,9 @@ function ParaSignerProviderInner({
|
|
|
224
263
|
// A {isConnected:false} context makes MidenProvider's init effect return early
|
|
225
264
|
// without creating any client, keeping the WASM module free for buildContext.
|
|
226
265
|
const disconnectedCtx = useRef<SignerContextValue>({
|
|
227
|
-
signCb: async () => {
|
|
266
|
+
signCb: async () => {
|
|
267
|
+
throw new Error('Para wallet not connected');
|
|
268
|
+
},
|
|
228
269
|
accountConfig: null as any,
|
|
229
270
|
storeName: '',
|
|
230
271
|
name: 'Para',
|
|
@@ -263,9 +304,7 @@ function ParaSignerProviderInner({
|
|
|
263
304
|
);
|
|
264
305
|
|
|
265
306
|
if (!cancelled) {
|
|
266
|
-
const { AccountStorageMode } = await import(
|
|
267
|
-
'@miden-sdk/miden-sdk'
|
|
268
|
-
);
|
|
307
|
+
const { AccountStorageMode } = await import('@miden-sdk/miden-sdk');
|
|
269
308
|
|
|
270
309
|
setSignerContext({
|
|
271
310
|
signCb: signCallback,
|
|
@@ -273,6 +312,7 @@ function ParaSignerProviderInner({
|
|
|
273
312
|
publicKeyCommitment: commitmentBytes,
|
|
274
313
|
accountType: 'RegularAccountImmutableCode',
|
|
275
314
|
storageMode: AccountStorageMode.public(),
|
|
315
|
+
...(customComponents?.length ? { customComponents } : {}),
|
|
276
316
|
},
|
|
277
317
|
storeName: `para_${wallet.id}`,
|
|
278
318
|
name: 'Para',
|