From 57ec5410d04cb11c4f81fef82fe2e4c69f431b25 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 17:41:16 -0300 Subject: [PATCH 1/7] feat: add options for default account types --- packages/appkit/src/client.ts | 1 + packages/appkit/src/utils/TypesUtil.ts | 7 +++++- packages/appkit/tests/appkit.test.ts | 15 +++++++++++ .../core/src/controllers/OptionsController.ts | 25 ++++++++++++++++++- packages/core/src/utils/TypeUtil.ts | 6 +++++ .../controllers/OptionsController.test.ts | 18 ++++++++++++- 6 files changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/appkit/src/client.ts b/packages/appkit/src/client.ts index a11541018b..662488a2f1 100644 --- a/packages/appkit/src/client.ts +++ b/packages/appkit/src/client.ts @@ -733,6 +733,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) { diff --git a/packages/appkit/src/utils/TypesUtil.ts b/packages/appkit/src/utils/TypesUtil.ts index a18a3efc33..253470b739 100644 --- a/packages/appkit/src/utils/TypesUtil.ts +++ b/packages/appkit/src/utils/TypesUtil.ts @@ -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 +} & Omit diff --git a/packages/appkit/tests/appkit.test.ts b/packages/appkit/tests/appkit.test.ts index f0ada099b2..3e5a9a02e8 100644 --- a/packages/appkit/tests/appkit.test.ts +++ b/packages/appkit/tests/appkit.test.ts @@ -128,6 +128,21 @@ describe('Base', () => { expect(OptionsController.setEIP6963Enabled).toHaveBeenCalledWith(false) }) + + it('should set partially defaultAccountType', () => { + new AppKit({ + ...mockOptions, + defaultAccountTypes: { + eip155: 'eoa', + bip122: 'ordinals' + } + }) + + expect(OptionsController.setDefaultAccountTypes).toHaveBeenCalledWith({ + eip155: 'eoa', + bip122: 'ordinals' + }) + }) }) describe('Base Public methods', () => { diff --git a/packages/core/src/controllers/OptionsController.ts b/packages/core/src/controllers/OptionsController.ts index fdb458ee5f..8c7e7ecc32 100644 --- a/packages/core/src/controllers/OptionsController.ts +++ b/packages/core/src/controllers/OptionsController.ts @@ -3,6 +3,7 @@ import { proxy } from 'valtio/vanilla' import type { ConnectMethod, CustomWallet, + DefaultAccountTypes, Features, Metadata, ProjectId, @@ -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 { @@ -159,7 +165,13 @@ const state = proxy({ features: ConstantsUtil.DEFAULT_FEATURES, projectId: '', sdkType: 'appkit', - sdkVersion: 'html-wagmi-undefined' + sdkVersion: 'html-wagmi-undefined', + defaultAccountTypes: { + bip122: 'payment', + eip155: 'smartAccount', + polkadot: 'eoa', + solana: 'eoa' + } }) // -- Controller ---------------------------------------- // @@ -317,5 +329,16 @@ export const OptionsController = { useInjectedUniversalProvider: OptionsControllerState['useInjectedUniversalProvider'] ) { state.useInjectedUniversalProvider = useInjectedUniversalProvider + }, + + setDefaultAccountTypes( + defaultAccountType: Partial = {} + ) { + Object.entries(defaultAccountType).forEach(([namespace, accountType]) => { + if (accountType) { + // @ts-expect-error - Keys are validated by the param type + state.defaultAccountTypes[namespace] = accountType + } + }) } } diff --git a/packages/core/src/utils/TypeUtil.ts b/packages/core/src/utils/TypeUtil.ts index 8edd46fd3a..c66ccef55c 100644 --- a/packages/core/src/utils/TypeUtil.ts +++ b/packages/core/src/utils/TypeUtil.ts @@ -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] } diff --git a/packages/core/tests/controllers/OptionsController.test.ts b/packages/core/tests/controllers/OptionsController.test.ts index 5de9895b1d..06a8557b33 100644 --- a/packages/core/tests/controllers/OptionsController.test.ts +++ b/packages/core/tests/controllers/OptionsController.test.ts @@ -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' + } }) }) @@ -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' + }) + }) }) From e9164c189a45db18b5976d71a1ad7de6e751ddb5 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 17:55:25 -0300 Subject: [PATCH 2/7] refactor: set default accounts types constant --- packages/core/src/controllers/OptionsController.ts | 7 +------ packages/core/src/utils/ConstantsUtil.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/core/src/controllers/OptionsController.ts b/packages/core/src/controllers/OptionsController.ts index 8c7e7ecc32..2b05f57d30 100644 --- a/packages/core/src/controllers/OptionsController.ts +++ b/packages/core/src/controllers/OptionsController.ts @@ -166,12 +166,7 @@ const state = proxy({ projectId: '', sdkType: 'appkit', sdkVersion: 'html-wagmi-undefined', - defaultAccountTypes: { - bip122: 'payment', - eip155: 'smartAccount', - polkadot: 'eoa', - solana: 'eoa' - } + defaultAccountTypes: ConstantsUtil.DEFAULT_ACCOUNT_TYPES }) // -- Controller ---------------------------------------- // diff --git a/packages/core/src/utils/ConstantsUtil.ts b/packages/core/src/utils/ConstantsUtil.ts index 2a65154ae4..ea440024b9 100644 --- a/packages/core/src/utils/ConstantsUtil.ts +++ b/packages/core/src/utils/ConstantsUtil.ts @@ -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' @@ -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 } From bd808cfcc777eec7bed54aea42040595ca2d6d8d Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 18:34:51 -0300 Subject: [PATCH 3/7] feat: use default account type for auth --- packages/appkit/src/client.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/appkit/src/client.ts b/packages/appkit/src/client.ts index 662488a2f1..16da6311e4 100644 --- a/packages/appkit/src/client.ts +++ b/packages/appkit/src/client.ts @@ -70,7 +70,7 @@ import { import { W3mFrameHelpers, W3mFrameRpcConstants, - type W3mFrameProvider, + W3mFrameProvider, type W3mFrameTypes } from '@reown/appkit-wallet' import { ProviderUtil, type ProviderStoreUtilState } from './store/ProviderUtil.js' @@ -1253,14 +1253,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] 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] ) ) From 284b907a486496cf773daf03fdf8b2f30f06e7d4 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 19:16:43 -0300 Subject: [PATCH 4/7] feat: use preferred account type from get user request --- packages/adapters/ethers/src/client.ts | 14 ++++++++++---- packages/adapters/ethers5/src/client.ts | 14 ++++++++++---- .../adapters/wagmi/src/connectors/AuthConnector.ts | 10 +++++++--- packages/appkit/src/utils/TypesUtil.ts | 2 +- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/adapters/ethers/src/client.ts b/packages/adapters/ethers/src/client.ts index f161f4782f..1077f27637 100644 --- a/packages/adapters/ethers/src/client.ts +++ b/packages/adapters/ethers/src/client.ts @@ -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' @@ -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] @@ -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 + }) } } @@ -531,7 +536,8 @@ export class EthersAdapter extends AdapterBlueprint { const authProvider = provider as W3mFrameProvider await authProvider.switchNetwork(caipNetwork.id) await authProvider.connect({ - chainId: caipNetwork.id + chainId: caipNetwork.id, + preferredAccountType: OptionsController.state.defaultAccountTypes.eip155 }) } else { try { diff --git a/packages/adapters/ethers5/src/client.ts b/packages/adapters/ethers5/src/client.ts index ccd3c042ee..478ab23391 100644 --- a/packages/adapters/ethers5/src/client.ts +++ b/packages/adapters/ethers5/src/client.ts @@ -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' @@ -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] @@ -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 + }) } } @@ -534,7 +539,8 @@ export class Ethers5Adapter extends AdapterBlueprint { const authProvider = provider as W3mFrameProvider await authProvider.switchNetwork(caipNetwork.id) await authProvider.connect({ - chainId: caipNetwork.id + chainId: caipNetwork.id, + preferredAccountType: OptionsController.state.defaultAccountTypes.eip155 }) } else { try { diff --git a/packages/adapters/wagmi/src/connectors/AuthConnector.ts b/packages/adapters/wagmi/src/connectors/AuthConnector.ts index a290bb4aa9..6423ce31f4 100644 --- a/packages/adapters/wagmi/src/connectors/AuthConnector.ts +++ b/packages/adapters/wagmi/src/connectors/AuthConnector.ts @@ -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 { @@ -52,7 +52,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] @@ -122,7 +123,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 diff --git a/packages/appkit/src/utils/TypesUtil.ts b/packages/appkit/src/utils/TypesUtil.ts index 253470b739..8ea8cabdd8 100644 --- a/packages/appkit/src/utils/TypesUtil.ts +++ b/packages/appkit/src/utils/TypesUtil.ts @@ -84,4 +84,4 @@ export type AppKitOptions = { * @default "{ bip122: 'payment', eip155: 'smartAccount', polkadot: 'eoa', solana: 'eoa' }" */ defaultAccountTypes?: Partial -} & Omit +} & Omit From c83efd9ab2a3a368558d21fe011cc1dc63516b41 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 19:20:04 -0300 Subject: [PATCH 5/7] chore: add changeset --- .changeset/nine-frogs-drive.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .changeset/nine-frogs-drive.md diff --git a/.changeset/nine-frogs-drive.md b/.changeset/nine-frogs-drive.md new file mode 100644 index 0000000000..00b9cd3f4f --- /dev/null +++ b/.changeset/nine-frogs-drive.md @@ -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. From 55879a72fd1b143626dece3dc6f64d637d64c5c1 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Thu, 9 Jan 2025 19:29:00 -0300 Subject: [PATCH 6/7] fix: wrong typing --- packages/appkit/src/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/appkit/src/client.ts b/packages/appkit/src/client.ts index 16da6311e4..86834e6c87 100644 --- a/packages/appkit/src/client.ts +++ b/packages/appkit/src/client.ts @@ -1253,8 +1253,8 @@ export class AppKit { this.setUser({ ...(AccountController.state.user || {}), email: user.email }) - const preferredAccountType = - user.preferredAccountType || OptionsController.state.defaultAccountTypes[namespace] + const preferredAccountType = (user.preferredAccountType || + OptionsController.state.defaultAccountTypes[namespace]) as W3mFrameTypes.AccountType this.setPreferredAccountType(preferredAccountType, namespace) const userAccounts = user.accounts?.map(account => From c6cab6afb3cd649fe719ef6059de2681eb527324 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Fri, 10 Jan 2025 18:03:47 -0300 Subject: [PATCH 7/7] fix: broken tests --- packages/adapters/ethers/src/tests/client.test.ts | 5 ++++- packages/adapters/ethers5/src/tests/client.test.ts | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/adapters/ethers/src/tests/client.test.ts b/packages/adapters/ethers/src/tests/client.test.ts index 5d03f8615e..c27a43ea9e 100644 --- a/packages/adapters/ethers/src/tests/client.test.ts +++ b/packages/adapters/ethers/src/tests/client.test.ts @@ -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 () => { diff --git a/packages/adapters/ethers5/src/tests/client.test.ts b/packages/adapters/ethers5/src/tests/client.test.ts index e2b5b2a216..4996f99c6b 100644 --- a/packages/adapters/ethers5/src/tests/client.test.ts +++ b/packages/adapters/ethers5/src/tests/client.test.ts @@ -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' + }) }) })