shogun-button-react 6.8.3 → 6.9.2

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.
@@ -34,14 +34,14 @@ type ShogunButtonProviderProps = {
34
34
  userPub: string;
35
35
  username: string;
36
36
  password?: string;
37
- authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof";
37
+ authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof" | "challenge" | "seed" | "pair";
38
38
  }) => void;
39
39
  onSignupSuccess?: (data: {
40
40
  userPub: string;
41
41
  username: string;
42
42
  password?: string;
43
43
  seedPhrase?: string;
44
- authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof";
44
+ authMethod?: "password" | "web3" | "webauthn" | "nostr" | "zkproof" | "challenge" | "seed" | "pair";
45
45
  }) => void;
46
46
  onError?: (error: string) => void;
47
47
  };
@@ -192,6 +192,35 @@ export function ShogunButtonProvider({ children, core, options, onLoginSuccess,
192
192
  throw new Error("ZK-Proof requires ShogunCore");
193
193
  }
194
194
  break;
195
+ case "challenge":
196
+ username = args[0];
197
+ if (!username)
198
+ throw new Error("Username required for challenge login");
199
+ if (isShogunCore(core)) {
200
+ const challengePlugin = core.getPlugin("challenge");
201
+ if (!challengePlugin)
202
+ throw new Error("Challenge plugin not available");
203
+ result = await challengePlugin.login(username);
204
+ authMethod = "challenge";
205
+ }
206
+ else {
207
+ throw new Error("Challenge auth requires ShogunCore");
208
+ }
209
+ break;
210
+ case "seed":
211
+ username = args[0];
212
+ const mnemonic = args[1];
213
+ if (!username || !mnemonic) {
214
+ throw new Error("Username and seed phrase are required");
215
+ }
216
+ if (isShogunCore(core)) {
217
+ result = await core.loginWithSeed(username, mnemonic);
218
+ authMethod = "seed";
219
+ }
220
+ else {
221
+ throw new Error("Seed authentication requires ShogunCore");
222
+ }
223
+ break;
195
224
  default:
196
225
  throw new Error("Unsupported login method");
197
226
  }
@@ -615,6 +644,8 @@ const ZkProofIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.or
615
644
  React.createElement("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
616
645
  React.createElement("path", { d: "M2 17l10 5 10-5" }),
617
646
  React.createElement("path", { d: "M2 12l10 5 10-5" })));
647
+ const ChallengeIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
648
+ React.createElement("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })));
618
649
  const ExportIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
619
650
  React.createElement("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
620
651
  React.createElement("polyline", { points: "14,2 14,8 20,8" }),
@@ -649,6 +680,7 @@ export const ShogunButton = (() => {
649
680
  const [showZkTrapdoorCopySuccess, setShowZkTrapdoorCopySuccess] = useState(false);
650
681
  const [webauthnSeedPhrase, setWebauthnSeedPhrase] = useState("");
651
682
  const [webauthnRecoverySeed, setWebauthnRecoverySeed] = useState("");
683
+ const [formMnemonic, setFormMnemonic] = useState("");
652
684
  const dropdownRef = useRef(null);
653
685
  // Handle click outside to close dropdown
654
686
  useEffect(() => {
@@ -891,6 +923,50 @@ export const ShogunButton = (() => {
891
923
  setLoading(false);
892
924
  }
893
925
  };
926
+ const handleChallengeAuth = () => {
927
+ if (!hasPlugin("challenge")) {
928
+ setError("Challenge plugin not available");
929
+ return;
930
+ }
931
+ setAuthView("challenge-username");
932
+ };
933
+ const handleChallengeLogin = async () => {
934
+ setError("");
935
+ setLoading(true);
936
+ try {
937
+ if (!formUsername.trim()) {
938
+ throw new Error("Please enter your username");
939
+ }
940
+ await handleAuth("challenge", formUsername);
941
+ setModalIsOpen(false);
942
+ }
943
+ catch (e) {
944
+ setError(e.message || "Challenge login failed");
945
+ }
946
+ finally {
947
+ setLoading(false);
948
+ }
949
+ };
950
+ const handleSeedLogin = async () => {
951
+ setError("");
952
+ setLoading(true);
953
+ try {
954
+ if (!formUsername.trim()) {
955
+ throw new Error("Please enter your username");
956
+ }
957
+ if (!formMnemonic.trim()) {
958
+ throw new Error("Please enter your seed phrase");
959
+ }
960
+ await handleAuth("seed", formUsername.trim(), formMnemonic.trim());
961
+ setModalIsOpen(false);
962
+ }
963
+ catch (e) {
964
+ setError(e.message || "Seed login failed");
965
+ }
966
+ finally {
967
+ setLoading(false);
968
+ }
969
+ };
894
970
  const handleRecover = async () => {
895
971
  setError("");
896
972
  setLoading(true);
@@ -1005,6 +1081,7 @@ export const ShogunButton = (() => {
1005
1081
  setShowZkTrapdoorCopySuccess(false);
1006
1082
  setWebauthnSeedPhrase("");
1007
1083
  setWebauthnRecoverySeed("");
1084
+ setFormMnemonic("");
1008
1085
  };
1009
1086
  const openModal = () => {
1010
1087
  resetForm();
@@ -1045,6 +1122,12 @@ export const ShogunButton = (() => {
1045
1122
  React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => handleAuth("nostr"), disabled: loading },
1046
1123
  React.createElement(NostrIcon, null),
1047
1124
  formMode === "login" ? "Login with Nostr" : "Signup with Nostr"))),
1125
+ options.showChallenge !== false && hasPlugin("challenge") && (React.createElement("div", { className: "shogun-auth-option-group" },
1126
+ React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: handleChallengeAuth, disabled: loading },
1127
+ React.createElement(ChallengeIcon, null),
1128
+ formMode === "login"
1129
+ ? "Login with Challenge"
1130
+ : "Signup with Challenge (N/A)"))),
1048
1131
  options.showZkProof !== false && hasPlugin("zkproof") && (React.createElement("div", { className: "shogun-auth-option-group" },
1049
1132
  React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: handleZkProofAuth, disabled: loading },
1050
1133
  React.createElement(ZkProofIcon, null),
@@ -1058,6 +1141,9 @@ export const ShogunButton = (() => {
1058
1141
  formMode === "login"
1059
1142
  ? "Login with Password"
1060
1143
  : "Signup with Password"),
1144
+ options.showSeedLogin !== false && formMode === "login" && (React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => setAuthView("seed-login"), disabled: loading },
1145
+ React.createElement(KeyIcon, null),
1146
+ "Login with Seed phrase")),
1061
1147
  formMode === "login" && (React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => setAuthView("import"), disabled: loading },
1062
1148
  React.createElement(ImportIcon, null),
1063
1149
  "Import Gun Pair"))));
@@ -1385,6 +1471,35 @@ export const ShogunButton = (() => {
1385
1471
  textAlign: "center",
1386
1472
  } }, "\u2705 You're now logged in with WebAuthn!"),
1387
1473
  React.createElement("button", { type: "button", className: "shogun-submit-button", style: { marginTop: "16px" }, onClick: finalizeZkProofSignup }, "Close and Start Using App")));
1474
+ const renderChallengeForm = () => (React.createElement("div", { className: "shogun-auth-form" },
1475
+ React.createElement("div", { className: "shogun-form-group" },
1476
+ React.createElement("label", { htmlFor: "challenge-username" },
1477
+ React.createElement(UserIcon, null),
1478
+ React.createElement("span", null, "Username")),
1479
+ React.createElement("input", { type: "text", id: "challenge-username", value: formUsername, onChange: (e) => setFormUsername(e.target.value), disabled: loading, required: true, placeholder: "Enter your username", autoFocus: true })),
1480
+ React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleChallengeLogin, disabled: loading }, loading ? "Processing..." : "Continue"),
1481
+ React.createElement("button", { type: "button", className: "shogun-back-button", onClick: () => setAuthView("options"), disabled: loading }, "Back")));
1482
+ const renderSeedLoginForm = () => (React.createElement("div", { className: "shogun-auth-form" },
1483
+ React.createElement("h3", null, "Login with Seed Phrase"),
1484
+ React.createElement("div", { className: "shogun-form-group" },
1485
+ React.createElement("label", { htmlFor: "seed-username" },
1486
+ React.createElement(UserIcon, null),
1487
+ React.createElement("span", null, "Username")),
1488
+ React.createElement("input", { type: "text", id: "seed-username", value: formUsername, onChange: (e) => setFormUsername(e.target.value), disabled: loading, required: true, placeholder: "Enter your username", autoFocus: true })),
1489
+ React.createElement("div", { className: "shogun-form-group" },
1490
+ React.createElement("label", { htmlFor: "seed-mnemonic" },
1491
+ React.createElement(KeyIcon, null),
1492
+ React.createElement("span", null, "Seed Phrase (12/24 words)")),
1493
+ React.createElement("textarea", { id: "seed-mnemonic", value: formMnemonic, onChange: (e) => setFormMnemonic(e.target.value), disabled: loading, required: true, placeholder: "Enter your seed phrase...", rows: 3, style: {
1494
+ fontFamily: "monospace",
1495
+ fontSize: "12px",
1496
+ width: "100%",
1497
+ padding: "8px",
1498
+ border: "1px solid #ccc",
1499
+ borderRadius: "4px",
1500
+ } })),
1501
+ React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleSeedLogin, disabled: loading || !formUsername.trim() || !formMnemonic.trim() }, loading ? "Processing..." : "Login with Seed"),
1502
+ React.createElement("button", { type: "button", className: "shogun-back-button", onClick: () => setAuthView("options"), disabled: loading }, "Back")));
1388
1503
  const renderImportForm = () => (React.createElement("div", { className: "shogun-auth-form" },
1389
1504
  React.createElement("h3", null, "Import Gun Pair"),
1390
1505
  React.createElement("div", { style: {
@@ -1459,9 +1574,11 @@ export const ShogunButton = (() => {
1459
1574
  ? "WebAuthn"
1460
1575
  : authView === "zkproof-login"
1461
1576
  ? "ZK-Proof Login"
1462
- : formMode === "login"
1463
- ? "Login"
1464
- : "Sign Up"),
1577
+ : authView === "seed-login"
1578
+ ? "Login with Seed"
1579
+ : formMode === "login"
1580
+ ? "Login"
1581
+ : "Sign Up"),
1465
1582
  React.createElement("button", { className: "shogun-close-button", onClick: closeModal, "aria-label": "Close" },
1466
1583
  React.createElement(CloseIcon, null))),
1467
1584
  React.createElement("div", { className: "shogun-modal-content" },
@@ -1472,6 +1589,7 @@ export const ShogunButton = (() => {
1472
1589
  React.createElement("button", { type: "button", className: "shogun-toggle-mode shogun-prominent-toggle", onClick: toggleMode, disabled: loading }, formMode === "login"
1473
1590
  ? "Don't have an account? Sign up"
1474
1591
  : "Already have an account? Log in")))),
1592
+ authView === "seed-login" && renderSeedLoginForm(),
1475
1593
  authView === "password" && (React.createElement(React.Fragment, null,
1476
1594
  React.createElement("button", { className: "shogun-back-button", onClick: () => setAuthView("options") }, "\u2190 Back"),
1477
1595
  renderPasswordForm())),
@@ -1487,7 +1605,9 @@ export const ShogunButton = (() => {
1487
1605
  renderWebauthnSignupResult(),
1488
1606
  authView === "zkproof-login" && renderZkProofLoginForm(),
1489
1607
  authView === "zkproof-signup-result" &&
1490
- renderZkProofSignupResult()))))));
1608
+ renderZkProofSignupResult(),
1609
+ authView === "challenge-username" &&
1610
+ renderChallengeForm()))))));
1491
1611
  };
1492
1612
  Button.displayName = "ShogunButton";
1493
1613
  return Object.assign(Button, {
package/dist/connector.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ShogunCore } from "shogun-core";
2
2
  export async function shogunConnector(options) {
3
- const { gunInstance, appName, timeouts, webauthn, nostr, web3, zkproof, showWebauthn, showNostr, showMetamask, showZkProof, darkMode, enableGunDebug = true, enableConnectionMonitoring = true, defaultPageSize = 20, connectionTimeout = 10000, debounceInterval = 100, crypto, ...restOptions } = options;
3
+ const { gunInstance, appName, timeouts, webauthn, nostr, web3, zkproof, challenge, showWebauthn, showNostr, showMetamask, showZkProof, showChallenge, darkMode, enableGunDebug = true, enableConnectionMonitoring = true, defaultPageSize = 20, connectionTimeout = 10000, debounceInterval = 100, crypto, ...restOptions } = options;
4
4
  let core = null;
5
5
  let gun = null;
6
6
  gun = gunInstance;
@@ -18,6 +18,7 @@ export async function shogunConnector(options) {
18
18
  enabled: true,
19
19
  defaultGroupId: zkproof.defaultGroupId || "shogun-users",
20
20
  } : undefined,
21
+ challenge: (challenge === null || challenge === void 0 ? void 0 : challenge.enabled) ? { enabled: true } : undefined,
21
22
  timeouts,
22
23
  silent: false, // Enable console logs for debugging
23
24
  });