Skip to content

Commit f9f5250

Browse files
committed
feat(auth): fetch ecosystem auth options from server (#3528)
<!-- start pr-codex --> ## PR-Codex overview The focus of this PR is to refactor ecosystem wallet related functions, update UI components, and integrate new auth options fetching mechanism. ### Detailed summary - Refactored ecosystem wallet related functions for better clarity and consistency. - Updated UI components in various files for improved user experience. - Integrated a new mechanism to fetch auth options for ecosystem wallets. - Added a loading screen component for better user feedback during data fetching. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 2ccb59e commit f9f5250

File tree

6 files changed

+104
-41
lines changed

6 files changed

+104
-41
lines changed

packages/thirdweb/src/react/web/wallets/ecosystem/EcosystemWalletHeader.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export function EcosystemWalletHeader(props: {
4444
)}
4545
</>
4646
}
47+
leftAligned
4748
/>
4849
);
4950
}

packages/thirdweb/src/react/web/wallets/in-app/InAppWalletFormUI.tsx

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,33 +55,34 @@ export function InAppWalletFormUIScreen(props: InAppWalletFormUIProps) {
5555
minHeight: "250px",
5656
}}
5757
>
58-
{isCompact && isInitialScreen ? (
59-
<>
60-
<ModalHeader
61-
onBack={onBack}
62-
leftAligned={true}
63-
title={
64-
<>
65-
{!props.meta.titleIconUrl ? null : (
66-
<Img
67-
src={props.meta.titleIconUrl}
68-
width={iconSize.md}
69-
height={iconSize.md}
70-
client={props.client}
71-
/>
72-
)}
73-
<ModalTitle>
74-
{props.meta.title ??
75-
props.inAppWalletLocale.emailLoginScreen.title}
76-
</ModalTitle>
77-
</>
78-
}
79-
/>
80-
<Spacer y="lg" />
81-
</>
82-
) : (
83-
<ModalHeader onBack={onBack} title={props.inAppWalletLocale.signIn} />
84-
)}
58+
{isCompact &&
59+
(isInitialScreen ? (
60+
<>
61+
<ModalHeader
62+
onBack={onBack}
63+
leftAligned={true}
64+
title={
65+
<>
66+
{!props.meta.titleIconUrl ? null : (
67+
<Img
68+
src={props.meta.titleIconUrl}
69+
width={iconSize.md}
70+
height={iconSize.md}
71+
client={props.client}
72+
/>
73+
)}
74+
<ModalTitle>
75+
{props.meta.title ??
76+
props.inAppWalletLocale.emailLoginScreen.title}
77+
</ModalTitle>
78+
</>
79+
}
80+
/>
81+
<Spacer y="lg" />
82+
</>
83+
) : (
84+
<ModalHeader onBack={onBack} title={props.inAppWalletLocale.signIn} />
85+
))}
8586

8687
<Container
8788
expand

packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"use client";
22
import styled from "@emotion/styled";
3-
import { useState } from "react";
3+
import { useQuery } from "@tanstack/react-query";
4+
import { useMemo, useState } from "react";
45
import type { Chain } from "../../../../chains/types.js";
56
import type { ThirdwebClient } from "../../../../client/client.js";
67
import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
8+
import { getEcosystemWalletAuthOptions } from "../../../../wallets/ecosystem/get-ecosystem-wallet-auth-options.js";
79
import { isEcosystemWallet } from "../../../../wallets/ecosystem/is-ecosystem-wallet.js";
810
import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js";
911
import type {
@@ -31,6 +33,7 @@ import { Button } from "../../ui/components/buttons.js";
3133
import { InputSelectionUI } from "../in-app/InputSelectionUI.js";
3234
import { socialIcons } from "../in-app/socialIcons.js";
3335
import { validateEmail } from "../in-app/validateEmail.js";
36+
import { LoadingScreen } from "./LoadingScreen.js";
3437
import type { InAppWalletLocale } from "./locale/types.js";
3538
import { openOauthSignInWindow } from "./openOauthSignInWindow.js";
3639
import { setLastAuthProvider } from "./storage.js";
@@ -87,15 +90,34 @@ export const ConnectWalletSocialOptions = (
8790
apple: locale.signInWithApple,
8891
};
8992

90-
const authOptions = defaultAuthOptions; // TODO: Fetch these from the backend
91-
const passKeyEnabled = authOptions.includes("passkey");
93+
const { data: ecosystemAuthOptions, isLoading } = useQuery({
94+
queryKey: ["auth-options", wallet.id],
95+
queryFn: async () => {
96+
if (isEcosystemWallet(wallet)) {
97+
return getEcosystemWalletAuthOptions(wallet.id);
98+
}
99+
return null;
100+
},
101+
enabled: isEcosystemWallet(wallet),
102+
retry: false,
103+
});
104+
const authOptions = isEcosystemWallet(wallet)
105+
? ecosystemAuthOptions ?? defaultAuthOptions
106+
: wallet.getConfig()?.auth?.options ?? defaultAuthOptions;
92107

93108
const emailIndex = authOptions.indexOf("email");
94109
const isEmailEnabled = emailIndex !== -1;
95110
const phoneIndex = authOptions.indexOf("phone");
96111
const isPhoneEnabled = phoneIndex !== -1;
97112

98-
const [inputMode, setInputMode] = useState<"email" | "phone" | "none">(() => {
113+
const [manualInputMode, setManualInputMode] = useState<
114+
"email" | "phone" | "none" | null
115+
>(null);
116+
117+
const inputMode = useMemo(() => {
118+
if (manualInputMode) {
119+
return manualInputMode;
120+
}
99121
if (isEmailEnabled && isPhoneEnabled) {
100122
return emailIndex < phoneIndex ? "email" : "phone";
101123
}
@@ -106,7 +128,13 @@ export const ConnectWalletSocialOptions = (
106128
return "phone";
107129
}
108130
return "none";
109-
});
131+
}, [isEmailEnabled, isPhoneEnabled, emailIndex, phoneIndex, manualInputMode]);
132+
133+
if (isEcosystemWallet(wallet) && isLoading) {
134+
return <LoadingScreen />;
135+
}
136+
137+
const passKeyEnabled = authOptions.includes("passkey");
110138

111139
const placeholder =
112140
inputMode === "email" ? locale.emailPlaceholder : locale.phonePlaceholder;
@@ -255,7 +283,7 @@ export const ConnectWalletSocialOptions = (
255283
client={props.client}
256284
icon={emailIcon}
257285
onClick={() => {
258-
setInputMode("email");
286+
setManualInputMode("email");
259287
}}
260288
// TODO locale
261289
title={"Email address"}
@@ -295,7 +323,7 @@ export const ConnectWalletSocialOptions = (
295323
client={props.client}
296324
icon={phoneIcon}
297325
onClick={() => {
298-
setInputMode("phone");
326+
setManualInputMode("phone");
299327
}}
300328
// TODO locale
301329
title={"Phone number"}

packages/thirdweb/src/wallets/ecosystem/get-ecosystem-partner-permissions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ export const getEcosystemPartnerPermissions = async (
66
ecosystemId: EcosystemWalletId,
77
partnerId?: string,
88
): Promise<EcosystemPermssions> => {
9-
const headers = new Headers();
10-
headers.set("x-ecosystem-id", ecosystemId);
11-
headers.set("x-ecosystem-partner-id", partnerId || "");
129
const res = await fetch(
1310
`${getThirdwebBaseUrl(
1411
"inAppWallet",
1512
)}/api/2024-05-05/ecosystem-wallet/${ecosystemId}/partner/${partnerId}`,
1613
{
17-
headers,
14+
headers: {
15+
"x-ecosystem-id": ecosystemId,
16+
"x-ecosystem-partner-id": partnerId || "",
17+
},
1818
},
1919
);
2020

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { getThirdwebBaseUrl } from "../../utils/domains.js";
2+
import type { AuthOption } from "../types.js";
3+
import type { EcosystemWalletId } from "../wallet-types.js";
4+
5+
/**
6+
* Retrieves the specified auth options for a given ecosystem wallet, if any.
7+
* @param walletId The ecosystem wallet ID.
8+
* @returns {AuthOption[] | undefined} The auth options for the ecosystem wallet.
9+
* @internal
10+
*/
11+
export async function getEcosystemWalletAuthOptions(
12+
walletId: EcosystemWalletId,
13+
): Promise<AuthOption[] | undefined> {
14+
const res = await fetch(
15+
`${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/ecosystem-wallet`,
16+
{
17+
headers: {
18+
"x-ecosystem-id": walletId,
19+
},
20+
},
21+
);
22+
23+
const data = await res.json();
24+
25+
if (!data || data.code === "UNAUTHORIZED") {
26+
throw new Error(
27+
data.message ||
28+
`Could not find ecosystem wallet with id ${walletId}, please check your ecosystem wallet configuration.`,
29+
);
30+
}
31+
32+
return data.authOptions ?? undefined;
33+
}

packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-info.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import type { EcosystemWalletId } from "../wallet-types.js";
1414
export async function getEcosystemWalletInfo(
1515
walletId: EcosystemWalletId,
1616
): Promise<Prettify<WalletInfo>> {
17-
const headers = new Headers();
18-
headers.set("x-ecosystem-id", walletId);
1917
const res = await fetch(
2018
`${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/ecosystem-wallet`,
2119
{
22-
headers,
20+
headers: {
21+
"x-ecosystem-id": walletId,
22+
},
2323
},
2424
);
2525

0 commit comments

Comments
 (0)