@iamgame/wallet-sdk 0.1.1 → 0.1.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.
package/dist/index.cjs CHANGED
@@ -80,6 +80,23 @@ var SolvenClient = class {
80
80
  this.opts.storage.set(session);
81
81
  return session;
82
82
  }
83
+ /** Email + OTP: send a one-time code to the address. */
84
+ async initiateEmail(email) {
85
+ return this.publicCall(
86
+ "POST",
87
+ "/auth/email/initiate",
88
+ { email }
89
+ );
90
+ }
91
+ /** Email + OTP: exchange the code for a session. */
92
+ async verifyEmail(email, code) {
93
+ const session = await this.publicCall("POST", "/auth/email/verify", {
94
+ email,
95
+ code
96
+ });
97
+ this.opts.storage.set(session);
98
+ return session;
99
+ }
83
100
  async refreshSession() {
84
101
  const current = this.opts.storage.get();
85
102
  if (!current) return null;
@@ -353,6 +370,20 @@ function useSolvenAuth() {
353
370
  const session2 = await client.verifyTelegram({ initData });
354
371
  setSession(session2);
355
372
  }, [client, setSession]);
373
+ const requestEmailOtp = react.useCallback(
374
+ async (email) => {
375
+ const { expiresAt } = await client.initiateEmail(email);
376
+ return { expiresAt };
377
+ },
378
+ [client]
379
+ );
380
+ const connectEmail = react.useCallback(
381
+ async (email, code) => {
382
+ const session2 = await client.verifyEmail(email, code);
383
+ setSession(session2);
384
+ },
385
+ [client, setSession]
386
+ );
356
387
  const logout = react.useCallback(async () => {
357
388
  await client.logout();
358
389
  setSession(null);
@@ -362,6 +393,8 @@ function useSolvenAuth() {
362
393
  status,
363
394
  connectExternal,
364
395
  connectTelegram,
396
+ requestEmailOtp,
397
+ connectEmail,
365
398
  logout
366
399
  };
367
400
  }
@@ -553,9 +586,13 @@ var defaultTheme = {
553
586
  fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
554
587
  };
555
588
  function SolvenLoginContent(props) {
556
- const { connectExternal, connectTelegram, status, user } = useSolvenAuth();
589
+ const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
557
590
  const [busy, setBusy] = react.useState(null);
558
591
  const [error, setError] = react.useState(null);
592
+ const [email, setEmail] = react.useState("");
593
+ const [otp, setOtp] = react.useState("");
594
+ const [otpSent, setOtpSent] = react.useState(false);
595
+ const showEmail = props.showEmail ?? true;
559
596
  const theme = react.useMemo(
560
597
  () => ({ ...defaultTheme, ...props.theme ?? {} }),
561
598
  [props.theme]
@@ -622,6 +659,31 @@ function SolvenLoginContent(props) {
622
659
  setBusy(null);
623
660
  }
624
661
  };
662
+ const handleSendOtp = async () => {
663
+ setBusy("email");
664
+ setError(null);
665
+ try {
666
+ await requestEmailOtp(email.trim());
667
+ setOtpSent(true);
668
+ } catch (e) {
669
+ setError(e instanceof Error ? e.message : "Couldn't send the code");
670
+ } finally {
671
+ setBusy(null);
672
+ }
673
+ };
674
+ const handleVerifyOtp = async () => {
675
+ setBusy("email");
676
+ setError(null);
677
+ try {
678
+ await connectEmail(email.trim(), otp.trim());
679
+ props.onSignIn?.();
680
+ props.onCloseAfterSignIn?.();
681
+ } catch (e) {
682
+ setError(e instanceof Error ? e.message : "Couldn't verify the code");
683
+ } finally {
684
+ setBusy(null);
685
+ }
686
+ };
625
687
  const buttonBase = {
626
688
  width: "100%",
627
689
  padding: "0.75rem 0.875rem",
@@ -707,6 +769,135 @@ function SolvenLoginContent(props) {
707
769
  w.id
708
770
  );
709
771
  }) }),
772
+ !inTma && showEmail && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem" }, children: [
773
+ /* @__PURE__ */ jsxRuntime.jsxs(
774
+ "div",
775
+ {
776
+ style: {
777
+ display: "flex",
778
+ alignItems: "center",
779
+ gap: "0.625rem",
780
+ margin: "0.25rem 0 0.875rem",
781
+ color: theme.muted,
782
+ fontSize: "0.8125rem"
783
+ },
784
+ children: [
785
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1, height: 1, background: theme.border } }),
786
+ "or",
787
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { flex: 1, height: 1, background: theme.border } })
788
+ ]
789
+ }
790
+ ),
791
+ !otpSent ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
792
+ /* @__PURE__ */ jsxRuntime.jsx(
793
+ "input",
794
+ {
795
+ type: "email",
796
+ inputMode: "email",
797
+ autoComplete: "email",
798
+ placeholder: "you@email.com",
799
+ value: email,
800
+ onChange: (e) => setEmail(e.target.value),
801
+ style: {
802
+ width: "100%",
803
+ padding: "0.75rem 0.875rem",
804
+ borderRadius: theme.radius,
805
+ border: `1px solid ${theme.border}`,
806
+ background: theme.surface,
807
+ color: theme.foreground,
808
+ fontSize: "0.9375rem",
809
+ outline: "none",
810
+ boxSizing: "border-box"
811
+ }
812
+ }
813
+ ),
814
+ /* @__PURE__ */ jsxRuntime.jsx(
815
+ "button",
816
+ {
817
+ type: "button",
818
+ onClick: handleSendOtp,
819
+ disabled: busy !== null || !email.includes("@"),
820
+ style: {
821
+ ...buttonBase,
822
+ justifyContent: "center",
823
+ background: theme.primary,
824
+ color: "#ffffff",
825
+ border: "none",
826
+ opacity: busy === "email" || !email.includes("@") ? 0.6 : 1
827
+ },
828
+ children: busy === "email" ? "Sending\u2026" : "Email me a code"
829
+ }
830
+ )
831
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
832
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: theme.muted, fontSize: "0.8125rem" }, children: [
833
+ "Enter the 6-digit code sent to ",
834
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: email.trim() }),
835
+ "."
836
+ ] }),
837
+ /* @__PURE__ */ jsxRuntime.jsx(
838
+ "input",
839
+ {
840
+ type: "text",
841
+ inputMode: "numeric",
842
+ autoComplete: "one-time-code",
843
+ maxLength: 6,
844
+ placeholder: "123456",
845
+ value: otp,
846
+ onChange: (e) => setOtp(e.target.value.replace(/\D/g, "")),
847
+ style: {
848
+ width: "100%",
849
+ padding: "0.75rem 0.875rem",
850
+ borderRadius: theme.radius,
851
+ border: `1px solid ${theme.border}`,
852
+ background: theme.surface,
853
+ color: theme.foreground,
854
+ fontSize: "1.125rem",
855
+ letterSpacing: "0.3em",
856
+ textAlign: "center",
857
+ outline: "none",
858
+ boxSizing: "border-box"
859
+ }
860
+ }
861
+ ),
862
+ /* @__PURE__ */ jsxRuntime.jsx(
863
+ "button",
864
+ {
865
+ type: "button",
866
+ onClick: handleVerifyOtp,
867
+ disabled: busy !== null || otp.length !== 6,
868
+ style: {
869
+ ...buttonBase,
870
+ justifyContent: "center",
871
+ background: theme.primary,
872
+ color: "#ffffff",
873
+ border: "none",
874
+ opacity: busy === "email" || otp.length !== 6 ? 0.6 : 1
875
+ },
876
+ children: busy === "email" ? "Verifying\u2026" : "Verify & sign in"
877
+ }
878
+ ),
879
+ /* @__PURE__ */ jsxRuntime.jsx(
880
+ "button",
881
+ {
882
+ type: "button",
883
+ onClick: () => {
884
+ setOtpSent(false);
885
+ setOtp("");
886
+ setError(null);
887
+ },
888
+ style: {
889
+ background: "none",
890
+ border: "none",
891
+ color: theme.muted,
892
+ fontSize: "0.8125rem",
893
+ cursor: "pointer",
894
+ padding: "0.25rem"
895
+ },
896
+ children: "Use a different email"
897
+ }
898
+ )
899
+ ] })
900
+ ] }),
710
901
  error && /* @__PURE__ */ jsxRuntime.jsx(
711
902
  "div",
712
903
  {
package/dist/index.d.cts CHANGED
@@ -1,12 +1,15 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
- type AuthMethod = "siws" | "telegram";
4
+ type AuthMethod = "siws" | "telegram" | "email";
5
5
  interface IUserIdentity {
6
6
  id: string;
7
7
  type: AuthMethod;
8
- /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. */
8
+ /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. For email: the address. */
9
9
  externalId: string;
10
+ /** Provider-specific profile captured at login (e.g. Telegram { username, firstName }).
11
+ * Display/attribution only — null when none was captured. */
12
+ profile?: Record<string, unknown> | null;
10
13
  }
11
14
  interface IUserWallet {
12
15
  /** base58 Solana pubkey */
@@ -156,7 +159,7 @@ interface IWebhookSignatureHeader {
156
159
  signature: string;
157
160
  }
158
161
 
159
- type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
162
+ type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "auth/method_not_allowed" | "auth/invalid_otp" | "auth/otp_not_found" | "auth/otp_locked" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
160
163
  interface IIAMGameErrorEnvelope {
161
164
  code: IAMGameErrorCode;
162
165
  message: string;
@@ -194,6 +197,13 @@ declare class IAMGameClient {
194
197
  requestSiwsChallenge(publicKey: string): Promise<ISiwsChallenge>;
195
198
  verifySiws(req: ISiwsVerifyRequest): Promise<ISession>;
196
199
  verifyTelegram(req: ITelegramVerifyRequest): Promise<ISession>;
200
+ /** Email + OTP: send a one-time code to the address. */
201
+ initiateEmail(email: string): Promise<{
202
+ sent: boolean;
203
+ expiresAt: string;
204
+ }>;
205
+ /** Email + OTP: exchange the code for a session. */
206
+ verifyEmail(email: string, code: string): Promise<ISession>;
197
207
  refreshSession(): Promise<ISession | null>;
198
208
  logout(): Promise<void>;
199
209
  getSession(): ISession | null;
@@ -251,6 +261,12 @@ interface IUseIAMGameAuth {
251
261
  connectExternal: (adapter: IExternalWalletAdapter) => Promise<void>;
252
262
  /** Run the Telegram TMA flow. Reads `window.Telegram.WebApp.initData` and posts to IAMGame. */
253
263
  connectTelegram: () => Promise<void>;
264
+ /** Email + OTP step 1: email a one-time code to the address. */
265
+ requestEmailOtp: (email: string) => Promise<{
266
+ expiresAt: string;
267
+ }>;
268
+ /** Email + OTP step 2: exchange the code for a session. */
269
+ connectEmail: (email: string, code: string) => Promise<void>;
254
270
  logout: () => Promise<void>;
255
271
  }
256
272
  declare function useIAMGameAuth(): IUseIAMGameAuth;
@@ -307,6 +323,12 @@ interface CommonProps {
307
323
  * no clicks. Defaults to true.
308
324
  */
309
325
  autoTelegram?: boolean;
326
+ /**
327
+ * Show the email + one-time-code login option (web / non-TMA). Defaults to true.
328
+ * The app must also enable `email` in its allowed auth methods, or the send-code
329
+ * call is rejected.
330
+ */
331
+ showEmail?: boolean;
310
332
  }
311
333
  type IAMGameLoginProps = CommonProps;
312
334
  interface IAMGameLoginModalProps extends CommonProps {
package/dist/index.d.ts CHANGED
@@ -1,12 +1,15 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
- type AuthMethod = "siws" | "telegram";
4
+ type AuthMethod = "siws" | "telegram" | "email";
5
5
  interface IUserIdentity {
6
6
  id: string;
7
7
  type: AuthMethod;
8
- /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. */
8
+ /** For SIWS: base58 Solana pubkey. For Telegram: numeric user id as string. For email: the address. */
9
9
  externalId: string;
10
+ /** Provider-specific profile captured at login (e.g. Telegram { username, firstName }).
11
+ * Display/attribution only — null when none was captured. */
12
+ profile?: Record<string, unknown> | null;
10
13
  }
11
14
  interface IUserWallet {
12
15
  /** base58 Solana pubkey */
@@ -156,7 +159,7 @@ interface IWebhookSignatureHeader {
156
159
  signature: string;
157
160
  }
158
161
 
159
- type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
162
+ type IAMGameErrorCode = "auth/invalid_signature" | "auth/challenge_expired" | "auth/challenge_already_redeemed" | "auth/invalid_init_data" | "auth/init_data_stale" | "auth/init_data_replayed" | "auth/missing_token" | "auth/invalid_token" | "auth/expired_token" | "auth/method_not_allowed" | "auth/invalid_otp" | "auth/otp_not_found" | "auth/otp_locked" | "wallet/not_found" | "wallet/insufficient_balance" | "wallet/export_blocked" | "wallet/already_exported" | "user/not_found" | "user/suspended" | "compliance/blocked" | "sign/invalid_transaction" | "sign/wallet_archived" | "sign/internal_failure" | "withdrawal/insufficient_balance" | "withdrawal/limit_exceeded" | "ledger/insufficient_balance" | "ledger/session_not_found" | "ledger/session_closed" | "ledger/bet_not_found" | "ledger/bet_rolled_back" | "ledger/currency_mismatch" | "ratelimit/exceeded" | "idempotency/key_in_use" | "validation/bad_request" | "server/internal";
160
163
  interface IIAMGameErrorEnvelope {
161
164
  code: IAMGameErrorCode;
162
165
  message: string;
@@ -194,6 +197,13 @@ declare class IAMGameClient {
194
197
  requestSiwsChallenge(publicKey: string): Promise<ISiwsChallenge>;
195
198
  verifySiws(req: ISiwsVerifyRequest): Promise<ISession>;
196
199
  verifyTelegram(req: ITelegramVerifyRequest): Promise<ISession>;
200
+ /** Email + OTP: send a one-time code to the address. */
201
+ initiateEmail(email: string): Promise<{
202
+ sent: boolean;
203
+ expiresAt: string;
204
+ }>;
205
+ /** Email + OTP: exchange the code for a session. */
206
+ verifyEmail(email: string, code: string): Promise<ISession>;
197
207
  refreshSession(): Promise<ISession | null>;
198
208
  logout(): Promise<void>;
199
209
  getSession(): ISession | null;
@@ -251,6 +261,12 @@ interface IUseIAMGameAuth {
251
261
  connectExternal: (adapter: IExternalWalletAdapter) => Promise<void>;
252
262
  /** Run the Telegram TMA flow. Reads `window.Telegram.WebApp.initData` and posts to IAMGame. */
253
263
  connectTelegram: () => Promise<void>;
264
+ /** Email + OTP step 1: email a one-time code to the address. */
265
+ requestEmailOtp: (email: string) => Promise<{
266
+ expiresAt: string;
267
+ }>;
268
+ /** Email + OTP step 2: exchange the code for a session. */
269
+ connectEmail: (email: string, code: string) => Promise<void>;
254
270
  logout: () => Promise<void>;
255
271
  }
256
272
  declare function useIAMGameAuth(): IUseIAMGameAuth;
@@ -307,6 +323,12 @@ interface CommonProps {
307
323
  * no clicks. Defaults to true.
308
324
  */
309
325
  autoTelegram?: boolean;
326
+ /**
327
+ * Show the email + one-time-code login option (web / non-TMA). Defaults to true.
328
+ * The app must also enable `email` in its allowed auth methods, or the send-code
329
+ * call is rejected.
330
+ */
331
+ showEmail?: boolean;
310
332
  }
311
333
  type IAMGameLoginProps = CommonProps;
312
334
  interface IAMGameLoginModalProps extends CommonProps {
package/dist/index.js CHANGED
@@ -78,6 +78,23 @@ var SolvenClient = class {
78
78
  this.opts.storage.set(session);
79
79
  return session;
80
80
  }
81
+ /** Email + OTP: send a one-time code to the address. */
82
+ async initiateEmail(email) {
83
+ return this.publicCall(
84
+ "POST",
85
+ "/auth/email/initiate",
86
+ { email }
87
+ );
88
+ }
89
+ /** Email + OTP: exchange the code for a session. */
90
+ async verifyEmail(email, code) {
91
+ const session = await this.publicCall("POST", "/auth/email/verify", {
92
+ email,
93
+ code
94
+ });
95
+ this.opts.storage.set(session);
96
+ return session;
97
+ }
81
98
  async refreshSession() {
82
99
  const current = this.opts.storage.get();
83
100
  if (!current) return null;
@@ -351,6 +368,20 @@ function useSolvenAuth() {
351
368
  const session2 = await client.verifyTelegram({ initData });
352
369
  setSession(session2);
353
370
  }, [client, setSession]);
371
+ const requestEmailOtp = useCallback(
372
+ async (email) => {
373
+ const { expiresAt } = await client.initiateEmail(email);
374
+ return { expiresAt };
375
+ },
376
+ [client]
377
+ );
378
+ const connectEmail = useCallback(
379
+ async (email, code) => {
380
+ const session2 = await client.verifyEmail(email, code);
381
+ setSession(session2);
382
+ },
383
+ [client, setSession]
384
+ );
354
385
  const logout = useCallback(async () => {
355
386
  await client.logout();
356
387
  setSession(null);
@@ -360,6 +391,8 @@ function useSolvenAuth() {
360
391
  status,
361
392
  connectExternal,
362
393
  connectTelegram,
394
+ requestEmailOtp,
395
+ connectEmail,
363
396
  logout
364
397
  };
365
398
  }
@@ -551,9 +584,13 @@ var defaultTheme = {
551
584
  fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
552
585
  };
553
586
  function SolvenLoginContent(props) {
554
- const { connectExternal, connectTelegram, status, user } = useSolvenAuth();
587
+ const { connectExternal, connectTelegram, requestEmailOtp, connectEmail, status, user } = useSolvenAuth();
555
588
  const [busy, setBusy] = useState(null);
556
589
  const [error, setError] = useState(null);
590
+ const [email, setEmail] = useState("");
591
+ const [otp, setOtp] = useState("");
592
+ const [otpSent, setOtpSent] = useState(false);
593
+ const showEmail = props.showEmail ?? true;
557
594
  const theme = useMemo(
558
595
  () => ({ ...defaultTheme, ...props.theme ?? {} }),
559
596
  [props.theme]
@@ -620,6 +657,31 @@ function SolvenLoginContent(props) {
620
657
  setBusy(null);
621
658
  }
622
659
  };
660
+ const handleSendOtp = async () => {
661
+ setBusy("email");
662
+ setError(null);
663
+ try {
664
+ await requestEmailOtp(email.trim());
665
+ setOtpSent(true);
666
+ } catch (e) {
667
+ setError(e instanceof Error ? e.message : "Couldn't send the code");
668
+ } finally {
669
+ setBusy(null);
670
+ }
671
+ };
672
+ const handleVerifyOtp = async () => {
673
+ setBusy("email");
674
+ setError(null);
675
+ try {
676
+ await connectEmail(email.trim(), otp.trim());
677
+ props.onSignIn?.();
678
+ props.onCloseAfterSignIn?.();
679
+ } catch (e) {
680
+ setError(e instanceof Error ? e.message : "Couldn't verify the code");
681
+ } finally {
682
+ setBusy(null);
683
+ }
684
+ };
623
685
  const buttonBase = {
624
686
  width: "100%",
625
687
  padding: "0.75rem 0.875rem",
@@ -705,6 +767,135 @@ function SolvenLoginContent(props) {
705
767
  w.id
706
768
  );
707
769
  }) }),
770
+ !inTma && showEmail && /* @__PURE__ */ jsxs("div", { style: { marginTop: "1rem" }, children: [
771
+ /* @__PURE__ */ jsxs(
772
+ "div",
773
+ {
774
+ style: {
775
+ display: "flex",
776
+ alignItems: "center",
777
+ gap: "0.625rem",
778
+ margin: "0.25rem 0 0.875rem",
779
+ color: theme.muted,
780
+ fontSize: "0.8125rem"
781
+ },
782
+ children: [
783
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, height: 1, background: theme.border } }),
784
+ "or",
785
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, height: 1, background: theme.border } })
786
+ ]
787
+ }
788
+ ),
789
+ !otpSent ? /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
790
+ /* @__PURE__ */ jsx(
791
+ "input",
792
+ {
793
+ type: "email",
794
+ inputMode: "email",
795
+ autoComplete: "email",
796
+ placeholder: "you@email.com",
797
+ value: email,
798
+ onChange: (e) => setEmail(e.target.value),
799
+ style: {
800
+ width: "100%",
801
+ padding: "0.75rem 0.875rem",
802
+ borderRadius: theme.radius,
803
+ border: `1px solid ${theme.border}`,
804
+ background: theme.surface,
805
+ color: theme.foreground,
806
+ fontSize: "0.9375rem",
807
+ outline: "none",
808
+ boxSizing: "border-box"
809
+ }
810
+ }
811
+ ),
812
+ /* @__PURE__ */ jsx(
813
+ "button",
814
+ {
815
+ type: "button",
816
+ onClick: handleSendOtp,
817
+ disabled: busy !== null || !email.includes("@"),
818
+ style: {
819
+ ...buttonBase,
820
+ justifyContent: "center",
821
+ background: theme.primary,
822
+ color: "#ffffff",
823
+ border: "none",
824
+ opacity: busy === "email" || !email.includes("@") ? 0.6 : 1
825
+ },
826
+ children: busy === "email" ? "Sending\u2026" : "Email me a code"
827
+ }
828
+ )
829
+ ] }) : /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
830
+ /* @__PURE__ */ jsxs("div", { style: { color: theme.muted, fontSize: "0.8125rem" }, children: [
831
+ "Enter the 6-digit code sent to ",
832
+ /* @__PURE__ */ jsx("strong", { children: email.trim() }),
833
+ "."
834
+ ] }),
835
+ /* @__PURE__ */ jsx(
836
+ "input",
837
+ {
838
+ type: "text",
839
+ inputMode: "numeric",
840
+ autoComplete: "one-time-code",
841
+ maxLength: 6,
842
+ placeholder: "123456",
843
+ value: otp,
844
+ onChange: (e) => setOtp(e.target.value.replace(/\D/g, "")),
845
+ style: {
846
+ width: "100%",
847
+ padding: "0.75rem 0.875rem",
848
+ borderRadius: theme.radius,
849
+ border: `1px solid ${theme.border}`,
850
+ background: theme.surface,
851
+ color: theme.foreground,
852
+ fontSize: "1.125rem",
853
+ letterSpacing: "0.3em",
854
+ textAlign: "center",
855
+ outline: "none",
856
+ boxSizing: "border-box"
857
+ }
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsx(
861
+ "button",
862
+ {
863
+ type: "button",
864
+ onClick: handleVerifyOtp,
865
+ disabled: busy !== null || otp.length !== 6,
866
+ style: {
867
+ ...buttonBase,
868
+ justifyContent: "center",
869
+ background: theme.primary,
870
+ color: "#ffffff",
871
+ border: "none",
872
+ opacity: busy === "email" || otp.length !== 6 ? 0.6 : 1
873
+ },
874
+ children: busy === "email" ? "Verifying\u2026" : "Verify & sign in"
875
+ }
876
+ ),
877
+ /* @__PURE__ */ jsx(
878
+ "button",
879
+ {
880
+ type: "button",
881
+ onClick: () => {
882
+ setOtpSent(false);
883
+ setOtp("");
884
+ setError(null);
885
+ },
886
+ style: {
887
+ background: "none",
888
+ border: "none",
889
+ color: theme.muted,
890
+ fontSize: "0.8125rem",
891
+ cursor: "pointer",
892
+ padding: "0.25rem"
893
+ },
894
+ children: "Use a different email"
895
+ }
896
+ )
897
+ ] })
898
+ ] }),
708
899
  error && /* @__PURE__ */ jsx(
709
900
  "div",
710
901
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamgame/wallet-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "IAMGame Wallet browser SDK — Telegram & Solana wallet auth, balances, server-side signing, and key export. Drop-in React provider for game frontends.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://wallet.iamgame.com",