Skip to content

[SDK] Fix: Automatically trigger login for connected wallets whe… #7009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/every-sides-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Automatically trigger SIWE sign in when a wallet is connected
14 changes: 14 additions & 0 deletions apps/playground-web/src/components/auth/auth-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,25 @@ import {
} from "@/app/connect/auth/server/actions/auth";
import { THIRDWEB_CLIENT } from "@/lib/client";
import { ConnectButton } from "thirdweb/react";
import { createWallet, inAppWallet } from "thirdweb/wallets";

export function AuthButton() {
return (
<ConnectButton
client={THIRDWEB_CLIENT}
wallets={[
inAppWallet({
auth: {
options: ["google", "telegram", "github"],
mode: "redirect",
},
}),
createWallet("io.metamask"),
createWallet("com.coinbase.wallet"),
createWallet("me.rainbow"),
createWallet("io.rabby"),
createWallet("io.zerion.wallet"),
]}
auth={{
isLoggedIn: (address) => isLoggedIn(address),
doLogin: (params) => login(params),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ export function ConnectButton(props: ConnectButtonProps) {
const status = useActiveWalletConnectionStatus();
const connectionManager = useConnectionManager();
const siweAuth = useSiweAuth(wallet, account, props.auth);
useAutoConnect(props);
useAutoConnect({
...props,
siweAuth: siweAuth,
});

const fadeAnim = useRef(new Animated.Value(0)); // For background opacity
const slideAnim = useRef(new Animated.Value(screenHeight)); // For bottom sheet position
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ export function ConnectButton(props: ConnectButtonProps) {
);
const localeQuery = useConnectLocale(props.locale || "en_US");
const connectionManager = useConnectionManager();
const activeAccount = useActiveAccount();
const activeWallet = useActiveWallet();
const siweAuth = useSiweAuth(activeWallet, activeAccount, props.auth);

usePreloadWalletProviders({
wallets,
Expand Down Expand Up @@ -337,6 +340,7 @@ export function ConnectButton(props: ConnectButtonProps) {
}
accountAbstraction={props.accountAbstraction}
onConnect={props.onConnect}
siweAuth={siweAuth}
/>
);

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

return (
<WalletUIStatesProvider theme={props.theme} isOpen={false}>
<ConnectButtonInner {...props} connectLocale={localeQuery.data} />
<ConnectButtonInner
{...props}
siweAuth={siweAuth}
connectLocale={localeQuery.data}
/>
<ConnectModal
shouldSetActive={true}
accountAbstraction={props.accountAbstraction}
Expand Down Expand Up @@ -396,11 +404,11 @@ export function ConnectButton(props: ConnectButtonProps) {
function ConnectButtonInner(
props: ConnectButtonProps & {
connectLocale: ConnectLocale;
siweAuth: ReturnType<typeof useSiweAuth>;
},
) {
const activeWallet = useActiveWallet();
const siweAuth = props.siweAuth;
const activeAccount = useActiveAccount();
const siweAuth = useSiweAuth(activeWallet, activeAccount, props.auth);
const [showSignatureModal, setShowSignatureModal] = useState(false);

// if wallet gets disconnected suddently, close the signature modal if it's open
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
chain={preferredChain}
appMetadata={props.appMetadata}
client={props.client}
siweAuth={siweAuth}

Check warning on line 250 in packages/thirdweb/src/react/web/ui/ConnectWallet/Modal/ConnectEmbed.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L250 was not covered by tests
wallets={wallets}
accountAbstraction={props.accountAbstraction}
timeout={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ import { sendTransaction } from "../../../../../../../transaction/actions/send-t
import type { WaitForReceiptOptions } from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
import { waitForReceipt } from "../../../../../../../transaction/actions/wait-for-tx-receipt.js";
import { formatNumber } from "../../../../../../../utils/formatNumber.js";
import { isEcosystemWallet } from "../../../../../../../wallets/ecosystem/is-ecosystem-wallet.js";
import { isInAppWallet } from "../../../../../../../wallets/in-app/core/wallet/index.js";
import type { Wallet } from "../../../../../../../wallets/interfaces/wallet.js";
import { isSmartWallet } from "../../../../../../../wallets/smart/is-smart-wallet.js";
import { isInAppSigner } from "../../../../../../../wallets/in-app/core/wallet/is-in-app-signer.js";
import { spacing } from "../../../../../../core/design-system/index.js";
import { useChainName } from "../../../../../../core/hooks/others/useChainQuery.js";
import { useBuyWithCryptoStatus } from "../../../../../../core/hooks/pay/useBuyWithCryptoStatus.js";
Expand Down Expand Up @@ -779,20 +776,3 @@ function useSwapMutation(props: {
},
});
}

function isInAppSigner(options: {
wallet: Wallet;
connectedWallets: Wallet[];
}) {
const isInAppOrEcosystem = (w: Wallet) =>
isInAppWallet(w) || isEcosystemWallet(w);
const isSmartWalletWithAdmin =
isSmartWallet(options.wallet) &&
options.connectedWallets.some(
(w) =>
isInAppOrEcosystem(w) &&
w.getAccount()?.address?.toLowerCase() ===
options.wallet.getAdminAccount?.()?.address?.toLowerCase(),
);
return isInAppOrEcosystem(options.wallet) || isSmartWalletWithAdmin;
}
16 changes: 15 additions & 1 deletion packages/thirdweb/src/react/web/ui/PayEmbed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@
import type { WalletId } from "../../../wallets/wallet-types.js";
import { CustomThemeProvider } from "../../core/design-system/CustomThemeProvider.js";
import type { Theme } from "../../core/design-system/index.js";
import type { SiweAuthOptions } from "../../core/hooks/auth/useSiweAuth.js";
import {
type SiweAuthOptions,
useSiweAuth,
} from "../../core/hooks/auth/useSiweAuth.js";
import type {
ConnectButton_connectModalOptions,
PayUIOptions,
} from "../../core/hooks/connection/ConnectButtonProps.js";
import { useActiveAccount } from "../../core/hooks/wallets/useActiveAccount.js";
import { useActiveWallet } from "../../core/hooks/wallets/useActiveWallet.js";
import { useConnectionManager } from "../../core/providers/connection-manager.js";
import type { SupportedTokens } from "../../core/utils/defaultTokens.js";
import { AutoConnect } from "../../web/ui/AutoConnect/AutoConnect.js";
import { EmbedContainer } from "./ConnectWallet/Modal/ConnectEmbed.js";
import { useConnectLocale } from "./ConnectWallet/locale/getConnectLocale.js";
import BuyScreen from "./ConnectWallet/screens/Buy/BuyScreen.js";
Expand Down Expand Up @@ -300,6 +306,13 @@
const [screen, setScreen] = useState<"buy" | "execute-tx">("buy");
const theme = props.theme || "dark";
const connectionManager = useConnectionManager();
const activeAccount = useActiveAccount();
const activeWallet = useActiveWallet();
const siweAuth = useSiweAuth(
activeWallet,
activeAccount,
props.connectOptions?.auth,
);

// Add props.chain and props.chains to defined chains store
useEffect(() => {
Expand Down Expand Up @@ -342,6 +355,7 @@
} else {
content = (
<>
<AutoConnect client={props.client} siweAuth={siweAuth} />

Check warning on line 358 in packages/thirdweb/src/react/web/ui/PayEmbed.tsx

View check run for this annotation

Codecov / codecov/patch

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

Added line #L358 was not covered by tests
{screen === "buy" && (
<BuyScreen
title={metadata?.name || "Buy"}
Expand Down
29 changes: 17 additions & 12 deletions packages/thirdweb/src/wallets/connection/autoConnectCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@
getStoredActiveWalletId(storage),
]);

const result = getUrlToken();
const urlToken = getUrlToken();

// If an auth cookie is found and this site supports the wallet, we'll set the auth cookie in the client storage
const wallet = wallets.find((w) => w.id === result?.walletId);
if (result?.authCookie && wallet) {
const wallet = wallets.find((w) => w.id === urlToken?.walletId);
if (urlToken?.authCookie && wallet) {
const clientStorage = new ClientScopedStorage({
storage,
clientId: props.client.clientId,
Expand All @@ -97,17 +97,17 @@
}
: undefined,
});
await clientStorage.saveAuthCookie(result.authCookie);
await clientStorage.saveAuthCookie(urlToken.authCookie);
}
if (result?.walletId) {
lastActiveWalletId = result.walletId;
lastConnectedWalletIds = lastConnectedWalletIds?.includes(result.walletId)
if (urlToken?.walletId) {
lastActiveWalletId = urlToken.walletId;
lastConnectedWalletIds = lastConnectedWalletIds?.includes(urlToken.walletId)
? lastConnectedWalletIds
: [result.walletId, ...(lastConnectedWalletIds || [])];
: [urlToken.walletId, ...(lastConnectedWalletIds || [])];

Check warning on line 106 in packages/thirdweb/src/wallets/connection/autoConnectCore.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L106 was not covered by tests
}

if (result?.authProvider) {
await setLastAuthProvider?.(result.authProvider, storage);
if (urlToken?.authProvider) {
await setLastAuthProvider?.(urlToken.authProvider, storage);
}

// if no wallets were last connected or we didn't receive an auth token
Expand All @@ -132,7 +132,7 @@
wallet: activeWallet,
client: props.client,
lastConnectedChain,
authResult: result?.authResult,
authResult: urlToken?.authResult,
}),
{
ms: timeout,
Expand Down Expand Up @@ -183,13 +183,18 @@
wallet,
client: props.client,
lastConnectedChain,
authResult: result?.authResult,
authResult: urlToken?.authResult,
});
manager.addConnectedWallet(wallet);
} catch {
// no-op
}
}

// Auto-login with SIWE
if (urlToken && activeWallet && props.siweAuth?.requiresAuth) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to invoke this? I thought it was a function

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do the same logic that would trigger the sign in button

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a function, it just checks if they're using SIWE

await props.siweAuth?.doLogin();
}

Check warning on line 197 in packages/thirdweb/src/wallets/connection/autoConnectCore.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/wallets/connection/autoConnectCore.ts#L196-L197

Added lines #L196 - L197 were not covered by tests
manager.isAutoConnecting.setValue(false);
return autoConnected; // useQuery needs a return value
};
Expand Down
8 changes: 8 additions & 0 deletions packages/thirdweb/src/wallets/connection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,12 @@ export type AutoConnectProps = {
* Callback to be called when the connection is timeout-ed
*/
onTimeout?: () => void;

/**
* @hidden
*/
siweAuth?: {
requiresAuth: boolean;
doLogin: () => Promise<void>;
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isEcosystemWallet } from "../../../../wallets/ecosystem/is-ecosystem-wallet.js";
import type { Wallet } from "../../../interfaces/wallet.js";
import { isSmartWallet } from "../../../smart/index.js";
import { isInAppWallet } from "./index.js";

export function isInAppSigner(options: {
wallet: Wallet;
connectedWallets: Wallet[];
}) {
const isInAppOrEcosystem = (w: Wallet) =>
isInAppWallet(w) || isEcosystemWallet(w);
const isSmartWalletWithAdmin =
isSmartWallet(options.wallet) &&
options.connectedWallets.some(
(w) =>
isInAppOrEcosystem(w) &&
w.getAccount()?.address?.toLowerCase() ===
options.wallet.getAdminAccount?.()?.address?.toLowerCase(),
);
return isInAppOrEcosystem(options.wallet) || isSmartWalletWithAdmin;
}

Check warning on line 21 in packages/thirdweb/src/wallets/in-app/core/wallet/is-in-app-signer.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/wallets/in-app/core/wallet/is-in-app-signer.ts#L9-L21

Added lines #L9 - L21 were not covered by tests
Loading