helius-wallet-kit 0.1.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.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # helius-wallet-kit
2
+
3
+ Embedded Solana wallets for Helius customers. One React provider, one hook — your users get non-custodial embedded wallets, and you're billed through your existing Helius plan.
4
+
5
+ ```tsx
6
+ import { HeliusWalletProvider, useHeliusWallet } from 'helius-wallet-kit';
7
+
8
+ // Wrap your app
9
+ <HeliusWalletProvider
10
+ config={{
11
+ apiKey: process.env.NEXT_PUBLIC_HELIUS_API_KEY!,
12
+ projectId: process.env.NEXT_PUBLIC_HELIUS_PROJECT_ID!,
13
+ }}
14
+ >
15
+ {children}
16
+ </HeliusWalletProvider>
17
+
18
+ // Use in any component
19
+ const { address, login, signAndSendTransaction, connection } = useHeliusWallet();
20
+ ```
21
+
22
+ ## Subpath exports
23
+
24
+ Single npm package. Source is organized into subdirectories that map to subpath exports:
25
+
26
+ | Import | Purpose |
27
+ |---|---|
28
+ | `helius-wallet-kit` | Meta — re-exports `core` + `ui` for the default install |
29
+ | `helius-wallet-kit/core` | Provider, `useHeliusWallet()` hook, Helius integrations |
30
+ | `helius-wallet-kit/ui/styles.css` | Wallet-modal stylesheet — pulls in the base modal styles and hides third-party branding. Import once in your root layout. |
31
+ | `helius-wallet-kit/next` | Next.js middleware — server-side proxies for the Helius API routes the client expects |
32
+
33
+ ## Prerequisites
34
+
35
+ - Node.js 18+
36
+ - A Helius account with WaaS enabled on a Business or Professional plan ([dashboard.helius.dev](https://dashboard.helius.dev))
37
+
38
+ ## Quick start
39
+
40
+ ```bash
41
+ npm install helius-wallet-kit
42
+ ```
43
+
44
+ Add a single catch-all route handler for server-side Helius API proxying:
45
+
46
+ ```ts
47
+ // src/app/api/helius/[...path]/route.ts
48
+ import { createHeliusRouteHandler } from 'helius-wallet-kit/next';
49
+ export const { GET, POST } = createHeliusRouteHandler();
50
+ ```
51
+
52
+ Import the stylesheet in your root layout:
53
+
54
+ ```tsx
55
+ // src/app/layout.tsx
56
+ import "helius-wallet-kit/ui/styles.css";
57
+ ```
58
+
59
+ Wrap your app:
60
+
61
+ ```tsx
62
+ // src/app/providers.tsx
63
+ 'use client';
64
+ import { HeliusWalletProvider } from 'helius-wallet-kit';
65
+
66
+ export function Providers({ children }) {
67
+ return (
68
+ <HeliusWalletProvider
69
+ config={{
70
+ apiKey: process.env.NEXT_PUBLIC_HELIUS_API_KEY!,
71
+ projectId: process.env.NEXT_PUBLIC_HELIUS_PROJECT_ID!,
72
+ cluster: 'devnet',
73
+ }}
74
+ >
75
+ {children}
76
+ </HeliusWalletProvider>
77
+ );
78
+ }
79
+ ```
80
+
81
+ Done. `useHeliusWallet()` works in any client component under the provider.
82
+
83
+ > **Note on your API key.** In this version the provider reads the key on the
84
+ > client (`NEXT_PUBLIC_HELIUS_API_KEY`), so it is visible in the browser. It's
85
+ > sent to Helius to bootstrap the wallet (origin-locked by the key's allowed
86
+ > domains) and to your route handler for RPC/transactions. Use a dedicated,
87
+ > domain-restricted key you can rotate. Fully server-side key handling (key
88
+ > never leaves your server) is on the roadmap.
89
+
90
+ ## Architecture in one paragraph
91
+
92
+ `HeliusWalletProvider` fetches bootstrap config from a Helius-owned `/waas/config` endpoint on mount, then stands up a non-custodial wallet client under the hood. Developers don't see or depend on the backing wallet infrastructure — it's an internal implementation detail isolated behind a single adapter module, so it can be swapped or upgraded without changing the consumer API.
93
+
94
+ ## License
95
+
96
+ MIT.
@@ -0,0 +1,461 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactWalletKit = require('@turnkey/react-wallet-kit');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var web3_js = require('@solana/web3.js');
7
+
8
+ // src/core/HeliusWalletProvider.tsx
9
+
10
+ // src/core/types.ts
11
+ var WAAS_ALLOWED_PLANS = ["business", "professional"];
12
+ function isWaasEligible(plan) {
13
+ return WAAS_ALLOWED_PLANS.includes(plan);
14
+ }
15
+
16
+ // src/core/constants.ts
17
+ var SOLANA_WALLET_ACCOUNT_CONFIG = {
18
+ curve: "CURVE_ED25519",
19
+ pathFormat: "PATH_FORMAT_BIP32",
20
+ path: "m/44'/501'/0'/0'",
21
+ addressFormat: "ADDRESS_FORMAT_SOLANA"
22
+ };
23
+ var DEFAULT_THEME = {
24
+ primaryColor: "#E84125",
25
+ borderRadius: "12px",
26
+ logoLight: "/Helius-Horizontal-Logo-Black.svg",
27
+ logoDark: "/Helius-Horizontal-Logo-White.svg",
28
+ darkMode: true
29
+ };
30
+ var DEFAULT_RPC_PROXY_PATH = "/api/helius/rpc";
31
+ var DEFAULT_HELIUS_API_URL = "https://dev-api.helius.xyz/v0";
32
+
33
+ // src/core/turnkey-config.ts
34
+ function buildTurnkeyConfig(config, bootstrap) {
35
+ const theme = { ...DEFAULT_THEME, ...config.theme };
36
+ const walletAccounts = [SOLANA_WALLET_ACCOUNT_CONFIG];
37
+ const walletConfig = {
38
+ walletName: "Solana Wallet",
39
+ walletAccounts
40
+ };
41
+ return {
42
+ organizationId: bootstrap.organizationId,
43
+ authProxyConfigId: bootstrap.authProxyConfigId,
44
+ auth: {
45
+ // subOrgName = projectId stamps every end-user sub-org with the project,
46
+ // so signatures can be attributed back to it for usage billing (looked up
47
+ // via getSubOrgIds by name). Without it, Turnkey defaults the name to the
48
+ // site hostname and attribution is lost.
49
+ createSuborgParams: {
50
+ passkeyAuth: {
51
+ userName: "Default User",
52
+ subOrgName: config.projectId,
53
+ passkeyName: "Helius Wallet",
54
+ customWallet: walletConfig
55
+ },
56
+ emailOtpAuth: {
57
+ userName: "Email User",
58
+ subOrgName: config.projectId,
59
+ customWallet: walletConfig
60
+ },
61
+ walletAuth: {
62
+ userName: "Wallet User",
63
+ subOrgName: config.projectId,
64
+ customWallet: walletConfig
65
+ },
66
+ oauth: {
67
+ userName: "OAuth User",
68
+ subOrgName: config.projectId,
69
+ customWallet: walletConfig
70
+ }
71
+ },
72
+ methods: config.authMethods ? {
73
+ passkeyAuthEnabled: config.authMethods.passkey ?? true,
74
+ emailOtpAuthEnabled: config.authMethods.email ?? true,
75
+ smsOtpAuthEnabled: config.authMethods.sms ?? false,
76
+ walletAuthEnabled: config.authMethods.wallet ?? false,
77
+ googleOauthEnabled: config.authMethods.google ?? false,
78
+ appleOauthEnabled: config.authMethods.apple ?? false,
79
+ discordOauthEnabled: config.authMethods.discord ?? false,
80
+ xOauthEnabled: config.authMethods.x ?? false
81
+ } : void 0,
82
+ autoRefreshSession: true
83
+ },
84
+ ui: {
85
+ logoLight: theme.logoLight,
86
+ logoDark: theme.logoDark,
87
+ darkMode: theme.darkMode,
88
+ borderRadius: theme.borderRadius,
89
+ colors: {
90
+ light: {
91
+ primary: theme.primaryColor,
92
+ primaryText: "#FFFFFF",
93
+ button: "#FFFFFF",
94
+ modalBackground: "#FFFFFF",
95
+ modalText: "#090909"
96
+ },
97
+ dark: {
98
+ primary: theme.primaryColor,
99
+ primaryText: "#FFFFFF",
100
+ button: "#222222",
101
+ modalBackground: "#090909",
102
+ modalText: "#DBDBDB",
103
+ iconText: "#999999",
104
+ iconBackground: "#333333"
105
+ }
106
+ }
107
+ }
108
+ };
109
+ }
110
+
111
+ // src/core/waas-config.ts
112
+ async function fetchWaasBootstrap(apiBaseUrl, apiKey) {
113
+ try {
114
+ const res = await fetch(`${apiBaseUrl}/waas/config`, {
115
+ headers: { "x-api-key": apiKey }
116
+ });
117
+ const data = await res.json().catch(() => ({}));
118
+ if (res.ok && data.organizationId && data.authProxyConfigId) {
119
+ return {
120
+ bootstrap: {
121
+ organizationId: data.organizationId,
122
+ authProxyConfigId: data.authProxyConfigId
123
+ }
124
+ };
125
+ }
126
+ return {
127
+ error: {
128
+ code: data.code,
129
+ message: data.message ?? `WaaS config request failed (${res.status})`
130
+ }
131
+ };
132
+ } catch (err) {
133
+ return {
134
+ error: { message: err instanceof Error ? err.message : "Unknown error" }
135
+ };
136
+ }
137
+ }
138
+ var HeliusWalletContext = react.createContext({
139
+ rpcProxyPath: DEFAULT_RPC_PROXY_PATH,
140
+ secureRpcUrl: void 0,
141
+ cluster: "devnet",
142
+ setCluster: () => {
143
+ },
144
+ apiKey: null,
145
+ projectId: null,
146
+ planTier: null,
147
+ waasEligible: false
148
+ });
149
+ function HeliusWalletProvider({
150
+ config,
151
+ children
152
+ }) {
153
+ const rpcProxyPath = config.rpcProxyPath ?? DEFAULT_RPC_PROXY_PATH;
154
+ const secureRpcUrl = react.useMemo(
155
+ () => config.secureRpcUrl,
156
+ [config.secureRpcUrl?.["mainnet-beta"], config.secureRpcUrl?.devnet]
157
+ );
158
+ const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_HELIUS_API_URL;
159
+ const [cluster, setCluster] = react.useState(config.cluster ?? "devnet");
160
+ const apiKey = config.apiKey ?? null;
161
+ const projectId = config.projectId ?? null;
162
+ const planTier = config.planTier ?? null;
163
+ const [bootstrap, setBootstrap] = react.useState(null);
164
+ const [bootstrapError, setBootstrapError] = react.useState(null);
165
+ const waasEligible = planTier ? isWaasEligible(planTier) : false;
166
+ react.useEffect(() => {
167
+ if (!apiKey) return;
168
+ let cancelled = false;
169
+ (async () => {
170
+ const result = await fetchWaasBootstrap(apiBaseUrl, apiKey);
171
+ if (cancelled) return;
172
+ if (result.bootstrap) {
173
+ setBootstrap(result.bootstrap);
174
+ } else if (result.error) {
175
+ setBootstrapError(result.error);
176
+ }
177
+ })();
178
+ return () => {
179
+ cancelled = true;
180
+ };
181
+ }, [apiKey, apiBaseUrl]);
182
+ const contextValue = react.useMemo(
183
+ () => ({ rpcProxyPath, secureRpcUrl, cluster, setCluster, apiKey, projectId, planTier, waasEligible }),
184
+ [rpcProxyPath, secureRpcUrl, cluster, apiKey, projectId, planTier, waasEligible]
185
+ );
186
+ if (planTier && !waasEligible) {
187
+ return /* @__PURE__ */ jsxRuntime.jsx(HeliusWalletContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
188
+ display: "flex",
189
+ flexDirection: "column",
190
+ alignItems: "center",
191
+ justifyContent: "center",
192
+ minHeight: "100vh",
193
+ gap: "16px",
194
+ padding: "24px",
195
+ fontFamily: "system-ui, sans-serif"
196
+ }, children: [
197
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: "/Helius-Icon.svg", alt: "Helius", style: { width: 48, height: 48 } }),
198
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "24px", fontWeight: 700, margin: 0 }, children: "Helius WaaS" }),
199
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { color: "#999", margin: 0, textAlign: "center", maxWidth: 400 }, children: [
200
+ "Wallet-as-a-Service requires a ",
201
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Business" }),
202
+ " or ",
203
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Professional" }),
204
+ " plan. Your current plan: ",
205
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: planTier }),
206
+ "."
207
+ ] }),
208
+ /* @__PURE__ */ jsxRuntime.jsx(
209
+ "a",
210
+ {
211
+ href: "https://dashboard.helius.dev",
212
+ target: "_blank",
213
+ rel: "noopener noreferrer",
214
+ style: {
215
+ background: "#E84125",
216
+ color: "#fff",
217
+ padding: "12px 24px",
218
+ borderRadius: "12px",
219
+ textDecoration: "none",
220
+ fontWeight: 500,
221
+ fontSize: "14px"
222
+ },
223
+ children: "Upgrade Plan"
224
+ }
225
+ )
226
+ ] }) });
227
+ }
228
+ const effectiveBootstrap = bootstrap ?? {
229
+ organizationId: "",
230
+ authProxyConfigId: ""
231
+ };
232
+ const turnkeyConfig = buildTurnkeyConfig(config, effectiveBootstrap);
233
+ const providerKey = bootstrap ? `ready:${bootstrap.organizationId}:${bootstrap.authProxyConfigId}` : bootstrapError ? "error" : "pending";
234
+ return /* @__PURE__ */ jsxRuntime.jsx(HeliusWalletContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
235
+ reactWalletKit.TurnkeyProvider,
236
+ {
237
+ config: turnkeyConfig,
238
+ callbacks: {
239
+ onError: (error) => {
240
+ const msg = error.message?.toLowerCase() ?? "";
241
+ if (msg.includes("cancel") || msg.includes("abort") || msg.includes("dismissed")) {
242
+ return;
243
+ }
244
+ if (!bootstrap) return;
245
+ config.onError?.(new Error(error.message));
246
+ }
247
+ },
248
+ children
249
+ },
250
+ providerKey
251
+ ) });
252
+ }
253
+
254
+ // src/core/rpc-url.ts
255
+ function resolveRpcUrl(secureRpcUrl, cluster, rpcProxyPath, origin) {
256
+ const secure = secureRpcUrl?.[cluster];
257
+ if (secure) return secure;
258
+ return `${origin}${rpcProxyPath}?cluster=${cluster}`;
259
+ }
260
+ function canSendDirect(secureRpcUrl, cluster) {
261
+ return Boolean(secureRpcUrl?.[cluster]);
262
+ }
263
+
264
+ // src/core/useHeliusWallet.ts
265
+ function deriveStatus(clientState, authState) {
266
+ if (clientState === void 0 || clientState === reactWalletKit.ClientState.Loading)
267
+ return "loading";
268
+ if (authState === reactWalletKit.AuthState.Authenticated) return "authenticated";
269
+ return "unauthenticated";
270
+ }
271
+ function useHeliusWallet() {
272
+ const {
273
+ handleLogin,
274
+ logout: turnkeyLogout,
275
+ authState,
276
+ clientState,
277
+ user: turnkeyUser,
278
+ session,
279
+ wallets,
280
+ signTransaction: turnkeySignTransaction,
281
+ handleSignMessage,
282
+ handleExportWallet
283
+ } = reactWalletKit.useTurnkey();
284
+ const { rpcProxyPath, secureRpcUrl, cluster, setCluster, apiKey, projectId, planTier } = react.useContext(HeliusWalletContext);
285
+ const rpcUrl = react.useMemo(() => {
286
+ const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
287
+ return resolveRpcUrl(secureRpcUrl, cluster, rpcProxyPath, origin);
288
+ }, [secureRpcUrl, rpcProxyPath, cluster]);
289
+ const connection = react.useMemo(() => new web3_js.Connection(rpcUrl), [rpcUrl]);
290
+ const status = deriveStatus(clientState, authState);
291
+ const address = wallets?.[0]?.accounts?.[0]?.address ?? null;
292
+ const user = turnkeyUser ? {
293
+ userId: turnkeyUser.userId,
294
+ username: turnkeyUser.userName,
295
+ email: turnkeyUser.userEmail ?? void 0,
296
+ // session.organizationId is the end-user's sub-org id under the
297
+ // configured auth proxy. Falls back to "" only in edge cases where
298
+ // useTurnkey returns a user before the session is fully populated.
299
+ subOrgId: session?.organizationId ?? "",
300
+ walletId: wallets?.[0]?.walletId ?? null
301
+ } : null;
302
+ const login = react.useCallback(() => handleLogin(), [handleLogin]);
303
+ const logout = react.useCallback(() => turnkeyLogout(), [turnkeyLogout]);
304
+ const signTransaction = react.useCallback(
305
+ async (transaction) => {
306
+ const walletAccount = wallets?.[0]?.accounts?.[0];
307
+ if (!walletAccount) throw new Error("No wallet available");
308
+ const hexEncoded = Buffer.from(transaction).toString("hex");
309
+ const signedHex = await turnkeySignTransaction({
310
+ walletAccount,
311
+ unsignedTransaction: hexEncoded,
312
+ transactionType: "TRANSACTION_TYPE_SOLANA"
313
+ });
314
+ return Buffer.from(signedHex, "hex");
315
+ },
316
+ [wallets, turnkeySignTransaction]
317
+ );
318
+ const signAndSendTransaction = react.useCallback(
319
+ async (transaction) => {
320
+ const signed = await signTransaction(transaction);
321
+ if (canSendDirect(secureRpcUrl, cluster)) {
322
+ return connection.sendRawTransaction(signed, { skipPreflight: true });
323
+ }
324
+ const base64Tx = Buffer.from(signed).toString("base64");
325
+ const headers = {
326
+ "Content-Type": "application/json"
327
+ };
328
+ if (apiKey) headers["x-helius-api-key"] = apiKey;
329
+ const res = await fetch("/api/helius/send", {
330
+ method: "POST",
331
+ headers,
332
+ body: JSON.stringify({ transaction: base64Tx, cluster, address })
333
+ });
334
+ const data = await res.json();
335
+ if (data.error) throw new Error(data.error);
336
+ return data.signature;
337
+ },
338
+ [signTransaction, cluster, apiKey, address, secureRpcUrl, connection]
339
+ );
340
+ const signMessage = react.useCallback(
341
+ async (message) => {
342
+ const walletAccount = wallets?.[0]?.accounts?.[0];
343
+ if (!walletAccount) throw new Error("No wallet available");
344
+ const result = await handleSignMessage({
345
+ message,
346
+ walletAccount
347
+ });
348
+ const rBytes = Buffer.from(result.r, "hex");
349
+ const sBytes = Buffer.from(result.s, "hex");
350
+ const sigBytes = Buffer.concat([rBytes, sBytes]);
351
+ return sigBytes.toString("hex");
352
+ },
353
+ [wallets, handleSignMessage]
354
+ );
355
+ const exportWallet = react.useCallback(async () => {
356
+ const wallet = wallets?.[0];
357
+ if (!wallet) throw new Error("No wallet available");
358
+ await handleExportWallet({ walletId: wallet.walletId });
359
+ }, [wallets, handleExportWallet]);
360
+ const getTransactions = react.useCallback(
361
+ async (options) => {
362
+ if (!address) return [];
363
+ const limit = options?.limit ?? 10;
364
+ const headers = {};
365
+ if (apiKey) headers["x-helius-api-key"] = apiKey;
366
+ const directMode = canSendDirect(secureRpcUrl, cluster);
367
+ const historyUnavailable = "getTransactions needs the Helius route handler (helius-wallet-kit/next); it isn't available in direct/secure-URL mode.";
368
+ let res;
369
+ try {
370
+ res = await fetch(
371
+ `/api/helius/transactions?address=${encodeURIComponent(address)}&cluster=${cluster}&limit=${limit}`,
372
+ { headers }
373
+ );
374
+ } catch (err) {
375
+ throw directMode ? new Error(historyUnavailable) : err;
376
+ }
377
+ if (res.status === 404 && directMode) throw new Error(historyUnavailable);
378
+ if (!res.ok) {
379
+ const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
380
+ throw new Error(err.error ?? `HTTP ${res.status}`);
381
+ }
382
+ const data = await res.json();
383
+ return Array.isArray(data) ? data : data.transactions ?? [];
384
+ },
385
+ [address, cluster, apiKey]
386
+ );
387
+ const getPriorityFee = react.useCallback(
388
+ async (accountKeys, priorityLevel = "Medium") => {
389
+ const res = await fetch(rpcUrl, {
390
+ method: "POST",
391
+ headers: { "Content-Type": "application/json" },
392
+ body: JSON.stringify({
393
+ jsonrpc: "2.0",
394
+ id: "helius-wallet-kit-priority-fee",
395
+ method: "getPriorityFeeEstimate",
396
+ params: [{ accountKeys, options: { priorityLevel } }]
397
+ })
398
+ });
399
+ const data = await res.json();
400
+ if (data.error) throw new Error(data.error.message ?? "RPC error");
401
+ return data.result?.priorityFeeEstimate ?? 0;
402
+ },
403
+ [rpcUrl]
404
+ );
405
+ const getPriorityFeeLevels = react.useCallback(
406
+ async (accountKeys) => {
407
+ const res = await fetch(rpcUrl, {
408
+ method: "POST",
409
+ headers: { "Content-Type": "application/json" },
410
+ body: JSON.stringify({
411
+ jsonrpc: "2.0",
412
+ id: "helius-wallet-kit-priority-fee-levels",
413
+ method: "getPriorityFeeEstimate",
414
+ params: [
415
+ { accountKeys, options: { includeAllPriorityFeeLevels: true } }
416
+ ]
417
+ })
418
+ });
419
+ const data = await res.json();
420
+ if (data.error) throw new Error(data.error.message ?? "RPC error");
421
+ const levels = data.result?.priorityFeeLevels ?? {};
422
+ return {
423
+ min: levels.min ?? 0,
424
+ low: levels.low ?? 0,
425
+ medium: levels.medium ?? 0,
426
+ high: levels.high ?? 0,
427
+ veryHigh: levels.veryHigh ?? 0,
428
+ unsafeMax: levels.unsafeMax ?? 0
429
+ };
430
+ },
431
+ [rpcUrl]
432
+ );
433
+ return {
434
+ address,
435
+ status,
436
+ user,
437
+ login,
438
+ logout,
439
+ signTransaction,
440
+ signAndSendTransaction,
441
+ signMessage,
442
+ exportWallet,
443
+ getTransactions,
444
+ getPriorityFee,
445
+ getPriorityFeeLevels,
446
+ connection,
447
+ rpcUrl,
448
+ cluster,
449
+ setCluster,
450
+ apiKey,
451
+ projectId,
452
+ planTier
453
+ };
454
+ }
455
+
456
+ exports.HeliusWalletContext = HeliusWalletContext;
457
+ exports.HeliusWalletProvider = HeliusWalletProvider;
458
+ exports.isWaasEligible = isWaasEligible;
459
+ exports.useHeliusWallet = useHeliusWallet;
460
+ //# sourceMappingURL=index.cjs.map
461
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/types.ts","../../src/core/constants.ts","../../src/core/turnkey-config.ts","../../src/core/waas-config.ts","../../src/core/HeliusWalletProvider.tsx","../../src/core/rpc-url.ts","../../src/core/useHeliusWallet.ts"],"names":["createContext","useMemo","useState","useEffect","jsx","jsxs","TurnkeyProvider","ClientState","AuthState","useTurnkey","useContext","Connection","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Connection } from \"@solana/web3.js\";\n\nexport interface HeliusWalletConfig {\n apiKey?: string;\n /**\n * Helius project id. Required — stamped as the Turnkey sub-org name on every\n * end-user wallet so signatures can be attributed to your project for usage\n * billing (resolved server-side via getSubOrgIds by name).\n */\n projectId: string;\n planTier?: HeliusPlan;\n rpcProxyPath?: string;\n /**\n * Base URL for the Helius WaaS control-plane API (the `/waas/config`\n * bootstrap). Defaults to Helius production; override for local/staging.\n */\n apiBaseUrl?: string;\n /**\n * Per-cluster Helius Secure RPC URL (key-less, safe in the browser). When set\n * for the active cluster, the wallet's Solana connection, priority-fee lookups,\n * and transaction sends go directly to it — no route handler needed. Sends use\n * standard RPC (not Helius Sender), so they forgo Sender's optimized landing;\n * use proxy mode for best mainnet landing. Falls back to the same-origin\n * `rpcProxyPath` proxy when unset. Pass a stable reference (memoize it) to\n * avoid unnecessary re-renders.\n */\n secureRpcUrl?: Partial<Record<Cluster, string>>;\n cluster?: Cluster;\n authMethods?: {\n passkey?: boolean;\n email?: boolean;\n sms?: boolean;\n wallet?: boolean;\n google?: boolean;\n apple?: boolean;\n discord?: boolean;\n x?: boolean;\n };\n theme?: {\n darkMode?: boolean;\n primaryColor?: string;\n borderRadius?: string;\n logoLight?: string;\n logoDark?: string;\n };\n onError?: (error: Error) => void;\n}\n\nexport type Cluster = \"devnet\" | \"mainnet-beta\";\n\nexport type HeliusPlan = \"basic\" | \"developer\" | \"business\" | \"professional\";\n\nconst WAAS_ALLOWED_PLANS: HeliusPlan[] = [\"business\", \"professional\"];\n\nexport function isWaasEligible(plan: HeliusPlan): boolean {\n return WAAS_ALLOWED_PLANS.includes(plan);\n}\n\nexport type AuthStatus = \"loading\" | \"unauthenticated\" | \"authenticated\";\n\nexport type PriorityLevel =\n | \"Min\"\n | \"Low\"\n | \"Medium\"\n | \"High\"\n | \"VeryHigh\"\n | \"UnsafeMax\";\n\n/**\n * All six priority-fee levels (in micro-lamports per compute unit) returned by\n * Helius's `getPriorityFeeEstimate` when called with\n * `includeAllPriorityFeeLevels: true`. The lowercase keys match the upstream\n * RPC response shape — intentionally distinct from the PascalCase\n * `PriorityLevel` union which is what the RPC accepts as input.\n */\nexport interface PriorityFeeLevels {\n min: number;\n low: number;\n medium: number;\n high: number;\n veryHigh: number;\n unsafeMax: number;\n}\n\n/**\n * One row of Helius Enhanced Transactions API response. Fields beyond the\n * common set are passed through verbatim via the index signature — Helius's\n * parsed-tx schema is evolving, and consumers rendering UI off specific fields\n * should cast at their call site rather than wait for us to widen this type.\n */\nexport interface EnhancedTransaction {\n signature: string;\n slot: number;\n timestamp: number;\n type: string;\n source: string;\n fee: number;\n feePayer: string;\n description?: string;\n nativeTransfers?: Array<{\n fromUserAccount: string;\n toUserAccount: string;\n amount: number;\n }>;\n tokenTransfers?: Array<{\n fromUserAccount: string;\n toUserAccount: string;\n mint: string;\n tokenAmount: number;\n }>;\n [key: string]: unknown;\n}\n\nexport interface HeliusWallet {\n address: string | null;\n status: AuthStatus;\n user: {\n userId: string;\n username: string;\n email?: string;\n /**\n * Turnkey sub-organization id for this end-user. Each authenticated user\n * gets their own sub-org, fully isolated. Useful for server-side audit\n * trails and admin observability. Always defined when status is\n * \"authenticated\".\n */\n subOrgId: string;\n /**\n * Turnkey wallet id (the wallet container holding this user's accounts).\n * May be undefined for a brief window post-signup before the wallet\n * provisioning completes.\n */\n walletId: string | null;\n } | null;\n\n login: () => Promise<void>;\n logout: () => Promise<void>;\n\n signTransaction: (transaction: Uint8Array | Buffer) => Promise<Buffer>;\n signAndSendTransaction: (transaction: Uint8Array | Buffer) => Promise<string>;\n signMessage: (message: string) => Promise<string>;\n\n exportWallet: () => Promise<void>;\n\n /**\n * Fetch parsed transaction history for the connected wallet via Helius\n * Enhanced Transactions API. Returns empty array if no wallet is connected.\n */\n getTransactions: (options?: { limit?: number }) => Promise<EnhancedTransaction[]>;\n\n /**\n * Estimate priority fee in micro-lamports for a transaction touching the\n * given writable accounts. `priorityLevel` defaults to \"Medium\". Uses\n * Helius's `getPriorityFeeEstimate` RPC method.\n */\n getPriorityFee: (\n accountKeys: string[],\n priorityLevel?: PriorityLevel\n ) => Promise<number>;\n\n /**\n * Like `getPriorityFee`, but returns every level Helius reports\n * (min/low/medium/high/veryHigh/unsafeMax). Use when rendering a fee\n * picker; otherwise prefer `getPriorityFee` for the single-value case.\n */\n getPriorityFeeLevels: (accountKeys: string[]) => Promise<PriorityFeeLevels>;\n\n connection: Connection;\n rpcUrl: string;\n\n cluster: Cluster;\n setCluster: (cluster: Cluster) => void;\n\n apiKey: string | null;\n projectId: string | null;\n planTier: HeliusPlan | null;\n}\n","export const SOLANA_WALLET_ACCOUNT_CONFIG = {\n curve: \"CURVE_ED25519\" as const,\n pathFormat: \"PATH_FORMAT_BIP32\" as const,\n path: \"m/44'/501'/0'/0'\",\n addressFormat: \"ADDRESS_FORMAT_SOLANA\" as const,\n};\n\nexport const DEFAULT_THEME = {\n primaryColor: \"#E84125\",\n borderRadius: \"12px\",\n logoLight: \"/Helius-Horizontal-Logo-Black.svg\",\n logoDark: \"/Helius-Horizontal-Logo-White.svg\",\n darkMode: true,\n};\n\n// Aligned with the @helius-labs/wallet-kit/next catch-all route structure —\n// consumers mount a single [...path] handler at /api/helius/, and the RPC\n// proxy lives under that tree alongside /send, /transactions, /plan, and\n// /waas/config. Previously `/api/rpc` (PoC-era top-level route); unified\n// here at M3 (2026-04-23) so one catch-all covers everything.\nexport const DEFAULT_RPC_PROXY_PATH = \"/api/helius/rpc\";\n\n// Helius WaaS control-plane API. The provider fetches its Turnkey bootstrap\n// (org id + auth-proxy config id) directly from here with the project's Helius\n// API key — no route handler required. The endpoint is origin-locked server-side\n// by the key's allowed-domains ACL.\nexport const DEFAULT_HELIUS_API_URL = \"https://dev-api.helius.xyz/v0\";\n","// Pure builder for the Turnkey provider config. Kept separate from\n// HeliusWalletProvider.tsx so it can be unit-tested without pulling in\n// @turnkey/react-wallet-kit at runtime — the Turnkey type below is a\n// type-only import (fully erased), so importing this module loads no\n// browser/ESM Turnkey code.\nimport type { TurnkeyProviderConfig } from \"./internal/turnkey-adapter\";\nimport type { HeliusWalletConfig } from \"./types\";\nimport { SOLANA_WALLET_ACCOUNT_CONFIG, DEFAULT_THEME } from \"./constants\";\n\nexport interface WaasBootstrap {\n organizationId: string;\n authProxyConfigId: string;\n}\n\nexport function buildTurnkeyConfig(\n config: HeliusWalletConfig,\n bootstrap: WaasBootstrap\n): TurnkeyProviderConfig {\n const theme = { ...DEFAULT_THEME, ...config.theme };\n const walletAccounts = [SOLANA_WALLET_ACCOUNT_CONFIG];\n const walletConfig = {\n walletName: \"Solana Wallet\",\n walletAccounts,\n };\n\n return {\n organizationId: bootstrap.organizationId,\n authProxyConfigId: bootstrap.authProxyConfigId,\n\n auth: {\n // subOrgName = projectId stamps every end-user sub-org with the project,\n // so signatures can be attributed back to it for usage billing (looked up\n // via getSubOrgIds by name). Without it, Turnkey defaults the name to the\n // site hostname and attribution is lost.\n createSuborgParams: {\n passkeyAuth: {\n userName: \"Default User\",\n subOrgName: config.projectId,\n passkeyName: \"Helius Wallet\",\n customWallet: walletConfig,\n },\n emailOtpAuth: {\n userName: \"Email User\",\n subOrgName: config.projectId,\n customWallet: walletConfig,\n },\n walletAuth: {\n userName: \"Wallet User\",\n subOrgName: config.projectId,\n customWallet: walletConfig,\n },\n oauth: {\n userName: \"OAuth User\",\n subOrgName: config.projectId,\n customWallet: walletConfig,\n },\n },\n methods: config.authMethods\n ? {\n passkeyAuthEnabled: config.authMethods.passkey ?? true,\n emailOtpAuthEnabled: config.authMethods.email ?? true,\n smsOtpAuthEnabled: config.authMethods.sms ?? false,\n walletAuthEnabled: config.authMethods.wallet ?? false,\n googleOauthEnabled: config.authMethods.google ?? false,\n appleOauthEnabled: config.authMethods.apple ?? false,\n discordOauthEnabled: config.authMethods.discord ?? false,\n xOauthEnabled: config.authMethods.x ?? false,\n }\n : undefined,\n autoRefreshSession: true,\n },\n\n ui: {\n logoLight: theme.logoLight,\n logoDark: theme.logoDark,\n darkMode: theme.darkMode,\n borderRadius: theme.borderRadius,\n colors: {\n light: {\n primary: theme.primaryColor,\n primaryText: \"#FFFFFF\",\n button: \"#FFFFFF\",\n modalBackground: \"#FFFFFF\",\n modalText: \"#090909\",\n },\n dark: {\n primary: theme.primaryColor,\n primaryText: \"#FFFFFF\",\n button: \"#222222\",\n modalBackground: \"#090909\",\n modalText: \"#DBDBDB\",\n iconText: \"#999999\",\n iconBackground: \"#333333\",\n },\n },\n },\n };\n}\n","// Fetches the Turnkey bootstrap (org id + auth-proxy config id) directly from\n// the Helius WaaS control-plane API. No route handler needed: the request is\n// authenticated by the project's Helius API key and origin-locked server-side by\n// the key's allowed-domains ACL. Kept separate from the provider so it can be\n// unit-tested with a mocked fetch.\nimport type { WaasBootstrap } from \"./turnkey-config\";\n\nexport interface WaasBootstrapResult {\n bootstrap?: WaasBootstrap;\n error?: { code?: string; message: string };\n}\n\nexport async function fetchWaasBootstrap(\n apiBaseUrl: string,\n apiKey: string,\n): Promise<WaasBootstrapResult> {\n try {\n const res = await fetch(`${apiBaseUrl}/waas/config`, {\n headers: { \"x-api-key\": apiKey },\n });\n const data = await res.json().catch(() => ({}));\n\n if (res.ok && data.organizationId && data.authProxyConfigId) {\n return {\n bootstrap: {\n organizationId: data.organizationId,\n authProxyConfigId: data.authProxyConfigId,\n },\n };\n }\n\n return {\n error: {\n code: data.code,\n message: data.message ?? `WaaS config request failed (${res.status})`,\n },\n };\n } catch (err) {\n return {\n error: { message: err instanceof Error ? err.message : \"Unknown error\" },\n };\n }\n}\n","\"use client\";\n\nimport React, { createContext, useState, useMemo, useEffect } from \"react\";\nimport { TurnkeyProvider } from \"./internal/turnkey-adapter\";\nimport type { HeliusWalletConfig, Cluster, HeliusPlan } from \"./types\";\nimport { isWaasEligible } from \"./types\";\nimport { DEFAULT_RPC_PROXY_PATH, DEFAULT_HELIUS_API_URL } from \"./constants\";\nimport { buildTurnkeyConfig, type WaasBootstrap } from \"./turnkey-config\";\nimport { fetchWaasBootstrap } from \"./waas-config\";\n\nexport const HeliusWalletContext = createContext<{\n rpcProxyPath: string;\n secureRpcUrl?: Partial<Record<Cluster, string>>;\n cluster: Cluster;\n setCluster: (cluster: Cluster) => void;\n apiKey: string | null;\n projectId: string | null;\n planTier: HeliusPlan | null;\n waasEligible: boolean;\n}>({\n rpcProxyPath: DEFAULT_RPC_PROXY_PATH,\n secureRpcUrl: undefined,\n cluster: \"devnet\",\n setCluster: () => {},\n apiKey: null,\n projectId: null,\n planTier: null,\n waasEligible: false,\n});\n\nexport function HeliusWalletProvider({\n config,\n children,\n}: {\n config: HeliusWalletConfig;\n children: React.ReactNode;\n}) {\n const rpcProxyPath = config.rpcProxyPath ?? DEFAULT_RPC_PROXY_PATH;\n // Stabilize by the actual cluster URLs so an inlined config object doesn't\n // churn the context value (and the memoized connection) every render.\n const secureRpcUrl = useMemo(\n () => config.secureRpcUrl,\n [config.secureRpcUrl?.[\"mainnet-beta\"], config.secureRpcUrl?.devnet],\n );\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_HELIUS_API_URL;\n const [cluster, setCluster] = useState<Cluster>(config.cluster ?? \"devnet\");\n const apiKey = config.apiKey ?? null;\n const projectId = config.projectId ?? null;\n const planTier = config.planTier ?? null;\n const [bootstrap, setBootstrap] = useState<WaasBootstrap | null>(null);\n const [bootstrapError, setBootstrapError] = useState<{ code?: string; message: string } | null>(null);\n const waasEligible = planTier ? isWaasEligible(planTier) : false;\n\n // Fetch the Turnkey bootstrap (org id + auth-proxy config id) directly from\n // the Helius WaaS API with the project's API key. No route handler needed —\n // the endpoint is origin-locked server-side by the key's allowed-domains ACL.\n // Plan eligibility is enforced server-side too (a PLAN_INELIGIBLE error here),\n // so there's no separate client-side plan lookup.\n useEffect(() => {\n if (!apiKey) return;\n\n let cancelled = false;\n (async () => {\n const result = await fetchWaasBootstrap(apiBaseUrl, apiKey);\n if (cancelled) return;\n if (result.bootstrap) {\n setBootstrap(result.bootstrap);\n } else if (result.error) {\n setBootstrapError(result.error);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [apiKey, apiBaseUrl]);\n\n const contextValue = useMemo(\n () => ({ rpcProxyPath, secureRpcUrl, cluster, setCluster, apiKey, projectId, planTier, waasEligible }),\n [rpcProxyPath, secureRpcUrl, cluster, apiKey, projectId, planTier, waasEligible]\n );\n\n // Gate: if planTier is provided but not eligible, show upgrade prompt\n if (planTier && !waasEligible) {\n return (\n <HeliusWalletContext.Provider value={contextValue}>\n <div style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n gap: \"16px\",\n padding: \"24px\",\n fontFamily: \"system-ui, sans-serif\",\n }}>\n <img src=\"/Helius-Icon.svg\" alt=\"Helius\" style={{ width: 48, height: 48 }} />\n <h1 style={{ fontSize: \"24px\", fontWeight: 700, margin: 0 }}>\n Helius WaaS\n </h1>\n <p style={{ color: \"#999\", margin: 0, textAlign: \"center\", maxWidth: 400 }}>\n Wallet-as-a-Service requires a <strong>Business</strong> or <strong>Professional</strong> plan.\n Your current plan: <strong>{planTier}</strong>.\n </p>\n <a\n href=\"https://dashboard.helius.dev\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n background: \"#E84125\",\n color: \"#fff\",\n padding: \"12px 24px\",\n borderRadius: \"12px\",\n textDecoration: \"none\",\n fontWeight: 500,\n fontSize: \"14px\",\n }}\n >\n Upgrade Plan\n </a>\n </div>\n </HeliusWalletContext.Provider>\n );\n }\n\n // TurnkeyProvider must ALWAYS be in the tree — useHeliusWallet calls\n // useTurnkey() unconditionally, and it throws if no TurnkeyProvider is\n // mounted. During SSR and the initial client render, bootstrap hasn't\n // resolved yet; we mount with placeholder identifiers and re-key the\n // provider so React remounts it with the real config once bootstrap lands.\n //\n // Placeholder identifiers put Turnkey's internal client into an error\n // state that useHeliusWallet surfaces as `status: \"loading\"` — no user\n // interaction is possible until bootstrap succeeds.\n const effectiveBootstrap: WaasBootstrap = bootstrap ?? {\n organizationId: \"\",\n authProxyConfigId: \"\",\n };\n\n const turnkeyConfig = buildTurnkeyConfig(config, effectiveBootstrap);\n\n // Re-key on real bootstrap → forces TurnkeyProvider to remount with the\n // actual Turnkey config. Without this, Turnkey memoizes initial props and\n // never picks up the real identifiers when they arrive post-useEffect.\n const providerKey = bootstrap\n ? `ready:${bootstrap.organizationId}:${bootstrap.authProxyConfigId}`\n : bootstrapError\n ? \"error\"\n : \"pending\";\n\n return (\n <HeliusWalletContext.Provider value={contextValue}>\n <TurnkeyProvider\n key={providerKey}\n config={turnkeyConfig}\n callbacks={{\n onError: (error) => {\n // Silently ignore user cancellations (dismissed passkey prompt, closed modal, etc.)\n const msg = error.message?.toLowerCase() ?? \"\";\n if (msg.includes(\"cancel\") || msg.includes(\"abort\") || msg.includes(\"dismissed\")) {\n return;\n }\n // Also silently ignore errors during the bootstrap-pending window —\n // Turnkey will throw against the placeholder identifiers, but that's\n // expected and transient; real errors surface after remount.\n if (!bootstrap) return;\n config.onError?.(new Error(error.message));\n },\n }}\n >\n {children}\n </TurnkeyProvider>\n </HeliusWalletContext.Provider>\n );\n}\n","import type { Cluster } from \"./types\";\n\n// Resolves the RPC endpoint the wallet's Solana connection uses. Prefers a\n// configured Secure RPC URL for the active cluster (key-less, safe to call\n// directly from the browser); falls back to the same-origin proxy path when\n// none is set for that cluster.\nexport function resolveRpcUrl(\n secureRpcUrl: Partial<Record<Cluster, string>> | undefined,\n cluster: Cluster,\n rpcProxyPath: string,\n origin: string,\n): string {\n const secure = secureRpcUrl?.[cluster];\n if (secure) return secure;\n return `${origin}${rpcProxyPath}?cluster=${cluster}`;\n}\n\n// True when sends can go directly through the secure RPC connection for the\n// active cluster (no Sender proxy needed).\nexport function canSendDirect(\n secureRpcUrl: Partial<Record<Cluster, string>> | undefined,\n cluster: Cluster,\n): boolean {\n return Boolean(secureRpcUrl?.[cluster]);\n}\n","\"use client\";\n\nimport { useContext, useMemo, useCallback } from \"react\";\nimport { useTurnkey, AuthState, ClientState } from \"./internal/turnkey-adapter\";\nimport { Connection } from \"@solana/web3.js\";\nimport { HeliusWalletContext } from \"./HeliusWalletProvider\";\nimport { resolveRpcUrl, canSendDirect } from \"./rpc-url\";\nimport type {\n AuthStatus,\n HeliusWallet,\n EnhancedTransaction,\n PriorityFeeLevels,\n PriorityLevel,\n} from \"./types\";\n\nfunction deriveStatus(\n clientState: typeof ClientState[keyof typeof ClientState] | undefined,\n authState: typeof AuthState[keyof typeof AuthState]\n): AuthStatus {\n if (clientState === undefined || clientState === ClientState.Loading)\n return \"loading\";\n if (authState === AuthState.Authenticated) return \"authenticated\";\n return \"unauthenticated\";\n}\n\nexport function useHeliusWallet(): HeliusWallet {\n const {\n handleLogin,\n logout: turnkeyLogout,\n authState,\n clientState,\n user: turnkeyUser,\n session,\n wallets,\n signTransaction: turnkeySignTransaction,\n handleSignMessage,\n handleExportWallet,\n } = useTurnkey();\n\n const { rpcProxyPath, secureRpcUrl, cluster, setCluster, apiKey, projectId, planTier } =\n useContext(HeliusWalletContext);\n\n const rpcUrl = useMemo(() => {\n const origin =\n typeof window !== \"undefined\"\n ? window.location.origin\n : \"http://localhost\";\n return resolveRpcUrl(secureRpcUrl, cluster, rpcProxyPath, origin);\n }, [secureRpcUrl, rpcProxyPath, cluster]);\n\n const connection = useMemo(() => new Connection(rpcUrl), [rpcUrl]);\n\n const status = deriveStatus(clientState, authState);\n\n const address = wallets?.[0]?.accounts?.[0]?.address ?? null;\n\n const user = turnkeyUser\n ? {\n userId: turnkeyUser.userId,\n username: turnkeyUser.userName,\n email: turnkeyUser.userEmail ?? undefined,\n // session.organizationId is the end-user's sub-org id under the\n // configured auth proxy. Falls back to \"\" only in edge cases where\n // useTurnkey returns a user before the session is fully populated.\n subOrgId: session?.organizationId ?? \"\",\n walletId: wallets?.[0]?.walletId ?? null,\n }\n : null;\n\n const login = useCallback(() => handleLogin(), [handleLogin]);\n\n const logout = useCallback(() => turnkeyLogout(), [turnkeyLogout]);\n\n const signTransaction = useCallback(\n async (transaction: Uint8Array | Buffer): Promise<Buffer> => {\n const walletAccount = wallets?.[0]?.accounts?.[0];\n if (!walletAccount) throw new Error(\"No wallet available\");\n\n const hexEncoded = Buffer.from(transaction).toString(\"hex\");\n const signedHex = await turnkeySignTransaction({\n walletAccount,\n unsignedTransaction: hexEncoded,\n transactionType: \"TRANSACTION_TYPE_SOLANA\",\n });\n return Buffer.from(signedHex, \"hex\");\n },\n [wallets, turnkeySignTransaction]\n );\n\n const signAndSendTransaction = useCallback(\n async (transaction: Uint8Array | Buffer): Promise<string> => {\n const signed = await signTransaction(transaction);\n\n // Direct mode: send straight through the secure RPC connection — no route\n // handler or exposed key needed. This uses standard RPC send, NOT Helius\n // Sender, so it forgoes Sender's optimized landing (Jito dual-routing);\n // use proxy mode for best mainnet landing. `skipPreflight: true` matches\n // the prior Sender contract and avoids a second call on the rate-limited\n // secure URL. The tx goes through the connection it was signed against.\n if (canSendDirect(secureRpcUrl, cluster)) {\n return connection.sendRawTransaction(signed, { skipPreflight: true });\n }\n\n // Proxy mode: route through Helius Sender for optimized landing.\n const base64Tx = Buffer.from(signed).toString(\"base64\");\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (apiKey) headers[\"x-helius-api-key\"] = apiKey;\n\n const res = await fetch(\"/api/helius/send\", {\n method: \"POST\",\n headers,\n body: JSON.stringify({ transaction: base64Tx, cluster, address }),\n });\n\n const data = await res.json();\n if (data.error) throw new Error(data.error);\n return data.signature;\n },\n [signTransaction, cluster, apiKey, address, secureRpcUrl, connection]\n );\n\n const signMessage = useCallback(\n async (message: string): Promise<string> => {\n const walletAccount = wallets?.[0]?.accounts?.[0];\n if (!walletAccount) throw new Error(\"No wallet available\");\n\n const result = await handleSignMessage({\n message,\n walletAccount,\n });\n\n // Turnkey returns r, s as hex strings for Ed25519.\n // Concatenate r + s to form the 64-byte signature.\n const rBytes = Buffer.from(result.r, \"hex\");\n const sBytes = Buffer.from(result.s, \"hex\");\n const sigBytes = Buffer.concat([rBytes, sBytes]);\n\n // Return as hex string (the API route handles base58 encoding).\n return sigBytes.toString(\"hex\");\n },\n [wallets, handleSignMessage]\n );\n\n const exportWallet = useCallback(async (): Promise<void> => {\n const wallet = wallets?.[0];\n if (!wallet) throw new Error(\"No wallet available\");\n await handleExportWallet({ walletId: wallet.walletId });\n }, [wallets, handleExportWallet]);\n\n const getTransactions = useCallback(\n async (options?: { limit?: number }): Promise<EnhancedTransaction[]> => {\n if (!address) return [];\n const limit = options?.limit ?? 10;\n const headers: Record<string, string> = {};\n if (apiKey) headers[\"x-helius-api-key\"] = apiKey;\n\n // Enhanced-tx history has no secure-URL equivalent. In direct mode (this\n // cluster is served by a secure URL, so there's no route handler) surface\n // a clear error. In proxy mode, let real network/HTTP errors through\n // unchanged so they aren't masked by a misleading direct-mode message.\n const directMode = canSendDirect(secureRpcUrl, cluster);\n const historyUnavailable =\n \"getTransactions needs the Helius route handler (helius-wallet-kit/next); it isn't available in direct/secure-URL mode.\";\n let res: Response;\n try {\n res = await fetch(\n `/api/helius/transactions?address=${encodeURIComponent(address)}&cluster=${cluster}&limit=${limit}`,\n { headers }\n );\n } catch (err) {\n throw directMode ? new Error(historyUnavailable) : err;\n }\n if (res.status === 404 && directMode) throw new Error(historyUnavailable);\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error(err.error ?? `HTTP ${res.status}`);\n }\n const data = await res.json();\n return Array.isArray(data) ? data : (data.transactions ?? []);\n },\n [address, cluster, apiKey]\n );\n\n const getPriorityFee = useCallback(\n async (\n accountKeys: string[],\n priorityLevel: PriorityLevel = \"Medium\"\n ): Promise<number> => {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: \"helius-wallet-kit-priority-fee\",\n method: \"getPriorityFeeEstimate\",\n params: [{ accountKeys, options: { priorityLevel } }],\n }),\n });\n const data = await res.json();\n if (data.error) throw new Error(data.error.message ?? \"RPC error\");\n return data.result?.priorityFeeEstimate ?? 0;\n },\n [rpcUrl]\n );\n\n const getPriorityFeeLevels = useCallback(\n async (accountKeys: string[]): Promise<PriorityFeeLevels> => {\n const res = await fetch(rpcUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: \"helius-wallet-kit-priority-fee-levels\",\n method: \"getPriorityFeeEstimate\",\n params: [\n { accountKeys, options: { includeAllPriorityFeeLevels: true } },\n ],\n }),\n });\n const data = await res.json();\n if (data.error) throw new Error(data.error.message ?? \"RPC error\");\n const levels = data.result?.priorityFeeLevels ?? {};\n return {\n min: levels.min ?? 0,\n low: levels.low ?? 0,\n medium: levels.medium ?? 0,\n high: levels.high ?? 0,\n veryHigh: levels.veryHigh ?? 0,\n unsafeMax: levels.unsafeMax ?? 0,\n };\n },\n [rpcUrl]\n );\n\n return {\n address,\n status,\n user,\n login,\n logout,\n signTransaction,\n signAndSendTransaction,\n signMessage,\n exportWallet,\n getTransactions,\n getPriorityFee,\n getPriorityFeeLevels,\n connection,\n rpcUrl,\n cluster,\n setCluster,\n apiKey,\n projectId,\n planTier,\n };\n}\n"]}