diff --git a/.changeset/fifty-houses-punch.md b/.changeset/fifty-houses-punch.md new file mode 100644 index 00000000000..802340f6689 --- /dev/null +++ b/.changeset/fifty-houses-punch.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Enable Sign in with Wallet for ecosystems diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/auth-options-form.client.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/auth-options-form.client.tsx index 54c4770531d..dcc7c558bde 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/auth-options-form.client.tsx +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/auth-options-form.client.tsx @@ -227,7 +227,10 @@ export function AuthOptionsForm({ ecosystem }: { ecosystem: Ecosystem }) { className="h-6 w-6" />

- {option.slice(0, 1).toUpperCase() + option.slice(1)} + {option === "siwe" + ? "Wallet" + : option.slice(0, 1).toUpperCase() + + option.slice(1)}

diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/types.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/types.ts index 909728152c8..a2bc2575f1f 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/types.ts +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/types.ts @@ -1,6 +1,9 @@ export const authOptions = [ "email", "phone", + "passkey", + "siwe", + "guest", "google", "facebook", "x", @@ -12,7 +15,6 @@ export const authOptions = [ "apple", "coinbase", "line", - "guest", ] as const; export type Ecosystem = { diff --git a/apps/dashboard/src/components/wallets/ConnectWalletMiniPlayground/MiniPlayground.tsx b/apps/dashboard/src/components/wallets/ConnectWalletMiniPlayground/MiniPlayground.tsx index 5e12590cbce..b0cd2a63265 100644 --- a/apps/dashboard/src/components/wallets/ConnectWalletMiniPlayground/MiniPlayground.tsx +++ b/apps/dashboard/src/components/wallets/ConnectWalletMiniPlayground/MiniPlayground.tsx @@ -79,6 +79,7 @@ function usePlaygroundWallets() { github: false, coinbase: false, guest: false, + wallet: false, }); const [enabledWallets, setEnabledWallets] = useState({ diff --git a/apps/playground-web/src/components/in-app-wallet/ecosystem.tsx b/apps/playground-web/src/components/in-app-wallet/ecosystem.tsx index fc119a3b53d..b2ae2f43c34 100644 --- a/apps/playground-web/src/components/in-app-wallet/ecosystem.tsx +++ b/apps/playground-web/src/components/in-app-wallet/ecosystem.tsx @@ -8,7 +8,7 @@ const getEcosystem = () => { process.env.NEXT_PUBLIC_IN_APP_WALLET_URL?.endsWith(".thirdweb-dev.com") ) { // dev ecosystem - return "ecosystem.bonfire-development"; + return "ecosystem.catlovers"; } // prod ecosystem return "ecosystem.new-age"; diff --git a/packages/thirdweb/src/extensions/prebuilts/deploy-erc1155.test.ts b/packages/thirdweb/src/extensions/prebuilts/deploy-erc1155.test.ts index 8cdd6c804ca..47cc2863c82 100644 --- a/packages/thirdweb/src/extensions/prebuilts/deploy-erc1155.test.ts +++ b/packages/thirdweb/src/extensions/prebuilts/deploy-erc1155.test.ts @@ -1,19 +1,19 @@ import { describe, expect, it } from "vitest"; import { ANVIL_CHAIN } from "../../../test/src/chains.js"; import { TEST_CLIENT } from "../../../test/src/test-clients.js"; -import { TEST_ACCOUNT_A } from "../../../test/src/test-wallets.js"; +import { TEST_ACCOUNT_B } from "../../../test/src/test-wallets.js"; import { getContract } from "../../contract/contract.js"; import { name } from "../common/read/name.js"; import { deployERC1155Contract } from "./deploy-erc1155.js"; -// skip this test suite if there is no secret key available to test with -// TODO: remove reliance on secret key during unit tests entirely +const account = TEST_ACCOUNT_B; + describe.runIf(process.env.TW_SECRET_KEY)("deployERC1155", () => { it("should deploy ERC1155 drop", async () => { const address = await deployERC1155Contract({ client: TEST_CLIENT, chain: ANVIL_CHAIN, - account: TEST_ACCOUNT_A, + account, type: "DropERC1155", params: { name: "EditionDrop", @@ -35,7 +35,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("deployERC1155", () => { const address = await deployERC1155Contract({ client: TEST_CLIENT, chain: ANVIL_CHAIN, - account: TEST_ACCOUNT_A, + account, type: "TokenERC1155", params: { name: "Edition", diff --git a/packages/thirdweb/src/extensions/prebuilts/deploy-pack.test.ts b/packages/thirdweb/src/extensions/prebuilts/deploy-pack.test.ts index 78af18c88b6..cfb5cc3dcef 100644 --- a/packages/thirdweb/src/extensions/prebuilts/deploy-pack.test.ts +++ b/packages/thirdweb/src/extensions/prebuilts/deploy-pack.test.ts @@ -1,14 +1,16 @@ import { describe, expect, it } from "vitest"; import { ANVIL_CHAIN } from "~test/chains.js"; import { TEST_CLIENT } from "~test/test-clients.js"; -import { TEST_ACCOUNT_A } from "~test/test-wallets.js"; +import { TEST_ACCOUNT_C } from "~test/test-wallets.js"; import { isAddress } from "../../utils/address.js"; import { deployPackContract } from "./deploy-pack.js"; +const account = TEST_ACCOUNT_C; + describe.runIf(process.env.TW_SECRET_KEY)("deploy-pack contract", () => { it("should deploy Pack contract", async () => { const address = await deployPackContract({ - account: TEST_ACCOUNT_A, + account, client: TEST_CLIENT, chain: ANVIL_CHAIN, params: { diff --git a/packages/thirdweb/src/react/web/wallets/ecosystem/EcosystemWalletConnectUI.tsx b/packages/thirdweb/src/react/web/wallets/ecosystem/EcosystemWalletConnectUI.tsx index 0baf6c852b5..6a8904b7ded 100644 --- a/packages/thirdweb/src/react/web/wallets/ecosystem/EcosystemWalletConnectUI.tsx +++ b/packages/thirdweb/src/react/web/wallets/ecosystem/EcosystemWalletConnectUI.tsx @@ -129,6 +129,7 @@ function EcosystemWalletConnectUI(props: { done={done} onBack={goBackToMain || (() => setSelectionData({}))} locale={props.connectLocale} + isLinking={state.walletLogin.linking} /> ); } diff --git a/packages/thirdweb/src/react/web/wallets/in-app/InAppWalletConnectUI.tsx b/packages/thirdweb/src/react/web/wallets/in-app/InAppWalletConnectUI.tsx index 1c271669c00..038d1e1b88d 100644 --- a/packages/thirdweb/src/react/web/wallets/in-app/InAppWalletConnectUI.tsx +++ b/packages/thirdweb/src/react/web/wallets/in-app/InAppWalletConnectUI.tsx @@ -116,6 +116,7 @@ function InAppWalletConnectUI(props: { done={done} onBack={goBackToMain || (() => setSelectionData({}))} locale={props.connectLocale} + isLinking={state.walletLogin.linking} /> ); } diff --git a/packages/thirdweb/src/react/web/wallets/in-app/WalletAuth.tsx b/packages/thirdweb/src/react/web/wallets/in-app/WalletAuth.tsx index c7d905d4c6d..0328b5a9657 100644 --- a/packages/thirdweb/src/react/web/wallets/in-app/WalletAuth.tsx +++ b/packages/thirdweb/src/react/web/wallets/in-app/WalletAuth.tsx @@ -28,6 +28,7 @@ export function WalletAuth(props: { inAppLocale: InAppWalletLocale; onBack: () => void; walletConnect: { projectId?: string } | undefined; + isLinking: boolean; meta?: { title?: string; titleIconUrl?: string; @@ -61,16 +62,25 @@ export function WalletAuth(props: { setStatus("loading"); walletToConnect.current = walletToLink; try { - await linkProfile({ - client: props.client, - strategy: "wallet", - wallet: walletToLink, - chain: wallet.getChain() || defineChain(1), - ecosystem, - }).catch((e) => { - setError(e.message); - throw e; - }); + if (props.isLinking) { + await linkProfile({ + client: props.client, + strategy: "wallet", + wallet: walletToLink, + chain: wallet.getChain() || defineChain(1), + ecosystem, + }).catch((e) => { + setError(e.message); + throw e; + }); + } else { + await wallet.connect({ + client: props.client, + strategy: "wallet", + wallet: walletToLink, + chain: walletToLink.getChain() || defineChain(1), + }); + } addConnectedWallet(walletToLink); done(); } catch { diff --git a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx index 2b2784a166a..6ea4eb673d8 100644 --- a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx +++ b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx @@ -57,7 +57,9 @@ export type ConnectWalletSelectUIState = connectionPromise: Promise; }; passkeyLogin?: boolean; - walletLogin?: boolean; + walletLogin?: { + linking: boolean; + }; }; const defaultAuthOptions: AuthOption[] = [ @@ -186,6 +188,7 @@ export const ConnectWalletSocialOptions = ( const passKeyEnabled = authOptions.includes("passkey"); const guestEnabled = authOptions.includes("guest"); + const siweEnabled = authOptions.includes("wallet"); const placeholder = inputMode === "email" ? locale.emailPlaceholder : locale.phonePlaceholder; @@ -306,7 +309,9 @@ export const ConnectWalletSocialOptions = ( function handleWalletLogin() { setData({ - walletLogin: true, + walletLogin: { + linking: props.isLinking || false, + }, }); props.select(); } @@ -467,6 +472,18 @@ export const ConnectWalletSocialOptions = ( /> )} + {/* SIWE login */} + {siweEnabled && ( + { + handleWalletLogin(); + }} + title={locale.signInWithWallet} + /> + )} + {/* Guest login */} {guestEnabled && ( o !== "siwe"); + data.authOptions.push("wallet"); + } + return data ?? null; } diff --git a/packages/thirdweb/src/wallets/in-app/core/authentication/getLoginPath.ts b/packages/thirdweb/src/wallets/in-app/core/authentication/getLoginPath.ts index b61b529dfbb..2dc6705dcd4 100644 --- a/packages/thirdweb/src/wallets/in-app/core/authentication/getLoginPath.ts +++ b/packages/thirdweb/src/wallets/in-app/core/authentication/getLoginPath.ts @@ -3,8 +3,8 @@ import { getThirdwebBaseUrl } from "../../../../utils/domains.js"; import { type AuthOption, authOptions } from "../../../../wallets/types.js"; import type { Ecosystem } from "../wallet/types.js"; -const getLoginOptionRoute = (option: AuthOption | "wallet") => { - if (!authOptions.includes(option as AuthOption) && option !== "wallet") { +const getLoginOptionRoute = (option: AuthOption) => { + if (!authOptions.includes(option as AuthOption)) { throw new Error(`Unknown auth option ${option}`); } switch (option) { @@ -22,7 +22,7 @@ export const getLoginUrl = ({ mode = "popup", redirectUrl, }: { - authOption: AuthOption | "wallet"; + authOption: AuthOption; client: ThirdwebClient; ecosystem?: Ecosystem; mode?: "popup" | "redirect" | "window"; @@ -60,7 +60,7 @@ export const getLoginCallbackUrl = ({ client, ecosystem, }: { - authOption: AuthOption | "wallet"; + authOption: AuthOption; client: ThirdwebClient; ecosystem?: Ecosystem; }): string => { diff --git a/packages/thirdweb/src/wallets/in-app/core/authentication/types.ts b/packages/thirdweb/src/wallets/in-app/core/authentication/types.ts index 33026dc95f8..93839b232d6 100644 --- a/packages/thirdweb/src/wallets/in-app/core/authentication/types.ts +++ b/packages/thirdweb/src/wallets/in-app/core/authentication/types.ts @@ -112,7 +112,7 @@ export type OAuthRedirectObject = { // TODO: type this better for each auth provider export type Profile = { - type: AuthOption | "wallet"; + type: AuthOption; details: { id?: string; email?: string; diff --git a/packages/thirdweb/src/wallets/types.ts b/packages/thirdweb/src/wallets/types.ts index f2442b8c575..52fc33f8314 100644 --- a/packages/thirdweb/src/wallets/types.ts +++ b/packages/thirdweb/src/wallets/types.ts @@ -41,6 +41,7 @@ export const authOptions = [ "email", "phone", "passkey", + "wallet", ] as const; export type AuthOption = (typeof authOptions)[number];