@crossmint/client-sdk-react-ui 1.7.1 → 1.9.1

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.
Files changed (52) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.d.cts +20 -7
  3. package/dist/index.d.ts +20 -7
  4. package/dist/index.js +1 -1
  5. package/package.json +17 -7
  6. package/src/components/auth/AuthForm.tsx +50 -0
  7. package/src/components/auth/AuthFormBackButton.tsx +26 -0
  8. package/src/components/auth/AuthFormDialog.tsx +33 -0
  9. package/src/components/auth/EmbeddedAuthForm.tsx +5 -0
  10. package/src/components/auth/methods/email/EmailAuthFlow.tsx +19 -0
  11. package/src/components/auth/methods/email/EmailOTPInput.tsx +123 -0
  12. package/src/components/auth/methods/email/EmailSignIn.tsx +113 -0
  13. package/src/components/auth/methods/farcaster/FarcasterSignIn.tsx +170 -0
  14. package/src/components/auth/methods/google/GoogleSignIn.tsx +62 -0
  15. package/src/components/common/Dialog.tsx +141 -0
  16. package/src/components/common/Divider.tsx +25 -0
  17. package/src/components/common/InputOTP.tsx +89 -0
  18. package/src/components/common/PoweredByCrossmint.tsx +4 -9
  19. package/src/components/common/Spinner.tsx +22 -0
  20. package/src/components/dynamic-xyz/DynamicContextProviderWrapper.tsx +31 -0
  21. package/src/components/embed/v3/CrossmintEmbeddedCheckoutV3.tsx +7 -0
  22. package/src/components/embed/v3/EmbeddedCheckoutV3IFrame.tsx +74 -0
  23. package/src/components/embed/v3/crypto/CryptoWalletConnectionHandler.tsx +138 -0
  24. package/src/components/embed/v3/crypto/utils/handleEvmTransaction.ts +65 -0
  25. package/src/components/embed/v3/crypto/utils/handleSendTransaction.ts +31 -0
  26. package/src/components/embed/v3/crypto/utils/handleSolanaTransaction.ts +51 -0
  27. package/src/components/embed/v3/index.ts +1 -0
  28. package/src/components/index.ts +3 -0
  29. package/src/hooks/index.ts +1 -0
  30. package/src/hooks/useAuthSignIn.ts +117 -0
  31. package/src/hooks/useCrossmintCheckout.tsx +54 -0
  32. package/src/hooks/useOAuthWindowListener.ts +87 -0
  33. package/src/hooks/useRefreshToken.test.ts +21 -8
  34. package/src/hooks/useRefreshToken.ts +5 -4
  35. package/src/icons/alert.tsx +19 -0
  36. package/src/icons/discord.tsx +18 -0
  37. package/src/icons/emailOTP.tsx +147 -0
  38. package/src/icons/farcaster.tsx +26 -0
  39. package/src/icons/google.tsx +30 -0
  40. package/src/icons/leftArrow.tsx +20 -0
  41. package/src/icons/poweredByLeaf.tsx +2 -2
  42. package/src/providers/CrossmintAuthProvider.test.tsx +4 -3
  43. package/src/providers/CrossmintAuthProvider.tsx +36 -32
  44. package/src/providers/CrossmintWalletProvider.tsx +3 -3
  45. package/src/providers/auth/AuthFormProvider.test.tsx +105 -0
  46. package/src/providers/auth/AuthFormProvider.tsx +116 -0
  47. package/src/providers/auth/FarcasterProvider.tsx +12 -0
  48. package/src/twind.config.ts +101 -1
  49. package/src/types/auth.ts +4 -0
  50. package/src/utils/authCookies.ts +0 -3
  51. package/src/utils/createCrossmintApiClient.ts +17 -0
  52. package/src/components/auth/AuthModal.tsx +0 -207
@@ -0,0 +1,54 @@
1
+ import { createContext, type ReactNode, useContext, useEffect, useState } from "react";
2
+ import type { embeddedCheckoutV3IncomingEvents } from "@crossmint/client-sdk-base";
3
+ import type { z } from "zod";
4
+ import { useCrossmint } from "./useCrossmint";
5
+ import { createCrossmintApiClient } from "@/utils/createCrossmintApiClient";
6
+
7
+ export interface CrossmintCheckoutContext {
8
+ order?: any;
9
+ orderClientSecret?: string;
10
+ }
11
+
12
+ const CrossmintCheckoutContext = createContext<CrossmintCheckoutContext | undefined>(undefined);
13
+
14
+ export function CrossmintCheckoutProvider({ children }: { children: ReactNode }) {
15
+ const [order, setOrder] = useState<any>();
16
+ const [orderClientSecret, setOrderClientSecret] = useState<string>();
17
+
18
+ const { crossmint } = useCrossmint();
19
+ const apiClient = createCrossmintApiClient(crossmint);
20
+
21
+ useEffect(() => {
22
+ const listener = (event: MessageEvent) => {
23
+ if (event.origin !== new URL(apiClient.baseUrl).origin) {
24
+ return;
25
+ }
26
+ if (event.data.event !== "order:updated") {
27
+ return;
28
+ }
29
+ const { order, orderClientSecret } = event.data.data as z.infer<
30
+ (typeof embeddedCheckoutV3IncomingEvents)["order:updated"]
31
+ >;
32
+ setOrder(order);
33
+ setOrderClientSecret(orderClientSecret);
34
+ };
35
+ window.addEventListener("message", listener);
36
+ return () => {
37
+ window.removeEventListener("message", listener);
38
+ };
39
+ }, [order]);
40
+
41
+ return (
42
+ <CrossmintCheckoutContext.Provider value={{ order, orderClientSecret }}>
43
+ {children}
44
+ </CrossmintCheckoutContext.Provider>
45
+ );
46
+ }
47
+
48
+ export function useCrossmintCheckout() {
49
+ const context = useContext(CrossmintCheckoutContext);
50
+ if (!context) {
51
+ throw new Error("useCrossmintCheckout must be used within a CrossmintCheckoutProvider");
52
+ }
53
+ return context;
54
+ }
@@ -0,0 +1,87 @@
1
+ import type { OAuthProvider } from "@crossmint/common-sdk-auth";
2
+ import { ChildWindow, PopupWindow } from "@crossmint/client-sdk-window";
3
+ import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { z } from "zod";
6
+ import { useAuthForm } from "@/providers/auth/AuthFormProvider";
7
+
8
+ export const useOAuthWindowListener = (
9
+ provider: OAuthProvider,
10
+ options: {
11
+ apiKey: string;
12
+ baseUrl: string;
13
+ fetchAuthMaterial: (refreshToken: string) => Promise<AuthMaterialWithUser>;
14
+ }
15
+ ) => {
16
+ const { oauthUrlMap } = useAuthForm();
17
+ const [isLoading, setIsLoading] = useState(false);
18
+ const childRef = useRef<ChildWindow<IncomingEvents, OutgoingEvents> | null>(null);
19
+
20
+ useEffect(() => {
21
+ if (childRef.current == null) {
22
+ childRef.current = new ChildWindow<IncomingEvents, OutgoingEvents>(window.opener || window.parent, "*", {
23
+ incomingEvents,
24
+ outgoingEvents,
25
+ });
26
+ }
27
+
28
+ return () => {
29
+ if (childRef.current != null) {
30
+ childRef.current.off("authMaterialFromPopupCallback");
31
+ }
32
+ };
33
+ }, []);
34
+
35
+ const createPopupAndSetupListeners = async () => {
36
+ if (childRef.current == null) {
37
+ throw new Error("Child window not initialized");
38
+ }
39
+ setIsLoading(true);
40
+ const popup = await PopupWindow.init(oauthUrlMap[provider], {
41
+ awaitToLoad: false,
42
+ crossOrigin: true,
43
+ width: 400,
44
+ height: 700,
45
+ });
46
+
47
+ const handleAuthMaterial = async (data: { oneTimeSecret: string }) => {
48
+ await options.fetchAuthMaterial(data.oneTimeSecret);
49
+ childRef.current?.off("authMaterialFromPopupCallback");
50
+ popup.window.close();
51
+ setIsLoading(false);
52
+ };
53
+
54
+ childRef.current.on("authMaterialFromPopupCallback", handleAuthMaterial);
55
+
56
+ // Add a check for manual window closure
57
+ // Ideally we should find a more explicit way of doing this, but I think this is fine for now.
58
+ const checkWindowClosure = setInterval(() => {
59
+ if (popup.window.closed) {
60
+ clearInterval(checkWindowClosure);
61
+ setIsLoading(false);
62
+ childRef.current?.off("authMaterialFromPopupCallback");
63
+ }
64
+ }, 2500); // Check every 2.5 seconds
65
+ };
66
+
67
+ return {
68
+ createPopupAndSetupListeners,
69
+ isLoading,
70
+ };
71
+ };
72
+
73
+ const incomingEvents = {
74
+ authMaterialFromPopupCallback: z.object({ oneTimeSecret: z.string() }),
75
+ };
76
+
77
+ const outgoingEvents = {
78
+ authMaterialFromAuthFrame: z.object({ oneTimeSecret: z.string() }),
79
+ };
80
+
81
+ type IncomingEvents = {
82
+ authMaterialFromPopupCallback: typeof incomingEvents.authMaterialFromPopupCallback;
83
+ };
84
+
85
+ type OutgoingEvents = {
86
+ authMaterialFromAuthFrame: typeof outgoingEvents.authMaterialFromAuthFrame;
87
+ };
@@ -1,11 +1,12 @@
1
1
  import { act, renderHook } from "@testing-library/react";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
3
 
4
+ import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth";
4
5
  import { type CrossmintAuthService, getJWTExpiration } from "@crossmint/client-sdk-auth";
5
6
  import { queueTask } from "@crossmint/client-sdk-base";
6
7
 
7
8
  import * as authCookies from "../utils/authCookies";
8
- import { type AuthMaterial, useRefreshToken } from "./useRefreshToken";
9
+ import { useRefreshToken } from "./useRefreshToken";
9
10
 
10
11
  vi.mock("@crossmint/client-sdk-auth", () => ({
11
12
  CrossmintAuthService: vi.fn(),
@@ -17,9 +18,13 @@ vi.mock("../utils/authCookies", () => ({
17
18
  REFRESH_TOKEN_PREFIX: "crossmint-refresh-token",
18
19
  }));
19
20
 
20
- vi.mock("@crossmint/client-sdk-base", () => ({
21
- queueTask: vi.fn(),
22
- }));
21
+ vi.mock("@crossmint/client-sdk-base", async () => {
22
+ const actual = await vi.importActual("@crossmint/client-sdk-base");
23
+ return {
24
+ ...actual,
25
+ queueTask: vi.fn(),
26
+ };
27
+ });
23
28
 
24
29
  describe("useRefreshToken", () => {
25
30
  const mockCrossmintAuthService = {
@@ -59,12 +64,16 @@ describe("useRefreshToken", () => {
59
64
 
60
65
  it("should refresh token if refresh token is present", async () => {
61
66
  const mockRefreshToken = "mock-refresh-token";
62
- const mockAuthMaterial: AuthMaterial = {
63
- jwtToken: "mock-jwt-token",
67
+ const mockAuthMaterial: AuthMaterialWithUser = {
68
+ jwt: "mock-jwt-token",
64
69
  refreshToken: {
65
70
  secret: "mock-secret",
66
71
  expiresAt: "2023-04-01T00:00:00Z",
67
72
  },
73
+ user: {
74
+ id: "123",
75
+ email: "test@test.com",
76
+ },
68
77
  };
69
78
 
70
79
  vi.mocked(authCookies.getCookie).mockReturnValue(mockRefreshToken);
@@ -89,12 +98,16 @@ describe("useRefreshToken", () => {
89
98
 
90
99
  it("should schedule next refresh before token expiration", async () => {
91
100
  const mockRefreshToken = "mock-refresh-token";
92
- const mockAuthMaterial: AuthMaterial = {
93
- jwtToken: "mock-jwt-token",
101
+ const mockAuthMaterial: AuthMaterialWithUser = {
102
+ jwt: "mock-jwt-token",
94
103
  refreshToken: {
95
104
  secret: "mock-secret",
96
105
  expiresAt: "2023-04-01T00:00:00Z",
97
106
  },
107
+ user: {
108
+ id: "123",
109
+ email: "test@test.com",
110
+ },
98
111
  };
99
112
 
100
113
  vi.mocked(authCookies.getCookie).mockReturnValue(mockRefreshToken);
@@ -1,18 +1,19 @@
1
1
  import { useCallback, useEffect, useRef } from "react";
2
2
 
3
- import type { AuthMaterial } from "@crossmint/common-sdk-auth";
3
+ import type { AuthMaterialWithUser } from "@crossmint/common-sdk-auth";
4
4
  import type { CrossmintAuthService } from "@crossmint/client-sdk-auth";
5
5
  import { getJWTExpiration } from "@crossmint/client-sdk-auth";
6
6
  import { queueTask, type CancellableTask } from "@crossmint/client-sdk-base";
7
+ import { REFRESH_TOKEN_PREFIX } from "@crossmint/common-sdk-auth";
7
8
 
8
- import { REFRESH_TOKEN_PREFIX, getCookie } from "../utils/authCookies";
9
+ import { getCookie } from "../utils/authCookies";
9
10
 
10
11
  // 2 minutes before jwt expiration
11
12
  const TIME_BEFORE_EXPIRING_JWT_IN_SECONDS = 120;
12
13
 
13
14
  type UseAuthTokenRefreshProps = {
14
15
  crossmintAuthService: CrossmintAuthService;
15
- setAuthMaterial: (authMaterial: AuthMaterial) => void;
16
+ setAuthMaterial: (authMaterial: AuthMaterialWithUser) => void;
16
17
  logout: () => void;
17
18
  };
18
19
 
@@ -34,7 +35,7 @@ export function useRefreshToken({ crossmintAuthService, setAuthMaterial, logout
34
35
  try {
35
36
  const result = await crossmintAuthService.refreshAuthMaterial(refreshToken);
36
37
  setAuthMaterial(result);
37
- const jwtExpiration = getJWTExpiration(result.jwtToken);
38
+ const jwtExpiration = getJWTExpiration(result.jwt);
38
39
 
39
40
  if (jwtExpiration == null) {
40
41
  throw new Error("Invalid JWT");
@@ -0,0 +1,19 @@
1
+ export function AlertIcon({ customColor = "#f44336" }: { customColor?: string }) {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="20"
6
+ height="20"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke={customColor}
10
+ strokeWidth="2"
11
+ strokeLinecap="round"
12
+ strokeLinejoin="round"
13
+ >
14
+ <circle cx="12" cy="12" r="10" />
15
+ <line x1="12" x2="12" y1="8" y2="12" />
16
+ <line x1="12" x2="12.01" y1="16" y2="16" />
17
+ </svg>
18
+ );
19
+ }
@@ -0,0 +1,18 @@
1
+ export function DiscordIcon({ className }: { className?: string }) {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ x="0px"
6
+ y="0px"
7
+ width="100"
8
+ height="100"
9
+ viewBox="0 0 48 48"
10
+ className={className}
11
+ >
12
+ <path
13
+ fill="#8c9eff"
14
+ d="M40,12c0,0-4.585-3.588-10-4l-0.488,0.976C34.408,10.174,36.654,11.891,39,14c-4.045-2.065-8.039-4-15-4s-10.955,1.935-15,4c2.346-2.109,5.018-4.015,9.488-5.024L18,8c-5.681,0.537-10,4-10,4s-5.121,7.425-6,22c5.162,5.953,13,6,13,6l1.639-2.185C13.857,36.848,10.715,35.121,8,32c3.238,2.45,8.125,5,16,5s12.762-2.55,16-5c-2.715,3.121-5.857,4.848-8.639,5.815L33,40c0,0,7.838-0.047,13-6C45.121,19.425,40,12,40,12z M17.5,30c-1.933,0-3.5-1.791-3.5-4c0-2.209,1.567-4,3.5-4s3.5,1.791,3.5,4C21,28.209,19.433,30,17.5,30z M30.5,30c-1.933,0-3.5-1.791-3.5-4c0-2.209,1.567-4,3.5-4s3.5,1.791,3.5,4C34,28.209,32.433,30,30.5,30z"
15
+ ></path>
16
+ </svg>
17
+ );
18
+ }
@@ -0,0 +1,147 @@
1
+ export function EmailOtpIcon({
2
+ customAccentColor = "#04AA6D",
3
+ customButtonBackgroundColor = "#F2F3F7",
4
+ customBackgroundColor = "#ffffff",
5
+ }: { customAccentColor?: string; customButtonBackgroundColor?: string; customBackgroundColor?: string }) {
6
+ return (
7
+ <svg width="136" height="113" viewBox="0 0 136 113" fill="none" xmlns="http://www.w3.org/2000/svg">
8
+ <mask id="mask0_944_1329" maskUnits="userSpaceOnUse" x="8" y="8" width="97" height="97">
9
+ <path
10
+ d="M104.598 56.2539C104.598 82.7636 83.1073 104.254 56.5977 104.254C30.088 104.254 8.59766 82.7636 8.59766 56.2539C8.59766 29.7442 30.088 8.25391 56.5977 8.25391C83.1073 8.25391 104.598 29.7442 104.598 56.2539Z"
11
+ fill="#D9D9D9"
12
+ />
13
+ </mask>
14
+ <g mask="url(#mask0_944_1329)">
15
+ <circle cx="56.5977" cy="56.2539" r="48" fill={customButtonBackgroundColor} />
16
+ <g filter="url(#filter0_d_944_1329)">
17
+ <mask id="mask1_944_1329" maskUnits="userSpaceOnUse" x="29" y="37" width="55" height="37">
18
+ <rect x="29.2957" y="37.5449" width="54.604" height="35.8658" rx="3.212" fill="#52E0B5" />
19
+ </mask>
20
+ <g mask="url(#mask1_944_1329)">
21
+ <rect
22
+ x="29.2957"
23
+ y="34.8662"
24
+ width="54.604"
25
+ height="38.544"
26
+ rx="3.212"
27
+ fill={customBackgroundColor}
28
+ />
29
+ <mask id="mask2_944_1329" maskUnits="userSpaceOnUse" x="29" y="51" width="55" height="41">
30
+ <path
31
+ d="M31.8833 74.2272C29.1168 72.267 29.1866 68.1383 32.0178 66.2728L53.9469 51.8234C55.5553 50.7636 57.6403 50.7636 59.2487 51.8234L81.1779 66.2728C84.0091 68.1383 84.0789 72.267 81.3124 74.2272L56.5978 91.7381L31.8833 74.2272Z"
32
+ fill="#52E0B5"
33
+ />
34
+ </mask>
35
+ <g mask="url(#mask2_944_1329)">
36
+ <path
37
+ d="M32.0675 73.9008C29.5307 72.1034 29.5947 68.3175 32.1909 66.6068L54.12 52.1574C55.5949 51.1856 57.5068 51.1856 58.9817 52.1574L80.9108 66.6068C83.507 68.3175 83.571 72.1034 81.0341 73.9008L56.5508 91.2479L32.0675 73.9008Z"
38
+ stroke="#D0D5DD"
39
+ strokeWidth="0.8"
40
+ />
41
+ </g>
42
+ <path
43
+ d="M26.9443 36.6072C23.1618 33.6476 22.8212 28.0457 26.2172 24.6497L50.9406 -0.073638C54.0648 -3.19783 59.1301 -3.19783 62.2543 -0.0736384L86.9776 24.6497C90.3737 28.0457 90.033 33.6476 86.2506 36.6072L61.5272 55.9514C58.6312 58.2173 54.5636 58.2173 51.6677 55.9514L26.9443 36.6072Z"
44
+ fill={customBackgroundColor}
45
+ />
46
+ <path
47
+ d="M27.1908 36.2921C23.5974 33.4806 23.2738 28.1588 26.5001 24.9326L51.2234 0.209205C54.1914 -2.75878 59.0035 -2.75878 61.9714 0.209205L86.6948 24.9326C89.921 28.1588 89.5974 33.4806 86.0041 36.2921L61.2807 55.6364C58.5296 57.789 54.6653 57.789 51.9142 55.6364L27.1908 36.2921Z"
48
+ stroke="#67797F"
49
+ strokeOpacity="0.45"
50
+ strokeWidth="0.8"
51
+ />
52
+ </g>
53
+ </g>
54
+ </g>
55
+ <g filter="url(#filter1_d_944_1329)">
56
+ <path
57
+ d="M106.88 68.5039H82.8799C74.5956 68.5039 67.8799 75.2196 67.8799 83.5039C67.8799 91.7882 74.5956 98.5039 82.8799 98.5039H106.88C115.164 98.5039 121.88 91.7882 121.88 83.5039C121.88 75.2196 115.164 68.5039 106.88 68.5039Z"
58
+ fill={customBackgroundColor}
59
+ />
60
+ </g>
61
+ <g clipPath="url(#clip0_944_1329)">
62
+ <mask id="mask3_944_1329" maskUnits="userSpaceOnUse" x="70" y="71" width="49" height="25">
63
+ <path d="M118.88 71.5039H70.8799V95.5039H118.88V71.5039Z" fill="white" />
64
+ </mask>
65
+ <g mask="url(#mask3_944_1329)">
66
+ <path d="M118.88 71.5039H70.8799V95.5039H118.88V71.5039Z" fill="url(#paint0_linear_944_1329)" />
67
+ <path d="M118.88 71.5039H70.8799V95.5039H118.88V71.5039Z" fill={customAccentColor} />
68
+ </g>
69
+ <path
70
+ d="M80.5866 87.7014L80.7337 85.1127L78.5604 86.5381L77.7805 85.183L80.1009 84.0196L77.7805 82.8563L78.5604 81.5012L80.7337 82.9266L80.5866 80.3378H82.1399L81.9993 82.9266L84.1726 81.5012L84.9524 82.8563L82.6257 84.0196L84.9524 85.183L84.1726 86.5381L81.9993 85.1127L82.1399 87.7014H80.5866ZM90.0001 87.7014L90.1471 85.1127L87.9738 86.5381L87.194 85.183L89.5143 84.0196L87.194 82.8563L87.9738 81.5012L90.1471 82.9266L90.0001 80.3378H91.5534L91.4127 82.9266L93.586 81.5012L94.3659 82.8563L92.0391 84.0196L94.3659 85.183L93.586 86.5381L91.4127 85.1127L91.5534 87.7014H90.0001ZM99.4135 87.7014L99.5605 85.1127L97.3872 86.5381L96.6074 85.183L98.9277 84.0196L96.6074 82.8563L97.3872 81.5012L99.5605 82.9266L99.4135 80.3378H100.967L100.826 82.9266L102.999 81.5012L103.779 82.8563L101.453 84.0196L103.779 85.183L102.999 86.5381L100.826 85.1127L100.967 87.7014H99.4135ZM108.827 87.7014L108.974 85.1127L106.801 86.5381L106.021 85.183L108.341 84.0196L106.021 82.8563L106.801 81.5012L108.974 82.9266L108.827 80.3378H110.38L110.24 82.9266L112.413 81.5012L113.193 82.8563L110.866 84.0196L113.193 85.183L112.413 86.5381L110.24 85.1127L110.38 87.7014H108.827Z"
71
+ fill={customBackgroundColor}
72
+ />
73
+ </g>
74
+ <defs>
75
+ <filter
76
+ id="filter0_d_944_1329"
77
+ x="11.6957"
78
+ y="28.7449"
79
+ width="89.804"
80
+ height="71.0657"
81
+ filterUnits="userSpaceOnUse"
82
+ colorInterpolationFilters="sRGB"
83
+ >
84
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
85
+ <feColorMatrix
86
+ in="SourceAlpha"
87
+ type="matrix"
88
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
89
+ result="hardAlpha"
90
+ />
91
+ <feOffset dy="8.8" />
92
+ <feGaussianBlur stdDeviation="8.8" />
93
+ <feComposite in2="hardAlpha" operator="out" />
94
+ <feColorMatrix
95
+ type="matrix"
96
+ values="0 0 0 0 0.0370486 0 0 0 0 0.087038 0 0 0 0 0.0916667 0 0 0 0.16 0"
97
+ />
98
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_944_1329" />
99
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_944_1329" result="shape" />
100
+ </filter>
101
+ <filter
102
+ id="filter1_d_944_1329"
103
+ x="53.8799"
104
+ y="54.5039"
105
+ width="82"
106
+ height="58"
107
+ filterUnits="userSpaceOnUse"
108
+ colorInterpolationFilters="sRGB"
109
+ >
110
+ <feFlood floodOpacity="0" result="BackgroundImageFix" />
111
+ <feColorMatrix
112
+ in="SourceAlpha"
113
+ type="matrix"
114
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
115
+ result="hardAlpha"
116
+ />
117
+ <feOffset />
118
+ <feGaussianBlur stdDeviation="7" />
119
+ <feComposite in2="hardAlpha" operator="out" />
120
+ <feColorMatrix
121
+ type="matrix"
122
+ values="0 0 0 0 0.0362847 0 0 0 0 0.0869733 0 0 0 0 0.0916667 0 0 0 0.12 0"
123
+ />
124
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_944_1329" />
125
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_944_1329" result="shape" />
126
+ </filter>
127
+ <linearGradient
128
+ id="paint0_linear_944_1329"
129
+ x1="103.915"
130
+ y1="95.5039"
131
+ x2="97.9027"
132
+ y2="68.179"
133
+ gradientUnits="userSpaceOnUse"
134
+ >
135
+ <stop stopColor="#2E996C" />
136
+ <stop offset="1" stopColor="#D0F2E5" />
137
+ </linearGradient>
138
+ <clipPath id="clip0_944_1329">
139
+ <path
140
+ d="M70.8799 83.5039C70.8799 76.8765 76.2525 71.5039 82.8799 71.5039H106.88C113.507 71.5039 118.88 76.8765 118.88 83.5039C118.88 90.1313 113.507 95.5039 106.88 95.5039H82.8799C76.2525 95.5039 70.8799 90.1313 70.8799 83.5039Z"
141
+ fill={customBackgroundColor}
142
+ />
143
+ </clipPath>
144
+ </defs>
145
+ </svg>
146
+ );
147
+ }
@@ -0,0 +1,26 @@
1
+ export const FarcasterIcon = ({ className }: { className?: string }) => {
2
+ return (
3
+ <svg
4
+ width="24"
5
+ height="24"
6
+ viewBox="0 0 1000 1000"
7
+ fill="none"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ className={className}
10
+ >
11
+ <rect width="1000" height="1000" fill="#855DCD" />
12
+ <path
13
+ d="M257.778 155.556H742.222V844.444H671.111V528.889H670.414C662.554 441.677 589.258 373.333 500 373.333C410.742 373.333 337.446 441.677 329.586 528.889H328.889V844.444H257.778V155.556Z"
14
+ fill="white"
15
+ />
16
+ <path
17
+ d="M128.889 253.333L157.778 351.111H182.222V746.667C169.949 746.667 160 756.616 160 768.889V795.556H155.556C143.283 795.556 133.333 805.505 133.333 817.778V844.444H382.222V817.778C382.222 805.505 372.273 795.556 360 795.556H355.556V768.889C355.556 756.616 345.606 746.667 333.333 746.667H306.667V253.333H128.889Z"
18
+ fill="white"
19
+ />
20
+ <path
21
+ d="M675.555 746.667C663.282 746.667 653.333 756.616 653.333 768.889V795.556H648.889C636.616 795.556 626.667 805.505 626.667 817.778V844.444H875.555V817.778C875.555 805.505 865.606 795.556 853.333 795.556H848.889V768.889C848.889 756.616 838.94 746.667 826.667 746.667V351.111H851.111L880 253.333H702.222V746.667H675.555Z"
22
+ fill="white"
23
+ />
24
+ </svg>
25
+ );
26
+ };
@@ -0,0 +1,30 @@
1
+ export function GoogleIcon({ className }: { className?: string }) {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ x="0px"
6
+ y="0px"
7
+ width="100"
8
+ height="100"
9
+ viewBox="0 0 48 48"
10
+ className={className}
11
+ >
12
+ <path
13
+ fill="#fbc02d"
14
+ d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12 s5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20 s20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"
15
+ ></path>
16
+ <path
17
+ fill="#e53935"
18
+ d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039 l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"
19
+ ></path>
20
+ <path
21
+ fill="#4caf50"
22
+ d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36 c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"
23
+ ></path>
24
+ <path
25
+ fill="#1565c0"
26
+ d="M43.611,20.083L43.595,20L42,20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571 c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"
27
+ ></path>
28
+ </svg>
29
+ );
30
+ }
@@ -0,0 +1,20 @@
1
+ export function LeftArrowIcon({ className, style }: { className?: string; style?: React.CSSProperties }) {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="24"
6
+ height="24"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ stroke="currentColor"
10
+ strokeWidth="2"
11
+ strokeLinecap="round"
12
+ strokeLinejoin="round"
13
+ className={className}
14
+ style={style}
15
+ >
16
+ <path d="m12 19-7-7 7-7" />
17
+ <path d="M19 12H5" />
18
+ </svg>
19
+ );
20
+ }
@@ -7,8 +7,8 @@ export const PoweredByLeaf = ({ color, size = "16" }: { color: string; size?: st
7
7
  maskUnits="userSpaceOnUse"
8
8
  x="0"
9
9
  y="0"
10
- width={size}
11
- height={size}
10
+ width="16"
11
+ height="16"
12
12
  >
13
13
  <mask id="path-1-inside-1_794_7000" fill="white">
14
14
  <path
@@ -1,4 +1,5 @@
1
- import { deleteCookie, REFRESH_TOKEN_PREFIX, SESSION_PREFIX } from "@/utils/authCookies";
1
+ import { deleteCookie } from "@/utils/authCookies";
2
+ import { SESSION_PREFIX, REFRESH_TOKEN_PREFIX } from "@crossmint/common-sdk-auth";
2
3
  import { fireEvent, render } from "@testing-library/react";
3
4
  import { type ReactNode, act } from "react";
4
5
  import { beforeEach, describe, expect, vi } from "vitest";
@@ -39,7 +40,7 @@ vi.mock("@crossmint/client-sdk-auth", async () => {
39
40
  getJWTExpiration: vi.fn(),
40
41
  CrossmintAuthService: vi.fn().mockImplementation(() => ({
41
42
  refreshAuthMaterial: vi.fn().mockResolvedValue({
42
- jwtToken: "new-mock-jwt",
43
+ jwt: "new-mock-jwt",
43
44
  refreshToken: {
44
45
  secret: "new-mock-refresh-token",
45
46
  expiresAt: new Date(Date.now() + 1000 * 60 * 60).toISOString(),
@@ -123,7 +124,7 @@ describe("CrossmintAuthProvider", () => {
123
124
 
124
125
  mockCrossmintAuthService = {
125
126
  refreshAuthMaterial: vi.fn().mockResolvedValue({
126
- jwtToken: "new-mock-jwt",
127
+ jwt: "new-mock-jwt",
127
128
  refreshToken: {
128
129
  secret: "new-mock-refresh-token",
129
130
  expiresAt: new Date(Date.now() + 1000 * 60 * 60).toISOString(),