|
| 1 | +import type { Provider, Signer, TypedDataField } from 'ethers' |
| 2 | +import type {Address, Hash, Transport, WalletClient, PublicClient } from 'viem' |
| 3 | + |
| 4 | +import { custom, createPublicClient, createWalletClient } from 'viem' |
| 5 | +import { toAccount } from 'viem/accounts' |
| 6 | + |
| 7 | +/** Convert an ethers provider to a viem transport. */ |
| 8 | +export function ethersProviderToTransport(provider: Provider): Transport { |
| 9 | + return custom({ |
| 10 | + async request({ method, params }) { |
| 11 | + return (provider as any).send(method, params as any) |
| 12 | + }, |
| 13 | + }) |
| 14 | +} |
| 15 | + |
| 16 | +/** Convert an ethers signer to a viem LocalAccount. */ |
| 17 | +export async function ethersSignerToAccount(signer: Signer) { |
| 18 | + return toAccount({ |
| 19 | + address: (await signer.getAddress()) as unknown as Address, |
| 20 | + async signMessage({ message }) { |
| 21 | + const data = typeof message === 'string' ? message : new TextDecoder().decode(message as any) |
| 22 | + return signer.signMessage(data) as unknown as Hash |
| 23 | + }, |
| 24 | + async signTransaction(txn) { |
| 25 | + return signer.signTransaction({ |
| 26 | + chainId: txn.chainId, |
| 27 | + data: txn.data, |
| 28 | + gasLimit: txn.gas, |
| 29 | + gasPrice: txn.gasPrice, |
| 30 | + nonce: txn.nonce, |
| 31 | + to: txn.to, |
| 32 | + value: txn.value, |
| 33 | + type: txn.type === 'legacy' ? 0 : txn.type === 'eip2930' ? 1 : txn.type === 'eip1559' ? 2 : undefined, |
| 34 | + ...(txn.type && txn.accessList ? { accessList: txn.accessList } : {}), |
| 35 | + ...(txn.maxPriorityFeePerGas ? { maxPriorityFeePerGas: txn.maxPriorityFeePerGas } : {}), |
| 36 | + ...(txn.maxFeePerGas ? { maxFeePerGas: txn.maxFeePerGas } : {}), |
| 37 | + } as any) as unknown as Hash |
| 38 | + }, |
| 39 | + async signTypedData({ domain, types, message }) { |
| 40 | + const { EIP712Domain: _removed, ...rest } = types as any |
| 41 | + const signTypedData = (signer as any)._signTypedData ?? (signer as any).signTypedData |
| 42 | + return signTypedData(domain ?? {}, rest as Record<string, TypedDataField[]>, message) as unknown as Hash |
| 43 | + }, |
| 44 | + }) |
| 45 | +} |
| 46 | + |
| 47 | +/** Create a viem PublicClient from an ethers provider. */ |
| 48 | +export function ethersProviderToPublicClient(provider: Provider, chain: any): PublicClient { |
| 49 | + return createPublicClient({ chain: chain as any, transport: ethersProviderToTransport(provider) }) as unknown as PublicClient |
| 50 | +} |
| 51 | + |
| 52 | +/** Create a viem WalletClient from an ethers signer. */ |
| 53 | +export async function ethersSignerToWalletClient( |
| 54 | + signer: Signer & { provider: Provider | null }, |
| 55 | + chain: any, |
| 56 | +): Promise<WalletClient> { |
| 57 | + if (!signer.provider) { |
| 58 | + throw new Error('ethers signer must be connected to a provider') |
| 59 | + } |
| 60 | + return createWalletClient({ |
| 61 | + chain: chain as any, |
| 62 | + transport: ethersProviderToTransport(signer.provider), |
| 63 | + account: await ethersSignerToAccount(signer), |
| 64 | + }) as unknown as WalletClient |
| 65 | +} |
0 commit comments