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/README.md +647 -0
- package/dist/index.d.mts +616 -0
- package/dist/index.d.ts +616 -0
- package/dist/index.js +2867 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2837 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +51 -0
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
|