@wagmi/core
Version:
VanillaJS library for Ethereum
111 lines (99 loc) • 3.41 kB
text/typescript
import type {
Address,
ResourceUnavailableRpcErrorType,
UserRejectedRequestErrorType,
} from 'viem'
import type { CreateConnectorFn } from '../connectors/createConnector.js'
import type { Config, Connector } from '../createConfig.js'
import type { BaseErrorType, ErrorType } from '../errors/base.js'
import {
ConnectorAlreadyConnectedError,
type ConnectorAlreadyConnectedErrorType,
} from '../errors/config.js'
import type { ChainIdParameter } from '../types/properties.js'
import type { Compute } from '../types/utils.js'
export type ConnectParameters<
config extends Config = Config,
connector extends Connector | CreateConnectorFn =
| Connector
| CreateConnectorFn,
///
parameters extends unknown | undefined =
| (connector extends CreateConnectorFn
? Omit<
NonNullable<Parameters<ReturnType<connector>['connect']>[0]>,
'isReconnecting'
>
: never)
| (connector extends Connector
? Omit<
NonNullable<Parameters<connector['connect']>[0]>,
'isReconnecting'
>
: never),
> = Compute<
ChainIdParameter<config> & {
connector: connector | CreateConnectorFn
}
> &
parameters
export type ConnectReturnType<config extends Config = Config> = {
accounts: readonly [Address, ...Address[]]
chainId:
| config['chains'][number]['id']
| (number extends config['chains'][number]['id'] ? number : number & {})
}
export type ConnectErrorType =
| ConnectorAlreadyConnectedErrorType
// connector.connect()
| UserRejectedRequestErrorType
| ResourceUnavailableRpcErrorType
// base
| BaseErrorType
| ErrorType
/** https://wagmi.sh/core/api/actions/connect */
export async function connect<
config extends Config,
connector extends Connector | CreateConnectorFn,
>(
config: config,
parameters: ConnectParameters<config, connector>,
): Promise<ConnectReturnType<config>> {
// "Register" connector if not already created
let connector: Connector
if (typeof parameters.connector === 'function') {
connector = config._internal.connectors.setup(parameters.connector)
} else connector = parameters.connector
// Check if connector is already connected
if (connector.uid === config.state.current)
throw new ConnectorAlreadyConnectedError()
try {
config.setState((x) => ({ ...x, status: 'connecting' }))
connector.emitter.emit('message', { type: 'connecting' })
const { connector: _, ...rest } = parameters
const data = await connector.connect(rest)
const accounts = data.accounts as readonly [Address, ...Address[]]
connector.emitter.off('connect', config._internal.events.connect)
connector.emitter.on('change', config._internal.events.change)
connector.emitter.on('disconnect', config._internal.events.disconnect)
await config.storage?.setItem('recentConnectorId', connector.id)
config.setState((x) => ({
...x,
connections: new Map(x.connections).set(connector.uid, {
accounts,
chainId: data.chainId,
connector: connector,
}),
current: connector.uid,
status: 'connected',
}))
return { accounts, chainId: data.chainId }
} catch (error) {
config.setState((x) => ({
...x,
// Keep existing connector connected in case of error
status: x.current ? 'connected' : 'disconnected',
}))
throw error
}
}