shogun-button-react 6.3.3 → 6.3.6
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.
|
@@ -21,6 +21,8 @@ type ShogunContextType = {
|
|
|
21
21
|
put: (path: string, data: any) => Promise<void>;
|
|
22
22
|
get: (path: string) => any;
|
|
23
23
|
remove: (path: string) => Promise<void>;
|
|
24
|
+
completePendingSignup: () => void;
|
|
25
|
+
hasPendingSignup: boolean;
|
|
24
26
|
};
|
|
25
27
|
export declare const useShogun: () => ShogunContextType;
|
|
26
28
|
type ShogunButtonProviderProps = {
|
|
@@ -25,6 +25,8 @@ const defaultShogunContext = {
|
|
|
25
25
|
put: async () => { },
|
|
26
26
|
get: () => null,
|
|
27
27
|
remove: async () => { },
|
|
28
|
+
completePendingSignup: () => { },
|
|
29
|
+
hasPendingSignup: false,
|
|
28
30
|
};
|
|
29
31
|
// Create context using React's createContext directly
|
|
30
32
|
const ShogunContext = createContext(defaultShogunContext);
|
|
@@ -36,6 +38,7 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
36
38
|
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
|
37
39
|
const [userPub, setUserPub] = useState(null);
|
|
38
40
|
const [username, setUsername] = useState(null);
|
|
41
|
+
const [pendingSignupData, setPendingSignupData] = useState(null);
|
|
39
42
|
// Effetto per gestire l'inizializzazione e pulizia
|
|
40
43
|
useEffect(() => {
|
|
41
44
|
var _a, _b;
|
|
@@ -324,12 +327,18 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
324
327
|
setIsLoggedIn(true);
|
|
325
328
|
setUserPub(userPub);
|
|
326
329
|
setUsername(displayName);
|
|
327
|
-
|
|
330
|
+
const signupPayload = {
|
|
328
331
|
userPub: userPub,
|
|
329
332
|
username: displayName,
|
|
330
|
-
seedPhrase: result.seedPhrase,
|
|
333
|
+
seedPhrase: result.seedPhrase,
|
|
331
334
|
authMethod: authMethod,
|
|
332
|
-
}
|
|
335
|
+
};
|
|
336
|
+
if (authMethod === "zkproof" && onSignupSuccess) {
|
|
337
|
+
setPendingSignupData(signupPayload);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
onSignupSuccess === null || onSignupSuccess === void 0 ? void 0 : onSignupSuccess(signupPayload);
|
|
341
|
+
}
|
|
333
342
|
}
|
|
334
343
|
else {
|
|
335
344
|
onError === null || onError === void 0 ? void 0 : onError(result.error);
|
|
@@ -349,6 +358,7 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
349
358
|
setIsLoggedIn(false);
|
|
350
359
|
setUserPub(null);
|
|
351
360
|
setUsername(null);
|
|
361
|
+
setPendingSignupData(null);
|
|
352
362
|
};
|
|
353
363
|
// Implementazione del metodo setProvider
|
|
354
364
|
const setProvider = (provider) => {
|
|
@@ -462,6 +472,13 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
462
472
|
const gunPlugin = null;
|
|
463
473
|
// Plugin hooks removed - GunAdvancedPlugin no longer available
|
|
464
474
|
const pluginHooks = {};
|
|
475
|
+
const completePendingSignup = React.useCallback(() => {
|
|
476
|
+
if (pendingSignupData) {
|
|
477
|
+
const dataToEmit = pendingSignupData;
|
|
478
|
+
setPendingSignupData(null);
|
|
479
|
+
onSignupSuccess === null || onSignupSuccess === void 0 ? void 0 : onSignupSuccess(dataToEmit);
|
|
480
|
+
}
|
|
481
|
+
}, [pendingSignupData, onSignupSuccess]);
|
|
465
482
|
// Create a properly typed context value
|
|
466
483
|
const contextValue = React.useMemo(() => ({
|
|
467
484
|
core,
|
|
@@ -479,6 +496,8 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
479
496
|
importGunPair,
|
|
480
497
|
setProvider,
|
|
481
498
|
gunPlugin,
|
|
499
|
+
completePendingSignup,
|
|
500
|
+
hasPendingSignup: Boolean(pendingSignupData),
|
|
482
501
|
put: async (path, data) => {
|
|
483
502
|
if (isShogunCore(core)) {
|
|
484
503
|
if (!core.gun)
|
|
@@ -537,6 +556,8 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
|
|
|
537
556
|
importGunPair,
|
|
538
557
|
gunPlugin,
|
|
539
558
|
pluginHooks,
|
|
559
|
+
pendingSignupData,
|
|
560
|
+
completePendingSignup,
|
|
540
561
|
]);
|
|
541
562
|
// Provide the context value to children
|
|
542
563
|
return (React.createElement(ShogunContext.Provider, { value: contextValue }, children));
|
|
@@ -586,7 +607,7 @@ const ExportIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org
|
|
|
586
607
|
// Component for Shogun login button
|
|
587
608
|
export const ShogunButton = (() => {
|
|
588
609
|
const Button = () => {
|
|
589
|
-
const { isLoggedIn, username, logout, login, signUp, core, options, exportGunPair, importGunPair, hasPlugin, } = useShogun();
|
|
610
|
+
const { isLoggedIn, username, logout, login, signUp, core, options, exportGunPair, importGunPair, hasPlugin, completePendingSignup, hasPendingSignup, } = useShogun();
|
|
590
611
|
// Form states
|
|
591
612
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
592
613
|
const [formUsername, setFormUsername] = useState("");
|
|
@@ -609,7 +630,9 @@ export const ShogunButton = (() => {
|
|
|
609
630
|
const [showImportSuccess, setShowImportSuccess] = useState(false);
|
|
610
631
|
const [zkTrapdoor, setZkTrapdoor] = useState("");
|
|
611
632
|
const [zkGeneratedTrapdoor, setZkGeneratedTrapdoor] = useState("");
|
|
633
|
+
const [webauthnSeedPhrase, setWebauthnSeedPhrase] = useState("");
|
|
612
634
|
const dropdownRef = useRef(null);
|
|
635
|
+
const [pendingZkConfirmation, setPendingZkConfirmation] = useState(false);
|
|
613
636
|
// Handle click outside to close dropdown
|
|
614
637
|
useEffect(() => {
|
|
615
638
|
const handleClickOutside = (event) => {
|
|
@@ -670,7 +693,19 @@ export const ShogunButton = (() => {
|
|
|
670
693
|
window.location.href = result.redirectUrl;
|
|
671
694
|
}
|
|
672
695
|
else {
|
|
673
|
-
|
|
696
|
+
const shouldShowWebauthnSeed = formMode === "signup" &&
|
|
697
|
+
method === "webauthn" &&
|
|
698
|
+
result &&
|
|
699
|
+
result.success &&
|
|
700
|
+
result.seedPhrase;
|
|
701
|
+
if (shouldShowWebauthnSeed) {
|
|
702
|
+
setWebauthnSeedPhrase(result.seedPhrase);
|
|
703
|
+
setShowCopySuccess(false);
|
|
704
|
+
setAuthView("webauthn-signup-result");
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
setModalIsOpen(false);
|
|
708
|
+
}
|
|
674
709
|
}
|
|
675
710
|
}
|
|
676
711
|
catch (e) {
|
|
@@ -772,6 +807,7 @@ export const ShogunButton = (() => {
|
|
|
772
807
|
// Show the trapdoor to the user - CRITICAL for account recovery!
|
|
773
808
|
setZkGeneratedTrapdoor(result.seedPhrase);
|
|
774
809
|
setAuthView("zkproof-signup-result");
|
|
810
|
+
setPendingZkConfirmation(true);
|
|
775
811
|
}
|
|
776
812
|
else if (result && !result.success) {
|
|
777
813
|
throw new Error(result.error || "ZK-Proof signup failed");
|
|
@@ -895,6 +931,8 @@ export const ShogunButton = (() => {
|
|
|
895
931
|
setRecoveredHint("");
|
|
896
932
|
setZkTrapdoor("");
|
|
897
933
|
setZkGeneratedTrapdoor("");
|
|
934
|
+
setWebauthnSeedPhrase("");
|
|
935
|
+
setPendingZkConfirmation(false);
|
|
898
936
|
};
|
|
899
937
|
const openModal = () => {
|
|
900
938
|
resetForm();
|
|
@@ -902,6 +940,17 @@ export const ShogunButton = (() => {
|
|
|
902
940
|
setModalIsOpen(true);
|
|
903
941
|
};
|
|
904
942
|
const closeModal = () => {
|
|
943
|
+
if (pendingZkConfirmation || hasPendingSignup) {
|
|
944
|
+
setError("Please save your trapdoor and confirm before leaving this screen.");
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
setModalIsOpen(false);
|
|
948
|
+
};
|
|
949
|
+
const finalizeZkProofSignup = () => {
|
|
950
|
+
completePendingSignup();
|
|
951
|
+
setError("");
|
|
952
|
+
setPendingZkConfirmation(false);
|
|
953
|
+
setAuthView("options");
|
|
905
954
|
setModalIsOpen(false);
|
|
906
955
|
};
|
|
907
956
|
const toggleMode = () => {
|
|
@@ -1127,6 +1176,52 @@ export const ShogunButton = (() => {
|
|
|
1127
1176
|
React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleZkProofLogin, disabled: loading || !zkTrapdoor.trim() }, loading ? "Processing..." : "Login Anonymously"),
|
|
1128
1177
|
React.createElement("div", { className: "shogun-form-footer" },
|
|
1129
1178
|
React.createElement("button", { className: "shogun-toggle-mode", onClick: () => setAuthView("options"), disabled: loading }, "Back to Login Options"))));
|
|
1179
|
+
const renderWebauthnSignupResult = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
1180
|
+
React.createElement("h3", null, "WebAuthn Account Created!"),
|
|
1181
|
+
React.createElement("div", { style: {
|
|
1182
|
+
backgroundColor: "#fef3c7",
|
|
1183
|
+
padding: "12px",
|
|
1184
|
+
borderRadius: "8px",
|
|
1185
|
+
marginBottom: "16px",
|
|
1186
|
+
border: "1px solid #f59e0b",
|
|
1187
|
+
} },
|
|
1188
|
+
React.createElement("p", { style: {
|
|
1189
|
+
fontSize: "14px",
|
|
1190
|
+
color: "#92400e",
|
|
1191
|
+
margin: "0",
|
|
1192
|
+
fontWeight: "500",
|
|
1193
|
+
} }, "\u26A0\uFE0F Important: Save Your Recovery Code"),
|
|
1194
|
+
React.createElement("p", { style: { fontSize: "13px", color: "#a16207", margin: "4px 0 0 0" } }, "This seed phrase lets you add new devices or recover your WebAuthn account. Keep it private and store it securely.")),
|
|
1195
|
+
React.createElement("div", { className: "shogun-form-group" },
|
|
1196
|
+
React.createElement("label", null, "Your WebAuthn Recovery Code (Seed Phrase):"),
|
|
1197
|
+
React.createElement("textarea", { value: webauthnSeedPhrase, readOnly: true, rows: 4, style: {
|
|
1198
|
+
fontFamily: "monospace",
|
|
1199
|
+
fontSize: "12px",
|
|
1200
|
+
width: "100%",
|
|
1201
|
+
padding: "8px",
|
|
1202
|
+
border: "2px solid #f59e0b",
|
|
1203
|
+
borderRadius: "4px",
|
|
1204
|
+
backgroundColor: "#fffbeb",
|
|
1205
|
+
} }),
|
|
1206
|
+
React.createElement("button", { type: "button", className: "shogun-submit-button", style: { marginTop: "8px" }, onClick: async () => {
|
|
1207
|
+
if (navigator.clipboard && webauthnSeedPhrase) {
|
|
1208
|
+
await navigator.clipboard.writeText(webauthnSeedPhrase);
|
|
1209
|
+
setShowCopySuccess(true);
|
|
1210
|
+
setTimeout(() => setShowCopySuccess(false), 3000);
|
|
1211
|
+
}
|
|
1212
|
+
}, disabled: !webauthnSeedPhrase }, showCopySuccess ? "✅ Copied!" : "📋 Copy Recovery Code"),
|
|
1213
|
+
!navigator.clipboard && (React.createElement("p", { style: { fontSize: "12px", color: "#666", marginTop: "8px" } }, "\u26A0\uFE0F Please manually copy the code above for safekeeping."))),
|
|
1214
|
+
React.createElement("div", { style: {
|
|
1215
|
+
backgroundColor: "#dcfce7",
|
|
1216
|
+
color: "#166534",
|
|
1217
|
+
padding: "12px",
|
|
1218
|
+
borderRadius: "8px",
|
|
1219
|
+
marginTop: "16px",
|
|
1220
|
+
fontSize: "14px",
|
|
1221
|
+
border: "1px solid #22c55e",
|
|
1222
|
+
textAlign: "center",
|
|
1223
|
+
} }, "\u2705 You're now logged in with WebAuthn!"),
|
|
1224
|
+
React.createElement("button", { type: "button", className: "shogun-submit-button", style: { marginTop: "16px" }, onClick: finalizeZkProofSignup }, "Close and Start Using App")));
|
|
1130
1225
|
const renderZkProofSignupResult = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
1131
1226
|
React.createElement("h3", null, "ZK-Proof Account Created!"),
|
|
1132
1227
|
React.createElement("div", { style: {
|
|
@@ -1172,7 +1267,7 @@ export const ShogunButton = (() => {
|
|
|
1172
1267
|
border: "1px solid #22c55e",
|
|
1173
1268
|
textAlign: "center",
|
|
1174
1269
|
} }, "\u2705 You're now logged in anonymously!"),
|
|
1175
|
-
React.createElement("button", { type: "button", className: "shogun-submit-button", style: { marginTop: "16px" }, onClick:
|
|
1270
|
+
React.createElement("button", { type: "button", className: "shogun-submit-button", style: { marginTop: "16px" }, onClick: finalizeZkProofSignup }, "Close and Start Using App")));
|
|
1176
1271
|
const renderImportForm = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
1177
1272
|
React.createElement("h3", null, "Import Gun Pair"),
|
|
1178
1273
|
React.createElement("div", { style: {
|
|
@@ -1232,7 +1327,13 @@ export const ShogunButton = (() => {
|
|
|
1232
1327
|
React.createElement("button", { className: "shogun-connect-button", onClick: openModal },
|
|
1233
1328
|
React.createElement(WalletIcon, null),
|
|
1234
1329
|
React.createElement("span", null, "Login / Sign Up")),
|
|
1235
|
-
modalIsOpen && (React.createElement("div", { className: "shogun-modal-overlay", onClick:
|
|
1330
|
+
modalIsOpen && (React.createElement("div", { className: "shogun-modal-overlay", onClick: () => {
|
|
1331
|
+
if (pendingZkConfirmation || hasPendingSignup) {
|
|
1332
|
+
setError("Please copy your trapdoor and press Continue before closing.");
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
closeModal();
|
|
1336
|
+
} },
|
|
1236
1337
|
React.createElement("div", { className: "shogun-modal", onClick: (e) => e.stopPropagation() },
|
|
1237
1338
|
React.createElement("div", { className: "shogun-modal-header" },
|
|
1238
1339
|
React.createElement("h2", null, authView === "recover"
|
|
@@ -1252,7 +1353,7 @@ export const ShogunButton = (() => {
|
|
|
1252
1353
|
: formMode === "login"
|
|
1253
1354
|
? "Login"
|
|
1254
1355
|
: "Sign Up"),
|
|
1255
|
-
React.createElement("button", { className: "shogun-close-button", onClick: closeModal, "aria-label": "Close" },
|
|
1356
|
+
React.createElement("button", { className: "shogun-close-button", onClick: closeModal, "aria-label": "Close", disabled: pendingZkConfirmation || hasPendingSignup },
|
|
1256
1357
|
React.createElement(CloseIcon, null))),
|
|
1257
1358
|
React.createElement("div", { className: "shogun-modal-content" },
|
|
1258
1359
|
error && React.createElement("div", { className: "shogun-error-message" }, error),
|
|
@@ -1271,6 +1372,8 @@ export const ShogunButton = (() => {
|
|
|
1271
1372
|
authView === "import" && renderImportForm(),
|
|
1272
1373
|
authView === "webauthn-username" &&
|
|
1273
1374
|
renderWebAuthnUsernameForm(),
|
|
1375
|
+
authView === "webauthn-signup-result" &&
|
|
1376
|
+
renderWebauthnSignupResult(),
|
|
1274
1377
|
authView === "zkproof-login" && renderZkProofLoginForm(),
|
|
1275
1378
|
authView === "zkproof-signup-result" &&
|
|
1276
1379
|
renderZkProofSignupResult()))))));
|