From f9fa5df6b18c9b0557af937371f923e3b0406c84 Mon Sep 17 00:00:00 2001 From: MananTank Date: Mon, 3 Mar 2025 21:17:31 +0000 Subject: [PATCH 1/3] [TOOl-3587] Dashboard: Add in-app-wallet login mode (#6400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## PR-Codex overview This PR introduces enhancements to the `LoginAndOnboardingPage` by adding support for an in-app wallet login option and refactoring the login handling logic. ### Detailed summary - Added `loginWithInAppWallet` prop to `LoginAndOnboardingPage` and `LoginAndOnboardingPageContent`. - Updated `Page` component to handle `in-app-wallet` search parameter. - Introduced `inAppWalletLoginOptions` for in-app wallet authentication. - Modified wallet selection logic based on `loginWithInAppWallet` prop. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` --- apps/dashboard/src/app/login/LoginPage.tsx | 36 +++++++++++++++++-- apps/dashboard/src/app/login/page.tsx | 13 +++++-- .../app/nebula-app/login/NebulaLoginPage.tsx | 1 + 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/apps/dashboard/src/app/login/LoginPage.tsx b/apps/dashboard/src/app/login/LoginPage.tsx index 9ccc1a0dcc2..cfba0ac2f09 100644 --- a/apps/dashboard/src/app/login/LoginPage.tsx +++ b/apps/dashboard/src/app/login/LoginPage.tsx @@ -24,7 +24,7 @@ const LazyOnboardingUI = lazy( () => import("./onboarding/on-boarding-ui.client"), ); -const wallets = [ +const loginOptions = [ inAppWallet({ auth: { options: [ @@ -45,9 +45,27 @@ const wallets = [ createWallet("io.zerion.wallet"), ]; +const inAppWalletLoginOptions = [ + inAppWallet({ + auth: { + options: [ + "google", + "apple", + "facebook", + "github", + "email", + "phone", + "passkey", + "wallet", + ], + }, + }), +]; + export function LoginAndOnboardingPage(props: { account: Account | undefined; redirectPath: string; + loginWithInAppWallet: boolean; }) { return (
@@ -91,6 +109,7 @@ export function LoginAndOnboardingPage(props: {
); @@ -99,6 +118,7 @@ export function LoginAndOnboardingPage(props: { export function LoginAndOnboardingPageContent(props: { account: Account | undefined; redirectPath: string; + loginWithInAppWallet: boolean; }) { return (
@@ -114,6 +134,7 @@ export function LoginAndOnboardingPageContent(props: { @@ -139,6 +160,7 @@ function LoadingCard() { function PageContent(props: { redirectPath: string; account: Account | undefined; + loginWithInAppWallet: boolean; }) { const [screen, setScreen] = useState< | { id: "login" } @@ -190,7 +212,12 @@ function PageContent(props: { } if (connectionStatus !== "connected" || screen.id === "login") { - return ; + return ( + + ); } if (screen.id === "onboarding") { @@ -215,6 +242,7 @@ function PageContent(props: { function CustomConnectEmbed(props: { onLogin: () => void; + loginWithInAppWallet: boolean; }) { const { theme } = useTheme(); const client = useThirdwebClient(); @@ -257,7 +285,9 @@ function CustomConnectEmbed(props: { return isLoggedInResult; }, }} - wallets={wallets} + wallets={ + props.loginWithInAppWallet ? inAppWalletLoginOptions : loginOptions + } client={client} modalSize="wide" theme={getSDKTheme(theme === "light" ? "light" : "dark")} diff --git a/apps/dashboard/src/app/login/page.tsx b/apps/dashboard/src/app/login/page.tsx index 1364df759bc..8275995b0a5 100644 --- a/apps/dashboard/src/app/login/page.tsx +++ b/apps/dashboard/src/app/login/page.tsx @@ -4,10 +4,13 @@ import { isValidEncodedRedirectPath } from "./isValidEncodedRedirectPath"; export default async function Page(props: { searchParams: Promise<{ - next?: string; + next: string | string[] | undefined; + "in-app-wallet": string | string[] | undefined; }>; }) { - const nextPath = (await props.searchParams).next; + const searchParams = await props.searchParams; + const nextPath = + typeof searchParams.next === "string" ? searchParams.next : undefined; const account = await getRawAccount(); // don't redirect away from login page if authToken is already present and onboarding is done @@ -20,6 +23,10 @@ export default async function Page(props: { nextPath && isValidEncodedRedirectPath(nextPath) ? nextPath : "/team"; return ( - + ); } diff --git a/apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx b/apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx index b672a1fecea..b2d39305553 100644 --- a/apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx +++ b/apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx @@ -53,6 +53,7 @@ export function NebulaLoginPage(props: { {showPage === "connect" && ( Date: Mon, 3 Mar 2025 13:32:38 -0800 Subject: [PATCH 2/3] remove secretHash from rotate key response (#6401) --- .../src/@3rdweb-sdk/react/hooks/useApi.ts | 1 - .../ProjectGeneralSettingsPage.stories.tsx | 5 +- .../bytecode/resolveImplementation.test.ts | 93 ++++++++++--------- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts index 9dba9002be5..dd0644b6736 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts @@ -371,7 +371,6 @@ export type RotateSecretKeyAPIReturnType = { data: { secret: string; secretMasked: string; - secretHash: string; }; }; diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx index b60adde94f2..783a6fad898 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.stories.tsx @@ -76,9 +76,8 @@ function Story(props: { await new Promise((resolve) => setTimeout(resolve, 1000)); return { data: { - secret: new Array(86).fill("x").join(""), - secretHash: new Array(64).fill("x").join(""), - secretMasked: "123...4567", + secret: `sk_${new Array(86).fill("x").join("")}`, + secretMasked: "sk_123...4567", }, }; }} diff --git a/packages/thirdweb/src/utils/bytecode/resolveImplementation.test.ts b/packages/thirdweb/src/utils/bytecode/resolveImplementation.test.ts index 4bb6a96107a..574c57b31b2 100644 --- a/packages/thirdweb/src/utils/bytecode/resolveImplementation.test.ts +++ b/packages/thirdweb/src/utils/bytecode/resolveImplementation.test.ts @@ -20,54 +20,57 @@ import { getContract } from "../../contract/contract.js"; import { deployContract } from "../../contract/deployment/deploy-with-abi.js"; import { resolveImplementation } from "./resolveImplementation.js"; -describe("Resolve implementation", async () => { - it("should extract implementation address for minimal proxy contract", async () => { - const resolved = resolveImplementation(NFT_DROP_CONTRACT); - expect((await resolved).address).to.equal(NFT_DROP_IMPLEMENTATION); - }); - - it("should extract implementation address for matic proxy contract", async () => { - const resolved = resolveImplementation(POLYGON_USDT_PROXY_CONTRACT); - expect((await resolved).address).to.equal( - POLYGON_USDT_IMPLEMENTATION.toLowerCase(), - ); - }); - - it("should extract implementation address for base USDC proxy contract", async () => { - const resolved = resolveImplementation(BASE_USDC_PROXY_CONTRACT); - expect((await resolved).address).to.equal( - BASE_USDC_IMPLEMENTATION.toLowerCase(), - ); - }); - - it("should extract implementation address for ERC1967 proxy contract", async () => { - const implementationAddress = await deployContract({ - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - account: TEST_ACCOUNT_A, - bytecode: DUMMY_BYTECODE, - abi: [], +describe.runIf(process.env.TW_SECRET_KEY)( + "Resolve implementation", + async () => { + it("should extract implementation address for minimal proxy contract", async () => { + const resolved = resolveImplementation(NFT_DROP_CONTRACT); + expect((await resolved).address).to.equal(NFT_DROP_IMPLEMENTATION); }); - const proxyAddress = await deployContract({ - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - account: TEST_ACCOUNT_A, - bytecode: ERC1967_PROXY_BYTECODE, - abi: ERC1967_PROXY_CONSTRUCTOR_ABI as Abi, - constructorParams: { - logic: implementationAddress, - data: "0x", - }, + it("should extract implementation address for matic proxy contract", async () => { + const resolved = resolveImplementation(POLYGON_USDT_PROXY_CONTRACT); + expect((await resolved).address).to.equal( + POLYGON_USDT_IMPLEMENTATION.toLowerCase(), + ); }); - const proxy = getContract({ - chain: ANVIL_CHAIN, - address: proxyAddress, - client: TEST_CLIENT, + it("should extract implementation address for base USDC proxy contract", async () => { + const resolved = resolveImplementation(BASE_USDC_PROXY_CONTRACT); + expect((await resolved).address).to.equal( + BASE_USDC_IMPLEMENTATION.toLowerCase(), + ); }); - const resolved = await resolveImplementation(proxy); - expect(resolved.address).to.equal(implementationAddress); - }); -}); + it("should extract implementation address for ERC1967 proxy contract", async () => { + const implementationAddress = await deployContract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + account: TEST_ACCOUNT_A, + bytecode: DUMMY_BYTECODE, + abi: [], + }); + + const proxyAddress = await deployContract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + account: TEST_ACCOUNT_A, + bytecode: ERC1967_PROXY_BYTECODE, + abi: ERC1967_PROXY_CONSTRUCTOR_ABI as Abi, + constructorParams: { + logic: implementationAddress, + data: "0x", + }, + }); + + const proxy = getContract({ + chain: ANVIL_CHAIN, + address: proxyAddress, + client: TEST_CLIENT, + }); + + const resolved = await resolveImplementation(proxy); + expect(resolved.address).to.equal(implementationAddress); + }); + }, +); From 9fcf1b80de6332bdad9cec777f84b3de07606611 Mon Sep 17 00:00:00 2001 From: Jonas Daniels Date: Mon, 3 Mar 2025 13:43:07 -0800 Subject: [PATCH 3/3] skip smart wallet tests without TW_SECRET_KEY (#6403) --- .../src/wallets/smart/smart-wallet-integration-v07.test.ts | 2 +- .../thirdweb/src/wallets/smart/smart-wallet-modular.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts b/packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts index 8e64e840028..6f8f29237af 100644 --- a/packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts +++ b/packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts @@ -49,7 +49,7 @@ const contract = getContract({ address: "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8", }); -describe.sequential( +describe.runIf(process.env.TW_SECRET_KEY).sequential( "SmartWallet 0.7 core tests", { timeout: 240_000, diff --git a/packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts b/packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts index 36e9c8870e8..c6ff4fadf80 100644 --- a/packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts +++ b/packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts @@ -28,7 +28,7 @@ const client = TEST_CLIENT; const DEFAULT_FACTORY_ADDRESS = "0xB1846E893CA01c5Dcdaa40371C1e13f2e0Df5717"; const DEFAULT_VALIDATOR_ADDRESS = "0x7D3631d823e0De311DC86f580946EeF2eEC81fba"; -describe.sequential( +describe.runIf(process.env.TW_SECRET_KEY).sequential( "SmartWallet modular tests", { retry: 0,