Skip to content

Commit

Permalink
feat: default account type option (#3607)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoruka authored Jan 14, 2025
1 parent 6b70aac commit a66de04
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 21 deletions.
23 changes: 23 additions & 0 deletions .changeset/nine-frogs-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit': patch
'@reown/appkit-core': patch
'@reown/appkit-adapter-bitcoin': patch
'@reown/appkit-adapter-solana': 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
---

Add defaultAccountTypes option for AppKit initialization.
11 changes: 8 additions & 3 deletions packages/adapters/ethers/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
type Connector,
type ConnectorType,
type Provider,
CoreHelperUtil
CoreHelperUtil,
OptionsController
} from '@reown/appkit-core'
import { ConstantsUtil, PresetsUtil } from '@reown/appkit-utils'
import { EthersHelpersUtil, type ProviderType } from '@reown/appkit-utils/ethers'
Expand Down Expand Up @@ -346,7 +347,8 @@ export class EthersAdapter extends AdapterBlueprint {

if (type === 'AUTH') {
const { address } = await (selectedProvider as unknown as W3mFrameProvider).connect({
chainId
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})

accounts = [address]
Expand Down Expand Up @@ -377,7 +379,10 @@ export class EthersAdapter extends AdapterBlueprint {
const connector = this.connectors.find(c => c.id === id)

if (connector && connector.type === 'AUTH' && chainId) {
await (connector.provider as W3mFrameProvider).connect({ chainId })
await (connector.provider as W3mFrameProvider).connect({
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})
}
}

Expand Down
5 changes: 4 additions & 1 deletion packages/adapters/ethers/src/tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,10 @@ describe('EthersAdapter', () => {
})

expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith('eip155:1')
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({ chainId: 'eip155:1' })
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({
chainId: 'eip155:1',
preferredAccountType: 'smartAccount'
})
})

it('should add Ethereum chain with external provider and use chain default', async () => {
Expand Down
11 changes: 8 additions & 3 deletions packages/adapters/ethers5/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
type CombinedProvider,
type Connector,
type ConnectorType,
type Provider
type Provider,
OptionsController
} from '@reown/appkit-core'
import { ConstantsUtil, PresetsUtil } from '@reown/appkit-utils'
import { EthersHelpersUtil, type ProviderType } from '@reown/appkit-utils/ethers'
Expand Down Expand Up @@ -346,7 +347,8 @@ export class Ethers5Adapter extends AdapterBlueprint {

if (type === 'AUTH') {
const { address } = await (selectedProvider as unknown as W3mFrameProvider).connect({
chainId
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})

accounts = [address]
Expand Down Expand Up @@ -407,7 +409,10 @@ export class Ethers5Adapter extends AdapterBlueprint {
const connector = this.connectors.find(c => c.id === id)

if (connector && connector.type === 'AUTH' && chainId) {
await (connector.provider as W3mFrameProvider).connect({ chainId })
await (connector.provider as W3mFrameProvider).connect({
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})
}
}

Expand Down
5 changes: 4 additions & 1 deletion packages/adapters/ethers5/src/tests/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,10 @@ describe('Ethers5Adapter', () => {
})

expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith('eip155:1')
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({ chainId: 'eip155:1' })
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({
chainId: 'eip155:1',
preferredAccountType: 'smartAccount'
})
})
})

Expand Down
10 changes: 7 additions & 3 deletions packages/adapters/wagmi/src/connectors/AuthConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { Address } from 'viem'
import { ErrorUtil } from '@reown/appkit-utils'
import { NetworkUtil } from '@reown/appkit-common'
import { W3mFrameProviderSingleton } from '@reown/appkit/auth-provider'
import { AlertController } from '@reown/appkit-core'
import { AlertController, OptionsController } from '@reown/appkit-core'

// -- Types ----------------------------------------------------------------------------------------
interface W3mFrameProviderOptions {
Expand Down Expand Up @@ -56,7 +56,8 @@ export function authConnector(parameters: AuthParameters) {
chainId: frameChainId,
accounts
} = await provider.connect({
chainId
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})

currentAccounts = accounts?.map(a => a.address as Address) || [address as Address]
Expand Down Expand Up @@ -126,7 +127,10 @@ export function authConnector(parameters: AuthParameters) {
}
const provider = await this.getProvider()
// We connect instead, since changing the chain may cause the address to change as well
const response = await provider.connect({ chainId })
const response = await provider.connect({
chainId,
preferredAccountType: OptionsController.state.defaultAccountTypes.eip155
})

currentAccounts = response?.accounts?.map(a => a.address as Address) || [
response.address as Address
Expand Down
7 changes: 5 additions & 2 deletions packages/appkit/src/adapters/ChainAdapterBlueprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
type AccountControllerState,
type Connector as AppKitConnector,
type Tokens,
type WriteContractArgs
type WriteContractArgs,
OptionsController
} from '@reown/appkit-core'
import UniversalProvider from '@walletconnect/universal-provider'
import { W3mFrameProvider } from '@reown/appkit-wallet'
Expand Down Expand Up @@ -241,7 +242,9 @@ export abstract class AdapterBlueprint<
const authProvider = provider as W3mFrameProvider
await authProvider.switchNetwork(caipNetwork.caipNetworkId)
const user = await authProvider.getUser({
chainId: caipNetwork.caipNetworkId
chainId: caipNetwork.caipNetworkId,
preferredAccountType:
OptionsController.state.defaultAccountTypes[caipNetwork.chainNamespace]
})

this.emit('switchNetwork', user)
Expand Down
8 changes: 5 additions & 3 deletions packages/appkit/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import {
import {
W3mFrameHelpers,
W3mFrameRpcConstants,
type W3mFrameProvider,
W3mFrameProvider,
type W3mFrameTypes
} from '@reown/appkit-wallet'
import { ProviderUtil, type ProviderStoreUtilState } from './store/ProviderUtil.js'
Expand Down Expand Up @@ -735,6 +735,7 @@ export class AppKit {
OptionsController.setCustomWallets(options.customWallets)
OptionsController.setFeatures(options.features)
OptionsController.setAllowUnsupportedChain(options.allowUnsupportedChain)
OptionsController.setDefaultAccountTypes(options.defaultAccountTypes)

const defaultMetaData = this.getDefaultMetaData()
if (!options.metadata && defaultMetaData) {
Expand Down Expand Up @@ -1242,14 +1243,15 @@ export class AppKit {

this.setUser({ ...(AccountController.state.user || {}), email: user.email })

const preferredAccountType = (user.preferredAccountType || 'eoa') as W3mFrameTypes.AccountType
const preferredAccountType = (user.preferredAccountType ||
OptionsController.state.defaultAccountTypes[namespace]) as W3mFrameTypes.AccountType
this.setPreferredAccountType(preferredAccountType, namespace)

const userAccounts = user.accounts?.map(account =>
CoreHelperUtil.createAccount(
namespace,
account.address,
namespace === ConstantsUtil.CHAIN.EVM ? account.type : 'eoa'
account.type || OptionsController.state.defaultAccountTypes[namespace]
)
)

Expand Down
7 changes: 6 additions & 1 deletion packages/appkit/src/utils/TypesUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ export type AppKitOptions = {
* @default undefined
*/
universalProvider?: UniversalProvider
} & OptionsControllerState
/**
* The default account type used for each chain namespace.
* @default "{ bip122: 'payment', eip155: 'smartAccount', polkadot: 'eoa', solana: 'eoa' }"
*/
defaultAccountTypes?: Partial<OptionsControllerState['defaultAccountTypes']>
} & Omit<OptionsControllerState, 'defaultAccountTypes'>
15 changes: 15 additions & 0 deletions packages/appkit/tests/appkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ describe('Base', () => {

expect(OptionsController.setEIP6963Enabled).toHaveBeenCalledWith(false)
})

it('should set partially defaultAccountType', () => {
new AppKit({
...mockOptions,
defaultAccountTypes: {
eip155: 'eoa',
bip122: 'ordinal'
}
})

expect(OptionsController.setDefaultAccountTypes).toHaveBeenCalledWith({
eip155: 'eoa',
bip122: 'ordinal'
})
})
})

describe('Base Public methods', () => {
Expand Down
20 changes: 19 additions & 1 deletion packages/core/src/controllers/OptionsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { proxy, snapshot } from 'valtio/vanilla'
import type {
ConnectMethod,
CustomWallet,
DefaultAccountTypes,
Features,
Metadata,
ProjectId,
Expand Down Expand Up @@ -140,6 +141,11 @@ export interface OptionsControllerStatePublic {
* @default false
*/
allowUnsupportedChain?: boolean
/**
* Default account types for each namespace.
* @default "{ bip122: 'payment', eip155: 'smartAccount', polkadot: 'eoa', solana: 'eoa' }"
*/
defaultAccountTypes: DefaultAccountTypes
}

export interface OptionsControllerStateInternal {
Expand All @@ -159,7 +165,8 @@ const state = proxy<OptionsControllerState & OptionsControllerStateInternal>({
features: ConstantsUtil.DEFAULT_FEATURES,
projectId: '',
sdkType: 'appkit',
sdkVersion: 'html-wagmi-undefined'
sdkVersion: 'html-wagmi-undefined',
defaultAccountTypes: ConstantsUtil.DEFAULT_ACCOUNT_TYPES
})

// -- Controller ---------------------------------------- //
Expand Down Expand Up @@ -319,6 +326,17 @@ export const OptionsController = {
state.useInjectedUniversalProvider = useInjectedUniversalProvider
},

setDefaultAccountTypes(
defaultAccountType: Partial<OptionsControllerState['defaultAccountTypes']> = {}
) {
Object.entries(defaultAccountType).forEach(([namespace, accountType]) => {
if (accountType) {
// @ts-expect-error - Keys are validated by the param type
state.defaultAccountTypes[namespace] = accountType
}
})
},

getSnapshot() {
return snapshot(state)
}
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/utils/ConstantsUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Features, SocialProvider } from './TypeUtil.js'
import type { DefaultAccountTypes, Features, SocialProvider } from './TypeUtil.js'
import type { ChainNamespace } from '@reown/appkit-common'

const SECURE_SITE = 'https://secure.walletconnect.org'
Expand Down Expand Up @@ -238,5 +238,12 @@ export const ConstantsUtil = {
collapseWallets: false,
walletFeaturesOrder: ['onramp', 'swaps', 'receive', 'send'],
connectMethodsOrder: undefined
} satisfies Features
} satisfies Features,

DEFAULT_ACCOUNT_TYPES: {
bip122: 'payment',
eip155: 'smartAccount',
polkadot: 'eoa',
solana: 'eoa'
} as const satisfies DefaultAccountTypes
}
6 changes: 6 additions & 0 deletions packages/core/src/utils/TypeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1119,3 +1119,9 @@ export type UseAppKitNetworkReturn = {
export type BadgeType = 'none' | 'certified'

export type ConnectionStatus = 'connected' | 'disconnected' | 'connecting' | 'reconnecting'

/**
* @description The default account types for each namespace.
* @default
*/
export type DefaultAccountTypes = { [Key in keyof NamespaceTypeMap]: NamespaceTypeMap[Key] }
18 changes: 17 additions & 1 deletion packages/core/tests/controllers/OptionsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ describe('OptionsController', () => {
features: ConstantsUtil.DEFAULT_FEATURES,
projectId: '',
sdkType: 'appkit',
sdkVersion: 'html-wagmi-undefined'
sdkVersion: 'html-wagmi-undefined',
defaultAccountTypes: {
bip122: 'payment',
eip155: 'smartAccount',
polkadot: 'eoa',
solana: 'eoa'
}
})
})

Expand All @@ -27,4 +33,14 @@ describe('OptionsController', () => {
OptionsController.setAllowUnsupportedChain(true)
expect(OptionsController.state.allowUnsupportedChain).toEqual(true)
})

it('should set defaultAccountType partially and not change if undefined is provided', () => {
OptionsController.setDefaultAccountTypes({ eip155: 'eoa', bip122: undefined })
expect(OptionsController.state.defaultAccountTypes).toEqual({
bip122: 'payment',
eip155: 'eoa',
polkadot: 'eoa',
solana: 'eoa'
})
})
})

0 comments on commit a66de04

Please sign in to comment.