Skip to content

Commit 560d8ad

Browse files
ElasticBottlejnsdlsMananTank
authored
feat: Add sign-in with Phone number in in-app wallet (#2679)
Signed-off-by: Winston Yeo <44563205+ElasticBottle@users.noreply.github.com> Signed-off-by: Jonas Daniels <jonas.daniels@outlook.com> Co-authored-by: Jonas Daniels <jonas.daniels@outlook.com> Co-authored-by: Manan Tank <manantankm@gmail.com>
1 parent 3be61dd commit 560d8ad

File tree

29 files changed

+1817
-136
lines changed

29 files changed

+1817
-136
lines changed

.changeset/flat-hotels-scream.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
"thirdweb": minor
3+
---
4+
5+
Add support for connecting in-app wallet using phone number
6+
7+
## Usage in TypeScript
8+
9+
```ts
10+
import { createThirdwebClient, createWallet } from "thirdweb";
11+
import { preAuthenticate } from "thirdweb/wallets/in-app";
12+
13+
const client = createThirdwebClient({ clientId: "..." });
14+
15+
const phoneNumber = '+123456789';
16+
17+
// Send OTP to given phone number
18+
async function sendOTP() {
19+
await preAuthenticate({
20+
strategy: "phone",
21+
phoneNumber,
22+
client,
23+
});
24+
}
25+
26+
async function connect() {
27+
// create a in-app wallet instance
28+
const wallet = createWallet('inApp');
29+
// if the OTP is correct, the wallet will be connected else an error will be thrown
30+
const account = await wallet.connect({
31+
client,
32+
strategy: "phone";
33+
phoneNumber,
34+
verificationCode: '...' // Pass the OTP entered by the user
35+
});
36+
37+
console.log('connected to', account);
38+
}
39+
```
40+
41+
## Usage in React
42+
43+
```tsx
44+
import { createThirdwebClient } from "thirdweb";
45+
import { preAuthenticate } from "thirdweb/wallets/in-app";
46+
import { useConnect } from "thirdweb/react";
47+
48+
const client = createThirdwebClient({ clientId: "..." });
49+
50+
function Component() {
51+
const { connect } = useConnect();
52+
const [phoneNumber, setPhoneNumber] = useState(''); // get phone number from user
53+
const [otp, setOtp] = useState(''); // get OTP from user
54+
55+
// Send OTP to given phone number
56+
async function sendOTP() {
57+
await preAuthenticate({
58+
strategy: "phone",
59+
phoneNumber,
60+
client,
61+
});
62+
}
63+
64+
async function connect() {
65+
// create a in-app wallet instance
66+
const wallet = createWallet('inApp');
67+
// if the OTP is correct, the wallet will be connected else an error will be thrown
68+
await wallet.connect({
69+
client,
70+
strategy: "phone";
71+
phoneNumber,
72+
verificationCode: otp
73+
});
74+
75+
// set the wallet as active
76+
connect(wallet)
77+
}
78+
79+
// render UI to get OTP and phone number from user
80+
return <div> ... </div>
81+
}
82+
```

.changeset/lovely-parents-hear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@thirdweb-dev/react": patch
3+
---
4+
5+
Fix In-App wallet country selector styles on windows

legacy_packages/react/src/design-system/elements.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export const StyledH2 = /* @__PURE__ */ styled.h2;
1212
export const StyledP = /* @__PURE__ */ styled.p;
1313
export const StyledUl = /* @__PURE__ */ styled.ul;
1414
export const StyledSelect = /* @__PURE__ */ styled.select;
15+
export const StyledOption = /* @__PURE__ */ styled.option;

legacy_packages/react/src/wallet/wallets/embeddedWallet/CountrySelector.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query";
22
import React, { useRef } from "react";
33
import { fontSize, spacing } from "../../../design-system";
44
import { useCustomTheme } from "../../../design-system/CustomThemeProvider";
5-
import { StyledSelect } from "../../../design-system/elements";
5+
import { StyledOption, StyledSelect } from "../../../design-system/elements";
66

77
export function CountrySelector({
88
countryCode,
@@ -52,20 +52,33 @@ export function CountrySelector({
5252
</option>
5353
{supportedCountriesForSms.map((country) => {
5454
return (
55-
<option
55+
<Option
5656
key={country.countryIsoCode}
5757
value={`${country.countryIsoCode} +${country.phoneNumberCode}`}
5858
>
5959
{country.countryName} +{country.phoneNumberCode}{" "}
60-
</option>
60+
</Option>
6161
);
6262
})}
6363
</Select>
6464
</>
6565
);
6666
}
6767

68-
export const Select = /* @__PURE__ */ StyledSelect(() => {
68+
69+
const Option = /* @__PURE__ */ StyledOption(() => {
70+
const theme = useCustomTheme();
71+
return {
72+
color: theme.colors.primaryText,
73+
background: theme.colors.modalBg,
74+
transition: "background 0.3s ease",
75+
"&:hover": {
76+
background: theme.colors.walletSelectorButtonHoverBg,
77+
},
78+
};
79+
});
80+
81+
const Select = /* @__PURE__ */ StyledSelect(() => {
6982
const theme = useCustomTheme();
7083
return {
7184
fontSize: fontSize.sm,

packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import styled from "@emotion/styled";
22
import {
33
ChevronRightIcon,
44
ExitIcon,
5-
// EnterIcon,
65
PaperPlaneIcon,
76
PinBottomIcon,
87
PlusIcon,
@@ -16,7 +15,6 @@ import { getContract } from "../../../../contract/contract.js";
1615
import { resolveAvatar } from "../../../../extensions/ens/resolve-avatar.js";
1716
import { resolveName } from "../../../../extensions/ens/resolve-name.js";
1817
import { isContractDeployed } from "../../../../utils/bytecode/is-contract-deployed.js";
19-
import { getUserEmail } from "../../../../wallets/in-app/core/authentication/index.js";
2018
import {
2119
useChainQuery,
2220
useChainsQuery,
@@ -27,7 +25,6 @@ import {
2725
useActiveAccount,
2826
useActiveWallet,
2927
useActiveWalletChain,
30-
// useConnect,
3128
useDisconnect,
3229
useSwitchActiveWalletChain,
3330
} from "../../../core/hooks/wallets/wallet-hooks.js";
@@ -383,7 +380,10 @@ export const ConnectedWalletDetails: React.FC<{
383380

384381
<Container px="lg">
385382
<ConnectedToSmartWallet />
386-
<InAppWalletEmail />
383+
384+
{(activeWallet?.id === "embedded" || activeWallet?.id === "inApp") && (
385+
<InAppWalletUserInfo />
386+
)}
387387

388388
{/* Send, Receive, Swap */}
389389
<Container
@@ -876,20 +876,31 @@ function ConnectedToSmartWallet() {
876876
return null;
877877
}
878878

879-
function InAppWalletEmail() {
879+
function InAppWalletUserInfo() {
880880
const { client } = useConnectUI();
881-
const emailQuery = useQuery({
882-
queryKey: ["in-app-wallet-user", client],
883-
queryFn: async () => {
884-
const data = await getUserEmail({
885-
client: client,
886-
});
881+
const account = useActiveAccount();
887882

888-
return data || null;
883+
const userInfoQuery = useQuery({
884+
queryKey: ["in-app-wallet-user", client, account?.address],
885+
queryFn: async () => {
886+
const { getUserEmail, getUserPhoneNumber } = await import(
887+
"../../../../wallets/in-app/core/authentication/index.js"
888+
);
889+
890+
const [email, phone] = await Promise.all([
891+
getUserEmail({
892+
client: client,
893+
}),
894+
getUserPhoneNumber({
895+
client: client,
896+
}),
897+
]);
898+
899+
return email || phone || null;
889900
},
890901
});
891902

892-
if (emailQuery.data) {
903+
if (userInfoQuery.data) {
893904
return (
894905
<Container
895906
flex="row"
@@ -898,7 +909,7 @@ function InAppWalletEmail() {
898909
paddingBottom: spacing.md,
899910
}}
900911
>
901-
<Text size="sm">{emailQuery.data}</Text>
912+
<Text size="sm">{userInfoQuery.data}</Text>
902913
</Container>
903914
);
904915
}

packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/ConnectModal.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useActiveAccount } from "../../../../core/hooks/wallets/wallet-hooks.js
44
import {
55
useIsWalletModalOpen,
66
useSetIsWalletModalOpen,
7+
useSetSelectionData,
78
} from "../../../providers/wallet-ui-states-provider.js";
89
import { Modal } from "../../components/Modal.js";
910
import { onModalUnmount, reservedScreens } from "../constants.js";
@@ -15,6 +16,7 @@ import { useSetupScreen } from "./screen.js";
1516
*/
1617
const ConnectModal = () => {
1718
const screenSetup = useSetupScreen();
19+
const setSelectionData = useSetSelectionData();
1820
const { screen, setScreen, initialScreen } = screenSetup;
1921
const isWalletModalOpen = useIsWalletModalOpen();
2022
const setIsWalletModalOpen = useSetIsWalletModalOpen();
@@ -25,8 +27,9 @@ const ConnectModal = () => {
2527
setIsWalletModalOpen(false);
2628
onModalUnmount(() => {
2729
setScreen(initialScreen);
30+
setSelectionData({});
2831
});
29-
}, [initialScreen, setIsWalletModalOpen, setScreen]);
32+
}, [initialScreen, setIsWalletModalOpen, setScreen, setSelectionData]);
3033

3134
const activeAccount = useActiveAccount();
3235

@@ -72,16 +75,8 @@ const ConnectModal = () => {
7275
return;
7376
}
7477

75-
setIsWalletModalOpen(value);
76-
7778
if (!value) {
78-
onModalUnmount(() => {
79-
// if (connectionStatus === "connecting") {
80-
// disconnect();
81-
// }
82-
83-
setScreen(initialScreen);
84-
});
79+
closeModal();
8580
}
8681
}}
8782
>

packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/ConnectModalContent.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Wallet } from "../../../../../wallets/interfaces/wallet.js";
33
import { useSiweAuth } from "../../../../core/hooks/auth/useSiweAuth.js";
44
import { useConnectUI } from "../../../../core/hooks/others/useWalletConnectionCtx.js";
55
import { useConnect } from "../../../../core/hooks/wallets/wallet-hooks.js";
6+
import { useSetSelectionData } from "../../../providers/wallet-ui-states-provider.js";
67
import { LoadingScreen } from "../../../wallets/shared/LoadingScreen.js";
78
import { WalletSelector } from "../WalletSelector.js";
89
import { onModalUnmount, reservedScreens } from "../constants.js";
@@ -39,6 +40,7 @@ export const ConnectModalContent = (props: {
3940
client,
4041
} = useConnectUI();
4142
const { connect } = useConnect();
43+
const setSelectionData = useSetSelectionData();
4244

4345
const siweAuth = useSiweAuth(auth);
4446
const showSignatureScreen = siweAuth.requiresAuth && !siweAuth.isLoggedIn;
@@ -52,6 +54,7 @@ export const ConnectModalContent = (props: {
5254
}
5355

5456
onModalUnmount(() => {
57+
setSelectionData({});
5558
setModalVisibility(true);
5659
});
5760

@@ -69,6 +72,7 @@ export const ConnectModalContent = (props: {
6972
connect,
7073
showSignatureScreen,
7174
setScreen,
75+
setSelectionData,
7276
],
7377
);
7478

packages/thirdweb/src/react/web/ui/design-system/elements.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export const StyledInput = /* @__PURE__ */ styled.input;
1111
export const StyledH2 = /* @__PURE__ */ styled.h2;
1212
export const StyledP = /* @__PURE__ */ styled.p;
1313
export const StyledUl = /* @__PURE__ */ styled.ul;
14+
export const StyledSelect = /* @__PURE__ */ styled.select;
15+
export const StyledOption = /* @__PURE__ */ styled.option;

0 commit comments

Comments
 (0)