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

Support custom connectors in web3-react #484

Merged
merged 2 commits into from
Dec 25, 2024
Merged
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
16 changes: 6 additions & 10 deletions packages/walletconnect/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ import {
ProviderEvent,
ProviderEventArgument,
RelayMethod,
ProjectMetaData,
SignClientOptions,
ChainInfo
} from './types'
import { isMobile } from './utils'
Expand All @@ -80,18 +80,14 @@ import { Sema } from 'async-sema'

const REQUESTS_PER_SECOND_LIMIT = 5

export interface ProviderOptions extends EnableOptionsBase {
export interface ProviderOptions extends EnableOptionsBase, SignClientOptions {
// Alephium options
networkId: NetworkId // the id of the network, e.g. mainnet, testnet or devnet.
addressGroup?: number // either a specific group or undefined to support all groups
methods?: RelayMethod[] // all of the methods to be used in relay; no need to configure in most cases

// WalletConnect options
projectId?: string
metadata?: ProjectMetaData // metadata used to initialize a sign client
logger?: string // default logger level is Error; no need to configure in most cases
client?: SignClient // existing sign client; no need to configure in most cases
relayUrl?: string // the url of the relay server; no need to configure in most cases
}

export class WalletConnectProvider extends SignerProvider {
Expand Down Expand Up @@ -240,7 +236,8 @@ export class WalletConnectProvider extends SignerProvider {
// ---------- Private ----------------------------------------------- //

private getWCStorageKey(prefix: string, version: string, name: string): string {
return prefix + version + '//' + name
const customStoragePrefix = this.providerOpts.customStoragePrefix ? `:${this.providerOpts.customStoragePrefix}` : ''
return prefix + version + customStoragePrefix + '//' + name
}

private async getSessionTopics(storage: KeyValueStorage): Promise<string[]> {
Expand Down Expand Up @@ -334,10 +331,9 @@ export class WalletConnectProvider extends SignerProvider {
this.client =
this.providerOpts.client ||
(await SignClient.init({
...this.providerOpts,
logger: this.providerOpts.logger || LOGGER,
relayUrl: this.providerOpts.relayUrl || RELAY_URL,
projectId: this.providerOpts.projectId,
metadata: this.providerOpts.metadata // fetch metadata automatically if not provided?
relayUrl: this.providerOpts.relayUrl || RELAY_URL
}))
}

Expand Down
1 change: 1 addition & 0 deletions packages/walletconnect/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,4 @@ export interface ChainInfo {
}

export type ProjectMetaData = SignClientTypes.Metadata
export type SignClientOptions = SignClientTypes.Options
25 changes: 18 additions & 7 deletions packages/web3-react/src/components/AlephiumConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
useConnectSettingContext
} from '../contexts/alephiumConnect'
import { getLastConnectedAccount, removeLastConnectedAccount } from '../utils/storage'
import { ConnectResult, getConnectorById } from '../utils/connector'
import { Connectors, ConnectResult, createDefaultConnectors } from '../utils/connector'
import { useInjectedProviders } from '../hooks/useInjectedProviders'

export const ConnectSettingProvider: React.FC<{
Expand Down Expand Up @@ -121,8 +121,9 @@ export const AlephiumConnectProvider: React.FC<{
network: NetworkId
addressGroup?: number
keyType?: KeyType
connectors?: Partial<Connectors>
children?: React.ReactNode
}> = ({ network, addressGroup, keyType, children }) => {
}> = ({ network, addressGroup, keyType, children, connectors }) => {
// Only allow for mounting AlephiumConnectProvider once, so we avoid weird global
// state collisions.
const context = useContext(AlephiumConnectContext)
Expand All @@ -134,6 +135,14 @@ export const AlephiumConnectProvider: React.FC<{
const [_addressGroup, setAddressGroup] = useState<number | undefined>(addressGroup)
const [_keyType, setKeyType] = useState<KeyType>(keyType ?? 'default')
const allInjectedProviders = useInjectedProviders()
const defaultConnectors = useMemo(() => createDefaultConnectors(allInjectedProviders), [allInjectedProviders])
const allConnectors: Connectors = useMemo(() => {
if (connectors === undefined || Object.keys(connectors).length === 0) {
return defaultConnectors
} else {
return { ...defaultConnectors, ...connectors }
}
}, [defaultConnectors, connectors])

useEffect(() => setNetwork(network), [network])
useEffect(() => setAddressGroup(addressGroup), [addressGroup])
Expand Down Expand Up @@ -196,15 +205,14 @@ export const AlephiumConnectProvider: React.FC<{
: [lastConnectorId].concat(allConnectorIds.filter((c) => c !== lastConnectorId))

for (const connectorId of sortedConnectorIds) {
const connector = getConnectorById(connectorId)
const connector = allConnectors[`${connectorId}`]
if (connector.autoConnect !== undefined) {
const result = await connector.autoConnect({
network,
addressGroup,
keyType,
onDisconnected,
onConnected,
allInjectedProviders: connectorId === 'injected' ? allInjectedProviders : undefined
onConnected
})
if (result !== undefined) {
return
Expand Down Expand Up @@ -234,7 +242,8 @@ export const AlephiumConnectProvider: React.FC<{
setConnectionStatus,
setAccount: updateAccount,
signerProvider,
setSignerProvider: updateSignerProvider
setSignerProvider: updateSignerProvider,
connectors: allConnectors
}

return <AlephiumConnectContext.Provider value={value}>{children}</AlephiumConnectContext.Provider>
Expand Down Expand Up @@ -313,6 +322,7 @@ type AlephiumWalletProviderProps = {
network: NetworkId
addressGroup?: number
keyType?: KeyType
connectors?: Partial<Connectors>
csrModeOnly?: boolean // whether to show the connect button only in CSR mode
children?: React.ReactNode
}
Expand All @@ -323,11 +333,12 @@ export const AlephiumWalletProvider = ({
network,
addressGroup,
keyType,
connectors,
csrModeOnly,
children
}: AlephiumWalletProviderProps) => {
return (
<AlephiumConnectProvider network={network} addressGroup={addressGroup} keyType={keyType}>
<AlephiumConnectProvider network={network} addressGroup={addressGroup} keyType={keyType} connectors={connectors}>
<ConnectSettingProvider
theme={theme === 'simple-light' || theme === 'simple-dark' ? 'auto' : theme}
mode={theme === 'simple-light' ? 'light' : theme === 'simple-dark' ? 'dark' : 'auto'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import { useConnect } from '../../../hooks/useConnect'
import { AlephiumWindowObject } from '@alephium/get-extension-wallet'
import { ConnectorButton, ConnectorIcon, ConnectorLabel, ConnectorsContainer } from '../../Pages/Connectors/styles'
import { useInjectedProviders } from '../../../hooks/useInjectedProviders'
import { getInjectedProviderId } from '../../../utils/injectedProviders'
import { InjectedProviderId } from '../../../types'

const states = {
CONNECTED: 'connected',
Expand Down Expand Up @@ -93,8 +95,8 @@ const ConnectWithInjector: React.FC<{
}> = ({ connectorId, switchConnectMethod, forceState }) => {
const { setOpen } = useConnectSettingContext()
const providers = useInjectedProviders()
const [injectedProvider, setInjectedProvider] = useState<AlephiumWindowObject | undefined>(
providers.length !== 0 ? providers[0] : undefined
const [injectedProviderId, setInjectedProviderId] = useState<InjectedProviderId | undefined>(
providers.length !== 0 ? getInjectedProviderId(providers[0]) : undefined
)
console.log(`providers size: ${providers.length}`)
const { connect } = useConnect()
Expand Down Expand Up @@ -127,23 +129,23 @@ const ConnectWithInjector: React.FC<{
)

const handleConnect = useCallback(
(injectedProvider) => {
setInjectedProvider(injectedProvider)
(injectedProviderId) => {
setInjectedProviderId(injectedProviderId)
setStatus(states.CONNECTING)
},
[setStatus, setInjectedProvider]
[setStatus, setInjectedProviderId]
)

const runConnect = useCallback(() => {
if (!hasExtensionInstalled || status === states.LISTING) return

connect(injectedProvider).then((address) => {
connect(injectedProviderId).then((address) => {
if (!!address) {
setStatus(states.CONNECTED)
}
setOpen(false)
})
}, [hasExtensionInstalled, setOpen, connect, status, injectedProvider])
}, [hasExtensionInstalled, setOpen, connect, status, injectedProviderId])

const connectTimeoutRef = useRef<ReturnType<typeof setTimeout>>()
useEffect(() => {
Expand Down Expand Up @@ -210,13 +212,13 @@ const ConnectWithInjector: React.FC<{
<>
<ConnectorsContainer>
{providers.map((provider) => {
const name = getProviderName(provider)
const id = getInjectedProviderId(provider)
return (
<ConnectorButton key={name} onClick={() => handleConnect(provider)}>
<ConnectorButton key={id} onClick={() => handleConnect(id)}>
<ConnectorIcon>
<img src={provider.icon} alt="Icon" />
</ConnectorIcon>
<ConnectorLabel>{name}</ConnectorLabel>
<ConnectorLabel>{id}</ConnectorLabel>
</ConnectorButton>
)
})}
Expand Down Expand Up @@ -497,10 +499,3 @@ const ConnectWithInjector: React.FC<{
}

export default ConnectWithInjector

function getProviderName(provider: AlephiumWindowObject): string {
if (provider.icon.includes('onekey')) {
return 'OneKey'
}
return 'Alephium'
}
2 changes: 2 additions & 0 deletions packages/web3-react/src/contexts/alephiumConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import React, { createContext, useContext } from 'react'
import { Account, KeyType, SignerProvider, NetworkId } from '@alephium/web3'
import { Theme, Mode, CustomTheme, ConnectorId } from '../types'
import { node } from '@alephium/web3'
import { Connectors } from '../utils/connector'

type Error = string | React.ReactNode | null

Expand Down Expand Up @@ -64,6 +65,7 @@ export type AlephiumConnectContextValue = {
setConnectionStatus: (status: ConnectionStatus) => void
signerProvider?: SignerProvider
setSignerProvider: (signerProvider: SignerProvider | undefined) => void
connectors: Connectors
}

export const AlephiumConnectContext = createContext<AlephiumConnectContextValue | null>(null)
Expand Down
23 changes: 16 additions & 7 deletions packages/web3-react/src/hooks/useConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
import { useAlephiumConnectContext, useConnectSettingContext } from '../contexts/alephiumConnect'
import { useCallback, useMemo } from 'react'
import { removeLastConnectedAccount } from '../utils/storage'
import { ConnectResult, getConnectorById } from '../utils/connector'
import { ConnectResult } from '../utils/connector'
import { InjectedProviderId } from '../types'

export function useConnect() {
const { connectorId } = useConnectSettingContext()
const { signerProvider, setSignerProvider, setConnectionStatus, setAccount, addressGroup, network, keyType } =
useAlephiumConnectContext()
const {
signerProvider,
setSignerProvider,
setConnectionStatus,
setAccount,
addressGroup,
network,
keyType,
connectors
} = useAlephiumConnectContext()

const onDisconnected = useCallback(() => {
removeLastConnectedAccount()
Expand All @@ -50,13 +59,13 @@ export function useConnect() {
}, [onDisconnected, onConnected, network, addressGroup, keyType])

const connector = useMemo(() => {
return getConnectorById(connectorId)
}, [connectorId])
return connectors[`${connectorId}`]
}, [connectorId, connectors])

const connect = useMemo(() => {
return async (injectedProvider?) => {
return async (injectedProviderId?: InjectedProviderId) => {
setConnectionStatus('connecting')
return await connector.connect({ ...connectOptions, injectedProvider })
return await connector.connect({ ...connectOptions, injectedProviderId })
}
}, [connector, connectOptions, setConnectionStatus])

Expand Down
2 changes: 1 addition & 1 deletion packages/web3-react/src/hooks/useInjectedProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { useSyncExternalStore } from 'use-sync-external-store/shim'
import { injectedProviderStore } from '../utils/providers'
import { injectedProviderStore } from '../utils/injectedProviders'

export const useInjectedProviders = () =>
useSyncExternalStore(
Expand Down
1 change: 1 addition & 0 deletions packages/web3-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ export { useBalance } from './hooks/useBalance'
export { useWallet, Wallet, useWalletConfig, WalletConfig } from './hooks/useWallet'

export * from './contexts/alephiumConnect'
export * from './utils/connector'
1 change: 1 addition & 0 deletions packages/web3-react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type Mode = 'light' | 'dark' | 'auto'
export type CustomTheme = any // TODO: define type
export const connectorIds = ['injected', 'walletConnect', 'desktopWallet'] as const
export type ConnectorId = (typeof connectorIds)[number]
export type InjectedProviderId = 'Alephium' | 'OneKey'

export type CustomStyle = {
theme?: Theme
Expand Down
Loading
Loading