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

fix: ethers5 adapter import in exports #2754

Merged
merged 10 commits into from
Sep 3, 2024
1 change: 1 addition & 0 deletions packages/base/adapters/evm/ethers/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '@web3modal/polyfills'

export { EVMEthersClient } from './client.js'
export * from '@web3modal/scaffold-utils/ethers'
Copy link
Collaborator

Choose a reason for hiding this comment

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

is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we are connecting to the EthersStoreUtil from the backwards compat packages' custom hooks, see. To make the ethers and base package use the same proxy object (state), the @web3modal/scaffold-utils/ethers needed to be exported from the adapter. Otherwise throwing this pmndrs/valtio#706 error.


// -- Types
export type { AdapterOptions } from './client.js'
Expand Down
215 changes: 213 additions & 2 deletions packages/base/adapters/evm/ethers5/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {
EthersHelpersUtil,
EthersStoreUtil
} from '@web3modal/scaffold-utils/ethers'
import { W3mFrameProvider, W3mFrameHelpers, W3mFrameRpcConstants } from '@web3modal/wallet'
import type { W3mFrameTypes } from '@web3modal/wallet'
import type { CombinedProvider } from '@web3modal/scaffold-utils/ethers'
import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider'
import { NetworkUtil } from '@web3modal/common'
import type { Chain as AvailableChain } from '@web3modal/common'
Expand Down Expand Up @@ -103,6 +106,8 @@ export class EVMEthers5Client {

private metadata?: Metadata

private authProvider?: W3mFrameProvider

public networkControllerClient: NetworkControllerClient

public connectionControllerClient: ConnectionControllerClient
Expand Down Expand Up @@ -437,6 +442,10 @@ export class EVMEthers5Client {
this.checkActiveInjectedProvider(this.ethersConfig)
}

if (this.ethersConfig.auth) {
this.syncAuthConnector(this.options.projectId, this.ethersConfig.auth)
}

if (this.ethersConfig.coinbase) {
this.checkActiveCoinbaseProvider(this.ethersConfig)
}
Expand Down Expand Up @@ -581,7 +590,8 @@ export class EVMEthers5Client {
id: `${ConstantsUtil.EIP155}:${chain.chainId}`,
name: chain.name,
imageId: PresetsUtil.EIP155NetworkImageIds[chain.chainId],
imageUrl: chainImages?.[chain.chainId]
imageUrl: chainImages?.[chain.chainId],
chain: CommonConstantsUtil.CHAIN.EVM
}) as CaipNetwork
)
this.appKit?.setRequestedCaipNetworks(requestedCaipNetworks ?? [], this.chain)
Expand Down Expand Up @@ -714,6 +724,46 @@ export class EVMEthers5Client {
}
}

private async setAuthProvider() {
window?.localStorage.setItem(EthersConstantsUtil.WALLET_ID, ConstantsUtil.AUTH_CONNECTOR_ID)
enesozturk marked this conversation as resolved.
Show resolved Hide resolved

if (this.authProvider) {
this.appKit?.setLoading(true)
const {
address,
chainId,
smartAccountDeployed,
preferredAccountType,
accounts = []
} = await this.authProvider.connect({ chainId: this.getChainId() })

const { smartAccountEnabledNetworks } =
await this.authProvider.getSmartAccountEnabledNetworks()

this.appKit?.setSmartAccountEnabledNetworks(smartAccountEnabledNetworks, this.chain)
if (address && chainId) {
this.appKit?.setAllAccounts(
accounts.length > 0
? accounts
: [{ address, type: preferredAccountType as 'eoa' | 'smartAccount' }],
this.chain
)

EthersStoreUtil.setChainId(NetworkUtil.parseEvmChainId(chainId))
EthersStoreUtil.setProviderType(ConstantsUtil.AUTH_CONNECTOR_ID as 'w3mAuth')
EthersStoreUtil.setProvider(this.authProvider as unknown as CombinedProvider)
EthersStoreUtil.setStatus('connected')
EthersStoreUtil.setIsConnected(true)
EthersStoreUtil.setAddress(address as Address)
EthersStoreUtil.setPreferredAccountType(preferredAccountType as W3mFrameTypes.AccountType)
this.appKit?.setSmartAccountDeployed(Boolean(smartAccountDeployed), this.chain)
this.watchAuth()
this.watchModal()
}
this.appKit?.setLoading(false)
}
}

private async watchWalletConnect() {
const WalletConnectProvider = await this.getWalletConnectProvider()

Expand Down Expand Up @@ -856,6 +906,93 @@ export class EVMEthers5Client {
}
}

private watchAuth() {
if (this.authProvider) {
this.authProvider.onRpcRequest(request => {
if (W3mFrameHelpers.checkIfRequestExists(request)) {
if (!W3mFrameHelpers.checkIfRequestIsAllowed(request)) {
if (this.appKit?.isOpen()) {
if (this.appKit?.isTransactionStackEmpty()) {
return
}
if (this.appKit?.isTransactionShouldReplaceView()) {
this.appKit?.replace('ApproveTransaction')
} else {
this.appKit?.redirect('ApproveTransaction')
}
} else {
this.appKit?.open({ view: 'ApproveTransaction' })
}
}
} else {
this.appKit?.open()
// eslint-disable-next-line no-console
console.error(W3mFrameRpcConstants.RPC_METHOD_NOT_ALLOWED_MESSAGE, {
method: request.method
})
setTimeout(() => {
this.appKit?.showErrorMessage(W3mFrameRpcConstants.RPC_METHOD_NOT_ALLOWED_UI_MESSAGE)
}, 300)
}
})

this.authProvider.onRpcError(() => {
const isModalOpen = this.appKit?.isOpen()

if (isModalOpen) {
if (this.appKit?.isTransactionStackEmpty()) {
this.appKit?.close()
} else {
this.appKit?.popTransactionStack(true)
}
}
})

this.authProvider.onRpcSuccess(() => {
if (this.appKit?.isTransactionStackEmpty()) {
this.appKit?.close()
} else {
this.appKit?.popTransactionStack()
}
})

this.authProvider.onNotConnected(() => {
this.appKit?.setIsConnected(false, this.chain)
this.appKit?.setLoading(false)
})

this.authProvider.onIsConnected(({ preferredAccountType }) => {
this.appKit?.setIsConnected(true, this.chain)
this.appKit?.setLoading(false)
EthersStoreUtil.setPreferredAccountType(preferredAccountType as W3mFrameTypes.AccountType)
})

this.authProvider.onSetPreferredAccount(({ address, type }) => {
if (!address) {
return
}
this.appKit?.setLoading(true)
const chainId = NetworkUtil.caipNetworkIdToNumber(this.appKit?.getCaipNetwork()?.id)
EthersStoreUtil.setAddress(address as Address)
EthersStoreUtil.setChainId(chainId)
EthersStoreUtil.setStatus('connected')
EthersStoreUtil.setIsConnected(true)
EthersStoreUtil.setPreferredAccountType(type as W3mFrameTypes.AccountType)
this.syncAccount().then(() => this.appKit?.setLoading(false))
})
}
}

private watchModal() {
if (this.authProvider) {
this.subscribeState(val => {
if (!val.open) {
this.authProvider?.rejectRpcRequests()
}
})
}
}

private async syncAccount() {
const address = EthersStoreUtil.state.address
const chainId = EthersStoreUtil.state.chainId
Expand Down Expand Up @@ -1039,7 +1176,6 @@ export class EVMEthers5Client {
method: 'wallet_switchEthereumChain',
params: [{ chainId: EthersHelpersUtil.numberToHexString(chain.chainId) }]
})

EthersStoreUtil.setChainId(chainId)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (switchError: any) {
Expand All @@ -1053,6 +1189,29 @@ export class EVMEthers5Client {
)
}
}
} else if (providerType === ConstantsUtil.INJECTED_CONNECTOR_ID && chain) {
const InjectedProvider = provider
if (InjectedProvider) {
try {
await InjectedProvider.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: EthersHelpersUtil.numberToHexString(chain.chainId) }]
})
EthersStoreUtil.setChainId(chain.chainId)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (switchError: any) {
if (
switchError.code === EthersConstantsUtil.ERROR_CODE_UNRECOGNIZED_CHAIN_ID ||
switchError.code === EthersConstantsUtil.ERROR_CODE_DEFAULT ||
switchError?.data?.originalError?.code ===
EthersConstantsUtil.ERROR_CODE_UNRECOGNIZED_CHAIN_ID
) {
await EthersHelpersUtil.addEthereumChain(InjectedProvider, chain)
} else {
throw new Error('Chain is not supported')
}
}
}
} else if (providerType === ConstantsUtil.EIP6963_CONNECTOR_ID && chain) {
const EIP6963Provider = provider

Expand Down Expand Up @@ -1095,9 +1254,33 @@ export class EVMEthers5Client {
EthersConstantsUtil.ERROR_CODE_UNRECOGNIZED_CHAIN_ID
) {
await EthersHelpersUtil.addEthereumChain(CoinbaseProvider, chain)
} else {
throw new Error('Error switching network')
}
}
}
} else if (providerType === ConstantsUtil.AUTH_CONNECTOR_ID) {
if (this.authProvider && chain?.chainId) {
try {
this.appKit?.setLoading(true)
await this.authProvider.switchNetwork(chain?.chainId)
EthersStoreUtil.setChainId(chain.chainId)

const { address, preferredAccountType } = await this.authProvider.connect({
chainId: chain?.chainId
})

EthersStoreUtil.setAddress(address as Address)
EthersStoreUtil.setPreferredAccountType(
preferredAccountType as W3mFrameTypes.AccountType
)
await this.syncAccount()
} catch {
throw new Error('Switching chain failed')
} finally {
this.appKit?.setLoading(false)
}
}
}
}
}
Expand Down Expand Up @@ -1149,6 +1332,34 @@ export class EVMEthers5Client {
this.appKit?.setConnectors(w3mConnectors)
}

private async syncAuthConnector(projectId: string, auth: ProviderType['auth']) {
if (typeof window !== 'undefined') {
this.authProvider = new W3mFrameProvider(projectId)

this.appKit?.addConnector({
id: ConstantsUtil.AUTH_CONNECTOR_ID,
type: 'AUTH',
name: 'Auth',
provider: this.authProvider,
email: auth?.email,
socials: auth?.socials,
showWallets: auth?.showWallets === undefined ? true : auth.showWallets,
chain: this.chain,
walletFeatures: auth?.walletFeatures
})

this.appKit?.setLoading(true)
const isLoginEmailUsed = this.authProvider.getLoginEmailUsed()
this.appKit?.setLoading(isLoginEmailUsed)
const { isConnected } = await this.authProvider.isConnected()
if (isConnected) {
await this.setAuthProvider()
} else {
this.appKit?.setLoading(false)
}
}
}

private eip6963EventHandler(event: CustomEventInit<EIP6963ProviderDetail>) {
if (event.detail) {
const { info, provider } = event.detail
Expand Down
1 change: 1 addition & 0 deletions packages/base/adapters/evm/ethers5/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '@web3modal/polyfills'

export { EVMEthers5Client } from './client.js'
export * from '@web3modal/scaffold-utils/ethers'

// -- Types
export type { AdapterOptions } from './client.js'
Expand Down
6 changes: 3 additions & 3 deletions packages/ethers5/exports/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { AppKit } from '@web3modal/base'
import type { AppKitOptions } from '@web3modal/base'
import { EVMEthersClient, type AdapterOptions } from '@web3modal/base/adapters/evm/ethers'
import { EVMEthers5Client, type AdapterOptions } from '@web3modal/base/adapters/evm/ethers5'
import { ConstantsUtil } from '@web3modal/scaffold-utils'
import { EthersStoreUtil } from '@web3modal/scaffold-utils/ethers'
import { getWeb3Modal } from '@web3modal/base/utils/library/react'
Expand All @@ -15,7 +15,7 @@ export { defaultConfig } from '@web3modal/base/adapters/evm/ethers'

// -- Setup -------------------------------------------------------------------
let appkit: AppKit | undefined = undefined
let ethersAdapter: EVMEthersClient | undefined = undefined
let ethersAdapter: EVMEthers5Client | undefined = undefined

export type Ethers5AppKitOptions = Omit<
AppKitOptions<Chain>,
Expand All @@ -24,7 +24,7 @@ export type Ethers5AppKitOptions = Omit<
AdapterOptions

export function createWeb3Modal(options: Ethers5AppKitOptions) {
ethersAdapter = new EVMEthersClient({
ethersAdapter = new EVMEthers5Client({
ethersConfig: options.ethersConfig,
siweConfig: options.siweConfig,
chains: options.chains,
Expand Down
6 changes: 3 additions & 3 deletions packages/ethers5/exports/vue.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AppKit } from '@web3modal/base'
import type { AppKitOptions } from '@web3modal/base'
import { EVMEthersClient, type AdapterOptions } from '@web3modal/base/adapters/evm/ethers'
import { EVMEthers5Client, type AdapterOptions } from '@web3modal/base/adapters/evm/ethers5'
import { ConstantsUtil } from '@web3modal/scaffold-utils'
import { getWeb3Modal } from '@web3modal/base/utils/library/vue'
import { onUnmounted, ref } from 'vue'
Expand All @@ -12,13 +12,13 @@ export { defaultConfig } from '@web3modal/base/adapters/evm/ethers'

// -- Setup -------------------------------------------------------------------
let appkit: AppKit | undefined = undefined
let ethersAdapter: EVMEthersClient | undefined = undefined
let ethersAdapter: EVMEthers5Client | undefined = undefined

type EthersAppKitOptions = Omit<AppKitOptions<Chain>, 'adapters' | 'sdkType' | 'sdkVersion'> &
AdapterOptions

export function createWeb3Modal(options: EthersAppKitOptions) {
ethersAdapter = new EVMEthersClient({
ethersAdapter = new EVMEthers5Client({
ethersConfig: options.ethersConfig,
siweConfig: options.siweConfig,
chains: options.chains,
Expand Down
Loading