Skip to content
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

chore: add authProvider field to useAppKitAccount and serialize correct provider in appkit.getProvider #3611

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
23 changes: 23 additions & 0 deletions .changeset/nervous-bugs-brake.md
Original file line number Diff line number Diff line change
@@ -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.
23 changes: 23 additions & 0 deletions .changeset/unlucky-islands-juggle.md
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion apps/laboratory/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
22 changes: 12 additions & 10 deletions packages/appkit/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,22 @@ export class AppKit {
}

public subscribeAccount(callback: (newState: UseAppKitAccountReturn) => void) {
const authConnector = ConnectorController.getAuthConnector()
function updateVal() {
callback({
allAccounts: AccountController.state.allAccounts,
caipAddress: ChainController.state.activeCaipAddress,
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
})
}

Expand Down Expand Up @@ -451,7 +455,9 @@ export class AppKit {
return ChainController.getAccountProp('address', chainNamespace)
}

public getProvider = () => AccountController.state.provider
public getProvider = <T>(namespace: ChainNamespace) => ProviderUtil.getProvider<T>(namespace)

public getProviderType = (namespace: ChainNamespace) => ProviderUtil.state.providerIds[namespace]

public getPreferredAccountType = () =>
AccountController.state.preferredAccountType as W3mFrameTypes.AccountType
Expand All @@ -460,10 +466,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)
}
Expand Down
17 changes: 5 additions & 12 deletions packages/appkit/tests/appkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
ConnectionController,
EnsController,
EventsController,
type CombinedProvider,
AssetUtil,
ConnectorController,
ChainController,
Expand Down Expand Up @@ -322,9 +321,11 @@
})

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
Copy link
Contributor

Choose a reason for hiding this comment

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

Possible to use vi.spyOn ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

tried but it was not working. I think spyiong on state.get works for snapshotting, but not when you query the state directly like in this case

vi.mocked(ProviderUtil.state).providerIds = { eip155: 'INJECTED' } as any

expect(appKit.getProvider<any>('eip155')).toBe(mockProvider)
})

it('should get preferred account type', () => {
Expand All @@ -347,14 +348,6 @@
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')
Expand Down Expand Up @@ -743,7 +736,7 @@

await appKit['syncAccount'](mockAccountData)

expect(AccountController.setConnectedWalletInfo).toHaveBeenCalledWith(

Check failure on line 739 in packages/appkit/tests/appkit.test.ts

View workflow job for this annotation

GitHub Actions / test

tests/appkit.test.ts > Base > Base Public methods > should set connected wallet info when syncing account

AssertionError: expected "setConnectedWalletInfo" to be called with arguments: [ ObjectContaining{…}, 'eip155' ] Received: 1st setConnectedWalletInfo call: Array [ - ObjectContaining { - "name": "test-wallet", + Object { + "icon": undefined, + "name": undefined, }, "eip155", ] Number of calls: 1 ❯ tests/appkit.test.ts:739:56
expect.objectContaining({
name: mockConnector.id
}),
Expand Down
6 changes: 3 additions & 3 deletions packages/core/exports/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,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)

Expand All @@ -42,6 +41,7 @@ export function useAppKitAccount(): UseAppKitAccountReturn {
embeddedWalletInfo: authConnector
? {
user,
authProvider: socialProvider || 'email',
accountType: preferredAccountType,
isSmartAccountDeployed: Boolean(smartAccountDeployed)
}
Expand Down
45 changes: 29 additions & 16 deletions packages/core/exports/vue.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
import { ref, onUnmounted } from 'vue'
import { ref, onUnmounted, type Ref } from 'vue'
import { AccountController } from '../src/controllers/AccountController.js'
import { CoreHelperUtil } from '../src/utils/CoreHelperUtil.js'
import { ChainController } from '../src/controllers/ChainController.js'
import { ConnectionController } from '../src/controllers/ConnectionController.js'
import { ConnectorController } from '../src/controllers/ConnectorController.js'
import type { SocialProvider, UseAppKitAccountReturn } from '../src/utils/TypeUtil.js'

// -- Hooks ------------------------------------------------------------
export function useAppKitAccount() {
export function useAppKitAccount(): Ref<UseAppKitAccountReturn> {
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 => {
state.value.allAccounts = [...val]
})

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(() => {
Expand Down
10 changes: 0 additions & 10 deletions packages/core/src/controllers/AccountController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { CoreHelperUtil } from '../utils/CoreHelperUtil.js'
import type {
AccountType,
AccountTypeMap,
CombinedProvider,
ConnectedWalletInfo,
User,
Provider,
SocialProvider
} from '../utils/TypeUtil.js'
import type { CaipAddress, ChainNamespace } from '@reown/appkit-common'
Expand All @@ -17,7 +15,6 @@ import { SwapApiUtil } from '../utils/SwapApiUtil.js'
import type { W3mFrameTypes } from '@reown/appkit-wallet'
import { ChainController } from './ChainController.js'
import { proxy, ref } from 'valtio/vanilla'
import type UniversalProvider from '@walletconnect/universal-provider'
import { ConstantsUtil } from '../utils/ConstantsUtil.js'

// -- Types --------------------------------------------- //
Expand All @@ -41,7 +38,6 @@ export interface AccountControllerState {
preferredAccountType?: W3mFrameTypes.AccountType
socialWindow?: Window
farcasterUrl?: string
provider?: UniversalProvider | Provider | CombinedProvider
status?: 'reconnecting' | 'connected' | 'disconnected' | 'connecting'
lastRetry?: number
}
Expand Down Expand Up @@ -109,12 +105,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
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/utils/TypeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,7 @@ export type UseAppKitAccountReturn = {
isConnected: boolean
embeddedWalletInfo?: {
user: AccountControllerState['user']
authProvider: AccountControllerState['socialProvider'] | 'email'
accountType: W3mFrameTypes.AccountType | undefined
isSmartAccountDeployed: boolean
}
Expand Down
44 changes: 44 additions & 0 deletions packages/core/tests/hooks/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,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'
}
Expand Down
Loading