diff --git a/package.json b/package.json index 4e1a3c51..5fa7b50f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lifi/sdk", - "version": "3.1.5", + "version": "3.2.0-alpha.1", "description": "LI.FI Any-to-Any Cross-Chain-Swap SDK", "keywords": [ "bridge", diff --git a/src/core/EVM/EVM.ts b/src/core/EVM/EVM.ts index a46db70a..0a40133a 100644 --- a/src/core/EVM/EVM.ts +++ b/src/core/EVM/EVM.ts @@ -22,13 +22,13 @@ export function EVM(options?: EVMProviderOptions): EVMProvider { options: StepExecutorOptions ): Promise { if (!_options.getWalletClient) { - throw new Error(`getWalletClient is not provided.`) + throw new Error(`Client is not provided.`) } const walletClient = await _options.getWalletClient() const executor = new EVMStepExecutor({ - walletClient, + client: walletClient, multisig: _options.multisig, routeId: options.routeId, executionOptions: { diff --git a/src/core/EVM/EVMStepExecutor.ts b/src/core/EVM/EVMStepExecutor.ts index 2bbe62e7..89987ce2 100644 --- a/src/core/EVM/EVMStepExecutor.ts +++ b/src/core/EVM/EVMStepExecutor.ts @@ -3,13 +3,8 @@ import type { FullStatusData, Process, } from '@lifi/types' -import type { - Hash, - PublicClient, - SendTransactionParameters, - WalletClient, -} from 'viem' -import { publicActions } from 'viem' +import type { Client, Hash, SendTransactionParameters } from 'viem' +import { getAddresses, sendTransaction } from 'viem/actions' import { config } from '../../config.js' import { LiFiErrorCode } from '../../errors/constants.js' import { TransactionError, ValidationError } from '../../errors/errors.js' @@ -37,40 +32,40 @@ import { getMaxPriorityFeePerGas } from './utils.js' import { waitForTransactionReceipt } from './waitForTransactionReceipt.js' export interface EVMStepExecutorOptions extends StepExecutorOptions { - walletClient: WalletClient + client: Client multisig?: MultisigConfig } export class EVMStepExecutor extends BaseStepExecutor { - private walletClient: WalletClient + private client: Client private multisig?: MultisigConfig constructor(options: EVMStepExecutorOptions) { super(options) - this.walletClient = options.walletClient + this.client = options.client this.multisig = options.multisig } // Ensure that we are using the right chain and wallet when executing transactions. - checkWalletClient = async ( + checkClient = async ( step: LiFiStepExtended, process?: Process - ): Promise => { - const updatedWalletClient = await switchChain( - this.walletClient, + ): Promise => { + const updatedClient = await switchChain( + this.client, this.statusManager, step, this.allowUserInteraction, this.executionOptions?.switchChainHook ) - if (updatedWalletClient) { - this.walletClient = updatedWalletClient + if (updatedClient) { + this.client = updatedClient } // Prevent execution of the quote by wallet different from the one which requested the quote - let accountAddress = this.walletClient.account?.address + let accountAddress = this.client.account?.address if (!accountAddress) { - const accountAddresses = await this.walletClient.getAddresses() + const accountAddresses = await getAddresses(this.client) accountAddress = accountAddresses?.[0] } if (accountAddress !== step.action.fromAddress) { @@ -100,7 +95,7 @@ export class EVMStepExecutor extends BaseStepExecutor { process ) } - return updatedWalletClient + return updatedClient } executeStep = async (step: LiFiStepExtended): Promise => { @@ -116,13 +111,13 @@ export class EVMStepExecutor extends BaseStepExecutor { // All changes are already done from the source chain // Return the step if (recievingChainProcess?.substatus !== 'WAIT_DESTINATION_TRANSACTION') { - const updatedWalletClient = await this.checkWalletClient(step) - if (!updatedWalletClient) { + const updatedClient = await this.checkClient(step) + if (!updatedClient) { return step } } - const isMultisigWalletClient = !!this.multisig?.isMultisigWalletClient + const isMultisigClient = !!this.multisig?.isMultisigClient const multisigBatchTransactions: MultisigTransaction[] = [] const shouldBatchTransactions = @@ -144,13 +139,13 @@ export class EVMStepExecutor extends BaseStepExecutor { const checkForAllowance = !existingProcess?.txHash && !isZeroAddress(step.action.fromToken.address) && - (shouldBatchTransactions || !isMultisigWalletClient) + (shouldBatchTransactions || !isMultisigClient) if (checkForAllowance) { const data = await checkAllowance( + this.client, fromChain, step, - this.walletClient, this.statusManager, this.executionOptions, this.allowUserInteraction, @@ -180,7 +175,7 @@ export class EVMStepExecutor extends BaseStepExecutor { ) try { - if (isMultisigWalletClient && multisigProcess) { + if (isMultisigClient && multisigProcess) { const multisigTxHash = multisigProcess.multisigTxHash as Hash if (!multisigTxHash) { throw new ValidationError( @@ -200,11 +195,8 @@ export class EVMStepExecutor extends BaseStepExecutor { let txHash: Hash if (process.txHash) { // Make sure that the chain is still correct - const updatedWalletClient = await this.checkWalletClient( - step, - process - ) - if (!updatedWalletClient) { + const updatedClient = await this.checkClient(step, process) + if (!updatedClient) { return step } @@ -218,7 +210,7 @@ export class EVMStepExecutor extends BaseStepExecutor { ) // Check balance - await checkBalance(this.walletClient.account!.address, step) + await checkBalance(this.client.account!.address, step) // Create new transaction if (!step.transactionRequest) { @@ -246,11 +238,8 @@ export class EVMStepExecutor extends BaseStepExecutor { // STEP 3: Send the transaction // Make sure that the chain is still correct - const updatedWalletClient = await this.checkWalletClient( - step, - process - ) - if (!updatedWalletClient) { + const updatedClient = await this.checkClient(step, process) + if (!updatedClient) { return step } @@ -281,10 +270,8 @@ export class EVMStepExecutor extends BaseStepExecutor { // ? BigInt(step.transactionRequest.maxFeePerGas as string) // : undefined, maxPriorityFeePerGas: - this.walletClient.account?.type === 'local' - ? await getMaxPriorityFeePerGas( - this.walletClient.extend(publicActions) as PublicClient - ) + this.client.account?.type === 'local' + ? await getMaxPriorityFeePerGas(this.client) : step.transactionRequest.maxPriorityFeePerGas ? BigInt(step.transactionRequest.maxPriorityFeePerGas) : undefined, @@ -322,9 +309,9 @@ export class EVMStepExecutor extends BaseStepExecutor { ) } } else { - txHash = await this.walletClient.sendTransaction({ + txHash = await sendTransaction(this.client, { to: transactionRequest.to, - account: this.walletClient.account!, + account: this.client.account!, data: transactionRequest.data, value: transactionRequest.value, gas: transactionRequest.gas, @@ -336,7 +323,7 @@ export class EVMStepExecutor extends BaseStepExecutor { } // STEP 4: Wait for the transaction - if (isMultisigWalletClient) { + if (isMultisigClient) { process = this.statusManager.updateProcess( step, process.type, @@ -359,7 +346,7 @@ export class EVMStepExecutor extends BaseStepExecutor { } const transactionReceipt = await waitForTransactionReceipt({ - walletClient: this.walletClient, + client: this.client, chainId: fromChain.id, txHash, onReplaced: (response) => { @@ -372,7 +359,7 @@ export class EVMStepExecutor extends BaseStepExecutor { // if it's multisig wallet client and the process is in ACTION_REQUIRED // then signatures are still needed - if (isMultisigWalletClient && process.status === 'ACTION_REQUIRED') { + if (isMultisigClient && process.status === 'ACTION_REQUIRED') { await updateMultisigRouteProcess( transactionReceipt?.transactionHash || txHash, step, @@ -386,7 +373,7 @@ export class EVMStepExecutor extends BaseStepExecutor { // Update pending process if the transaction hash from the receipt is different. // This might happen if the transaction was replaced. if ( - !isMultisigWalletClient && + !isMultisigClient && transactionReceipt?.transactionHash && transactionReceipt.transactionHash !== txHash ) { diff --git a/src/core/EVM/checkAllowance.ts b/src/core/EVM/checkAllowance.ts index 72c3c87d..84e66ca6 100644 --- a/src/core/EVM/checkAllowance.ts +++ b/src/core/EVM/checkAllowance.ts @@ -1,5 +1,5 @@ import type { Chain, LiFiStep, Process, ProcessType } from '@lifi/types' -import type { Address, Hash, WalletClient } from 'viem' +import type { Address, Client, Hash } from 'viem' import type { StatusManager } from '../StatusManager.js' import type { ExecutionOptions } from '../types.js' import { getAllowance } from './getAllowance.js' @@ -8,9 +8,9 @@ import { setAllowance } from './setAllowance.js' import { waitForTransactionReceipt } from './waitForTransactionReceipt.js' export const checkAllowance = async ( + client: Client, chain: Chain, step: LiFiStep, - walletClient: WalletClient, statusManager: StatusManager, settings?: ExecutionOptions, allowUserInteraction = false, @@ -26,7 +26,7 @@ export const checkAllowance = async ( try { if (allowanceProcess.txHash && allowanceProcess.status !== 'DONE') { await waitForApprovalTransaction( - walletClient, + client, allowanceProcess.txHash! as Address, allowanceProcess.type, step, @@ -43,7 +43,7 @@ export const checkAllowance = async ( const approved = await getAllowance( chain.id, step.action.fromToken.address, - walletClient.account!.address, + client.account!.address, step.estimate.approvalAddress ) @@ -56,7 +56,7 @@ export const checkAllowance = async ( if (shouldBatchTransactions) { const approveTxHash = await setAllowance( - walletClient, + client, step.action.fromToken.address, step.estimate.approvalAddress, fromAmount, @@ -74,13 +74,13 @@ export const checkAllowance = async ( } const approveTxHash = await setAllowance( - walletClient, + client, step.action.fromToken.address, step.estimate.approvalAddress, fromAmount ) await waitForApprovalTransaction( - walletClient, + client, approveTxHash, allowanceProcess.type, step, @@ -114,7 +114,7 @@ export const checkAllowance = async ( } const waitForApprovalTransaction = async ( - walletClient: WalletClient, + client: Client, txHash: Hash, processType: ProcessType, step: LiFiStep, @@ -127,7 +127,7 @@ const waitForApprovalTransaction = async ( }) const transactionReceipt = await waitForTransactionReceipt({ - walletClient, + client: client, chainId: chain.id, txHash: txHash, onReplaced(response) { diff --git a/src/core/EVM/getAllowance.ts b/src/core/EVM/getAllowance.ts index f34eec3e..cc2d84ec 100644 --- a/src/core/EVM/getAllowance.ts +++ b/src/core/EVM/getAllowance.ts @@ -1,6 +1,6 @@ import type { BaseToken, ChainId } from '@lifi/types' import type { Address } from 'viem' -import { getContract } from 'viem' +import { multicall, readContract } from 'viem/actions' import { isNativeTokenAddress } from '../../utils/utils.js' import { allowanceAbi } from './abi.js' import { getPublicClient } from './publicClient.js' @@ -18,17 +18,13 @@ export const getAllowance = async ( spenderAddress: string ): Promise => { const client = await getPublicClient(chainId) - const contract = getContract({ - address: tokenAddress as Address, - abi: allowanceAbi, - client: client, - }) - try { - const approved = (await contract.read.allowance([ - ownerAddress, - spenderAddress, - ])) as bigint + const approved = (await readContract(client, { + address: tokenAddress as Address, + abi: allowanceAbi, + functionName: 'allowance', + args: [ownerAddress, spenderAddress], + })) as bigint return approved } catch (e) { return 0n @@ -57,7 +53,7 @@ export const getAllowanceMulticall = async ( args: [ownerAddress, token.spenderAddress], })) - const results = await client.multicall({ + const results = await multicall(client, { contracts, multicallAddress: multicallAddress as Address, }) diff --git a/src/core/EVM/getENSAddress.ts b/src/core/EVM/getENSAddress.ts index ce78f19f..67836ab1 100644 --- a/src/core/EVM/getENSAddress.ts +++ b/src/core/EVM/getENSAddress.ts @@ -1,5 +1,5 @@ import { ChainId } from '@lifi/types' -import { normalize } from 'viem/ens' +import { getEnsAddress, normalize } from 'viem/ens' import { getPublicClient } from './publicClient.js' export const getENSAddress = async ( @@ -7,7 +7,7 @@ export const getENSAddress = async ( ): Promise => { try { const client = await getPublicClient(ChainId.ETH) - const address = await client.getEnsAddress({ + const address = await getEnsAddress(client, { name: normalize(name), }) return address as string | undefined diff --git a/src/core/EVM/getEVMBalance.ts b/src/core/EVM/getEVMBalance.ts index 20c32459..07e8fdc1 100644 --- a/src/core/EVM/getEVMBalance.ts +++ b/src/core/EVM/getEVMBalance.ts @@ -1,5 +1,11 @@ import type { ChainId, Token, TokenAmount } from '@lifi/types' import type { Address } from 'viem' +import { + getBalance, + getBlockNumber, + multicall, + readContract, +} from 'viem/actions' import { isZeroAddress } from '../../utils/utils.js' import { balanceOfAbi, getEthBalanceAbi } from './abi.js' import { getPublicClient } from './publicClient.js' @@ -57,8 +63,8 @@ const getEVMBalanceMulticall = async ( args: [walletAddress], } }) - const blockNumber = await client.getBlockNumber() - const results = await client.multicall({ + const blockNumber = await getBlockNumber(client) + const results = await multicall(client, { contracts, multicallAddress: multicallAddress as Address, blockNumber, @@ -83,14 +89,14 @@ const getEVMBalanceDefault = async ( walletAddress: string ): Promise => { const client = await getPublicClient(chainId) - const blockNumber = await client.getBlockNumber() + const blockNumber = await getBlockNumber(client) const queue: Promise[] = tokens.map((token) => { if (isZeroAddress(token.address)) { - return client.getBalance({ + return getBalance(client, { address: walletAddress as Address, }) } - return client.readContract({ + return readContract(client, { address: token.address as Address, abi: balanceOfAbi, functionName: 'balanceOf', diff --git a/src/core/EVM/publicClient.ts b/src/core/EVM/publicClient.ts index 42be0c40..4f41812e 100644 --- a/src/core/EVM/publicClient.ts +++ b/src/core/EVM/publicClient.ts @@ -1,21 +1,19 @@ import { ChainId } from '@lifi/types' -import type { PublicClient } from 'viem' -import { createPublicClient, fallback, http, webSocket } from 'viem' +import type { Client } from 'viem' +import { createClient, fallback, http, webSocket } from 'viem' import { mainnet, type Chain } from 'viem/chains' import { config } from '../../config.js' import { getRpcUrls } from '../rpc.js' // cached providers -const publicClients: Record = {} +const publicClients: Record = {} /** * Get an instance of a provider for a specific chain * @param chainId - Id of the chain the provider is for * @returns The public client for the given chain */ -export const getPublicClient = async ( - chainId: number -): Promise => { +export const getPublicClient = async (chainId: number): Promise => { if (!publicClients[chainId]) { const urls = await getRpcUrls(chainId) const fallbackTransports = urls.map((url) => @@ -44,7 +42,7 @@ export const getPublicClient = async ( ...chain.contracts, } } - publicClients[chainId] = createPublicClient({ + publicClients[chainId] = createClient({ chain: chain, transport: fallback(fallbackTransports), batch: { diff --git a/src/core/EVM/setAllowance.int.spec.ts b/src/core/EVM/setAllowance.int.spec.ts index 8a2ce683..92f36031 100644 --- a/src/core/EVM/setAllowance.int.spec.ts +++ b/src/core/EVM/setAllowance.int.spec.ts @@ -1,6 +1,7 @@ -import type { Address, WalletClient } from 'viem' -import { createWalletClient, http, publicActions } from 'viem' +import type { Address, Client } from 'viem' +import { createClient, http } from 'viem' import { mnemonicToAccount } from 'viem/accounts' +import { waitForTransactionReceipt } from 'viem/actions' import { polygon } from 'viem/chains' import { beforeAll, describe, expect, it } from 'vitest' import { setupTestEnvironment } from '../../../tests/setup.js' @@ -28,27 +29,25 @@ describe.skipIf(!MNEMONIC)('Approval integration tests', () => { } const account = mnemonicToAccount(MNEMONIC as Address) - const walletClient: WalletClient = createWalletClient({ + const client: Client = createClient({ account, chain: polygon, transport: http(), }) - const client = walletClient.extend(publicActions) - beforeAll(setupTestEnvironment) it( 'should revoke allowance for ERC20 on POL', async () => { const revokeTxHash = await revokeTokenApproval({ - walletClient, + walletClient: client, token: testToken, spenderAddress: defaultSpenderAddress, }) if (revokeTxHash) { - const transactionReceipt = await client.waitForTransactionReceipt({ + const transactionReceipt = await waitForTransactionReceipt(client, { hash: revokeTxHash!, retryCount, retryDelay, @@ -64,14 +63,14 @@ describe.skipIf(!MNEMONIC)('Approval integration tests', () => { 'should set allowance ERC20 on POL', async () => { const approvalTxHash = await setTokenAllowance({ - walletClient, + walletClient: client, token: testToken, spenderAddress: defaultSpenderAddress, amount: defaultAllowance, }) if (approvalTxHash) { - const transactionReceipt = await client.waitForTransactionReceipt({ + const transactionReceipt = await waitForTransactionReceipt(client, { hash: approvalTxHash!, retryCount, retryDelay, diff --git a/src/core/EVM/setAllowance.ts b/src/core/EVM/setAllowance.ts index 00df326c..9b3478d6 100644 --- a/src/core/EVM/setAllowance.ts +++ b/src/core/EVM/setAllowance.ts @@ -1,10 +1,6 @@ -import type { - Hash, - PublicClient, - SendTransactionParameters, - WalletClient, -} from 'viem' -import { encodeFunctionData, publicActions } from 'viem' +import type { Client, Hash, SendTransactionParameters } from 'viem' +import { encodeFunctionData } from 'viem' +import { sendTransaction } from 'viem/actions' import { isNativeTokenAddress } from '../../utils/utils.js' import type { ExecutionOptions, TransactionParameters } from '../types.js' import { approveAbi } from './abi.js' @@ -13,7 +9,7 @@ import type { ApproveTokenRequest, RevokeApprovalRequest } from './types.js' import { getMaxPriorityFeePerGas } from './utils.js' export const setAllowance = async ( - walletClient: WalletClient, + client: Client, tokenAddress: string, contractAddress: string, amount: bigint, @@ -29,14 +25,13 @@ export const setAllowance = async ( if (returnPopulatedTransaction) { return data } - const client = walletClient.extend(publicActions) let transactionRequest: TransactionParameters = { to: tokenAddress, data, maxPriorityFeePerGas: - walletClient.account?.type === 'local' - ? await getMaxPriorityFeePerGas(client as PublicClient) + client.account?.type === 'local' + ? await getMaxPriorityFeePerGas(client) : undefined, } @@ -53,9 +48,9 @@ export const setAllowance = async ( } } - return client.sendTransaction({ + return sendTransaction(client, { to: transactionRequest.to, - account: walletClient.account!, + account: client.account!, data: transactionRequest.data, gas: transactionRequest.gas, gasPrice: transactionRequest.gasPrice, diff --git a/src/core/EVM/switchChain.ts b/src/core/EVM/switchChain.ts index 0ef22071..81b2b1b0 100644 --- a/src/core/EVM/switchChain.ts +++ b/src/core/EVM/switchChain.ts @@ -1,4 +1,5 @@ -import type { WalletClient } from 'viem' +import type { Client } from 'viem' +import { getChainId } from 'viem/actions' import { LiFiErrorCode } from '../../errors/constants.js' import { ProviderError } from '../../errors/errors.js' import type { StatusManager } from '../StatusManager.js' @@ -10,28 +11,28 @@ import type { LiFiStepExtended, SwitchChainHook } from '../types.js' * 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 WalletClient from the switchChainHook in order to continue execution on a new chain. + * 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 WalletClient from the switchChainHook in order to continue execution on a new chain. - * @param walletClient + * 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 WalletClient + * @returns New connector client */ export const switchChain = async ( - walletClient: WalletClient, + client: Client, statusManager: StatusManager, step: LiFiStepExtended, allowUserInteraction: boolean, switchChainHook?: SwitchChainHook -): Promise => { +): Promise => { // if we are already on the correct chain we can proceed directly - const currentChainId = await walletClient.getChainId() + const currentChainId = await getChainId(client) if (currentChainId === step.action.fromChainId) { - return walletClient + return client } // -> set status message @@ -49,8 +50,11 @@ export const switchChain = async ( } try { - const updatedWalletClient = await switchChainHook?.(step.action.fromChainId) - const updatedChainId = await updatedWalletClient?.getChainId() + const updatedClient = await switchChainHook?.(step.action.fromChainId) + let updatedChainId + if (updatedClient) { + updatedChainId = await getChainId(updatedClient) + } if (updatedChainId !== step.action.fromChainId) { throw new ProviderError( LiFiErrorCode.ChainSwitchError, @@ -64,7 +68,7 @@ export const switchChain = async ( 'DONE' ) statusManager.updateExecution(step, 'PENDING') - return updatedWalletClient + return updatedClient } catch (error: any) { statusManager.updateProcess(step, switchProcess.type, 'FAILED', { error: { diff --git a/src/core/EVM/switchChain.unit.spec.ts b/src/core/EVM/switchChain.unit.spec.ts index ec7c94e4..1ec71313 100644 --- a/src/core/EVM/switchChain.unit.spec.ts +++ b/src/core/EVM/switchChain.unit.spec.ts @@ -1,5 +1,5 @@ import type { LiFiStep } from '@lifi/types' -import type { WalletClient } from 'viem' +import type { Client } from 'viem' import type { Mock } from 'vitest' import { beforeEach, describe, expect, it, vi } from 'vitest' import { buildStepObject } from '../../../tests/fixtures.js' @@ -7,11 +7,11 @@ import type { StatusManager } from '../StatusManager.js' import type { ExecutionOptions } from '../types.js' import { switchChain } from './switchChain.js' -let walletClient: WalletClient, +let client: Client, step: LiFiStep, statusManager: StatusManager, hooks: ExecutionOptions, - getChainIdMock: Mock, + requestMock: Mock, switchChainHookMock: Mock, findOrCreateProcessMock: Mock, updateExecutionMock: Mock, @@ -19,11 +19,6 @@ let walletClient: WalletClient, describe('switchChain', () => { beforeEach(() => { - getChainIdMock = vi.fn() - walletClient = { - getChainId: getChainIdMock, - } as unknown as WalletClient - switchChainHookMock = vi.fn() hooks = { switchChainHook: switchChainHookMock, @@ -31,6 +26,11 @@ describe('switchChain', () => { step = buildStepObject({ includingExecution: false }) + requestMock = vi.fn(() => 1) + client = { + request: requestMock, + } as unknown as Client + findOrCreateProcessMock = vi.fn() updateExecutionMock = vi.fn() updateProcessMock = vi.fn() @@ -45,19 +45,19 @@ describe('switchChain', () => { describe('when the chain is already correct', () => { beforeEach(() => { - getChainIdMock.mockResolvedValue(step.action.fromChainId) + requestMock.mockResolvedValue(step.action.fromChainId) }) - it('should return the WalletClient and do nothing else', async () => { - const updatedWalletClient = await switchChain( - walletClient, + it('should return the connector client and do nothing else', async () => { + const updatedClient = await switchChain( + client, statusManager, step, true, hooks.switchChainHook ) - expect(updatedWalletClient).toEqual(walletClient) + expect(updatedClient).toEqual(client) expect(statusManager.initExecutionObject).not.toHaveBeenCalled() expect(hooks.switchChainHook).not.toHaveBeenCalled() }) @@ -65,21 +65,21 @@ describe('switchChain', () => { describe('when the chain is not correct', () => { beforeEach(() => { - getChainIdMock.mockResolvedValueOnce(1) + requestMock.mockResolvedValueOnce(1) findOrCreateProcessMock.mockReturnValue({ type: 'SWITCH_CHAIN' }) }) describe('when allowUserInteraction is false', () => { it('should initialize the status manager and abort', async () => { - const updatedWalletClient = await switchChain( - walletClient, + const updatedClient = await switchChain( + client, statusManager, step, false, hooks.switchChainHook ) - expect(updatedWalletClient).toBeUndefined() + expect(updatedClient).toBeUndefined() expect(statusManager.initExecutionObject).toHaveBeenCalled() expect(statusManager.findOrCreateProcess).toHaveBeenCalled() @@ -98,7 +98,7 @@ describe('switchChain', () => { it('should throw the error', async () => { await expect( switchChain( - walletClient, + client, statusManager, step, true, @@ -115,13 +115,13 @@ describe('switchChain', () => { describe("when the switchChainHook doesn't change the chain", () => { beforeEach(() => { - switchChainHookMock.mockResolvedValue(walletClient) + switchChainHookMock.mockResolvedValue(client) }) it('should throw the error', async () => { await expect( switchChain( - walletClient, + client, statusManager, step, true, @@ -137,19 +137,19 @@ describe('switchChain', () => { }) describe('when the switchChainHook changes the chain', () => { - let newWalletClient: WalletClient + let newClient: Client beforeEach(() => { - newWalletClient = { - getChainId: () => Promise.resolve(step.action.fromChainId), - } as unknown as WalletClient + newClient = { + request: () => Promise.resolve(step.action.fromChainId), + } as unknown as Client - switchChainHookMock.mockResolvedValue(newWalletClient) + switchChainHookMock.mockResolvedValue(newClient) }) - it('should return the updated WalletClient', async () => { - const updatedWalletClient = await switchChain( - walletClient, + it('should return the updated connector client', async () => { + const updatedClient = await switchChain( + client, statusManager, step, true, @@ -159,7 +159,7 @@ describe('switchChain', () => { expect(switchChainHookMock).toHaveBeenCalledWith( step.action.fromChainId ) - expect(updatedWalletClient).toEqual(newWalletClient) + expect(updatedClient).toEqual(newClient) expect(statusManager.updateProcess).toHaveBeenCalledWith( step, 'SWITCH_CHAIN', diff --git a/src/core/EVM/types.ts b/src/core/EVM/types.ts index 51b0de09..43856854 100644 --- a/src/core/EVM/types.ts +++ b/src/core/EVM/types.ts @@ -1,10 +1,10 @@ import { ChainType, type BaseToken } from '@lifi/types' -import type { Hash, WalletClient } from 'viem' +import type { Client, Hash } from 'viem' import type { SwitchChainHook } from '../types.js' import { type SDKProvider } from '../types.js' export interface EVMProviderOptions { - getWalletClient?: () => Promise + getWalletClient?: () => Promise switchChain?: SwitchChainHook multisig?: MultisigConfig } @@ -35,7 +35,7 @@ export type TokenSpenderAllowance = { } export interface ApproveTokenRequest { - walletClient: WalletClient + walletClient: Client token: BaseToken spenderAddress: string amount: bigint @@ -46,7 +46,7 @@ export interface ApproveTokenRequest { } export interface RevokeApprovalRequest { - walletClient: WalletClient + walletClient: Client token: BaseToken spenderAddress: string } @@ -63,7 +63,7 @@ export interface MultisigTransaction { } export interface MultisigConfig { - isMultisigWalletClient: boolean + isMultisigClient: boolean getMultisigTransactionDetails: ( txHash: Hash, fromChainId: number, diff --git a/src/core/EVM/utils.ts b/src/core/EVM/utils.ts index 83dcccf5..4f2046b7 100644 --- a/src/core/EVM/utils.ts +++ b/src/core/EVM/utils.ts @@ -1,12 +1,13 @@ import { type ChainId } from '@lifi/types' -import type { PublicClient, Transaction } from 'viem' +import type { Client, Transaction } from 'viem' +import { getBlock } from 'viem/actions' import { config } from '../../config.js' import { median } from '../../utils/median.js' export const getMaxPriorityFeePerGas = async ( - client: PublicClient + client: Client ): Promise => { - const block = await client.getBlock({ + const block = await getBlock(client, { includeTransactions: true, }) diff --git a/src/core/EVM/waitForTransactionReceipt.ts b/src/core/EVM/waitForTransactionReceipt.ts index e83e95e2..a892add0 100644 --- a/src/core/EVM/waitForTransactionReceipt.ts +++ b/src/core/EVM/waitForTransactionReceipt.ts @@ -1,33 +1,32 @@ import type { ChainId } from '@lifi/types' import type { Chain, + Client, Hash, - PublicClient, ReplacementReason, ReplacementReturnType, TransactionReceipt, - WalletClient, } from 'viem' -import { publicActions } from 'viem' +import { waitForTransactionReceipt as waitForTransactionReceiptInternal } from 'viem/actions' import { LiFiErrorCode, TransactionError } from '../../utils/index.js' import { getPublicClient } from './publicClient.js' import { retryCount, retryDelay } from './utils.js' interface WaitForTransactionReceiptProps { - walletClient: WalletClient + client: Client chainId: ChainId txHash: Hash onReplaced?: (response: ReplacementReturnType) => void } export async function waitForTransactionReceipt({ - walletClient, + client, chainId, txHash, onReplaced, }: WaitForTransactionReceiptProps): Promise { let { transactionReceipt, replacementReason } = await waitForReceipt( - walletClient.extend(publicActions), + client, txHash, onReplaced ) @@ -56,7 +55,7 @@ export async function waitForTransactionReceipt({ } async function waitForReceipt( - client: PublicClient | WalletClient, + client: Client, txHash: Hash, onReplaced?: (response: ReplacementReturnType) => void ): Promise<{ @@ -67,9 +66,7 @@ async function waitForReceipt( let transactionReceipt: TransactionReceipt | undefined try { - transactionReceipt = await ( - client as PublicClient - ).waitForTransactionReceipt({ + transactionReceipt = await waitForTransactionReceiptInternal(client, { hash: txHash, onReplaced: (response) => { replacementReason = response.reason diff --git a/src/core/execution.unit.spec.ts b/src/core/execution.unit.spec.ts index 5498689c..bbf1845f 100644 --- a/src/core/execution.unit.spec.ts +++ b/src/core/execution.unit.spec.ts @@ -1,5 +1,6 @@ import { setupServer } from 'msw/node' -import type { WalletClient } from 'viem' +import type { Client } from 'viem' +import { sendTransaction } from 'viem/actions' import { afterAll, afterEach, @@ -15,14 +16,14 @@ import { requestSettings } from '../request.js' import { executeRoute } from './execution.js' import { lifiHandlers } from './execution.unit.handlers.js' -let walletClient: Partial +let client: Partial vi.mock('../balance', () => ({ checkBalance: vi.fn(() => Promise.resolve([])), })) vi.mock('../execution/switchChain', () => ({ - switchChain: vi.fn(() => Promise.resolve(walletClient)), + switchChain: vi.fn(() => Promise.resolve(client)), })) vi.mock('../allowance/getAllowance', () => ({ @@ -42,12 +43,12 @@ describe.skip('Should pick up gas from wallet client estimation', () => { requestSettings.retries = 0 vi.clearAllMocks() - walletClient = { + client = { sendTransaction: () => Promise.resolve('0xabc'), getChainId: () => Promise.resolve(137), getAddresses: () => Promise.resolve(['0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0']), - } as Partial + } as Partial }) afterEach(() => server.resetHandlers()) @@ -62,7 +63,7 @@ describe.skip('Should pick up gas from wallet client estimation', () => { await executeRoute(route) - expect(walletClient.sendTransaction).toHaveBeenCalledWith({ + expect(sendTransaction).toHaveBeenCalledWith(client, { gasLimit: 125000n, gasPrice: 100000n, // TODO: Check the cause for gasLimit being outside transactionRequest. Currently working as expected in widget diff --git a/src/core/types.ts b/src/core/types.ts index 40257f7b..c3997964 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -7,7 +7,7 @@ import type { Token, TokenAmount, } from '@lifi/types' -import type { WalletClient } from 'viem' +import type { Client } from 'viem' export interface SDKProvider { readonly type: ChainType @@ -82,9 +82,7 @@ export type TransactionRequestUpdateHook = ( updatedTxRequest: TransactionRequestParameters ) => Promise -export type SwitchChainHook = ( - chainId: number -) => Promise +export type SwitchChainHook = (chainId: number) => Promise export interface AcceptSlippageUpdateHookParams { toToken: Token diff --git a/src/version.ts b/src/version.ts index 3fbaec04..db21a732 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,2 +1,2 @@ export const name = '@lifi/sdk' -export const version = '3.1.5' +export const version = '3.2.0-alpha.1'