cilantro-react 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/dist/index.js ADDED
@@ -0,0 +1,2867 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ AddSignerForm: () => AddSignerForm,
35
+ AuthForm: () => AuthForm,
36
+ AuthGuard: () => AuthGuard,
37
+ CilantroAuthProvider: () => CilantroAuthProvider,
38
+ CilantroProvider: () => CilantroProvider,
39
+ DelegatedKeySelector: () => DelegatedKeySelector,
40
+ LoginForm: () => LoginForm,
41
+ MessageSigningForm: () => MessageSigningForm,
42
+ RegisterForm: () => RegisterForm,
43
+ SIGNER_TYPES: () => SIGNER_TYPES,
44
+ SignerList: () => SignerList,
45
+ SignerSelector: () => SignerSelector,
46
+ TransactionSigningForm: () => TransactionSigningForm,
47
+ WalletProvider: () => WalletProvider,
48
+ WalletSelector: () => WalletSelector,
49
+ extractErrorMessage: () => extractErrorMessage,
50
+ extractResponseData: () => extractResponseData,
51
+ getSignerPublicKey: () => getSignerPublicKey,
52
+ getWalletData: () => getWalletData,
53
+ signAndSendTransactionWithSigner: () => signAndSendTransactionWithSigner,
54
+ signMessageWithSigner: () => signMessageWithSigner,
55
+ signTransactionWithSigner: () => signTransactionWithSigner,
56
+ useCilantroAuth: () => useCilantroAuth,
57
+ useMessageSigning: () => useMessageSigning,
58
+ useSignerSelection: () => useSignerSelection,
59
+ useSigners: () => useSigners,
60
+ useTransactionSigning: () => useTransactionSigning,
61
+ useWallets: () => useWallets
62
+ });
63
+ module.exports = __toCommonJS(index_exports);
64
+
65
+ // src/providers/CilantroProvider.tsx
66
+ var import_react3 = require("react");
67
+
68
+ // src/providers/CilantroAuthProvider.tsx
69
+ var import_react = require("react");
70
+ var import_cilantro_sdk2 = require("cilantro-sdk");
71
+ var import_auth = require("cilantro-sdk/auth");
72
+ var import_user = require("cilantro-sdk/user");
73
+
74
+ // src/core/auth.ts
75
+ var import_cilantro_sdk = require("cilantro-sdk");
76
+ var platformApiKey = "";
77
+ var apiUrl;
78
+ function setAuthConfig(config) {
79
+ platformApiKey = config.platformApiKey;
80
+ apiUrl = config.apiUrl;
81
+ const authPayload = {};
82
+ if (config.jwt) {
83
+ authPayload.jwt = config.jwt;
84
+ }
85
+ if (platformApiKey) {
86
+ authPayload.platformApiKey = platformApiKey;
87
+ }
88
+ if (apiUrl) {
89
+ authPayload.apiUrl = apiUrl;
90
+ }
91
+ (0, import_cilantro_sdk.setAuth)(authPayload);
92
+ }
93
+ function setSdkAuth(jwt) {
94
+ const authConfig = {};
95
+ if (jwt) {
96
+ authConfig.jwt = jwt;
97
+ }
98
+ if (platformApiKey) {
99
+ authConfig.platformApiKey = platformApiKey;
100
+ }
101
+ if (apiUrl) {
102
+ authConfig.apiUrl = apiUrl;
103
+ }
104
+ (0, import_cilantro_sdk.setAuth)(authConfig);
105
+ }
106
+ function getPlatformApiKey() {
107
+ return platformApiKey;
108
+ }
109
+
110
+ // src/core/types.ts
111
+ function extractResponseData(response) {
112
+ if (!response) return null;
113
+ if (typeof response !== "object" || response === null) {
114
+ return response;
115
+ }
116
+ if ("data" in response) {
117
+ const data = response.data;
118
+ if (data && typeof data === "object" && !Array.isArray(data)) {
119
+ const dataObj = data;
120
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) {
121
+ const authSigners = Array.isArray(dataObj.authenticationSigners) ? dataObj.authenticationSigners : [];
122
+ const onChainSigners = Array.isArray(dataObj.onChainSigners) ? dataObj.onChainSigners : [];
123
+ return [...authSigners, ...onChainSigners];
124
+ }
125
+ }
126
+ return data;
127
+ }
128
+ if ("success" in response && "data" in response) {
129
+ const data = response.data;
130
+ if (data && typeof data === "object" && !Array.isArray(data)) {
131
+ const dataObj = data;
132
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) {
133
+ const authSigners = Array.isArray(dataObj.authenticationSigners) ? dataObj.authenticationSigners : [];
134
+ const onChainSigners = Array.isArray(dataObj.onChainSigners) ? dataObj.onChainSigners : [];
135
+ return [...authSigners, ...onChainSigners];
136
+ }
137
+ }
138
+ return data;
139
+ }
140
+ if ("authenticationSigners" in response || "onChainSigners" in response) {
141
+ const responseObj = response;
142
+ const authSigners = Array.isArray(responseObj.authenticationSigners) ? responseObj.authenticationSigners : [];
143
+ const onChainSigners = Array.isArray(responseObj.onChainSigners) ? responseObj.onChainSigners : [];
144
+ return [...authSigners, ...onChainSigners];
145
+ }
146
+ return response;
147
+ }
148
+ function extractOnChainSigners(response) {
149
+ if (!response || typeof response !== "object" || response === null) return [];
150
+ let signersObj = null;
151
+ if ("data" in response) {
152
+ const data = response.data;
153
+ if (data && typeof data === "object" && !Array.isArray(data)) {
154
+ const dataObj = data;
155
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) signersObj = dataObj;
156
+ }
157
+ }
158
+ if (!signersObj && "success" in response && "data" in response) {
159
+ const data = response.data;
160
+ if (data && typeof data === "object" && !Array.isArray(data)) {
161
+ const dataObj = data;
162
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) signersObj = dataObj;
163
+ }
164
+ }
165
+ if (!signersObj && ("authenticationSigners" in response || "onChainSigners" in response)) {
166
+ signersObj = response;
167
+ }
168
+ if (signersObj) {
169
+ return Array.isArray(signersObj.onChainSigners) ? signersObj.onChainSigners : [];
170
+ }
171
+ if (Array.isArray(response)) return response;
172
+ return [];
173
+ }
174
+ function extractAuthenticationSigners(response) {
175
+ if (!response || typeof response !== "object" || response === null) return [];
176
+ let signersObj = null;
177
+ if ("data" in response) {
178
+ const data = response.data;
179
+ if (data && typeof data === "object" && !Array.isArray(data)) {
180
+ const dataObj = data;
181
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) signersObj = dataObj;
182
+ }
183
+ }
184
+ if (!signersObj && "success" in response && "data" in response) {
185
+ const data = response.data;
186
+ if (data && typeof data === "object" && !Array.isArray(data)) {
187
+ const dataObj = data;
188
+ if ("authenticationSigners" in dataObj || "onChainSigners" in dataObj) signersObj = dataObj;
189
+ }
190
+ }
191
+ if (!signersObj && ("authenticationSigners" in response || "onChainSigners" in response)) {
192
+ signersObj = response;
193
+ }
194
+ if (signersObj) {
195
+ return Array.isArray(signersObj.authenticationSigners) ? signersObj.authenticationSigners : [];
196
+ }
197
+ return [];
198
+ }
199
+ function isErrorWithResponse(error) {
200
+ return typeof error === "object" && error !== null && "response" in error;
201
+ }
202
+ function isErrorWithMessage(error) {
203
+ return typeof error === "object" && error !== null && "message" in error;
204
+ }
205
+
206
+ // src/core/error-utils.ts
207
+ function extractErrorMessage(error) {
208
+ if (!error) return "An unknown error occurred";
209
+ if (error instanceof Error) return error.message;
210
+ if (isErrorWithResponse(error)) {
211
+ if (error.response?.data?.message) return String(error.response.data.message);
212
+ if (error.response?.data?.error) return String(error.response.data.error);
213
+ }
214
+ if (isErrorWithMessage(error)) return String(error.message);
215
+ if (typeof error === "object" && error !== null && "error" in error) {
216
+ return String(error.error);
217
+ }
218
+ return String(error);
219
+ }
220
+
221
+ // src/providers/CilantroAuthProvider.tsx
222
+ var import_jsx_runtime = require("react/jsx-runtime");
223
+ var AuthContext = (0, import_react.createContext)(void 0);
224
+ var DEFAULT_JWT_STORAGE_KEY = "cilantro_jwt";
225
+ function CilantroAuthProvider({
226
+ children,
227
+ platformApiKey: platformApiKey2,
228
+ apiUrl: apiUrl2,
229
+ jwtStorageKey = DEFAULT_JWT_STORAGE_KEY,
230
+ onLoginSuccess,
231
+ onLogout,
232
+ onRegisterSuccess
233
+ }) {
234
+ const [user, setUser] = (0, import_react.useState)(null);
235
+ const [token, setToken] = (0, import_react.useState)(null);
236
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
237
+ (0, import_react.useEffect)(() => {
238
+ setAuthConfig({ platformApiKey: platformApiKey2, apiUrl: apiUrl2 });
239
+ setSdkAuth(null);
240
+ const storedToken = typeof window !== "undefined" ? localStorage.getItem(jwtStorageKey) : null;
241
+ if (storedToken) {
242
+ setToken(storedToken);
243
+ setSdkAuth(storedToken);
244
+ try {
245
+ const payload = JSON.parse(atob(storedToken.split(".")[1]));
246
+ setUser({
247
+ username: payload.username,
248
+ email: payload.email,
249
+ userType: payload.userType
250
+ });
251
+ } catch {
252
+ }
253
+ }
254
+ setIsLoading(false);
255
+ }, [platformApiKey2, apiUrl2, jwtStorageKey]);
256
+ const login = async (usernameOrEmail, password) => {
257
+ try {
258
+ const result = await (0, import_auth.login)({ usernameOrEmail, password });
259
+ const responseData = extractResponseData(result);
260
+ if (!responseData?.jwt) throw new Error("No JWT token received from server");
261
+ const jwt = responseData.jwt;
262
+ const userType = responseData.userType;
263
+ setToken(jwt);
264
+ setSdkAuth(jwt);
265
+ if (typeof window !== "undefined") {
266
+ localStorage.setItem(jwtStorageKey, jwt);
267
+ document.cookie = `cilantro_jwt=${jwt}; path=/; max-age=${60 * 60 * 24 * 7}`;
268
+ }
269
+ try {
270
+ const payload = JSON.parse(atob(jwt.split(".")[1]));
271
+ setUser({
272
+ username: payload.username,
273
+ email: payload.email,
274
+ userType: userType ?? payload.userType
275
+ });
276
+ } catch {
277
+ setUser({ userType });
278
+ }
279
+ onLoginSuccess?.();
280
+ } catch (error) {
281
+ throw new Error(extractErrorMessage(error));
282
+ }
283
+ };
284
+ const register = async (username, email, password, isActive = true) => {
285
+ try {
286
+ setSdkAuth(null);
287
+ const platformKey = getPlatformApiKey();
288
+ const userData = { username, email, password, isActive };
289
+ if (platformKey) userData.platformApiKey = platformKey;
290
+ await (0, import_user.create)(userData);
291
+ await login(username, password);
292
+ onRegisterSuccess?.();
293
+ } catch (error) {
294
+ throw new Error(extractErrorMessage(error));
295
+ }
296
+ };
297
+ const logout = () => {
298
+ setUser(null);
299
+ setToken(null);
300
+ (0, import_cilantro_sdk2.clearAuth)();
301
+ if (typeof window !== "undefined") {
302
+ localStorage.removeItem(jwtStorageKey);
303
+ const keys = Object.keys(localStorage);
304
+ keys.forEach((key) => {
305
+ if (key.startsWith("delegated-key-")) localStorage.removeItem(key);
306
+ });
307
+ document.cookie = "cilantro_jwt=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
308
+ }
309
+ setSdkAuth(null);
310
+ onLogout?.();
311
+ };
312
+ const value = {
313
+ user,
314
+ token,
315
+ isAuthenticated: !!token,
316
+ login,
317
+ register,
318
+ logout,
319
+ isLoading
320
+ };
321
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthContext.Provider, { value, children });
322
+ }
323
+ function useCilantroAuth() {
324
+ const context = (0, import_react.useContext)(AuthContext);
325
+ if (context === void 0) {
326
+ throw new Error("useCilantroAuth must be used within a CilantroAuthProvider");
327
+ }
328
+ return context;
329
+ }
330
+
331
+ // src/providers/WalletProvider.tsx
332
+ var import_react2 = require("react");
333
+ var import_wallet = require("cilantro-sdk/wallet");
334
+ var import_jsx_runtime2 = require("react/jsx-runtime");
335
+ var WalletContext = (0, import_react2.createContext)(void 0);
336
+ var DEFAULT_STORAGE_KEY = "cilantro_selected_wallet_id";
337
+ function WalletProvider({ children, storageKey = DEFAULT_STORAGE_KEY }) {
338
+ const { token } = useCilantroAuth();
339
+ const [wallets, setWallets] = (0, import_react2.useState)([]);
340
+ const [selectedWallet, setSelectedWallet] = (0, import_react2.useState)(null);
341
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
342
+ (0, import_react2.useEffect)(() => {
343
+ if (token) {
344
+ loadWallets();
345
+ } else {
346
+ setWallets([]);
347
+ setSelectedWallet(null);
348
+ setIsLoading(false);
349
+ }
350
+ }, [token]);
351
+ (0, import_react2.useEffect)(() => {
352
+ if (wallets.length > 0 && !selectedWallet) {
353
+ const storedWalletId = typeof window !== "undefined" ? localStorage.getItem(storageKey) : null;
354
+ if (storedWalletId) {
355
+ const wallet = wallets.find((w) => w.id === storedWalletId || w.walletId === storedWalletId);
356
+ if (wallet) {
357
+ setSelectedWallet(wallet);
358
+ } else {
359
+ setSelectedWallet(wallets[0]);
360
+ if (typeof window !== "undefined") localStorage.setItem(storageKey, wallets[0].id);
361
+ }
362
+ } else {
363
+ if (wallets.length > 0) {
364
+ setSelectedWallet(wallets[0]);
365
+ if (typeof window !== "undefined") localStorage.setItem(storageKey, wallets[0].id);
366
+ }
367
+ }
368
+ } else if (wallets.length === 0) {
369
+ setSelectedWallet(null);
370
+ if (typeof window !== "undefined") localStorage.removeItem(storageKey);
371
+ }
372
+ }, [wallets, storageKey]);
373
+ const loadWallets = async () => {
374
+ try {
375
+ setIsLoading(true);
376
+ if (token) setSdkAuth(token);
377
+ const result = await (0, import_wallet.findAll)();
378
+ const walletsList = extractResponseData(result) ?? [];
379
+ const formattedWallets = Array.isArray(walletsList) ? walletsList.map((wallet) => {
380
+ const w = wallet;
381
+ return {
382
+ id: String(w.walletId ?? w.id ?? ""),
383
+ walletId: String(w.walletId ?? w.id ?? ""),
384
+ walletName: w.walletName ?? "",
385
+ address: w.walletAddress ?? w.address ?? "",
386
+ walletAddress: w.walletAddress ?? w.address ?? "",
387
+ chain: w.chain ?? "solana",
388
+ active: w.active !== false,
389
+ ...w
390
+ };
391
+ }) : [];
392
+ setWallets(formattedWallets);
393
+ } catch (error) {
394
+ console.error("Failed to load wallets:", error);
395
+ setWallets([]);
396
+ } finally {
397
+ setIsLoading(false);
398
+ }
399
+ };
400
+ const selectWallet = (walletId) => {
401
+ const wallet = wallets.find((w) => w.id === walletId || w.walletId === walletId);
402
+ if (wallet) {
403
+ setSelectedWallet(wallet);
404
+ if (typeof window !== "undefined") localStorage.setItem(storageKey, wallet.id);
405
+ }
406
+ };
407
+ const refreshWallets = async () => {
408
+ await loadWallets();
409
+ };
410
+ const value = {
411
+ selectedWallet,
412
+ wallets,
413
+ selectWallet,
414
+ refreshWallets,
415
+ isLoading
416
+ };
417
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(WalletContext.Provider, { value, children });
418
+ }
419
+ function useWallets() {
420
+ const context = (0, import_react2.useContext)(WalletContext);
421
+ if (context === void 0) {
422
+ throw new Error("useWallets must be used within a WalletProvider");
423
+ }
424
+ return context;
425
+ }
426
+
427
+ // src/core/storage-adapter.ts
428
+ var import_helpers = require("cilantro-sdk/helpers");
429
+ var storageAdapterInstance = null;
430
+ var initializationPromise = null;
431
+ async function initializeStorageAdapter() {
432
+ if (storageAdapterInstance) return storageAdapterInstance;
433
+ if (initializationPromise) return initializationPromise;
434
+ if (typeof window === "undefined") {
435
+ throw new Error("Storage adapter can only be initialized in browser environment.");
436
+ }
437
+ initializationPromise = (async () => {
438
+ try {
439
+ storageAdapterInstance = (0, import_helpers.createIndexedDBAdapter)();
440
+ return storageAdapterInstance;
441
+ } catch (error) {
442
+ initializationPromise = null;
443
+ throw error;
444
+ }
445
+ })();
446
+ return initializationPromise;
447
+ }
448
+ function getStorageAdapter() {
449
+ if (storageAdapterInstance) return storageAdapterInstance;
450
+ if (typeof window === "undefined") {
451
+ throw new Error("Storage adapter can only be initialized in browser environment.");
452
+ }
453
+ storageAdapterInstance = (0, import_helpers.createIndexedDBAdapter)();
454
+ return storageAdapterInstance;
455
+ }
456
+
457
+ // src/providers/CilantroProvider.tsx
458
+ var import_jsx_runtime3 = require("react/jsx-runtime");
459
+ function CilantroProvider({
460
+ children,
461
+ platformApiKey: platformApiKey2,
462
+ apiUrl: apiUrl2,
463
+ jwtStorageKey,
464
+ walletStorageKey,
465
+ onLoginSuccess,
466
+ onLogout,
467
+ onRegisterSuccess
468
+ }) {
469
+ (0, import_react3.useEffect)(() => {
470
+ initializeStorageAdapter().catch((err) => {
471
+ console.error("[CilantroProvider] Failed to initialize storage adapter:", err);
472
+ });
473
+ }, []);
474
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
475
+ CilantroAuthProvider,
476
+ {
477
+ platformApiKey: platformApiKey2,
478
+ apiUrl: apiUrl2,
479
+ jwtStorageKey,
480
+ onLoginSuccess,
481
+ onLogout,
482
+ onRegisterSuccess,
483
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WalletProvider, { storageKey: walletStorageKey, children })
484
+ }
485
+ );
486
+ }
487
+
488
+ // src/hooks/useSigners.ts
489
+ var import_react4 = require("react");
490
+
491
+ // src/core/signer-helpers.ts
492
+ var import_helpers2 = require("cilantro-sdk/helpers");
493
+ var import_wallet2 = require("cilantro-sdk/wallet");
494
+ async function loadSigners(walletId) {
495
+ if (!walletId) return [];
496
+ try {
497
+ let signersResult = await (0, import_helpers2.getSigners)(walletId);
498
+ let onChainSigners = extractOnChainSigners(signersResult);
499
+ let authSigners = extractAuthenticationSigners(signersResult);
500
+ if ((!onChainSigners || !Array.isArray(onChainSigners) || onChainSigners.length === 0) && (!authSigners || !Array.isArray(authSigners) || authSigners.length === 0)) {
501
+ const response = await (0, import_wallet2.listSigners)(walletId);
502
+ onChainSigners = extractOnChainSigners(response);
503
+ authSigners = extractAuthenticationSigners(response);
504
+ }
505
+ const processedOnChain = onChainSigners.filter((s) => s && typeof s === "object").map((signer) => processSigner(signer, "onchain"));
506
+ const processedAuth = authSigners.filter((s) => s && typeof s === "object").map((signer) => processSigner(signer, "authenticationsigner"));
507
+ return [...processedOnChain, ...processedAuth].filter((s) => s.id && (s.type || s.signerType));
508
+ } catch (error) {
509
+ console.error("Failed to load signers:", error);
510
+ return [];
511
+ }
512
+ }
513
+ function processSigner(signer, category) {
514
+ const parsed = (0, import_helpers2.parseSignerResponse)(signer);
515
+ const signerId = signer.id ?? signer.signerId ?? parsed.signerId;
516
+ const signerType = signer.signerType ?? signer.type ?? parsed.type;
517
+ const signerPubkey = signer.signerPubkey ?? signer.publicKey ?? parsed.publicKey ?? "";
518
+ const authId = signer.authId ?? parsed.email ?? parsed.phone;
519
+ const walletId = signer.walletId ?? parsed.walletId;
520
+ let email = signer.email ?? parsed.email;
521
+ let phone = signer.phone ?? parsed.phone;
522
+ if (!email && !phone && authId) {
523
+ if (signerType === "email") email = authId;
524
+ else if (signerType === "phone") phone = authId;
525
+ }
526
+ const signerConfig = signer.signerConfig;
527
+ if (signerConfig) {
528
+ if (!email && signerConfig.email) email = signerConfig.email;
529
+ if (!phone && signerConfig.phone) phone = signerConfig.phone;
530
+ }
531
+ const isActive = signer.isActive !== void 0 ? signer.isActive : parsed.isActive !== void 0 ? parsed.isActive : true;
532
+ return {
533
+ ...signer,
534
+ id: signerId,
535
+ signerId,
536
+ walletId: walletId ?? "",
537
+ type: signerType,
538
+ signerType,
539
+ publicKey: signerPubkey,
540
+ signerPubkey,
541
+ email,
542
+ phone,
543
+ isActive,
544
+ credentialId: signer.credentialId ?? (signerType === "passkey" ? authId : void 0),
545
+ authId,
546
+ deviceIdentities: signer.deviceIdentities,
547
+ signerConfig: signer.signerConfig,
548
+ permissions: signer.permissions,
549
+ signerCategory: category
550
+ };
551
+ }
552
+ function getSignerType(signer) {
553
+ return signer.type || signer.signerType || "";
554
+ }
555
+ function getSignerTypeLabel(type) {
556
+ if (!type) return "Unknown";
557
+ const t = type.toLowerCase();
558
+ if (t === "email") return "Email";
559
+ if (t === "phone") return "Phone";
560
+ if (t === "external" || t === "external-wallet") return "External Wallet";
561
+ if (t === "passkey") return "Passkey";
562
+ if (t === "api-key" || t === "apikey") return "API Key";
563
+ return type;
564
+ }
565
+ function getSignerDisplayName(signer) {
566
+ const signerType = getSignerType(signer);
567
+ const typeLabel = getSignerTypeLabel(signerType);
568
+ const shortId = signer.id.length > 8 ? `${signer.id.slice(0, 4)}...${signer.id.slice(-4)}` : signer.id;
569
+ if (signer.email) return `${typeLabel}: ${signer.email}`;
570
+ if (signer.phone) return `${typeLabel}: ${signer.phone}`;
571
+ if (signerType === "passkey") {
572
+ const credId = signer.credentialId ?? signer.authId ?? signer.signerConfig?.credentialId;
573
+ if (credId) {
574
+ const shortCredId = credId.length > 12 ? `${credId.slice(0, 6)}...${credId.slice(-6)}` : credId;
575
+ return `${typeLabel} (${shortCredId})`;
576
+ }
577
+ return `${typeLabel} (${shortId})`;
578
+ }
579
+ return `${typeLabel} (${shortId})`;
580
+ }
581
+ function getSignerUniqueId(signer) {
582
+ if (signer.id) return signer.id.length > 12 ? `${signer.id.slice(0, 6)}...${signer.id.slice(-6)}` : signer.id;
583
+ if (signer.publicKey) return `${signer.publicKey.slice(0, 6)}...${signer.publicKey.slice(-6)}`;
584
+ return "Unknown";
585
+ }
586
+ function extractSignerInfo(signer) {
587
+ const signerType = signer.type || signer.signerType;
588
+ const signerId = signer.id || signer.signerId;
589
+ if (!signerType) throw new Error(`Signer type is missing. Signer data: ${JSON.stringify(signer)}`);
590
+ if (!signerId) throw new Error(`Signer ID is missing. Signer data: ${JSON.stringify(signer)}`);
591
+ return { signerId, signerType };
592
+ }
593
+
594
+ // src/hooks/useSigners.ts
595
+ function useSigners(options = {}) {
596
+ const { walletId: walletIdOption } = options;
597
+ const { token } = useCilantroAuth();
598
+ const [signers, setSigners] = (0, import_react4.useState)([]);
599
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
600
+ const [error, setError] = (0, import_react4.useState)(null);
601
+ const load = (0, import_react4.useCallback)(async (walletId) => {
602
+ if (!walletId) {
603
+ setSigners([]);
604
+ return;
605
+ }
606
+ setIsLoading(true);
607
+ setError(null);
608
+ try {
609
+ if (token) setSdkAuth(token);
610
+ const list = await loadSigners(walletId);
611
+ setSigners(list);
612
+ } catch (err) {
613
+ const message = err instanceof Error ? err.message : String(err);
614
+ setError(message);
615
+ setSigners([]);
616
+ } finally {
617
+ setIsLoading(false);
618
+ }
619
+ }, [token]);
620
+ (0, import_react4.useEffect)(() => {
621
+ const id = walletIdOption ?? void 0;
622
+ if (id) load(id);
623
+ else {
624
+ setSigners([]);
625
+ setError(null);
626
+ }
627
+ }, [walletIdOption, load]);
628
+ const refresh = (0, import_react4.useCallback)(async () => {
629
+ const id = walletIdOption ?? void 0;
630
+ if (id) await load(id);
631
+ }, [walletIdOption, load]);
632
+ return { signers, isLoading, error, refresh };
633
+ }
634
+
635
+ // src/hooks/useSignerSelection.ts
636
+ var import_react5 = require("react");
637
+ function useSignerSelection(options = {}) {
638
+ const { walletId: walletIdOverride, signingMethod = "sdk-signer" } = options;
639
+ const { selectedWallet } = useWallets();
640
+ const effectiveWalletId = walletIdOverride ?? selectedWallet?.id ?? selectedWallet?.walletId ?? "";
641
+ const { signers: availableSigners, isLoading: isLoadingSigners } = useSigners({
642
+ walletId: effectiveWalletId || null
643
+ });
644
+ const [selectedWalletId, setSelectedWalletId] = (0, import_react5.useState)(effectiveWalletId);
645
+ const [selectedSigner, setSelectedSigner] = (0, import_react5.useState)(null);
646
+ (0, import_react5.useEffect)(() => {
647
+ setSelectedWalletId(effectiveWalletId);
648
+ }, [effectiveWalletId]);
649
+ (0, import_react5.useEffect)(() => {
650
+ if (signingMethod !== "sdk-signer") {
651
+ setSelectedSigner(null);
652
+ }
653
+ }, [signingMethod]);
654
+ const reset = (0, import_react5.useCallback)(() => {
655
+ setSelectedWalletId("");
656
+ setSelectedSigner(null);
657
+ }, []);
658
+ return {
659
+ selectedWalletId: selectedWalletId || effectiveWalletId,
660
+ setSelectedWalletId,
661
+ availableSigners,
662
+ selectedSigner,
663
+ setSelectedSigner,
664
+ isLoadingSigners,
665
+ reset
666
+ };
667
+ }
668
+
669
+ // src/hooks/useMessageSigning.ts
670
+ var import_react6 = require("react");
671
+
672
+ // src/core/signer-signing/core.ts
673
+ var import_web3 = require("@solana/web3.js");
674
+ var import_helpers3 = require("cilantro-sdk/helpers");
675
+
676
+ // src/core/signer-signing/constants.ts
677
+ var CACHE_CONFIG = { enabled: true, ttl: 3e5 };
678
+ var SIGNER_TYPES = {
679
+ EMAIL: "email",
680
+ PHONE: "phone",
681
+ PASSKEY: "passkey",
682
+ EXTERNAL: "external",
683
+ API_KEY: "apiKey"
684
+ };
685
+ function isValidSignerType(type) {
686
+ return Object.values(SIGNER_TYPES).includes(type);
687
+ }
688
+
689
+ // src/core/signer-signing/storage.ts
690
+ function getSignerStorage() {
691
+ return getStorageAdapter();
692
+ }
693
+ function getStorageOptions() {
694
+ return {
695
+ deviceKeyManager: getSignerStorage(),
696
+ cache: CACHE_CONFIG
697
+ };
698
+ }
699
+
700
+ // src/core/signer-signing/core.ts
701
+ async function getSignerPublicKey(walletId, signer, signerType, signerId) {
702
+ const existingPubkey = signer.signerPubkey || signer.publicKey;
703
+ if (existingPubkey && typeof existingPubkey === "string" && existingPubkey.trim()) {
704
+ return new import_web3.PublicKey(existingPubkey.trim());
705
+ }
706
+ const storageOptions = getStorageOptions();
707
+ if (signerType === SIGNER_TYPES.EMAIL) {
708
+ const keypair = await (0, import_helpers3.getEmailSignerKeypair)(walletId, signerId, storageOptions);
709
+ return new import_web3.PublicKey(keypair.publicKey);
710
+ }
711
+ if (signerType === SIGNER_TYPES.PHONE) {
712
+ const keypair = await (0, import_helpers3.getPhoneSignerKeypair)(walletId, signerId, storageOptions);
713
+ return new import_web3.PublicKey(keypair.publicKey);
714
+ }
715
+ if (signerType === SIGNER_TYPES.EXTERNAL || signerType === SIGNER_TYPES.API_KEY) {
716
+ const keypair = await (0, import_helpers3.deriveSignerKeypair)(walletId, signerId, signerType, storageOptions);
717
+ return new import_web3.PublicKey(keypair.publicKey);
718
+ }
719
+ throw new Error(`Unsupported signer type: ${signerType}`);
720
+ }
721
+
722
+ // src/core/signer-signing/message-signing.ts
723
+ var import_helpers6 = require("cilantro-sdk/helpers");
724
+
725
+ // src/core/signer-creation.ts
726
+ var import_web32 = require("@solana/web3.js");
727
+ var import_helpers4 = require("cilantro-sdk/helpers");
728
+ var import_transactions = require("cilantro-sdk/transactions");
729
+ var import_wallet3 = require("cilantro-sdk/wallet");
730
+ async function createEmailSignerHelper(walletId, email) {
731
+ const trimmedEmail = email.trim();
732
+ if (!trimmedEmail) throw new Error("Email address is required");
733
+ if (!(0, import_helpers4.isValidEmail)(trimmedEmail)) throw new Error("Invalid email address format");
734
+ const deviceKeyManager = getStorageAdapter();
735
+ return await (0, import_helpers4.createEmailSignerHelper)(walletId, { email: trimmedEmail, deviceKeyManager });
736
+ }
737
+ async function createPhoneSignerHelper(walletId, phone) {
738
+ const trimmedPhone = phone.trim();
739
+ if (!trimmedPhone) throw new Error("Phone number is required");
740
+ if (!(0, import_helpers4.isValidPhone)(trimmedPhone)) throw new Error("Invalid phone number format");
741
+ const deviceKeyManager = getStorageAdapter();
742
+ return await (0, import_helpers4.createPhoneSignerHelper)(walletId, { phone: trimmedPhone, deviceKeyManager });
743
+ }
744
+ async function createExternalSignerHelper(walletId, address) {
745
+ if (!address.trim()) throw new Error("Wallet address is required");
746
+ return await (0, import_wallet3.createExternalWalletSigner)(walletId, { address: address.trim(), chain: "solana" });
747
+ }
748
+ async function registerPasskeySigner(walletId) {
749
+ if (!(0, import_helpers4.isWebAuthnSupported)()) throw new Error("WebAuthn is not supported in this browser");
750
+ return await (0, import_helpers4.registerPasskeyComplete)(walletId);
751
+ }
752
+ async function signWithPasskey(walletId, signerId, message, options) {
753
+ if (!(0, import_helpers4.isWebAuthnSupported)()) throw new Error("WebAuthn is not supported in this browser");
754
+ const messageBytes = new TextEncoder().encode(message);
755
+ const signature = await (0, import_helpers4.signWithPasskeySigner)(walletId, signerId, messageBytes, options);
756
+ return {
757
+ signature: Buffer.from(signature).toString("hex"),
758
+ signer: signerId
759
+ };
760
+ }
761
+ async function signAndSendPasskeyTransaction(walletId, signerId, transaction, options) {
762
+ if (!(0, import_helpers4.isWebAuthnSupported)()) throw new Error("WebAuthn is not supported in this browser");
763
+ let credentialId = options?.credentialId;
764
+ if (!credentialId) {
765
+ const signers = await loadSigners(walletId);
766
+ const passkeySigner = signers.find((s) => s.id === signerId || s.signerId === signerId);
767
+ if (!passkeySigner) {
768
+ throw new Error(
769
+ `Passkey signer ${signerId} not found in wallet. Available signers: ${signers.map((s) => `${s.id} (${s.type})`).join(", ")}`
770
+ );
771
+ }
772
+ credentialId = passkeySigner.credentialId ?? passkeySigner.signerConfig?.credentialId ?? passkeySigner.authId;
773
+ if (!credentialId) {
774
+ throw new Error(`Credential ID not found for passkey signer ${signerId}.`);
775
+ }
776
+ }
777
+ let mintAddress = options?.mintAddress;
778
+ if (!mintAddress && transaction.instructions.length > 0) {
779
+ const systemProgramId = new import_web32.PublicKey("11111111111111111111111111111111");
780
+ const feePayer = transaction.feePayer || systemProgramId;
781
+ transaction.instructions.forEach((ix) => {
782
+ ix.keys.forEach((key) => {
783
+ if (key.isWritable && key.isSigner && !key.pubkey.equals(feePayer) && !mintAddress) {
784
+ mintAddress = key.pubkey.toString();
785
+ }
786
+ });
787
+ });
788
+ }
789
+ const unsignedTransaction = transaction.serialize({ verifySignatures: false }).toString("base64");
790
+ const authOptions = await (0, import_wallet3.startPasskeyAuthentication)(walletId, {
791
+ credentialId: options?.credentialId
792
+ });
793
+ const authData = extractResponseData(authOptions);
794
+ if (!authData) throw new Error("Failed to get authentication options");
795
+ const authDataValue = authData && typeof authData === "object" && "data" in authData ? authData.data : authData;
796
+ const credential = await (0, import_helpers4.authenticateWithPasskey)(
797
+ authDataValue,
798
+ { useBrowserAutofill: options?.useBrowserAutofill ?? false }
799
+ );
800
+ const formattedCredential = (0, import_helpers4.formatAuthenticationResponse)(credential);
801
+ const dto = {
802
+ walletId,
803
+ credentialId,
804
+ unsignedTransaction,
805
+ signature: formattedCredential.response.signature,
806
+ authenticatorData: formattedCredential.response.authenticatorData,
807
+ clientDataJSON: formattedCredential.response.clientDataJSON
808
+ };
809
+ const result = await (0, import_transactions.sendRawPasskeyTransaction)(dto);
810
+ const resultData = extractResponseData(result);
811
+ return { signature: resultData?.signature ?? "", status: resultData?.status };
812
+ }
813
+
814
+ // src/core/signer-signing/errors.ts
815
+ var import_helpers5 = require("cilantro-sdk/helpers");
816
+ function handleDeviceKeyError(error, signerType) {
817
+ if (error instanceof import_helpers5.DeviceKeyNotFoundError) {
818
+ throw new Error(
819
+ `Device key not found. Please create the ${signerType} signer first using the Signers page. The device key is generated when you create the signer.`
820
+ );
821
+ }
822
+ if (error instanceof import_helpers5.DeviceKeyMismatchError) {
823
+ throw new Error(
824
+ "Device key mismatch. The stored device key doesn't match the server. You may need to create a new signer or update the device identity."
825
+ );
826
+ }
827
+ if (error instanceof import_helpers5.SignerNotFoundError) {
828
+ throw new Error(`Signer not found. Please ensure the ${signerType} signer exists.`);
829
+ }
830
+ if (error instanceof import_helpers5.SignerInactiveError) {
831
+ throw new Error(`${signerType} signer is not active. Please activate the signer first.`);
832
+ }
833
+ if (error instanceof Error) {
834
+ if (error.message.includes("Device key not found") || error.name === "DeviceKeyNotFoundError") {
835
+ throw new Error(
836
+ `Device key not found. Please create the ${signerType} signer first using the Signers page. The device key is generated when you create the signer.`
837
+ );
838
+ }
839
+ if (error.message.includes("Device key mismatch") || error.name === "DeviceKeyMismatchError") {
840
+ throw new Error(
841
+ "Device key mismatch. The stored device key doesn't match the server. You may need to create a new signer or update the device identity."
842
+ );
843
+ }
844
+ }
845
+ throw error;
846
+ }
847
+
848
+ // src/core/signer-signing/signer-types.ts
849
+ function extractSignerInfo2(signer) {
850
+ const signerType = signer.type || signer.signerType;
851
+ const signerId = signer.id || signer.signerId;
852
+ if (!signerType || !signerId) {
853
+ throw new Error(`Signer type or ID is missing. Signer data: ${JSON.stringify(signer)}`);
854
+ }
855
+ if (!isValidSignerType(signerType)) {
856
+ throw new Error(`Unsupported signer type: ${signerType}`);
857
+ }
858
+ return { signerType, signerId };
859
+ }
860
+ function requiresActiveStatus(signerType) {
861
+ return signerType === SIGNER_TYPES.EMAIL || signerType === SIGNER_TYPES.PHONE || signerType === SIGNER_TYPES.EXTERNAL || signerType === SIGNER_TYPES.API_KEY;
862
+ }
863
+ function validateSignerActive(signer, signerType) {
864
+ if (requiresActiveStatus(signerType) && !signer.isActive) {
865
+ throw new Error(`${signerType} signer is not active. Please activate the signer first.`);
866
+ }
867
+ }
868
+
869
+ // src/core/signer-signing/message-signing.ts
870
+ async function signMessageWithSigner(walletId, signer, messageText) {
871
+ const { signerType, signerId } = extractSignerInfo2(signer);
872
+ const message = new TextEncoder().encode(messageText);
873
+ if (signerType === SIGNER_TYPES.EMAIL) {
874
+ validateSignerActive(signer, signerType);
875
+ const storageOptions = getStorageOptions();
876
+ try {
877
+ const signature = await (0, import_helpers6.signWithEmailSigner)(walletId, signerId, message, storageOptions);
878
+ const keypair = await (0, import_helpers6.getEmailSignerKeypair)(walletId, signerId, storageOptions);
879
+ return {
880
+ signature: Buffer.from(signature).toString("hex"),
881
+ publicKey: Buffer.from(keypair.publicKey).toString("hex"),
882
+ signerType: SIGNER_TYPES.EMAIL
883
+ };
884
+ } catch (error) {
885
+ throw handleDeviceKeyError(error, SIGNER_TYPES.EMAIL);
886
+ }
887
+ }
888
+ if (signerType === SIGNER_TYPES.PHONE) {
889
+ validateSignerActive(signer, signerType);
890
+ const storageOptions = getStorageOptions();
891
+ try {
892
+ const signature = await (0, import_helpers6.signWithPhoneSigner)(walletId, signerId, message, storageOptions);
893
+ const keypair = await (0, import_helpers6.getPhoneSignerKeypair)(walletId, signerId, storageOptions);
894
+ return {
895
+ signature: Buffer.from(signature).toString("hex"),
896
+ publicKey: Buffer.from(keypair.publicKey).toString("hex"),
897
+ signerType: SIGNER_TYPES.PHONE
898
+ };
899
+ } catch (error) {
900
+ throw handleDeviceKeyError(error, SIGNER_TYPES.PHONE);
901
+ }
902
+ }
903
+ if (signerType === SIGNER_TYPES.PASSKEY) {
904
+ const signResult = await signWithPasskey(walletId, signerId, messageText, { useBrowserAutofill: false });
905
+ return {
906
+ signature: signResult.signature,
907
+ signerType: SIGNER_TYPES.PASSKEY,
908
+ signer: signResult.signer
909
+ };
910
+ }
911
+ if (signerType === SIGNER_TYPES.EXTERNAL || signerType === SIGNER_TYPES.API_KEY) {
912
+ validateSignerActive(signer, signerType);
913
+ const storageOptions = getStorageOptions();
914
+ const signature = await (0, import_helpers6.signWithSigner)(walletId, signerId, signerType, message, storageOptions);
915
+ const keypair = await (0, import_helpers6.deriveSignerKeypair)(walletId, signerId, signerType, storageOptions);
916
+ return {
917
+ signature: Buffer.from(signature).toString("hex"),
918
+ publicKey: Buffer.from(keypair.publicKey).toString("base64"),
919
+ signerType
920
+ };
921
+ }
922
+ throw new Error(`Unsupported signer type: ${signerType}`);
923
+ }
924
+
925
+ // src/core/signer-signing/transaction-signing.ts
926
+ var import_helpers7 = require("cilantro-sdk/helpers");
927
+ var import_wallet4 = require("cilantro-sdk/wallet");
928
+
929
+ // src/core/signer-signing/validation.ts
930
+ var import_web33 = require("@solana/web3.js");
931
+ async function validateSignerInTransaction(signedTransactionBase64, expectedSignerPublicKey) {
932
+ const errors = [];
933
+ const warnings = [];
934
+ try {
935
+ const transactionBuffer = Buffer.from(signedTransactionBase64, "base64");
936
+ const transaction = import_web33.Transaction.from(transactionBuffer);
937
+ let allSignaturesValid = true;
938
+ try {
939
+ transaction.verifySignatures();
940
+ } catch (error) {
941
+ allSignaturesValid = false;
942
+ errors.push(`Signature verification failed: ${extractErrorMessage(error)}`);
943
+ }
944
+ const signers = transaction.signatures.map((sig) => {
945
+ const publicKeyStr = sig.publicKey.toString();
946
+ const hasSignature = sig.signature !== null && sig.signature.length > 0;
947
+ const signatureLength = sig.signature !== null ? sig.signature.length : 0;
948
+ let matchesExpected = false;
949
+ if (expectedSignerPublicKey) {
950
+ const expectedPubkey = typeof expectedSignerPublicKey === "string" ? new import_web33.PublicKey(expectedSignerPublicKey) : expectedSignerPublicKey;
951
+ matchesExpected = sig.publicKey.equals(expectedPubkey);
952
+ }
953
+ if (!hasSignature) warnings.push(`Signer ${publicKeyStr} has no signature (unsigned)`);
954
+ return { publicKey: publicKeyStr, hasSignature, signatureLength, matchesExpected };
955
+ });
956
+ let expectedSignerFound = false;
957
+ if (expectedSignerPublicKey) {
958
+ const expectedPubkey = typeof expectedSignerPublicKey === "string" ? new import_web33.PublicKey(expectedSignerPublicKey) : expectedSignerPublicKey;
959
+ expectedSignerFound = signers.some((s) => s.matchesExpected);
960
+ if (!expectedSignerFound) {
961
+ errors.push(`Expected signer ${expectedPubkey.toString()} not found in transaction signers`);
962
+ }
963
+ }
964
+ if (expectedSignerFound && expectedSignerPublicKey) {
965
+ const expectedSigner = signers.find((s) => s.matchesExpected);
966
+ if (expectedSigner && !expectedSigner.hasSignature) {
967
+ errors.push(
968
+ `Expected signer ${typeof expectedSignerPublicKey === "string" ? expectedSignerPublicKey : expectedSignerPublicKey.toString()} is present but has no signature`
969
+ );
970
+ }
971
+ }
972
+ const isValid = allSignaturesValid && (expectedSignerPublicKey ? expectedSignerFound : true) && errors.length === 0;
973
+ return {
974
+ isValid,
975
+ transaction,
976
+ signers,
977
+ expectedSignerFound,
978
+ allSignaturesValid,
979
+ feePayer: transaction.feePayer?.toString(),
980
+ recentBlockhash: transaction.recentBlockhash ?? void 0,
981
+ errors,
982
+ warnings
983
+ };
984
+ } catch (error) {
985
+ errors.push(`Failed to deserialize transaction: ${extractErrorMessage(error)}`);
986
+ throw new Error(
987
+ `Transaction validation failed: ${errors.join("; ")}
988
+ Original error: ${extractErrorMessage(error)}`
989
+ );
990
+ }
991
+ }
992
+
993
+ // src/core/signer-signing/transaction-signing.ts
994
+ function prepareTransactionForSigning(transaction, signerPublicKey) {
995
+ const signerPubkeyStr = signerPublicKey.toString();
996
+ const hasSignerInSignatures = transaction.signatures.some(
997
+ (sig) => sig.publicKey.toString() === signerPubkeyStr
998
+ );
999
+ if (!hasSignerInSignatures) {
1000
+ transaction.signatures.push({
1001
+ publicKey: signerPublicKey,
1002
+ signature: null
1003
+ });
1004
+ }
1005
+ if (transaction.feePayer) {
1006
+ const feePayerStr = transaction.feePayer.toString();
1007
+ const hasFeePayerInSignatures = transaction.signatures.some(
1008
+ (sig) => sig.publicKey.toString() === feePayerStr
1009
+ );
1010
+ if (!hasFeePayerInSignatures) {
1011
+ transaction.signatures.push({ publicKey: transaction.feePayer, signature: null });
1012
+ }
1013
+ }
1014
+ }
1015
+ async function signTransactionWithEmailOrPhone(walletId, signerId, signerType, unsignedTransactionBase64) {
1016
+ const storageOptions = getStorageOptions();
1017
+ if (signerType === SIGNER_TYPES.EMAIL) {
1018
+ return await (0, import_helpers7.signTransactionWithEmailSigner)(
1019
+ walletId,
1020
+ signerId,
1021
+ unsignedTransactionBase64,
1022
+ storageOptions
1023
+ );
1024
+ }
1025
+ return await (0, import_helpers7.signTransactionWithPhoneSigner)(
1026
+ walletId,
1027
+ signerId,
1028
+ unsignedTransactionBase64,
1029
+ storageOptions
1030
+ );
1031
+ }
1032
+ async function submitSignedTransaction(walletId, signedTransactionBase64) {
1033
+ const submitResult = await (0, import_wallet4.submitTransaction)(walletId, {
1034
+ signedTransaction: signedTransactionBase64
1035
+ });
1036
+ const resultData = extractResponseData(submitResult);
1037
+ if (!resultData?.signature) throw new Error("Server did not return a transaction signature");
1038
+ return {
1039
+ signature: resultData.signature,
1040
+ confirmationStatus: resultData.status === "confirmed" ? "confirmed" : "pending"
1041
+ };
1042
+ }
1043
+ async function handlePasskeyTransaction(walletId, signerId, transaction, connection) {
1044
+ if (!connection) {
1045
+ throw new Error(
1046
+ "Connection is required for passkey sign-and-send. Pass the connection from your Solana config to useTransactionSigning / TransactionSigningForm."
1047
+ );
1048
+ }
1049
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
1050
+ const result = await signAndSendPasskeyTransaction(walletId, signerId, transaction, {
1051
+ useBrowserAutofill: false
1052
+ });
1053
+ let confirmationStatus = "confirmed";
1054
+ try {
1055
+ await connection.confirmTransaction({
1056
+ signature: result.signature,
1057
+ blockhash,
1058
+ lastValidBlockHeight
1059
+ });
1060
+ } catch (error) {
1061
+ const errorMsg = extractErrorMessage(error);
1062
+ if (errorMsg.includes("block height exceeded") || errorMsg.includes("expired") || errorMsg.includes("timeout")) {
1063
+ confirmationStatus = "pending";
1064
+ } else {
1065
+ throw new Error(`Transaction confirmation failed: ${errorMsg}. Signature: ${result.signature}`);
1066
+ }
1067
+ }
1068
+ return { signature: result.signature, confirmationStatus };
1069
+ }
1070
+ async function handleEmailOrPhoneTransaction(walletId, signer, signerType, signerId, transaction) {
1071
+ validateSignerActive(signer, signerType);
1072
+ const signerPublicKey = await getSignerPublicKey(walletId, signer, signerType, signerId);
1073
+ prepareTransactionForSigning(transaction, signerPublicKey);
1074
+ const unsignedTransactionBase64 = Buffer.from(
1075
+ transaction.serialize({ verifySignatures: false })
1076
+ ).toString("base64");
1077
+ let signedTransactionBase64;
1078
+ try {
1079
+ signedTransactionBase64 = await signTransactionWithEmailOrPhone(
1080
+ walletId,
1081
+ signerId,
1082
+ signerType,
1083
+ unsignedTransactionBase64
1084
+ );
1085
+ } catch (error) {
1086
+ handleDeviceKeyError(error, signerType);
1087
+ throw error;
1088
+ }
1089
+ try {
1090
+ const validationResult = await validateSignerInTransaction(
1091
+ signedTransactionBase64,
1092
+ signerPublicKey
1093
+ );
1094
+ if (!validationResult.isValid) {
1095
+ console.error("Transaction validation failed:", {
1096
+ errors: validationResult.errors,
1097
+ warnings: validationResult.warnings
1098
+ });
1099
+ }
1100
+ } catch (validationError) {
1101
+ console.error("Validation error (non-fatal):", extractErrorMessage(validationError));
1102
+ }
1103
+ return await submitSignedTransaction(walletId, signedTransactionBase64);
1104
+ }
1105
+ async function handleExternalOrApiKeyTransaction(walletId, signer, signerType, signerId, transaction) {
1106
+ validateSignerActive(signer, signerType);
1107
+ const messageBytes = transaction.serializeMessage();
1108
+ const storageOptions = getStorageOptions();
1109
+ const signatureBytes = await (0, import_helpers7.signWithSigner)(
1110
+ walletId,
1111
+ signerId,
1112
+ signerType,
1113
+ messageBytes,
1114
+ storageOptions
1115
+ );
1116
+ const signerPublicKey = await getSignerPublicKey(walletId, signer, signerType, signerId);
1117
+ const signatureBuffer = Buffer.from(signatureBytes);
1118
+ transaction.addSignature(signerPublicKey, signatureBuffer);
1119
+ const signedTransactionBytes = transaction.serialize();
1120
+ const signedTransactionBase64 = Buffer.from(signedTransactionBytes).toString("base64");
1121
+ return await submitSignedTransaction(walletId, signedTransactionBase64);
1122
+ }
1123
+ async function signTransactionWithSigner(walletId, signer, transactionBuffer) {
1124
+ const { signerType, signerId } = extractSignerInfo2(signer);
1125
+ const storageOptions = getStorageOptions();
1126
+ if (signerType === SIGNER_TYPES.EMAIL) {
1127
+ validateSignerActive(signer, signerType);
1128
+ try {
1129
+ const signature = await (0, import_helpers7.signWithEmailSigner)(walletId, signerId, transactionBuffer, storageOptions);
1130
+ return { signature: Buffer.from(signature).toString("hex"), signerType: SIGNER_TYPES.EMAIL };
1131
+ } catch (error) {
1132
+ throw handleDeviceKeyError(error, SIGNER_TYPES.EMAIL);
1133
+ }
1134
+ }
1135
+ if (signerType === SIGNER_TYPES.PHONE) {
1136
+ validateSignerActive(signer, signerType);
1137
+ try {
1138
+ const signature = await (0, import_helpers7.signWithPhoneSigner)(walletId, signerId, transactionBuffer, storageOptions);
1139
+ return { signature: Buffer.from(signature).toString("hex"), signerType: SIGNER_TYPES.PHONE };
1140
+ } catch (error) {
1141
+ throw handleDeviceKeyError(error, SIGNER_TYPES.PHONE);
1142
+ }
1143
+ }
1144
+ if (signerType === SIGNER_TYPES.PASSKEY) {
1145
+ const { signWithPasskeySigner: signWithPasskeySigner2 } = await import("cilantro-sdk/helpers");
1146
+ const signature = await signWithPasskeySigner2(walletId, signerId, transactionBuffer, {
1147
+ useBrowserAutofill: false
1148
+ });
1149
+ return { signature: Buffer.from(signature).toString("hex"), signerType: SIGNER_TYPES.PASSKEY };
1150
+ }
1151
+ if (signerType === SIGNER_TYPES.EXTERNAL || signerType === SIGNER_TYPES.API_KEY) {
1152
+ validateSignerActive(signer, signerType);
1153
+ const signature = await (0, import_helpers7.signWithSigner)(
1154
+ walletId,
1155
+ signerId,
1156
+ signerType,
1157
+ transactionBuffer,
1158
+ storageOptions
1159
+ );
1160
+ return { signature: Buffer.from(signature).toString("hex"), signerType };
1161
+ }
1162
+ throw new Error(`Unsupported signer type: ${signerType}`);
1163
+ }
1164
+ async function signAndSendTransactionWithSigner(walletId, signer, transaction, connection) {
1165
+ const { signerType, signerId } = extractSignerInfo2(signer);
1166
+ if (signerType === SIGNER_TYPES.PASSKEY) {
1167
+ return await handlePasskeyTransaction(walletId, signerId, transaction, connection);
1168
+ }
1169
+ if (signerType === SIGNER_TYPES.EMAIL || signerType === SIGNER_TYPES.PHONE) {
1170
+ return await handleEmailOrPhoneTransaction(walletId, signer, signerType, signerId, transaction);
1171
+ }
1172
+ if (signerType === SIGNER_TYPES.EXTERNAL || signerType === SIGNER_TYPES.API_KEY) {
1173
+ return await handleExternalOrApiKeyTransaction(walletId, signer, signerType, signerId, transaction);
1174
+ }
1175
+ throw new Error(`Unsupported signer type: ${signerType}`);
1176
+ }
1177
+
1178
+ // src/core/signer-signing/wallet-data.ts
1179
+ var import_web34 = require("@solana/web3.js");
1180
+ var import_wallet5 = require("cilantro-sdk/wallet");
1181
+ async function getWalletData(walletId) {
1182
+ const walletDataResponse = await (0, import_wallet5.findOne)(walletId);
1183
+ const walletData = extractResponseData(walletDataResponse);
1184
+ if (!walletData) throw new Error("Wallet data is empty");
1185
+ const address = String(
1186
+ walletData.address ?? walletData.walletAddress ?? walletData.solanaAddress ?? walletData.publicKey ?? walletData.pubkey ?? ""
1187
+ ).trim();
1188
+ if (!address) throw new Error(`No wallet address found. Available fields: ${Object.keys(walletData).join(", ")}`);
1189
+ const walletPublicKey = new import_web34.PublicKey(address);
1190
+ const adminData = walletData.admin;
1191
+ const adminPubkey = String(
1192
+ walletData.adminSignerPubkey ?? walletData.adminSigner ?? adminData?.publicKey ?? ""
1193
+ ).trim();
1194
+ if (!adminPubkey) {
1195
+ throw new Error(
1196
+ `adminSignerPubkey not found in wallet data. Available fields: ${Object.keys(walletData).join(", ")}`
1197
+ );
1198
+ }
1199
+ const adminSignerPubkey = new import_web34.PublicKey(adminPubkey);
1200
+ return { walletPublicKey, adminSignerPubkey };
1201
+ }
1202
+
1203
+ // src/hooks/useMessageSigning.ts
1204
+ function useMessageSigning(options) {
1205
+ const {
1206
+ token,
1207
+ signingMethod,
1208
+ selectedSigner,
1209
+ selectedWalletId,
1210
+ walletAdapterSignMessage,
1211
+ walletAdapterPublicKey
1212
+ } = options;
1213
+ const [messageText, setMessageText] = (0, import_react6.useState)("Hello, Solana!");
1214
+ const [signResultState, setSignResultState] = (0, import_react6.useState)({ status: "idle" });
1215
+ const [isSigning, setIsSigning] = (0, import_react6.useState)(false);
1216
+ const handleSign = async () => {
1217
+ setIsSigning(true);
1218
+ setSignResultState({ status: "loading" });
1219
+ try {
1220
+ if (token) setSdkAuth(token);
1221
+ if (!messageText.trim()) throw new Error("Please enter a message to sign.");
1222
+ if (signingMethod === "wallet-adapter") {
1223
+ if (!walletAdapterSignMessage) {
1224
+ throw new Error("Wallet adapter signMessage not provided.");
1225
+ }
1226
+ const message = new TextEncoder().encode(messageText);
1227
+ const signature = await walletAdapterSignMessage(message);
1228
+ setSignResultState({
1229
+ status: "success",
1230
+ message: "Message signed successfully!",
1231
+ detail: {
1232
+ message: messageText,
1233
+ signature: Array.from(signature).map((b) => b.toString(16).padStart(2, "0")).join(""),
1234
+ publicKey: walletAdapterPublicKey ?? void 0
1235
+ }
1236
+ });
1237
+ return;
1238
+ }
1239
+ if (!selectedSigner || !selectedWalletId) throw new Error("Please select a signer.");
1240
+ const result = await signMessageWithSigner(selectedWalletId, selectedSigner, messageText);
1241
+ const { signerType } = extractSignerInfo(selectedSigner);
1242
+ setSignResultState({
1243
+ status: "success",
1244
+ message: `Message signed successfully with ${signerType} signer!`,
1245
+ detail: { message: messageText, ...result }
1246
+ });
1247
+ } catch (error) {
1248
+ const errorMsg = extractErrorMessage(error);
1249
+ const isCancelled = errorMsg.toLowerCase().includes("cancel") || errorMsg.toLowerCase().includes("notallowederror");
1250
+ setSignResultState({
1251
+ status: "error",
1252
+ message: isCancelled ? "User cancelled authentication" : errorMsg
1253
+ });
1254
+ } finally {
1255
+ setIsSigning(false);
1256
+ }
1257
+ };
1258
+ const reset = () => {
1259
+ setMessageText("Hello, Solana!");
1260
+ setSignResultState({ status: "idle" });
1261
+ };
1262
+ return {
1263
+ messageText,
1264
+ setMessageText,
1265
+ signResultState,
1266
+ isSigning,
1267
+ handleSign,
1268
+ reset
1269
+ };
1270
+ }
1271
+
1272
+ // src/hooks/useTransactionSigning.ts
1273
+ var import_react7 = require("react");
1274
+ function useTransactionSigning(options) {
1275
+ const {
1276
+ token,
1277
+ signingMethod,
1278
+ selectedSigner,
1279
+ selectedWalletId,
1280
+ walletAdapterSignTransaction,
1281
+ walletAdapterPublicKey,
1282
+ connection
1283
+ } = options;
1284
+ const [transactionResultState, setTransactionResultState] = (0, import_react7.useState)({ status: "idle" });
1285
+ const [isSigningTransaction, setIsSigningTransaction] = (0, import_react7.useState)(false);
1286
+ const [isSendingTransaction, setIsSendingTransaction] = (0, import_react7.useState)(false);
1287
+ const signTransaction = async (transaction) => {
1288
+ setIsSigningTransaction(true);
1289
+ setTransactionResultState({ status: "loading" });
1290
+ try {
1291
+ if (token) setSdkAuth(token);
1292
+ if (signingMethod === "wallet-adapter") {
1293
+ if (!walletAdapterSignTransaction || !walletAdapterPublicKey) {
1294
+ throw new Error("Wallet adapter signTransaction or publicKey not provided.");
1295
+ }
1296
+ const signed = await walletAdapterSignTransaction(transaction);
1297
+ setTransactionResultState({
1298
+ status: "success",
1299
+ message: "Transaction signed successfully!",
1300
+ detail: { transaction: signed.serialize().toString("base64") }
1301
+ });
1302
+ return;
1303
+ }
1304
+ if (!selectedSigner || !selectedWalletId) throw new Error("Please select a signer.");
1305
+ const { signerId, signerType } = extractSignerInfo(selectedSigner);
1306
+ if (signerType === "passkey") {
1307
+ throw new Error("Passkey signers cannot be used for sign-only. Use sign-and-send instead.");
1308
+ }
1309
+ const transactionBuffer = transaction.serializeMessage();
1310
+ const result = await signTransactionWithSigner(
1311
+ selectedWalletId,
1312
+ selectedSigner,
1313
+ transactionBuffer
1314
+ );
1315
+ setTransactionResultState({
1316
+ status: "success",
1317
+ message: `Transaction signed with ${signerType} signer!`,
1318
+ detail: { ...result }
1319
+ });
1320
+ } catch (error) {
1321
+ const errorMsg = extractErrorMessage(error);
1322
+ const isCancelled = errorMsg.toLowerCase().includes("cancel") || errorMsg.toLowerCase().includes("notallowederror");
1323
+ setTransactionResultState({
1324
+ status: "error",
1325
+ message: isCancelled ? "User cancelled authentication" : errorMsg
1326
+ });
1327
+ } finally {
1328
+ setIsSigningTransaction(false);
1329
+ }
1330
+ };
1331
+ const signAndSendTransaction = async (transaction) => {
1332
+ setIsSendingTransaction(true);
1333
+ setTransactionResultState({ status: "loading" });
1334
+ try {
1335
+ if (token) setSdkAuth(token);
1336
+ if (signingMethod === "wallet-adapter") {
1337
+ if (!walletAdapterSignTransaction || !walletAdapterPublicKey || !connection) {
1338
+ throw new Error("Wallet adapter signTransaction, publicKey, or connection not provided.");
1339
+ }
1340
+ const signed = await walletAdapterSignTransaction(transaction);
1341
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
1342
+ const signature = await connection.sendRawTransaction(Buffer.from(signed.serialize()));
1343
+ await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });
1344
+ setTransactionResultState({
1345
+ status: "success",
1346
+ message: "Transaction sent successfully!",
1347
+ detail: { signature, explorerUrl: `https://solscan.io/tx/${signature}?cluster=devnet` }
1348
+ });
1349
+ return;
1350
+ }
1351
+ if (!selectedSigner || !selectedWalletId) throw new Error("Please select a signer.");
1352
+ const { signerType } = extractSignerInfo(selectedSigner);
1353
+ const result = await signAndSendTransactionWithSigner(
1354
+ selectedWalletId,
1355
+ selectedSigner,
1356
+ transaction,
1357
+ connection ?? void 0
1358
+ );
1359
+ setTransactionResultState({
1360
+ status: "success",
1361
+ message: `Transaction sent with ${signerType} signer!`,
1362
+ detail: {
1363
+ signature: result.signature,
1364
+ confirmationStatus: result.confirmationStatus,
1365
+ explorerUrl: `https://solscan.io/tx/${result.signature}?cluster=devnet`
1366
+ }
1367
+ });
1368
+ } catch (error) {
1369
+ const errorMsg = extractErrorMessage(error);
1370
+ const isCancelled = errorMsg.toLowerCase().includes("cancel") || errorMsg.toLowerCase().includes("notallowederror");
1371
+ setTransactionResultState({
1372
+ status: "error",
1373
+ message: isCancelled ? "User cancelled transaction" : errorMsg,
1374
+ detail: { error: errorMsg, walletId: selectedWalletId }
1375
+ });
1376
+ } finally {
1377
+ setIsSendingTransaction(false);
1378
+ }
1379
+ };
1380
+ const reset = () => {
1381
+ setTransactionResultState({ status: "idle" });
1382
+ };
1383
+ return {
1384
+ transactionResultState,
1385
+ isSigningTransaction,
1386
+ isSendingTransaction,
1387
+ signTransaction,
1388
+ signAndSendTransaction,
1389
+ reset
1390
+ };
1391
+ }
1392
+
1393
+ // src/ui/select.tsx
1394
+ var React = __toESM(require("react"));
1395
+ var SelectPrimitive = __toESM(require("@radix-ui/react-select"));
1396
+
1397
+ // src/ui/cn.ts
1398
+ var import_clsx = require("clsx");
1399
+ var import_tailwind_merge = require("tailwind-merge");
1400
+ function cn(...inputs) {
1401
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
1402
+ }
1403
+
1404
+ // src/ui/select.tsx
1405
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1406
+ var Select = SelectPrimitive.Root;
1407
+ var SelectValue = SelectPrimitive.Value;
1408
+ var SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1409
+ SelectPrimitive.Trigger,
1410
+ {
1411
+ ref,
1412
+ className: cn(
1413
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
1414
+ className
1415
+ ),
1416
+ ...props,
1417
+ children: [
1418
+ children,
1419
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "ml-2 h-4 w-4 shrink-0 opacity-50", children: "\u25BC" }) })
1420
+ ]
1421
+ }
1422
+ ));
1423
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
1424
+ var SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1425
+ SelectPrimitive.Content,
1426
+ {
1427
+ ref,
1428
+ className: cn(
1429
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1430
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1431
+ className
1432
+ ),
1433
+ position,
1434
+ ...props,
1435
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1436
+ SelectPrimitive.Viewport,
1437
+ {
1438
+ className: cn(
1439
+ "p-1",
1440
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
1441
+ ),
1442
+ children
1443
+ }
1444
+ )
1445
+ }
1446
+ ) }));
1447
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
1448
+ var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1449
+ SelectPrimitive.Item,
1450
+ {
1451
+ ref,
1452
+ className: cn(
1453
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1454
+ className
1455
+ ),
1456
+ ...props,
1457
+ children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.ItemIndicator, { children: "\u2713" }) }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPrimitive.ItemText, { children })
1460
+ ]
1461
+ }
1462
+ ));
1463
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
1464
+
1465
+ // src/components/WalletSelector.tsx
1466
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1467
+ function WalletSelector(props) {
1468
+ const {
1469
+ value,
1470
+ onWalletChange,
1471
+ className,
1472
+ classNames,
1473
+ placeholder = "Select a wallet",
1474
+ renderTrigger,
1475
+ renderList,
1476
+ children
1477
+ } = props;
1478
+ const { wallets, selectedWallet, selectWallet, isLoading, refreshWallets } = useWallets();
1479
+ const effectiveValue = value ?? selectedWallet?.id ?? selectedWallet?.walletId ?? "";
1480
+ const selected = wallets.find((w) => w.id === effectiveValue || w.walletId === effectiveValue) ?? selectedWallet;
1481
+ const handleSelect = (wallet) => {
1482
+ selectWallet(wallet.id);
1483
+ onWalletChange?.(wallet.id, wallet);
1484
+ };
1485
+ const handleValueChange = (id) => {
1486
+ selectWallet(id);
1487
+ onWalletChange?.(id, wallets.find((w) => w.id === id || w.walletId === id) ?? null);
1488
+ };
1489
+ if (children) {
1490
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: children({
1491
+ wallets,
1492
+ selectedWallet: selected,
1493
+ selectWallet: (id) => {
1494
+ selectWallet(id);
1495
+ onWalletChange?.(id, wallets.find((w) => w.id === id || w.walletId === id) ?? null);
1496
+ },
1497
+ isLoading,
1498
+ refreshWallets
1499
+ }) });
1500
+ }
1501
+ if (renderTrigger || renderList) {
1502
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn(className, classNames?.root), "data-cilantro-wallet-selector": true, children: [
1503
+ renderTrigger?.({ selectedWallet: selected, wallets, isLoading, open: false, setOpen: () => {
1504
+ } }),
1505
+ renderList?.({ wallets, selectedWallet: selected, onSelect: handleSelect, isLoading })
1506
+ ] });
1507
+ }
1508
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-wallet-selector": true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Select, { value: effectiveValue || void 0, onValueChange: handleValueChange, disabled: isLoading, children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectTrigger, { className: classNames?.trigger, "aria-label": "Select wallet", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectValue, { placeholder: isLoading ? "Loading..." : placeholder }) }),
1510
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectContent, { className: classNames?.content, children: wallets.map((w) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectItem, { value: w.id, className: classNames?.item, children: w.walletName || w.id }, w.id)) })
1511
+ ] }) });
1512
+ }
1513
+
1514
+ // src/ui/button.tsx
1515
+ var React2 = __toESM(require("react"));
1516
+ var import_react_slot = require("@radix-ui/react-slot");
1517
+ var import_class_variance_authority = require("class-variance-authority");
1518
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1519
+ var buttonVariants = (0, import_class_variance_authority.cva)(
1520
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1521
+ {
1522
+ variants: {
1523
+ variant: {
1524
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
1525
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1526
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
1527
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
1528
+ ghost: "hover:bg-accent hover:text-accent-foreground",
1529
+ link: "text-primary underline-offset-4 hover:underline"
1530
+ },
1531
+ size: {
1532
+ default: "h-10 px-4 py-2",
1533
+ sm: "h-9 rounded-md px-3",
1534
+ lg: "h-11 rounded-md px-8",
1535
+ icon: "h-10 w-10"
1536
+ }
1537
+ },
1538
+ defaultVariants: {
1539
+ variant: "default",
1540
+ size: "default"
1541
+ }
1542
+ }
1543
+ );
1544
+ var Button = React2.forwardRef(
1545
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
1546
+ const Comp = asChild ? import_react_slot.Slot : "button";
1547
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
1548
+ }
1549
+ );
1550
+ Button.displayName = "Button";
1551
+
1552
+ // src/components/SignerSelector.tsx
1553
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1554
+ function SignerSelector({
1555
+ selectedWalletId,
1556
+ availableSigners,
1557
+ selectedSigner,
1558
+ isLoadingSigners = false,
1559
+ onSignerSelect,
1560
+ className,
1561
+ classNames,
1562
+ renderList,
1563
+ children
1564
+ }) {
1565
+ if (!selectedWalletId) return null;
1566
+ if (children) {
1567
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: children({ signers: availableSigners, selectedSigner, onSignerSelect, isLoading: isLoadingSigners }) });
1568
+ }
1569
+ if (renderList) {
1570
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-signer-selector": true, children: renderList({
1571
+ signers: availableSigners,
1572
+ selectedSigner,
1573
+ onSelect: onSignerSelect,
1574
+ isLoading: isLoadingSigners,
1575
+ getSignerDisplayName,
1576
+ getSignerTypeLabel,
1577
+ getSignerUniqueId
1578
+ }) });
1579
+ }
1580
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-signer-selector": true, role: "listbox", "aria-label": "Select signer", children: isLoadingSigners ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "Loading signers..." }) : availableSigners.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "No signers for this wallet." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: cn("space-y-1", classNames?.list), children: availableSigners.map((signer) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1581
+ Button,
1582
+ {
1583
+ type: "button",
1584
+ variant: selectedSigner?.id === signer.id ? "secondary" : "ghost",
1585
+ size: "sm",
1586
+ className: cn("w-full justify-start", classNames?.item),
1587
+ onClick: () => onSignerSelect(signer),
1588
+ "aria-pressed": selectedSigner?.id === signer.id,
1589
+ children: [
1590
+ getSignerDisplayName(signer),
1591
+ " (",
1592
+ getSignerTypeLabel(signer.type || signer.signerType || ""),
1593
+ ")"
1594
+ ]
1595
+ }
1596
+ ) }, signer.id)) }) });
1597
+ }
1598
+
1599
+ // src/components/DelegatedKeySelector.tsx
1600
+ var import_react8 = require("react");
1601
+ var import_delegated_keys = require("cilantro-sdk/delegated-keys");
1602
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1603
+ function DelegatedKeySelector(props) {
1604
+ const {
1605
+ walletId,
1606
+ value,
1607
+ onChange,
1608
+ filterActive = true,
1609
+ className,
1610
+ classNames,
1611
+ placeholder = "Select a delegated key",
1612
+ children
1613
+ } = props;
1614
+ const { token } = useCilantroAuth();
1615
+ const [keys, setKeys] = (0, import_react8.useState)([]);
1616
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1617
+ const [error, setError] = (0, import_react8.useState)(null);
1618
+ const loadKeys = (0, import_react8.useCallback)(async () => {
1619
+ if (!walletId) {
1620
+ setKeys([]);
1621
+ return;
1622
+ }
1623
+ setIsLoading(true);
1624
+ setError(null);
1625
+ try {
1626
+ if (token) setSdkAuth(token);
1627
+ const result = await (0, import_delegated_keys.findAll)(walletId);
1628
+ const keysData = extractResponseData(result) ?? [];
1629
+ const list = Array.isArray(keysData) ? keysData : [];
1630
+ let loaded = list.filter((k) => k != null && typeof k === "object" && "id" in k).map((k) => ({
1631
+ id: String(k.id ?? ""),
1632
+ walletId: String(k.walletId ?? ""),
1633
+ name: k.name,
1634
+ publicKey: String(k.publicKey ?? ""),
1635
+ permissions: k.permissions ?? {},
1636
+ isActive: k.isActive !== false,
1637
+ createdAt: k.createdAt,
1638
+ expiresAt: k.expiresAt,
1639
+ ...k
1640
+ }));
1641
+ if (filterActive) {
1642
+ const now = Date.now();
1643
+ loaded = loaded.filter((key) => {
1644
+ if (!key.isActive) return false;
1645
+ const exp = key.expiresAt ? new Date(key.expiresAt).getTime() : null;
1646
+ return exp === null || exp > now;
1647
+ });
1648
+ }
1649
+ setKeys(loaded);
1650
+ } catch (err) {
1651
+ setError(err instanceof Error ? err.message : String(err));
1652
+ setKeys([]);
1653
+ } finally {
1654
+ setIsLoading(false);
1655
+ }
1656
+ }, [walletId, token, filterActive]);
1657
+ (0, import_react8.useEffect)(() => {
1658
+ loadKeys();
1659
+ }, [loadKeys]);
1660
+ const onSelect = (key) => {
1661
+ onChange?.(key.id, key);
1662
+ };
1663
+ const handleValueChange = (id) => {
1664
+ const key = keys.find((k) => k.id === id) ?? null;
1665
+ onChange?.(id, key);
1666
+ };
1667
+ if (children) {
1668
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: children({ keys, selectedKeyId: value, onSelect, isLoading, error, refresh: loadKeys }) });
1669
+ }
1670
+ if (!walletId) {
1671
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn(className, classNames?.root, "text-sm text-muted-foreground"), children: "Select a wallet first" });
1672
+ }
1673
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-delegated-key-selector": true, children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "Loading delegated keys..." }) : error ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: cn("text-sm text-destructive", classNames?.message), role: "alert", children: error }) : keys.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "No delegated keys found." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Select, { value: (value ?? "") || void 0, onValueChange: handleValueChange, children: [
1674
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectTrigger, { className: classNames?.trigger, "aria-label": "Select delegated key", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectValue, { placeholder }) }),
1675
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectContent, { className: classNames?.content, children: keys.map((k) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: k.id, className: classNames?.item, children: k.name || k.publicKey.slice(0, 8) + "..." }, k.id)) })
1676
+ ] }) });
1677
+ }
1678
+
1679
+ // src/ui/textarea.tsx
1680
+ var React3 = __toESM(require("react"));
1681
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1682
+ var Textarea = React3.forwardRef(
1683
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1684
+ "textarea",
1685
+ {
1686
+ className: cn(
1687
+ "flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1688
+ className
1689
+ ),
1690
+ ref,
1691
+ ...props
1692
+ }
1693
+ )
1694
+ );
1695
+ Textarea.displayName = "Textarea";
1696
+
1697
+ // src/ui/label.tsx
1698
+ var React4 = __toESM(require("react"));
1699
+ var LabelPrimitive = __toESM(require("@radix-ui/react-label"));
1700
+ var import_class_variance_authority2 = require("class-variance-authority");
1701
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1702
+ var labelVariants = (0, import_class_variance_authority2.cva)(
1703
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
1704
+ );
1705
+ var Label = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props }));
1706
+ Label.displayName = LabelPrimitive.Root.displayName;
1707
+
1708
+ // src/ui/card.tsx
1709
+ var React5 = __toESM(require("react"));
1710
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1711
+ var Card = React5.forwardRef(
1712
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1713
+ "div",
1714
+ {
1715
+ ref,
1716
+ className: cn("rounded-xl border bg-card text-card-foreground shadow", className),
1717
+ ...props
1718
+ }
1719
+ )
1720
+ );
1721
+ Card.displayName = "Card";
1722
+ var CardHeader = React5.forwardRef(
1723
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
1724
+ );
1725
+ CardHeader.displayName = "CardHeader";
1726
+ var CardTitle = React5.forwardRef(
1727
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1728
+ "h3",
1729
+ {
1730
+ ref,
1731
+ className: cn("font-semibold leading-none tracking-tight", className),
1732
+ ...props
1733
+ }
1734
+ )
1735
+ );
1736
+ CardTitle.displayName = "CardTitle";
1737
+ var CardDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1738
+ CardDescription.displayName = "CardDescription";
1739
+ var CardContent = React5.forwardRef(
1740
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ref, className: cn("p-6 pt-0", className), ...props })
1741
+ );
1742
+ CardContent.displayName = "CardContent";
1743
+ var CardFooter = React5.forwardRef(
1744
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ref, className: cn("flex items-center p-6 pt-0", className), ...props })
1745
+ );
1746
+ CardFooter.displayName = "CardFooter";
1747
+
1748
+ // src/components/MessageSigningForm.tsx
1749
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1750
+ function MessageSigningForm({
1751
+ token: tokenOverride,
1752
+ selectedWalletId: walletIdOverride,
1753
+ selectedSigner: signerOverride,
1754
+ signingMethod: methodOverride,
1755
+ walletAdapterSignMessage,
1756
+ walletAdapterPublicKey,
1757
+ className,
1758
+ classNames,
1759
+ showContext = true,
1760
+ showCharCount = false,
1761
+ children
1762
+ }) {
1763
+ const { token: contextToken } = useCilantroAuth();
1764
+ const token = tokenOverride ?? contextToken;
1765
+ const selection = useSignerSelection({
1766
+ signingMethod: methodOverride ?? "sdk-signer",
1767
+ walletId: walletIdOverride
1768
+ });
1769
+ const selectedWalletId = walletIdOverride ?? selection.selectedWalletId;
1770
+ const selectedSigner = signerOverride ?? selection.selectedSigner;
1771
+ const signingMethod = methodOverride ?? "sdk-signer";
1772
+ const signing = useMessageSigning({
1773
+ token,
1774
+ signingMethod,
1775
+ selectedSigner,
1776
+ selectedWalletId,
1777
+ walletAdapterSignMessage,
1778
+ walletAdapterPublicKey
1779
+ });
1780
+ if (children) {
1781
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-message-signing-form": true, children: children({
1782
+ messageText: signing.messageText,
1783
+ setMessageText: signing.setMessageText,
1784
+ signResultState: signing.signResultState,
1785
+ isSigning: signing.isSigning,
1786
+ handleSign: signing.handleSign,
1787
+ reset: signing.reset
1788
+ }) });
1789
+ }
1790
+ const resultStatus = signing.signResultState.status;
1791
+ const isSuccess = resultStatus === "success";
1792
+ const isError = resultStatus === "error";
1793
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { className: cn(className, classNames?.root), "data-cilantro-message-signing-form": true, children: [
1794
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CardHeader, { className: classNames?.header, children: [
1795
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardTitle, { className: cn("text-lg", classNames?.title), children: "Sign message" }),
1796
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardDescription, { className: classNames?.description, children: "Sign a message with your selected wallet or signer. The signature proves you control the key." }),
1797
+ showContext && (selectedWalletId || selectedSigner) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: cn("mt-1 text-xs text-muted-foreground", classNames?.context), children: [
1798
+ selectedWalletId && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1799
+ "Wallet: ",
1800
+ selectedWalletId.slice(0, 8),
1801
+ "\u2026"
1802
+ ] }),
1803
+ selectedSigner && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: selectedWalletId ? " ml-2" : "", children: [
1804
+ "Signer: ",
1805
+ getSignerDisplayName(selectedSigner),
1806
+ " (",
1807
+ getSignerTypeLabel(selectedSigner.type || selectedSigner.signerType || ""),
1808
+ ")"
1809
+ ] })
1810
+ ] })
1811
+ ] }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(CardContent, { className: "space-y-4", children: [
1813
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-2", children: [
1814
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label, { htmlFor: "cilantro-message-text", className: classNames?.label, children: "Message" }),
1815
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1816
+ Textarea,
1817
+ {
1818
+ id: "cilantro-message-text",
1819
+ className: classNames?.textarea,
1820
+ value: signing.messageText,
1821
+ onChange: (e) => signing.setMessageText(e.target.value),
1822
+ placeholder: "Enter the message you want to sign...",
1823
+ rows: 4
1824
+ }
1825
+ ),
1826
+ showCharCount && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: cn("text-right text-xs text-muted-foreground", classNames?.charCount), children: [
1827
+ signing.messageText.length,
1828
+ " character",
1829
+ signing.messageText.length !== 1 ? "s" : ""
1830
+ ] })
1831
+ ] }),
1832
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center", children: [
1833
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1834
+ Button,
1835
+ {
1836
+ type: "button",
1837
+ className: cn("w-full sm:w-auto", classNames?.button),
1838
+ onClick: signing.handleSign,
1839
+ disabled: signing.isSigning || !signing.messageText.trim(),
1840
+ children: signing.isSigning ? "Signing..." : "Sign message"
1841
+ }
1842
+ ),
1843
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1844
+ Button,
1845
+ {
1846
+ type: "button",
1847
+ variant: "outline",
1848
+ className: cn("w-full sm:w-auto", classNames?.resetButton),
1849
+ onClick: signing.reset,
1850
+ disabled: signing.isSigning,
1851
+ children: "Clear"
1852
+ }
1853
+ )
1854
+ ] }),
1855
+ resultStatus !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1856
+ "div",
1857
+ {
1858
+ className: cn(
1859
+ "rounded-lg border px-3 py-2 text-sm",
1860
+ isSuccess && cn("border-green-500/50 bg-green-500/10 text-green-700 dark:text-green-400", classNames?.resultSuccess),
1861
+ isError && cn("border-destructive/50 bg-destructive/10 text-destructive", classNames?.resultError),
1862
+ resultStatus === "loading" && "border-muted bg-muted/50 text-muted-foreground",
1863
+ classNames?.result
1864
+ ),
1865
+ "data-status": resultStatus,
1866
+ children: [
1867
+ signing.signResultState.message,
1868
+ signing.signResultState.detail != null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { className: cn("mt-2 overflow-auto rounded-md bg-muted/80 p-2 text-xs", classNames?.resultPre), children: JSON.stringify(signing.signResultState.detail, null, 2) })
1869
+ ]
1870
+ }
1871
+ )
1872
+ ] })
1873
+ ] });
1874
+ }
1875
+
1876
+ // src/components/TransactionSigningForm.tsx
1877
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1878
+ function TransactionSigningForm({
1879
+ token: tokenOverride,
1880
+ selectedWalletId: walletIdOverride,
1881
+ selectedSigner: signerOverride,
1882
+ signingMethod: methodOverride,
1883
+ walletAdapterSignTransaction,
1884
+ walletAdapterPublicKey,
1885
+ connection,
1886
+ className,
1887
+ classNames,
1888
+ showContext = true,
1889
+ children
1890
+ }) {
1891
+ const { token: contextToken } = useCilantroAuth();
1892
+ const token = tokenOverride ?? contextToken;
1893
+ const selection = useSignerSelection({
1894
+ signingMethod: methodOverride ?? "sdk-signer",
1895
+ walletId: walletIdOverride
1896
+ });
1897
+ const selectedWalletId = walletIdOverride ?? selection.selectedWalletId;
1898
+ const selectedSigner = signerOverride ?? selection.selectedSigner;
1899
+ const signingMethod = methodOverride ?? "sdk-signer";
1900
+ const signing = useTransactionSigning({
1901
+ token,
1902
+ signingMethod,
1903
+ selectedSigner,
1904
+ selectedWalletId,
1905
+ walletAdapterSignTransaction,
1906
+ walletAdapterPublicKey,
1907
+ connection
1908
+ });
1909
+ if (children) {
1910
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-transaction-signing-form": true, children: children({
1911
+ transactionResultState: signing.transactionResultState,
1912
+ isSigningTransaction: signing.isSigningTransaction,
1913
+ isSendingTransaction: signing.isSendingTransaction,
1914
+ signTransaction: signing.signTransaction,
1915
+ signAndSendTransaction: signing.signAndSendTransaction,
1916
+ reset: signing.reset
1917
+ }) });
1918
+ }
1919
+ const resultStatus = signing.transactionResultState.status;
1920
+ const isSuccess = resultStatus === "success";
1921
+ const isError = resultStatus === "error";
1922
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Card, { className: cn(className, classNames?.root), "data-cilantro-transaction-signing-form": true, children: [
1923
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardHeader, { className: classNames?.header, children: [
1924
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardTitle, { className: cn("text-lg", classNames?.title), children: "Sign transaction" }),
1925
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardDescription, { className: classNames?.description, children: [
1926
+ "Build a transaction in your app, then pass it to ",
1927
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { className: "text-xs", children: "signTransaction(tx)" }),
1928
+ " to sign only, or ",
1929
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { className: "text-xs", children: "signAndSendTransaction(tx)" }),
1930
+ " to sign and send. Use the render props (children) to wire your own UI."
1931
+ ] }),
1932
+ showContext && (selectedWalletId || selectedSigner) && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: cn("mt-1 text-xs text-muted-foreground", classNames?.context), children: [
1933
+ selectedWalletId && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
1934
+ "Wallet: ",
1935
+ selectedWalletId.slice(0, 8),
1936
+ "\u2026"
1937
+ ] }),
1938
+ selectedSigner && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: selectedWalletId ? " ml-2" : "", children: [
1939
+ "Signer: ",
1940
+ getSignerDisplayName(selectedSigner),
1941
+ " (",
1942
+ getSignerTypeLabel(selectedSigner.type || selectedSigner.signerType || ""),
1943
+ ")"
1944
+ ] })
1945
+ ] })
1946
+ ] }),
1947
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardContent, { className: "space-y-4", children: [
1948
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1949
+ Button,
1950
+ {
1951
+ type: "button",
1952
+ variant: "outline",
1953
+ className: classNames?.button,
1954
+ onClick: signing.reset,
1955
+ disabled: signing.isSigningTransaction || signing.isSendingTransaction,
1956
+ children: "Reset status"
1957
+ }
1958
+ ),
1959
+ resultStatus !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1960
+ "div",
1961
+ {
1962
+ className: cn(
1963
+ "rounded-lg border px-3 py-2 text-sm",
1964
+ isSuccess && cn("border-green-500/50 bg-green-500/10 text-green-700 dark:text-green-400", classNames?.resultSuccess),
1965
+ isError && cn("border-destructive/50 bg-destructive/10 text-destructive", classNames?.resultError),
1966
+ resultStatus === "loading" && "border-muted bg-muted/50 text-muted-foreground",
1967
+ classNames?.result
1968
+ ),
1969
+ "data-status": resultStatus,
1970
+ children: [
1971
+ signing.transactionResultState.message,
1972
+ signing.transactionResultState.detail != null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("pre", { className: cn("mt-2 overflow-auto rounded-md bg-muted/80 p-2 text-xs", classNames?.resultPre), children: JSON.stringify(signing.transactionResultState.detail, null, 2) })
1973
+ ]
1974
+ }
1975
+ )
1976
+ ] })
1977
+ ] });
1978
+ }
1979
+
1980
+ // src/components/LoginForm.tsx
1981
+ var import_react9 = require("react");
1982
+
1983
+ // src/ui/input.tsx
1984
+ var React6 = __toESM(require("react"));
1985
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1986
+ var Input = React6.forwardRef(
1987
+ ({ className, type, ...props }, ref) => {
1988
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1989
+ "input",
1990
+ {
1991
+ type,
1992
+ className: cn(
1993
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1994
+ className
1995
+ ),
1996
+ ref,
1997
+ ...props
1998
+ }
1999
+ );
2000
+ }
2001
+ );
2002
+ Input.displayName = "Input";
2003
+
2004
+ // src/components/LoginForm.tsx
2005
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2006
+ function LoginForm({
2007
+ className,
2008
+ classNames,
2009
+ onSuccess,
2010
+ onError,
2011
+ submitLabel = "Sign in",
2012
+ title = "Sign in",
2013
+ description,
2014
+ renderSwitchToRegister
2015
+ }) {
2016
+ const { login, isLoading } = useCilantroAuth();
2017
+ const [usernameOrEmail, setUsernameOrEmail] = (0, import_react9.useState)("");
2018
+ const [password, setPassword] = (0, import_react9.useState)("");
2019
+ const [error, setError] = (0, import_react9.useState)(null);
2020
+ const handleSubmit = async (e) => {
2021
+ e.preventDefault();
2022
+ setError(null);
2023
+ try {
2024
+ await login(usernameOrEmail.trim(), password);
2025
+ onSuccess?.();
2026
+ } catch (err) {
2027
+ const message = err instanceof Error ? err.message : String(err);
2028
+ setError(message);
2029
+ onError?.(message);
2030
+ }
2031
+ };
2032
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Card, { className: cn(className, classNames?.root), "data-cilantro-login-form": true, children: [
2033
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(CardHeader, { className: classNames?.header, children: [
2034
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardTitle, { className: classNames?.title, children: title }),
2035
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardDescription, { className: classNames?.description, children: description })
2036
+ ] }),
2037
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("form", { onSubmit: handleSubmit, className: cn("space-y-4", classNames?.form), children: [
2038
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-2", children: [
2039
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Label, { htmlFor: "cilantro-login-username", className: classNames?.label, children: "Username or email" }),
2040
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2041
+ Input,
2042
+ {
2043
+ id: "cilantro-login-username",
2044
+ type: "text",
2045
+ autoComplete: "username",
2046
+ className: classNames?.input,
2047
+ value: usernameOrEmail,
2048
+ onChange: (e) => setUsernameOrEmail(e.target.value),
2049
+ placeholder: "Username or email",
2050
+ required: true,
2051
+ disabled: isLoading
2052
+ }
2053
+ )
2054
+ ] }),
2055
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-2", children: [
2056
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Label, { htmlFor: "cilantro-login-password", className: classNames?.label, children: "Password" }),
2057
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2058
+ Input,
2059
+ {
2060
+ id: "cilantro-login-password",
2061
+ type: "password",
2062
+ autoComplete: "current-password",
2063
+ className: classNames?.input,
2064
+ value: password,
2065
+ onChange: (e) => setPassword(e.target.value),
2066
+ placeholder: "Password",
2067
+ required: true,
2068
+ disabled: isLoading
2069
+ }
2070
+ )
2071
+ ] }),
2072
+ error && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2073
+ "div",
2074
+ {
2075
+ className: cn(
2076
+ "rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",
2077
+ classNames?.error
2078
+ ),
2079
+ role: "alert",
2080
+ children: error
2081
+ }
2082
+ ),
2083
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2084
+ Button,
2085
+ {
2086
+ type: "submit",
2087
+ className: cn("w-full", classNames?.submitButton),
2088
+ disabled: isLoading || !usernameOrEmail.trim() || !password,
2089
+ children: isLoading ? "Signing in..." : submitLabel
2090
+ }
2091
+ ),
2092
+ renderSwitchToRegister && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "text-center text-sm text-muted-foreground", children: renderSwitchToRegister() })
2093
+ ] }) })
2094
+ ] });
2095
+ }
2096
+
2097
+ // src/components/RegisterForm.tsx
2098
+ var import_react10 = require("react");
2099
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2100
+ function RegisterForm({
2101
+ className,
2102
+ classNames,
2103
+ onSuccess,
2104
+ onError,
2105
+ submitLabel = "Create account",
2106
+ title = "Create an account",
2107
+ description,
2108
+ isActive = true,
2109
+ renderSwitchToLogin
2110
+ }) {
2111
+ const { register, isLoading } = useCilantroAuth();
2112
+ const [username, setUsername] = (0, import_react10.useState)("");
2113
+ const [email, setEmail] = (0, import_react10.useState)("");
2114
+ const [password, setPassword] = (0, import_react10.useState)("");
2115
+ const [error, setError] = (0, import_react10.useState)(null);
2116
+ const handleSubmit = async (e) => {
2117
+ e.preventDefault();
2118
+ setError(null);
2119
+ try {
2120
+ await register(username.trim(), email.trim(), password, isActive);
2121
+ onSuccess?.();
2122
+ } catch (err) {
2123
+ const message = err instanceof Error ? err.message : String(err);
2124
+ setError(message);
2125
+ onError?.(message);
2126
+ }
2127
+ };
2128
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Card, { className: cn(className, classNames?.root), "data-cilantro-register-form": true, children: [
2129
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(CardHeader, { className: classNames?.header, children: [
2130
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardTitle, { className: classNames?.title, children: title }),
2131
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardDescription, { className: classNames?.description, children: description })
2132
+ ] }),
2133
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("form", { onSubmit: handleSubmit, className: cn("space-y-4", classNames?.form), children: [
2134
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-2", children: [
2135
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Label, { htmlFor: "cilantro-register-username", className: classNames?.label, children: "Username" }),
2136
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2137
+ Input,
2138
+ {
2139
+ id: "cilantro-register-username",
2140
+ type: "text",
2141
+ autoComplete: "username",
2142
+ className: classNames?.input,
2143
+ value: username,
2144
+ onChange: (e) => setUsername(e.target.value),
2145
+ placeholder: "Username",
2146
+ required: true,
2147
+ disabled: isLoading
2148
+ }
2149
+ )
2150
+ ] }),
2151
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-2", children: [
2152
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Label, { htmlFor: "cilantro-register-email", className: classNames?.label, children: "Email" }),
2153
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2154
+ Input,
2155
+ {
2156
+ id: "cilantro-register-email",
2157
+ type: "email",
2158
+ autoComplete: "email",
2159
+ className: classNames?.input,
2160
+ value: email,
2161
+ onChange: (e) => setEmail(e.target.value),
2162
+ placeholder: "Email",
2163
+ required: true,
2164
+ disabled: isLoading
2165
+ }
2166
+ )
2167
+ ] }),
2168
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-2", children: [
2169
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Label, { htmlFor: "cilantro-register-password", className: classNames?.label, children: "Password" }),
2170
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2171
+ Input,
2172
+ {
2173
+ id: "cilantro-register-password",
2174
+ type: "password",
2175
+ autoComplete: "new-password",
2176
+ className: classNames?.input,
2177
+ value: password,
2178
+ onChange: (e) => setPassword(e.target.value),
2179
+ placeholder: "Password",
2180
+ required: true,
2181
+ disabled: isLoading
2182
+ }
2183
+ )
2184
+ ] }),
2185
+ error && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2186
+ "div",
2187
+ {
2188
+ className: cn(
2189
+ "rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",
2190
+ classNames?.error
2191
+ ),
2192
+ role: "alert",
2193
+ children: error
2194
+ }
2195
+ ),
2196
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2197
+ Button,
2198
+ {
2199
+ type: "submit",
2200
+ className: cn("w-full", classNames?.submitButton),
2201
+ disabled: isLoading || !username.trim() || !email.trim() || !password,
2202
+ children: isLoading ? "Creating account..." : submitLabel
2203
+ }
2204
+ ),
2205
+ renderSwitchToLogin && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "text-center text-sm text-muted-foreground", children: renderSwitchToLogin() })
2206
+ ] }) })
2207
+ ] });
2208
+ }
2209
+
2210
+ // src/components/AuthForm.tsx
2211
+ var import_react11 = require("react");
2212
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2213
+ function AuthForm({
2214
+ defaultMode = "login",
2215
+ className,
2216
+ classNames,
2217
+ onSuccess,
2218
+ onError,
2219
+ loginSubmitLabel = "Sign in",
2220
+ registerSubmitLabel = "Create account",
2221
+ loginTitle = "Welcome back",
2222
+ registerTitle = "Create an account",
2223
+ loginDescription = "Sign in with your username or email.",
2224
+ registerDescription = "Enter your details to get started.",
2225
+ switchToRegisterText = "Don't have an account? Create one",
2226
+ switchToLoginText = "Already have an account? Sign in",
2227
+ isActive = true
2228
+ }) {
2229
+ const { login, register, isLoading } = useCilantroAuth();
2230
+ const [mode, setMode] = (0, import_react11.useState)(defaultMode);
2231
+ const [usernameOrEmail, setUsernameOrEmail] = (0, import_react11.useState)("");
2232
+ const [username, setUsername] = (0, import_react11.useState)("");
2233
+ const [email, setEmail] = (0, import_react11.useState)("");
2234
+ const [password, setPassword] = (0, import_react11.useState)("");
2235
+ const [error, setError] = (0, import_react11.useState)(null);
2236
+ const isLogin = mode === "login";
2237
+ const handleSubmit = async (e) => {
2238
+ e.preventDefault();
2239
+ setError(null);
2240
+ try {
2241
+ if (isLogin) {
2242
+ await login(usernameOrEmail.trim(), password);
2243
+ } else {
2244
+ await register(username.trim(), email.trim(), password, isActive);
2245
+ }
2246
+ onSuccess?.();
2247
+ } catch (err) {
2248
+ const message = err instanceof Error ? err.message : String(err);
2249
+ setError(message);
2250
+ onError?.(message);
2251
+ }
2252
+ };
2253
+ const switchMode = () => {
2254
+ setMode(isLogin ? "register" : "login");
2255
+ setError(null);
2256
+ };
2257
+ const canSubmit = isLogin ? usernameOrEmail.trim().length > 0 && password.length > 0 : username.trim().length > 0 && email.trim().length > 0 && password.length > 0;
2258
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Card, { className: cn("w-full max-w-sm", className, classNames?.root), "data-cilantro-auth-form": true, children: [
2259
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(CardHeader, { className: cn("space-y-1 text-center sm:text-left", classNames?.header), children: [
2260
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardTitle, { className: cn("text-xl", classNames?.title), children: isLogin ? loginTitle : registerTitle }),
2261
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardDescription, { className: classNames?.description, children: isLogin ? loginDescription : registerDescription })
2262
+ ] }),
2263
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("form", { onSubmit: handleSubmit, className: cn("space-y-4", classNames?.form), children: [
2264
+ isLogin ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
2265
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-2", children: [
2266
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: "cilantro-auth-username", className: classNames?.label, children: "Username or email" }),
2267
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2268
+ Input,
2269
+ {
2270
+ id: "cilantro-auth-username",
2271
+ type: "text",
2272
+ autoComplete: "username",
2273
+ className: classNames?.input,
2274
+ value: usernameOrEmail,
2275
+ onChange: (e) => setUsernameOrEmail(e.target.value),
2276
+ placeholder: "you@example.com",
2277
+ required: true,
2278
+ disabled: isLoading
2279
+ }
2280
+ )
2281
+ ] }),
2282
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-2", children: [
2283
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: "cilantro-auth-password", className: classNames?.label, children: "Password" }),
2284
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2285
+ Input,
2286
+ {
2287
+ id: "cilantro-auth-password",
2288
+ type: "password",
2289
+ autoComplete: "current-password",
2290
+ className: classNames?.input,
2291
+ value: password,
2292
+ onChange: (e) => setPassword(e.target.value),
2293
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
2294
+ required: true,
2295
+ disabled: isLoading
2296
+ }
2297
+ )
2298
+ ] })
2299
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
2300
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-2", children: [
2301
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: "cilantro-auth-reg-username", className: classNames?.label, children: "Username" }),
2302
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2303
+ Input,
2304
+ {
2305
+ id: "cilantro-auth-reg-username",
2306
+ type: "text",
2307
+ autoComplete: "username",
2308
+ className: classNames?.input,
2309
+ value: username,
2310
+ onChange: (e) => setUsername(e.target.value),
2311
+ placeholder: "johndoe",
2312
+ required: true,
2313
+ disabled: isLoading
2314
+ }
2315
+ )
2316
+ ] }),
2317
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-2", children: [
2318
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: "cilantro-auth-reg-email", className: classNames?.label, children: "Email" }),
2319
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2320
+ Input,
2321
+ {
2322
+ id: "cilantro-auth-reg-email",
2323
+ type: "email",
2324
+ autoComplete: "email",
2325
+ className: classNames?.input,
2326
+ value: email,
2327
+ onChange: (e) => setEmail(e.target.value),
2328
+ placeholder: "you@example.com",
2329
+ required: true,
2330
+ disabled: isLoading
2331
+ }
2332
+ )
2333
+ ] }),
2334
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-2", children: [
2335
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: "cilantro-auth-reg-password", className: classNames?.label, children: "Password" }),
2336
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2337
+ Input,
2338
+ {
2339
+ id: "cilantro-auth-reg-password",
2340
+ type: "password",
2341
+ autoComplete: "new-password",
2342
+ className: classNames?.input,
2343
+ value: password,
2344
+ onChange: (e) => setPassword(e.target.value),
2345
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
2346
+ required: true,
2347
+ disabled: isLoading
2348
+ }
2349
+ )
2350
+ ] })
2351
+ ] }),
2352
+ error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2353
+ "div",
2354
+ {
2355
+ className: cn(
2356
+ "rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",
2357
+ classNames?.error
2358
+ ),
2359
+ role: "alert",
2360
+ children: error
2361
+ }
2362
+ ),
2363
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2364
+ Button,
2365
+ {
2366
+ type: "submit",
2367
+ className: cn("w-full", classNames?.submitButton),
2368
+ disabled: isLoading || !canSubmit,
2369
+ children: isLoading ? isLogin ? "Signing in..." : "Creating account..." : isLogin ? loginSubmitLabel : registerSubmitLabel
2370
+ }
2371
+ ),
2372
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: cn("text-center text-sm text-muted-foreground", classNames?.toggle), children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2373
+ "button",
2374
+ {
2375
+ type: "button",
2376
+ className: cn("underline underline-offset-2 hover:text-foreground", classNames?.toggleLink),
2377
+ onClick: switchMode,
2378
+ disabled: isLoading,
2379
+ children: isLogin ? switchToRegisterText : switchToLoginText
2380
+ }
2381
+ ) })
2382
+ ] }) })
2383
+ ] });
2384
+ }
2385
+
2386
+ // src/components/AuthGuard.tsx
2387
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2388
+ function AuthGuard({
2389
+ children,
2390
+ fallback,
2391
+ className,
2392
+ classNames,
2393
+ showFallback = true
2394
+ }) {
2395
+ const { isAuthenticated, isLoading } = useCilantroAuth();
2396
+ if (isLoading) {
2397
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-auth-guard": true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: cn("text-sm text-muted-foreground", classNames?.fallback), children: "Loading..." }) });
2398
+ }
2399
+ if (!isAuthenticated) {
2400
+ if (!showFallback) return null;
2401
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-auth-guard": true, children: fallback ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LoginForm, { className: classNames?.fallback }) });
2402
+ }
2403
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children });
2404
+ }
2405
+
2406
+ // src/components/AddSignerForm.tsx
2407
+ var import_react12 = require("react");
2408
+
2409
+ // src/ui/dialog.tsx
2410
+ var React7 = __toESM(require("react"));
2411
+ var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
2412
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2413
+ var Dialog = DialogPrimitive.Root;
2414
+ var DialogPortal = DialogPrimitive.Portal;
2415
+ var DialogOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2416
+ DialogPrimitive.Overlay,
2417
+ {
2418
+ ref,
2419
+ className: cn(
2420
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
2421
+ className
2422
+ ),
2423
+ ...props
2424
+ }
2425
+ ));
2426
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
2427
+ var DialogContent = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogPortal, { children: [
2428
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogOverlay, {}),
2429
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2430
+ DialogPrimitive.Content,
2431
+ {
2432
+ ref,
2433
+ className: cn(
2434
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
2435
+ className
2436
+ ),
2437
+ ...props,
2438
+ children
2439
+ }
2440
+ )
2441
+ ] }));
2442
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
2443
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
2444
+ DialogHeader.displayName = "DialogHeader";
2445
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2446
+ "div",
2447
+ {
2448
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
2449
+ ...props
2450
+ }
2451
+ );
2452
+ DialogFooter.displayName = "DialogFooter";
2453
+ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2454
+ DialogPrimitive.Title,
2455
+ {
2456
+ ref,
2457
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
2458
+ ...props
2459
+ }
2460
+ ));
2461
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
2462
+ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2463
+ DialogPrimitive.Description,
2464
+ {
2465
+ ref,
2466
+ className: cn("text-sm text-muted-foreground", className),
2467
+ ...props
2468
+ }
2469
+ ));
2470
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
2471
+
2472
+ // src/components/AddSignerForm.tsx
2473
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2474
+ function AddSignerForm({
2475
+ walletId,
2476
+ open = true,
2477
+ onOpenChange,
2478
+ onSuccess,
2479
+ onCancel,
2480
+ onError,
2481
+ className,
2482
+ classNames,
2483
+ asDialog = true
2484
+ }) {
2485
+ const [signerType, setSignerType] = (0, import_react12.useState)(null);
2486
+ const [email, setEmail] = (0, import_react12.useState)("");
2487
+ const [phone, setPhone] = (0, import_react12.useState)("");
2488
+ const [address, setAddress] = (0, import_react12.useState)("");
2489
+ const [isSubmitting, setIsSubmitting] = (0, import_react12.useState)(false);
2490
+ const [error, setError] = (0, import_react12.useState)(null);
2491
+ const resetForm = () => {
2492
+ setSignerType(null);
2493
+ setEmail("");
2494
+ setPhone("");
2495
+ setAddress("");
2496
+ setError(null);
2497
+ };
2498
+ const handleClose = (open2) => {
2499
+ if (!open2) {
2500
+ resetForm();
2501
+ onCancel?.();
2502
+ }
2503
+ onOpenChange?.(open2);
2504
+ };
2505
+ const handleSubmit = async (e) => {
2506
+ e.preventDefault();
2507
+ if (!signerType) return;
2508
+ setError(null);
2509
+ setIsSubmitting(true);
2510
+ try {
2511
+ if (signerType === "email") {
2512
+ await createEmailSignerHelper(walletId, email);
2513
+ } else if (signerType === "phone") {
2514
+ await createPhoneSignerHelper(walletId, phone);
2515
+ } else if (signerType === "passkey") {
2516
+ await registerPasskeySigner(walletId);
2517
+ } else if (signerType === "external") {
2518
+ await createExternalSignerHelper(walletId, address);
2519
+ }
2520
+ resetForm();
2521
+ onSuccess?.();
2522
+ handleClose(false);
2523
+ } catch (err) {
2524
+ const message = err instanceof Error ? err.message : String(err);
2525
+ setError(message);
2526
+ onError?.(message);
2527
+ } finally {
2528
+ setIsSubmitting(false);
2529
+ }
2530
+ };
2531
+ const handlePasskeyClick = () => {
2532
+ setSignerType("passkey");
2533
+ setError(null);
2534
+ setIsSubmitting(true);
2535
+ registerPasskeySigner(walletId).then(() => {
2536
+ resetForm();
2537
+ onSuccess?.();
2538
+ handleClose(false);
2539
+ }).catch((err) => {
2540
+ const message = err instanceof Error ? err.message : String(err);
2541
+ setError(message);
2542
+ onError?.(message);
2543
+ }).finally(() => setIsSubmitting(false));
2544
+ };
2545
+ const formContent = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("form", { onSubmit: handleSubmit, className: cn("space-y-4", classNames?.form), children: [
2546
+ !signerType ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2547
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-2", children: [
2548
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Label, { className: classNames?.label, children: "Signer type" }),
2549
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-wrap gap-2", children: [
2550
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2551
+ Button,
2552
+ {
2553
+ type: "button",
2554
+ variant: "outline",
2555
+ size: "sm",
2556
+ onClick: () => setSignerType("email"),
2557
+ disabled: isSubmitting,
2558
+ children: "Email"
2559
+ }
2560
+ ),
2561
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2562
+ Button,
2563
+ {
2564
+ type: "button",
2565
+ variant: "outline",
2566
+ size: "sm",
2567
+ onClick: () => setSignerType("phone"),
2568
+ disabled: isSubmitting,
2569
+ children: "Phone"
2570
+ }
2571
+ ),
2572
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2573
+ Button,
2574
+ {
2575
+ type: "button",
2576
+ variant: "outline",
2577
+ size: "sm",
2578
+ onClick: handlePasskeyClick,
2579
+ disabled: isSubmitting,
2580
+ children: "Passkey"
2581
+ }
2582
+ ),
2583
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2584
+ Button,
2585
+ {
2586
+ type: "button",
2587
+ variant: "outline",
2588
+ size: "sm",
2589
+ onClick: () => setSignerType("external"),
2590
+ disabled: isSubmitting,
2591
+ children: "External wallet"
2592
+ }
2593
+ )
2594
+ ] })
2595
+ ] }),
2596
+ asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogFooter, { className: "gap-2 sm:gap-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2597
+ Button,
2598
+ {
2599
+ type: "button",
2600
+ variant: "outline",
2601
+ className: classNames?.cancelButton,
2602
+ onClick: () => handleClose(false),
2603
+ disabled: isSubmitting,
2604
+ children: "Cancel"
2605
+ }
2606
+ ) })
2607
+ ] }) : signerType === "email" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2608
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-2", children: [
2609
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Label, { htmlFor: "add-signer-email", className: classNames?.label, children: "Email" }),
2610
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2611
+ Input,
2612
+ {
2613
+ id: "add-signer-email",
2614
+ type: "email",
2615
+ autoComplete: "email",
2616
+ className: classNames?.input,
2617
+ value: email,
2618
+ onChange: (e) => setEmail(e.target.value),
2619
+ placeholder: "email@example.com",
2620
+ required: true,
2621
+ disabled: isSubmitting
2622
+ }
2623
+ )
2624
+ ] }),
2625
+ asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { className: "gap-2 sm:gap-0", children: [
2626
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2627
+ Button,
2628
+ {
2629
+ type: "button",
2630
+ variant: "outline",
2631
+ className: classNames?.cancelButton,
2632
+ onClick: () => setSignerType(null),
2633
+ disabled: isSubmitting,
2634
+ children: "Back"
2635
+ }
2636
+ ),
2637
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2638
+ ] }),
2639
+ !asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-2", children: [
2640
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2641
+ Button,
2642
+ {
2643
+ type: "button",
2644
+ variant: "outline",
2645
+ className: classNames?.cancelButton,
2646
+ onClick: () => setSignerType(null),
2647
+ disabled: isSubmitting,
2648
+ children: "Back"
2649
+ }
2650
+ ),
2651
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2652
+ ] })
2653
+ ] }) : signerType === "phone" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2654
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-2", children: [
2655
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Label, { htmlFor: "add-signer-phone", className: classNames?.label, children: "Phone number" }),
2656
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2657
+ Input,
2658
+ {
2659
+ id: "add-signer-phone",
2660
+ type: "tel",
2661
+ autoComplete: "tel",
2662
+ className: classNames?.input,
2663
+ value: phone,
2664
+ onChange: (e) => setPhone(e.target.value),
2665
+ placeholder: "+1234567890",
2666
+ required: true,
2667
+ disabled: isSubmitting
2668
+ }
2669
+ )
2670
+ ] }),
2671
+ asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { className: "gap-2 sm:gap-0", children: [
2672
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2673
+ Button,
2674
+ {
2675
+ type: "button",
2676
+ variant: "outline",
2677
+ className: classNames?.cancelButton,
2678
+ onClick: () => setSignerType(null),
2679
+ disabled: isSubmitting,
2680
+ children: "Back"
2681
+ }
2682
+ ),
2683
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2684
+ ] }),
2685
+ !asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-2", children: [
2686
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2687
+ Button,
2688
+ {
2689
+ type: "button",
2690
+ variant: "outline",
2691
+ className: classNames?.cancelButton,
2692
+ onClick: () => setSignerType(null),
2693
+ disabled: isSubmitting,
2694
+ children: "Back"
2695
+ }
2696
+ ),
2697
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2698
+ ] })
2699
+ ] }) : signerType === "external" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2700
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-2", children: [
2701
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Label, { htmlFor: "add-signer-address", className: classNames?.label, children: "Wallet address" }),
2702
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2703
+ Input,
2704
+ {
2705
+ id: "add-signer-address",
2706
+ type: "text",
2707
+ className: classNames?.input,
2708
+ value: address,
2709
+ onChange: (e) => setAddress(e.target.value),
2710
+ placeholder: "Solana address",
2711
+ required: true,
2712
+ disabled: isSubmitting
2713
+ }
2714
+ )
2715
+ ] }),
2716
+ asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { className: "gap-2 sm:gap-0", children: [
2717
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2718
+ Button,
2719
+ {
2720
+ type: "button",
2721
+ variant: "outline",
2722
+ className: classNames?.cancelButton,
2723
+ onClick: () => setSignerType(null),
2724
+ disabled: isSubmitting,
2725
+ children: "Back"
2726
+ }
2727
+ ),
2728
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2729
+ ] }),
2730
+ !asDialog && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-2", children: [
2731
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2732
+ Button,
2733
+ {
2734
+ type: "button",
2735
+ variant: "outline",
2736
+ className: classNames?.cancelButton,
2737
+ onClick: () => setSignerType(null),
2738
+ disabled: isSubmitting,
2739
+ children: "Back"
2740
+ }
2741
+ ),
2742
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { type: "submit", className: classNames?.submitButton, disabled: isSubmitting, children: isSubmitting ? "Adding..." : "Add signer" })
2743
+ ] })
2744
+ ] }) : null,
2745
+ error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: cn("text-sm text-destructive", classNames?.error), role: "alert", children: error })
2746
+ ] });
2747
+ if (asDialog) {
2748
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogContent, { className: cn(classNames?.dialog), children: [
2749
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogHeader, { children: [
2750
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogTitle, { children: "Add signer" }),
2751
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogDescription, { children: "Add a new signer to this wallet." })
2752
+ ] }),
2753
+ formContent
2754
+ ] }) });
2755
+ }
2756
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn(className, classNames?.root), "data-cilantro-add-signer-form": true, children: [
2757
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-sm font-medium mb-2", children: "Add signer" }),
2758
+ formContent
2759
+ ] });
2760
+ }
2761
+
2762
+ // src/components/SignerList.tsx
2763
+ var import_react13 = require("react");
2764
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2765
+ function SignerList({
2766
+ walletId,
2767
+ className,
2768
+ classNames,
2769
+ onSignerAdded,
2770
+ children
2771
+ }) {
2772
+ const { signers, isLoading, error, refresh } = useSigners({ walletId });
2773
+ const [addSignerOpen, setAddSignerOpen] = (0, import_react13.useState)(false);
2774
+ const handleAddSuccess = () => {
2775
+ refresh();
2776
+ onSignerAdded?.();
2777
+ };
2778
+ if (children) {
2779
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
2780
+ children({
2781
+ signers,
2782
+ isLoading,
2783
+ error,
2784
+ refresh,
2785
+ openAddSigner: () => setAddSignerOpen(true)
2786
+ }),
2787
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2788
+ AddSignerForm,
2789
+ {
2790
+ walletId,
2791
+ open: addSignerOpen,
2792
+ onOpenChange: setAddSignerOpen,
2793
+ onSuccess: handleAddSuccess,
2794
+ asDialog: true
2795
+ }
2796
+ )
2797
+ ] });
2798
+ }
2799
+ if (!walletId) {
2800
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn(className, classNames?.root), "data-cilantro-signer-list": true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "Select a wallet first." }) });
2801
+ }
2802
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn(className, classNames?.root), "data-cilantro-signer-list": true, children: [
2803
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("flex items-center justify-between gap-2 mb-2", classNames?.header), children: [
2804
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm font-medium", children: "Signers" }),
2805
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2806
+ Button,
2807
+ {
2808
+ type: "button",
2809
+ size: "sm",
2810
+ variant: "outline",
2811
+ className: classNames?.addButton,
2812
+ onClick: () => setAddSignerOpen(true),
2813
+ disabled: isLoading,
2814
+ children: "Add signer"
2815
+ }
2816
+ )
2817
+ ] }),
2818
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "Loading signers..." }) : error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: cn("text-sm text-destructive", classNames?.message), role: "alert", children: error }) : signers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: cn("text-sm text-muted-foreground", classNames?.message), children: "No signers. Add one to get started." }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: cn("space-y-1", classNames?.list), role: "list", children: signers.map((signer) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: cn("text-sm", classNames?.item), children: [
2819
+ getSignerDisplayName(signer),
2820
+ " (",
2821
+ getSignerTypeLabel(signer.type || signer.signerType || ""),
2822
+ ")"
2823
+ ] }, signer.id)) }),
2824
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2825
+ AddSignerForm,
2826
+ {
2827
+ walletId,
2828
+ open: addSignerOpen,
2829
+ onOpenChange: setAddSignerOpen,
2830
+ onSuccess: handleAddSuccess,
2831
+ asDialog: true
2832
+ }
2833
+ )
2834
+ ] });
2835
+ }
2836
+ // Annotate the CommonJS export names for ESM import in node:
2837
+ 0 && (module.exports = {
2838
+ AddSignerForm,
2839
+ AuthForm,
2840
+ AuthGuard,
2841
+ CilantroAuthProvider,
2842
+ CilantroProvider,
2843
+ DelegatedKeySelector,
2844
+ LoginForm,
2845
+ MessageSigningForm,
2846
+ RegisterForm,
2847
+ SIGNER_TYPES,
2848
+ SignerList,
2849
+ SignerSelector,
2850
+ TransactionSigningForm,
2851
+ WalletProvider,
2852
+ WalletSelector,
2853
+ extractErrorMessage,
2854
+ extractResponseData,
2855
+ getSignerPublicKey,
2856
+ getWalletData,
2857
+ signAndSendTransactionWithSigner,
2858
+ signMessageWithSigner,
2859
+ signTransactionWithSigner,
2860
+ useCilantroAuth,
2861
+ useMessageSigning,
2862
+ useSignerSelection,
2863
+ useSigners,
2864
+ useTransactionSigning,
2865
+ useWallets
2866
+ });
2867
+ //# sourceMappingURL=index.js.map