diff --git a/.changeset/silver-candles-float.md b/.changeset/silver-candles-float.md new file mode 100644 index 00000000000..161616e60c7 --- /dev/null +++ b/.changeset/silver-candles-float.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Support smart account options for ecosystem wallets diff --git a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx index baf5dac90dc..c00b57cc832 100644 --- a/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx +++ b/packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx @@ -5,7 +5,7 @@ import { useMemo, useState } from "react"; import type { Chain } from "../../../../chains/types.js"; import type { ThirdwebClient } from "../../../../client/client.js"; import { webLocalStorage } from "../../../../utils/storage/webStorage.js"; -import { getEcosystemWalletAuthOptions } from "../../../../wallets/ecosystem/get-ecosystem-wallet-auth-options.js"; +import { getEcosystemOptions } from "../../../../wallets/ecosystem/get-ecosystem-wallet-auth-options.js"; import { isEcosystemWallet } from "../../../../wallets/ecosystem/is-ecosystem-wallet.js"; import type { Profile } from "../../../../wallets/in-app/core/authentication/types.js"; import { linkProfile } from "../../../../wallets/in-app/web/lib/auth/index.js"; @@ -121,7 +121,8 @@ export const ConnectWalletSocialOptions = ( queryKey: ["auth-options", wallet.id], queryFn: async () => { if (isEcosystemWallet(wallet)) { - return getEcosystemWalletAuthOptions(wallet.id); + const options = await getEcosystemOptions(wallet.id); + return options?.authOptions ?? null; } return null; }, diff --git a/packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-auth-options.ts b/packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-auth-options.ts index b3fa3b6aabb..a9f9e788c76 100644 --- a/packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-auth-options.ts +++ b/packages/thirdweb/src/wallets/ecosystem/get-ecosystem-wallet-auth-options.ts @@ -2,15 +2,26 @@ import { getThirdwebBaseUrl } from "../../utils/domains.js"; import type { AuthOption } from "../types.js"; import type { EcosystemWalletId } from "../wallet-types.js"; +export type EcosystemOptions = { + authOptions: AuthOption[]; + smartAccountOptions: SmartAccountOptions; +}; + +type SmartAccountOptions = { + chainIds: number[]; + sponsorGas: boolean; + accountFactoryAddress: string; +}; + /** * Retrieves the specified auth options for a given ecosystem wallet, if any. * @param walletId The ecosystem wallet ID. * @returns {AuthOption[] | undefined} The auth options for the ecosystem wallet. * @internal */ -export async function getEcosystemWalletAuthOptions( +export async function getEcosystemOptions( walletId: EcosystemWalletId, -): Promise { +): Promise { const res = await fetch( `${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/ecosystem-wallet`, { @@ -29,5 +40,5 @@ export async function getEcosystemWalletAuthOptions( ); } - return data.authOptions ?? undefined; + return data ?? null; } diff --git a/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts b/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts index 8cce2b03fac..1a9efe58ddd 100644 --- a/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts +++ b/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts @@ -70,6 +70,7 @@ export function createInAppWallet(args: { options, createOptions, connector, + ecosystem, ); // set the states @@ -96,6 +97,7 @@ export function createInAppWallet(args: { options, createOptions, connector, + ecosystem, ); // set the states client = options.client; @@ -142,6 +144,7 @@ export function createInAppWallet(args: { }, createOptions, connector, + ecosystem, ); account = connectedAccount; chain = connectedChain; diff --git a/packages/thirdweb/src/wallets/in-app/core/wallet/index.ts b/packages/thirdweb/src/wallets/in-app/core/wallet/index.ts index cd21db10632..9b508436a01 100644 --- a/packages/thirdweb/src/wallets/in-app/core/wallet/index.ts +++ b/packages/thirdweb/src/wallets/in-app/core/wallet/index.ts @@ -1,10 +1,12 @@ import { ethereum } from "../../../../chains/chain-definitions/ethereum.js"; import type { Chain } from "../../../../chains/types.js"; +import { getCachedChain } from "../../../../chains/utils.js"; import type { ThirdwebClient } from "../../../../client/client.js"; import { type SocialAuthOption, socialAuthOptions, } from "../../../../wallets/types.js"; +import { getEcosystemOptions } from "../../../ecosystem/get-ecosystem-wallet-auth-options.js"; import type { Account, Wallet } from "../../../interfaces/wallet.js"; import type { EcosystemWalletId, WalletId } from "../../../wallet-types.js"; import type { @@ -13,6 +15,7 @@ import type { WalletConnectionOption, } from "../../../wallet-types.js"; import type { InAppConnector } from "../interfaces/connector.js"; +import type { Ecosystem } from "./types.js"; /** * Checks if the provided wallet is an in-app wallet. @@ -37,6 +40,7 @@ export async function connectInAppWallet( | CreateWalletArgs<"inApp">[1] | CreateWalletArgs[1], connector: InAppConnector, + ecosystem: Ecosystem | undefined, ): Promise<[Account, Chain]> { if ( // if auth mode is not specified, the default is popup @@ -73,6 +77,33 @@ export async function connectInAppWallet( }); } + if (ecosystem) { + const ecosystemOptions = await getEcosystemOptions(ecosystem.id); + const smartAccountOptions = ecosystemOptions?.smartAccountOptions; + if (smartAccountOptions) { + const allowedChains = smartAccountOptions.chainIds; + const firstAllowedChain = allowedChains[0]; + if (!firstAllowedChain) { + throw new Error( + "At least one chain must be allowed for ecosystem smart account", + ); + } + const preferredChain = + options.chain && allowedChains.includes(options.chain.id) + ? options.chain + : getCachedChain(firstAllowedChain); + return convertToSmartAccount({ + client: options.client, + authAccount, + smartAccountOptions: { + chain: preferredChain, + sponsorGas: smartAccountOptions.sponsorGas, + factoryAddress: smartAccountOptions.accountFactoryAddress, + }, + }); + } + } + return [authAccount, options.chain || ethereum] as const; } @@ -87,6 +118,7 @@ export async function autoConnectInAppWallet( | CreateWalletArgs<"inApp">[1] | CreateWalletArgs[1], connector: InAppConnector, + ecosystem: Ecosystem | undefined, ): Promise<[Account, Chain]> { if (options.authResult && connector.loginWithAuthToken) { await connector.loginWithAuthToken(options.authResult); @@ -112,6 +144,33 @@ export async function autoConnectInAppWallet( }); } + if (ecosystem) { + const ecosystemOptions = await getEcosystemOptions(ecosystem.id); + const smartAccountOptions = ecosystemOptions?.smartAccountOptions; + if (smartAccountOptions) { + const allowedChains = smartAccountOptions.chainIds; + const firstAllowedChain = allowedChains[0]; + if (!firstAllowedChain) { + throw new Error( + "At least one chain must be allowed for ecosystem smart account", + ); + } + const preferredChain = + options.chain && allowedChains.includes(options.chain.id) + ? options.chain + : getCachedChain(firstAllowedChain); + return convertToSmartAccount({ + client: options.client, + authAccount, + smartAccountOptions: { + chain: preferredChain, + sponsorGas: smartAccountOptions.sponsorGas, + factoryAddress: smartAccountOptions.accountFactoryAddress, + }, + }); + } + } + return [authAccount, options.chain || ethereum] as const; }