Skip to content

Commit 5a13ad4

Browse files
gregfromstlclaude
andauthored
[SDK] Fix: Automatically trigger login for connected wallets whe… (#7009)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 557a29a commit 5a13ad4

File tree

10 files changed

+97
-38
lines changed

10 files changed

+97
-38
lines changed

.changeset/every-sides-invent.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Automatically trigger SIWE sign in when a wallet is connected

apps/playground-web/src/components/auth/auth-button.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,25 @@ import {
88
} from "@/app/connect/auth/server/actions/auth";
99
import { THIRDWEB_CLIENT } from "@/lib/client";
1010
import { ConnectButton } from "thirdweb/react";
11+
import { createWallet, inAppWallet } from "thirdweb/wallets";
1112

1213
export function AuthButton() {
1314
return (
1415
<ConnectButton
1516
client={THIRDWEB_CLIENT}
17+
wallets={[
18+
inAppWallet({
19+
auth: {
20+
options: ["google", "telegram", "github"],
21+
mode: "redirect",
22+
},
23+
}),
24+
createWallet("io.metamask"),
25+
createWallet("com.coinbase.wallet"),
26+
createWallet("me.rainbow"),
27+
createWallet("io.rabby"),
28+
createWallet("io.zerion.wallet"),
29+
]}
1630
auth={{
1731
isLoggedIn: (address) => isLoggedIn(address),
1832
doLogin: (params) => login(params),

packages/thirdweb/src/react/native/ui/connect/ConnectButton.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ export function ConnectButton(props: ConnectButtonProps) {
4747
const status = useActiveWalletConnectionStatus();
4848
const connectionManager = useConnectionManager();
4949
const siweAuth = useSiweAuth(wallet, account, props.auth);
50-
useAutoConnect(props);
50+
useAutoConnect({
51+
...props,
52+
siweAuth: siweAuth,
53+
});
5154

5255
const fadeAnim = useRef(new Animated.Value(0)); // For background opacity
5356
const slideAnim = useRef(new Animated.Value(screenHeight)); // For bottom sheet position

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ export function ConnectButton(props: ConnectButtonProps) {
297297
);
298298
const localeQuery = useConnectLocale(props.locale || "en_US");
299299
const connectionManager = useConnectionManager();
300+
const activeAccount = useActiveAccount();
301+
const activeWallet = useActiveWallet();
302+
const siweAuth = useSiweAuth(activeWallet, activeAccount, props.auth);
300303

301304
usePreloadWalletProviders({
302305
wallets,
@@ -337,6 +340,7 @@ export function ConnectButton(props: ConnectButtonProps) {
337340
}
338341
accountAbstraction={props.accountAbstraction}
339342
onConnect={props.onConnect}
343+
siweAuth={siweAuth}
340344
/>
341345
);
342346

@@ -362,7 +366,11 @@ export function ConnectButton(props: ConnectButtonProps) {
362366

363367
return (
364368
<WalletUIStatesProvider theme={props.theme} isOpen={false}>
365-
<ConnectButtonInner {...props} connectLocale={localeQuery.data} />
369+
<ConnectButtonInner
370+
{...props}
371+
siweAuth={siweAuth}
372+
connectLocale={localeQuery.data}
373+
/>
366374
<ConnectModal
367375
shouldSetActive={true}
368376
accountAbstraction={props.accountAbstraction}
@@ -396,11 +404,11 @@ export function ConnectButton(props: ConnectButtonProps) {
396404
function ConnectButtonInner(
397405
props: ConnectButtonProps & {
398406
connectLocale: ConnectLocale;
407+
siweAuth: ReturnType<typeof useSiweAuth>;
399408
},
400409
) {
401-
const activeWallet = useActiveWallet();
410+
const siweAuth = props.siweAuth;
402411
const activeAccount = useActiveAccount();
403-
const siweAuth = useSiweAuth(activeWallet, activeAccount, props.auth);
404412
const [showSignatureModal, setShowSignatureModal] = useState(false);
405413

406414
// if wallet gets disconnected suddently, close the signature modal if it's open

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ export function ConnectEmbed(props: ConnectEmbedProps) {
247247
chain={preferredChain}
248248
appMetadata={props.appMetadata}
249249
client={props.client}
250+
siweAuth={siweAuth}
250251
wallets={wallets}
251252
accountAbstraction={props.accountAbstraction}
252253
timeout={

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ import { sendTransaction } from "../../../../../../../transaction/actions/send-t
2323
import type { WaitForReceiptOptions } from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
2424
import { waitForReceipt } from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
2525
import { formatNumber } from "../../../../../../../utils/formatNumber.js";
26-
import { isEcosystemWallet } from "../../../../../../../wallets/ecosystem/is-ecosystem-wallet.js";
27-
import { isInAppWallet } from "../../../../../../../wallets/in-app/core/wallet/index.js";
28-
import type { Wallet } from "../../../../../../../wallets/interfaces/wallet.js";
29-
import { isSmartWallet } from "../../../../../../../wallets/smart/is-smart-wallet.js";
26+
import { isInAppSigner } from "../../../../../../../wallets/in-app/core/wallet/is-in-app-signer.js";
3027
import { spacing } from "../../../../../../core/design-system/index.js";
3128
import { useChainName } from "../../../../../../core/hooks/others/useChainQuery.js";
3229
import { useBuyWithCryptoStatus } from "../../../../../../core/hooks/pay/useBuyWithCryptoStatus.js";
@@ -779,20 +776,3 @@ function useSwapMutation(props: {
779776
},
780777
});
781778
}
782-
783-
function isInAppSigner(options: {
784-
wallet: Wallet;
785-
connectedWallets: Wallet[];
786-
}) {
787-
const isInAppOrEcosystem = (w: Wallet) =>
788-
isInAppWallet(w) || isEcosystemWallet(w);
789-
const isSmartWalletWithAdmin =
790-
isSmartWallet(options.wallet) &&
791-
options.connectedWallets.some(
792-
(w) =>
793-
isInAppOrEcosystem(w) &&
794-
w.getAccount()?.address?.toLowerCase() ===
795-
options.wallet.getAdminAccount?.()?.address?.toLowerCase(),
796-
);
797-
return isInAppOrEcosystem(options.wallet) || isSmartWalletWithAdmin;
798-
}

packages/thirdweb/src/react/web/ui/PayEmbed.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ import type { AppMetadata } from "../../../wallets/types.js";
99
import type { WalletId } from "../../../wallets/wallet-types.js";
1010
import { CustomThemeProvider } from "../../core/design-system/CustomThemeProvider.js";
1111
import type { Theme } from "../../core/design-system/index.js";
12-
import type { SiweAuthOptions } from "../../core/hooks/auth/useSiweAuth.js";
12+
import {
13+
type SiweAuthOptions,
14+
useSiweAuth,
15+
} from "../../core/hooks/auth/useSiweAuth.js";
1316
import type {
1417
ConnectButton_connectModalOptions,
1518
PayUIOptions,
1619
} from "../../core/hooks/connection/ConnectButtonProps.js";
20+
import { useActiveAccount } from "../../core/hooks/wallets/useActiveAccount.js";
21+
import { useActiveWallet } from "../../core/hooks/wallets/useActiveWallet.js";
1722
import { useConnectionManager } from "../../core/providers/connection-manager.js";
1823
import type { SupportedTokens } from "../../core/utils/defaultTokens.js";
24+
import { AutoConnect } from "../../web/ui/AutoConnect/AutoConnect.js";
1925
import { EmbedContainer } from "./ConnectWallet/Modal/ConnectEmbed.js";
2026
import { useConnectLocale } from "./ConnectWallet/locale/getConnectLocale.js";
2127
import BuyScreen from "./ConnectWallet/screens/Buy/BuyScreen.js";
@@ -300,6 +306,13 @@ export function PayEmbed(props: PayEmbedProps) {
300306
const [screen, setScreen] = useState<"buy" | "execute-tx">("buy");
301307
const theme = props.theme || "dark";
302308
const connectionManager = useConnectionManager();
309+
const activeAccount = useActiveAccount();
310+
const activeWallet = useActiveWallet();
311+
const siweAuth = useSiweAuth(
312+
activeWallet,
313+
activeAccount,
314+
props.connectOptions?.auth,
315+
);
303316

304317
// Add props.chain and props.chains to defined chains store
305318
useEffect(() => {
@@ -342,6 +355,7 @@ export function PayEmbed(props: PayEmbedProps) {
342355
} else {
343356
content = (
344357
<>
358+
<AutoConnect client={props.client} siweAuth={siweAuth} />
345359
{screen === "buy" && (
346360
<BuyScreen
347361
title={metadata?.name || "Buy"}

packages/thirdweb/src/wallets/connection/autoConnectCore.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ const _autoConnectCore = async ({
8282
getStoredActiveWalletId(storage),
8383
]);
8484

85-
const result = getUrlToken();
85+
const urlToken = getUrlToken();
8686

8787
// If an auth cookie is found and this site supports the wallet, we'll set the auth cookie in the client storage
88-
const wallet = wallets.find((w) => w.id === result?.walletId);
89-
if (result?.authCookie && wallet) {
88+
const wallet = wallets.find((w) => w.id === urlToken?.walletId);
89+
if (urlToken?.authCookie && wallet) {
9090
const clientStorage = new ClientScopedStorage({
9191
storage,
9292
clientId: props.client.clientId,
@@ -97,17 +97,17 @@ const _autoConnectCore = async ({
9797
}
9898
: undefined,
9999
});
100-
await clientStorage.saveAuthCookie(result.authCookie);
100+
await clientStorage.saveAuthCookie(urlToken.authCookie);
101101
}
102-
if (result?.walletId) {
103-
lastActiveWalletId = result.walletId;
104-
lastConnectedWalletIds = lastConnectedWalletIds?.includes(result.walletId)
102+
if (urlToken?.walletId) {
103+
lastActiveWalletId = urlToken.walletId;
104+
lastConnectedWalletIds = lastConnectedWalletIds?.includes(urlToken.walletId)
105105
? lastConnectedWalletIds
106-
: [result.walletId, ...(lastConnectedWalletIds || [])];
106+
: [urlToken.walletId, ...(lastConnectedWalletIds || [])];
107107
}
108108

109-
if (result?.authProvider) {
110-
await setLastAuthProvider?.(result.authProvider, storage);
109+
if (urlToken?.authProvider) {
110+
await setLastAuthProvider?.(urlToken.authProvider, storage);
111111
}
112112

113113
// if no wallets were last connected or we didn't receive an auth token
@@ -132,7 +132,7 @@ const _autoConnectCore = async ({
132132
wallet: activeWallet,
133133
client: props.client,
134134
lastConnectedChain,
135-
authResult: result?.authResult,
135+
authResult: urlToken?.authResult,
136136
}),
137137
{
138138
ms: timeout,
@@ -183,13 +183,18 @@ const _autoConnectCore = async ({
183183
wallet,
184184
client: props.client,
185185
lastConnectedChain,
186-
authResult: result?.authResult,
186+
authResult: urlToken?.authResult,
187187
});
188188
manager.addConnectedWallet(wallet);
189189
} catch {
190190
// no-op
191191
}
192192
}
193+
194+
// Auto-login with SIWE
195+
if (urlToken && activeWallet && props.siweAuth?.requiresAuth) {
196+
await props.siweAuth?.doLogin();
197+
}
193198
manager.isAutoConnecting.setValue(false);
194199
return autoConnected; // useQuery needs a return value
195200
};

packages/thirdweb/src/wallets/connection/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,12 @@ export type AutoConnectProps = {
118118
* Callback to be called when the connection is timeout-ed
119119
*/
120120
onTimeout?: () => void;
121+
122+
/**
123+
* @hidden
124+
*/
125+
siweAuth?: {
126+
requiresAuth: boolean;
127+
doLogin: () => Promise<void>;
128+
};
121129
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { isEcosystemWallet } from "../../../../wallets/ecosystem/is-ecosystem-wallet.js";
2+
import type { Wallet } from "../../../interfaces/wallet.js";
3+
import { isSmartWallet } from "../../../smart/index.js";
4+
import { isInAppWallet } from "./index.js";
5+
6+
export function isInAppSigner(options: {
7+
wallet: Wallet;
8+
connectedWallets: Wallet[];
9+
}) {
10+
const isInAppOrEcosystem = (w: Wallet) =>
11+
isInAppWallet(w) || isEcosystemWallet(w);
12+
const isSmartWalletWithAdmin =
13+
isSmartWallet(options.wallet) &&
14+
options.connectedWallets.some(
15+
(w) =>
16+
isInAppOrEcosystem(w) &&
17+
w.getAccount()?.address?.toLowerCase() ===
18+
options.wallet.getAdminAccount?.()?.address?.toLowerCase(),
19+
);
20+
return isInAppOrEcosystem(options.wallet) || isSmartWalletWithAdmin;
21+
}

0 commit comments

Comments
 (0)