diff --git a/.changeset/nervous-bugs-brake.md b/.changeset/nervous-bugs-brake.md new file mode 100644 index 0000000000..9ecbf4c72f --- /dev/null +++ b/.changeset/nervous-bugs-brake.md @@ -0,0 +1,23 @@ +--- +'@reown/appkit': patch +'@reown/appkit-core': patch +'@reown/appkit-adapter-bitcoin': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-cli': patch +'@reown/appkit-common': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-siwx': patch +'@reown/appkit-ui': patch +'@reown/appkit-wallet': patch +'@reown/appkit-wallet-button': patch +--- + +Fixes issue where appKit.getProvider() would not return correct provider. diff --git a/.changeset/unlucky-islands-juggle.md b/.changeset/unlucky-islands-juggle.md new file mode 100644 index 0000000000..ea2c7db045 --- /dev/null +++ b/.changeset/unlucky-islands-juggle.md @@ -0,0 +1,23 @@ +--- +'@reown/appkit': patch +'@reown/appkit-core': patch +'@reown/appkit-adapter-bitcoin': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-cli': patch +'@reown/appkit-common': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit-siwe': patch +'@reown/appkit-siwx': patch +'@reown/appkit-ui': patch +'@reown/appkit-wallet': patch +'@reown/appkit-wallet-button': patch +--- + +Adds authProvider to embeddedWalletInfo in useAppKitAccount diff --git a/packages/appkit/src/client.ts b/packages/appkit/src/client.ts index f25b4b97a6..59e1e6425f 100644 --- a/packages/appkit/src/client.ts +++ b/packages/appkit/src/client.ts @@ -285,6 +285,7 @@ export class AppKit { } public subscribeAccount(callback: (newState: UseAppKitAccountReturn) => void) { + const authConnector = ConnectorController.getAuthConnector() function updateVal() { callback({ allAccounts: AccountController.state.allAccounts, @@ -292,11 +293,14 @@ export class AppKit { address: CoreHelperUtil.getPlainAddress(ChainController.state.activeCaipAddress), isConnected: Boolean(ChainController.state.activeCaipAddress), status: AccountController.state.status, - embeddedWalletInfo: { - user: AccountController.state.user, - accountType: AccountController.state.preferredAccountType, - isSmartAccountDeployed: Boolean(AccountController.state.smartAccountDeployed) - } + embeddedWalletInfo: authConnector + ? { + user: AccountController.state.user, + authProvider: AccountController.state.socialProvider || 'email', + accountType: AccountController.state.preferredAccountType, + isSmartAccountDeployed: Boolean(AccountController.state.smartAccountDeployed) + } + : undefined }) } @@ -424,7 +428,9 @@ export class AppKit { return ChainController.getAccountProp('address', chainNamespace) } - public getProvider = () => AccountController.state.provider + public getProvider = (namespace: ChainNamespace) => ProviderUtil.getProvider(namespace) + + public getProviderType = (namespace: ChainNamespace) => ProviderUtil.state.providerIds[namespace] public getPreferredAccountType = () => AccountController.state.preferredAccountType as W3mFrameTypes.AccountType @@ -433,10 +439,6 @@ export class AppKit { AccountController.setCaipAddress(caipAddress, chain) } - public setProvider: (typeof AccountController)['setProvider'] = (provider, chain) => { - AccountController.setProvider(provider, chain) - } - public setBalance: (typeof AccountController)['setBalance'] = (balance, balanceSymbol, chain) => { AccountController.setBalance(balance, balanceSymbol, chain) } @@ -1643,7 +1645,8 @@ export class AppKit { private syncConnectedWalletInfo(chainNamespace: ChainNamespace) { const connectorId = StorageUtil.getConnectedConnectorId(chainNamespace) - const providerType = ProviderUtil.state.providerIds[chainNamespace] + const providerType = ProviderUtil.getProviderId(chainNamespace) + if ( providerType === UtilConstantsUtil.CONNECTOR_TYPE_ANNOUNCED || providerType === UtilConstantsUtil.CONNECTOR_TYPE_INJECTED diff --git a/packages/appkit/tests/appkit.test.ts b/packages/appkit/tests/appkit.test.ts index 43446f03fe..f1d53047ff 100644 --- a/packages/appkit/tests/appkit.test.ts +++ b/packages/appkit/tests/appkit.test.ts @@ -20,7 +20,6 @@ import { type ChainAdapter, ChainController, type ChainControllerState, - type CombinedProvider, ConnectionController, type Connector, ConnectorController, @@ -353,9 +352,11 @@ describe('Base', () => { }) it('should get provider', () => { - const mockProvider = { request: vi.fn() } - vi.mocked(AccountController).state = { provider: mockProvider } as any - expect(appKit.getProvider()).toBe(mockProvider) + const mockProvider = vi.fn() + vi.mocked(ProviderUtil.state).providers = { eip155: mockProvider } as any + vi.mocked(ProviderUtil.state).providerIds = { eip155: 'INJECTED' } as any + + expect(appKit.getProvider('eip155')).toBe(mockProvider) }) it('should get preferred account type', () => { @@ -376,14 +377,6 @@ describe('Base', () => { expect(appKit.getIsConnectedState()).toBe(true) }) - it('should set provider', () => { - const mockProvider = { - request: vi.fn() - } - appKit.setProvider(mockProvider as unknown as CombinedProvider, 'eip155') - expect(AccountController.setProvider).toHaveBeenCalledWith(mockProvider, 'eip155') - }) - it('should set balance', () => { appKit.setBalance('1.5', 'ETH', 'eip155') expect(AccountController.setBalance).toHaveBeenCalledWith('1.5', 'ETH', 'eip155') @@ -730,7 +723,9 @@ describe('Base', () => { vi.mocked(appKit as any).caipNetworks = [mainnet] // Mock the connector data const mockConnector = { - id: 'test-wallet' + id: 'test-wallet', + name: 'Test Wallet', + imageUrl: 'test-wallet-icon' } as Connector vi.mocked(ConnectorController.getConnectors).mockReturnValue([mockConnector]) @@ -752,7 +747,8 @@ describe('Base', () => { expect(AccountController.setConnectedWalletInfo).toHaveBeenCalledWith( expect.objectContaining({ - name: mockConnector.id + name: mockConnector.name, + icon: mockConnector.imageUrl }), 'eip155' ) diff --git a/packages/core/exports/react.ts b/packages/core/exports/react.ts index 22289c754b..9fee680ded 100644 --- a/packages/core/exports/react.ts +++ b/packages/core/exports/react.ts @@ -26,9 +26,8 @@ export function useAppKitNetworkCore(): Pick< } export function useAppKitAccount(): UseAppKitAccountReturn { - const { status, user, preferredAccountType, smartAccountDeployed, allAccounts } = useSnapshot( - AccountController.state - ) + const { status, user, preferredAccountType, smartAccountDeployed, allAccounts, socialProvider } = + useSnapshot(AccountController.state) const { activeCaipAddress } = useSnapshot(ChainController.state) @@ -43,6 +42,7 @@ export function useAppKitAccount(): UseAppKitAccountReturn { embeddedWalletInfo: authConnector ? { user, + authProvider: socialProvider || 'email', accountType: preferredAccountType, isSmartAccountDeployed: Boolean(smartAccountDeployed) } diff --git a/packages/core/exports/vue.ts b/packages/core/exports/vue.ts index 4b5e59b78d..dc1f8602a1 100644 --- a/packages/core/exports/vue.ts +++ b/packages/core/exports/vue.ts @@ -1,33 +1,40 @@ -import { onUnmounted, ref } from 'vue' +import { type Ref, onUnmounted, ref } from 'vue' import { AccountController } from '../src/controllers/AccountController.js' import { ChainController } from '../src/controllers/ChainController.js' import { ConnectionController } from '../src/controllers/ConnectionController.js' +import { ConnectorController } from '../src/controllers/ConnectorController.js' import { CoreHelperUtil } from '../src/utils/CoreHelperUtil.js' +import type { SocialProvider, UseAppKitAccountReturn } from '../src/utils/TypeUtil.js' // -- Hooks ------------------------------------------------------------ -export function useAppKitAccount() { +export function useAppKitAccount(): Ref { + const authConnector = ConnectorController.getAuthConnector() const state = ref({ allAccounts: AccountController.state.allAccounts, - address: CoreHelperUtil.getPlainAddress(ChainController.state.activeCaipAddress) ?? null, - caipAddress: ChainController.state.activeCaipAddress ?? null, - status: AccountController.state.status ?? null, + address: CoreHelperUtil.getPlainAddress(ChainController.state.activeCaipAddress), + caipAddress: ChainController.state.activeCaipAddress, + status: AccountController.state.status, isConnected: Boolean(ChainController.state.activeCaipAddress), - embeddedWalletInfo: { - user: AccountController.state.user ?? null, - accountType: AccountController.state.preferredAccountType ?? null, - isSmartAccountDeployed: Boolean(AccountController.state.smartAccountDeployed) - } + embeddedWalletInfo: authConnector + ? { + user: AccountController.state.user, + authProvider: + AccountController.state.socialProvider ?? ('email' as SocialProvider | 'email'), + accountType: AccountController.state.preferredAccountType, + isSmartAccountDeployed: Boolean(AccountController.state.smartAccountDeployed) + } + : undefined }) const unsubscribeCaipAddress = ChainController.subscribeKey('activeCaipAddress', val => { - state.value.caipAddress = val ?? null - state.value.address = CoreHelperUtil.getPlainAddress(val) ?? null + state.value.caipAddress = val + state.value.address = CoreHelperUtil.getPlainAddress(val) state.value.isConnected = Boolean(val) }) const unsubscribeStatus = AccountController.subscribeKey('status', val => { - state.value.status = val ?? null + state.value.status = val }) const unsubscribeAllAccounts = AccountController.subscribeKey('allAccounts', val => { @@ -35,15 +42,21 @@ export function useAppKitAccount() { }) const unsubscribeAccountDeployed = AccountController.subscribeKey('smartAccountDeployed', val => { - state.value.embeddedWalletInfo.isSmartAccountDeployed = Boolean(val) + if (state.value.embeddedWalletInfo) { + state.value.embeddedWalletInfo.isSmartAccountDeployed = Boolean(val) + } }) const unsubscribeAccountType = AccountController.subscribeKey('preferredAccountType', val => { - state.value.embeddedWalletInfo.accountType = val ?? null + if (state.value.embeddedWalletInfo) { + state.value.embeddedWalletInfo.accountType = val + } }) const unsubscribeUser = AccountController.subscribeKey('user', val => { - state.value.embeddedWalletInfo.user = val ?? null + if (state.value.embeddedWalletInfo) { + state.value.embeddedWalletInfo.user = val + } }) onUnmounted(() => { diff --git a/packages/core/src/controllers/AccountController.ts b/packages/core/src/controllers/AccountController.ts index 361e5d990d..e0331c60fd 100644 --- a/packages/core/src/controllers/AccountController.ts +++ b/packages/core/src/controllers/AccountController.ts @@ -1,4 +1,3 @@ -import type UniversalProvider from '@walletconnect/universal-provider' import { proxy, ref } from 'valtio/vanilla' import type { CaipAddress, ChainNamespace } from '@reown/appkit-common' @@ -11,9 +10,7 @@ import { SwapApiUtil } from '../utils/SwapApiUtil.js' import type { AccountType, AccountTypeMap, - CombinedProvider, ConnectedWalletInfo, - Provider, SocialProvider, User } from '../utils/TypeUtil.js' @@ -43,7 +40,6 @@ export interface AccountControllerState { preferredAccountType?: W3mFrameTypes.AccountType socialWindow?: Window farcasterUrl?: string - provider?: UniversalProvider | Provider | CombinedProvider status?: 'reconnecting' | 'connected' | 'disconnected' | 'connecting' lastRetry?: number } @@ -111,12 +107,6 @@ export const AccountController = { return ChainController.getAccountProp('caipAddress', chain) }, - setProvider(provider: AccountControllerState['provider'], chain: ChainNamespace | undefined) { - if (provider) { - ChainController.setAccountProp('provider', provider, chain) - } - }, - setCaipAddress( caipAddress: AccountControllerState['caipAddress'], chain: ChainNamespace | undefined diff --git a/packages/core/src/utils/TypeUtil.ts b/packages/core/src/utils/TypeUtil.ts index 4eb4b34b7f..55f994c3ab 100644 --- a/packages/core/src/utils/TypeUtil.ts +++ b/packages/core/src/utils/TypeUtil.ts @@ -1105,6 +1105,7 @@ export type UseAppKitAccountReturn = { isConnected: boolean embeddedWalletInfo?: { user: AccountControllerState['user'] + authProvider: AccountControllerState['socialProvider'] | 'email' accountType: W3mFrameTypes.AccountType | undefined isSmartAccountDeployed: boolean } diff --git a/packages/core/tests/hooks/react.test.ts b/packages/core/tests/hooks/react.test.ts index e06fe1488c..ed96f359de 100644 --- a/packages/core/tests/hooks/react.test.ts +++ b/packages/core/tests/hooks/react.test.ts @@ -115,6 +115,50 @@ describe('useAppKitAccount', () => { email: 'email@email.test', userName: 'test' }, + authProvider: 'email', + isSmartAccountDeployed: false, + accountType: 'eoa' + } + }) + + expect(useSnapshot).toHaveBeenCalledWith(AccountController.state) + expect(useSnapshot).toHaveBeenCalledWith(ChainController.state) + }) + + it('should return appropiate auth provider when social provider is set', () => { + const mockCaipAddress = 'eip155:1:0x123...' + const mockPlainAddress = '0x123...' + + vi.spyOn(ConnectorController, 'getAuthConnector').mockReturnValue({} as any) + + // Mock the useSnapshot hook for both calls + useSnapshot + .mockReturnValueOnce({ + allAccounts: undefined, + status: 'connected', + socialProvider: 'google', + preferredAccountType: 'eoa', + smartAccountDeployed: false, + user: { + email: 'email@email.test', + userName: 'test' + } + }) // For AccountController + .mockReturnValueOnce({ activeCaipAddress: mockCaipAddress }) // For ChainController + + const result = useAppKitAccount() + + expect(result).toEqual({ + address: mockPlainAddress, + caipAddress: mockCaipAddress, + isConnected: true, + status: 'connected', + embeddedWalletInfo: { + user: { + email: 'email@email.test', + userName: 'test' + }, + authProvider: 'google', isSmartAccountDeployed: false, accountType: 'eoa' }