@openocean.finance/widget-sdk
Version:
OpenOcean Any-to-Any Cross-Chain-Swap SDK
92 lines (85 loc) • 2.87 kB
text/typescript
import type { Client, GetChainIdReturnType } from 'viem'
import { getChainId } from 'viem/actions'
import { getAction } from 'viem/utils'
import { OpenOceanErrorCode } from '../../errors/constants.js'
import { ProviderError } from '../../errors/errors.js'
import type { StatusManager } from '../StatusManager.js'
import type { OpenOceanStepExtended, SwitchChainHook } from '../types.js'
/**
* This method checks whether the wallet client is configured for the correct chain.
* If yes it returns the wallet clien.
* If no and if user interaction is allowed it triggers the switchChainHook. If no user interaction is allowed it aborts.
*
* Account Type: local -
* We need to create and return a new connector client from the switchChainHook in order to continue execution on a new chain.
*
* Account Type: json-rpc -
* We can switch chain and return existing connector client from the switchChainHook in order to continue execution on a new chain.
* @param client
* @param statusManager
* @param step
* @param switchChainHook
* @param allowUserInteraction
* @returns New connector client
*/
export const switchChain = async (
client: Client,
statusManager: StatusManager,
step: OpenOceanStepExtended,
allowUserInteraction: boolean,
switchChainHook?: SwitchChainHook
): Promise<Client | undefined> => {
// if we are already on the correct chain we can proceed directly
const currentChainId = (await getAction(
client,
getChainId,
'getChainId'
)(undefined)) as GetChainIdReturnType
if (currentChainId === step.action.fromChainId) {
return client
}
// -> set status message
step.execution = statusManager.initExecutionObject(step)
statusManager.updateExecution(step, 'ACTION_REQUIRED')
let switchProcess = statusManager.findOrCreateProcess({
step,
type: 'SWITCH_CHAIN',
status: 'ACTION_REQUIRED',
})
if (!allowUserInteraction) {
return
}
try {
const updatedClient = await switchChainHook?.(step.action.fromChainId)
let updatedChainId: number | undefined
if (updatedClient) {
updatedChainId = (await getAction(
updatedClient,
getChainId,
'getChainId'
)(undefined)) as GetChainIdReturnType
}
if (updatedChainId !== step.action.fromChainId) {
throw new ProviderError(
OpenOceanErrorCode.ChainSwitchError,
'Chain switch required.'
)
}
switchProcess = statusManager.updateProcess(
step,
switchProcess.type,
'DONE'
)
statusManager.updateExecution(step, 'PENDING')
return updatedClient
} catch (error: any) {
statusManager.updateProcess(step, switchProcess.type, 'FAILED', {
error: {
message: error.message,
code: OpenOceanErrorCode.ChainSwitchError,
},
})
statusManager.updateExecution(step, 'FAILED')
throw error
}
}