@zerodev/sdk
Version:
A utility library for working with ERC-4337
135 lines (122 loc) • 4.23 kB
text/typescript
import { EventEmitter } from "events"
import { hexToBigInt } from "viem"
import type {
EIP1193Parameters,
EIP1193RequestFn,
Hash,
Hex,
SendTransactionParameters
} from "viem"
import type { KernelAccountClient } from "../clients/kernelAccountClient.js"
export class KernelEIP1193Provider extends EventEmitter {
private kernelClient: KernelAccountClient
constructor(kernelClient: KernelAccountClient) {
super()
this.kernelClient = kernelClient
}
async request({
method,
params = []
}: EIP1193Parameters): ReturnType<EIP1193RequestFn> {
switch (method) {
case "eth_requestAccounts":
return this.handleEthRequestAccounts()
case "eth_accounts":
return this.handleEthAccounts()
case "eth_sendTransaction":
return this.handleEthSendTransaction(params)
case "eth_sign":
return this.handleEthSign(params as [string, string])
case "personal_sign":
return this.handlePersonalSign(params as [string, string])
case "eth_signTypedData":
case "eth_signTypedData_v4":
return this.handleEthSignTypedDataV4(params as [string, string])
default:
return this.kernelClient.transport.request({ method, params })
}
}
private async handleEthRequestAccounts(): Promise<string[]> {
if (!this.kernelClient.account) {
return []
}
return [this.kernelClient.account.address]
}
private async handleEthAccounts(): Promise<string[]> {
if (!this.kernelClient.account) {
return []
}
return [this.kernelClient.account.address]
}
private async handleEthSendTransaction(params: unknown): Promise<Hash> {
const [tx] = params as [
Omit<SendTransactionParameters, "value"> & { value?: Hex }
]
return this.kernelClient.sendTransaction({
...tx,
value: tx.value ? hexToBigInt(tx.value) : undefined
} as SendTransactionParameters)
}
private async handleEthSign(params: [string, string]): Promise<string> {
if (!this.kernelClient?.account) {
throw new Error("account not connected!")
}
const [address, message] = params
if (
address.toLowerCase() !==
this.kernelClient.account.address.toLowerCase()
) {
throw new Error(
"cannot sign for address that is not the current account"
)
}
return this.kernelClient.signMessage({
message,
account: this.kernelClient.account
})
}
private async handlePersonalSign(
params: [string, string]
): Promise<string> {
if (!this.kernelClient?.account) {
throw new Error("account not connected!")
}
const [message, address] = params
if (
address.toLowerCase() !==
this.kernelClient.account.address.toLowerCase()
) {
throw new Error(
"cannot sign for address that is not the current account"
)
}
return this.kernelClient.signMessage({
message,
account: this.kernelClient.account
})
}
private async handleEthSignTypedDataV4(
params: [string, string]
): Promise<string> {
if (!this.kernelClient?.account) {
throw new Error("account not connected!")
}
const [address, typedDataJSON] = params
const typedData = JSON.parse(typedDataJSON)
if (
address.toLowerCase() !==
this.kernelClient.account.address.toLowerCase()
) {
throw new Error(
"cannot sign for address that is not the current account"
)
}
return this.kernelClient.signTypedData({
account: this.kernelClient.account,
domain: typedData.domain,
types: typedData.types,
message: typedData.message,
primaryType: typedData.primaryType
})
}
}