113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
|
|
import { ethers, providers } from "ethers";
|
||
|
|
import { SmartWalletConfig, SmartWalletType } from "../../types";
|
||
|
|
|
||
|
|
// ERC-4337 Account Abstraction support
|
||
|
|
// This is a placeholder implementation - full implementation would require
|
||
|
|
// bundler service integration and UserOperation creation
|
||
|
|
|
||
|
|
export interface ERC4337Config {
|
||
|
|
entryPoint: string;
|
||
|
|
factory: string;
|
||
|
|
bundlerUrl: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
const ERC4337_CONFIGS: Record<number, ERC4337Config> = {
|
||
|
|
1: {
|
||
|
|
entryPoint: "0x0576a174D229E3cFA37253523E645A78A0C91B57",
|
||
|
|
factory: "0x9406Cc6185a346906296840746125a0E44976454",
|
||
|
|
bundlerUrl: "https://bundler.eth-infinitism.com/rpc",
|
||
|
|
},
|
||
|
|
5: {
|
||
|
|
entryPoint: "0x0576a174D229E3cFA37253523E645A78A0C91B57",
|
||
|
|
factory: "0x9406Cc6185a346906296840746125a0E44976454",
|
||
|
|
bundlerUrl: "https://bundler-goerli.eth-infinitism.com/rpc",
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
export async function connectToERC4337(
|
||
|
|
accountAddress: string,
|
||
|
|
networkId: number,
|
||
|
|
provider: providers.Provider
|
||
|
|
): Promise<SmartWalletConfig | null> {
|
||
|
|
try {
|
||
|
|
// In full implementation, this would:
|
||
|
|
// 1. Verify the account is an ERC-4337 account
|
||
|
|
// 2. Fetch owners/signers from the account
|
||
|
|
// 3. Get threshold configuration
|
||
|
|
|
||
|
|
// For now, return a placeholder config
|
||
|
|
return {
|
||
|
|
id: `erc4337_${accountAddress}_${networkId}`,
|
||
|
|
type: SmartWalletType.ERC4337,
|
||
|
|
address: accountAddress,
|
||
|
|
networkId,
|
||
|
|
owners: [accountAddress], // Placeholder
|
||
|
|
threshold: 1, // Placeholder
|
||
|
|
createdAt: Date.now(),
|
||
|
|
updatedAt: Date.now(),
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Failed to connect to ERC-4337 account", error);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function createUserOperation(
|
||
|
|
to: string,
|
||
|
|
value: string,
|
||
|
|
data: string,
|
||
|
|
accountAddress: string,
|
||
|
|
networkId: number
|
||
|
|
): Promise<any> {
|
||
|
|
const config = ERC4337_CONFIGS[networkId];
|
||
|
|
if (!config) {
|
||
|
|
throw new Error(`ERC-4337 not supported on network ${networkId}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Placeholder UserOperation structure
|
||
|
|
// Full implementation would:
|
||
|
|
// 1. Get nonce from account
|
||
|
|
// 2. Calculate callData
|
||
|
|
// 3. Estimate gas
|
||
|
|
// 4. Sign with account owner
|
||
|
|
return {
|
||
|
|
sender: accountAddress,
|
||
|
|
nonce: "0x0",
|
||
|
|
initCode: "0x",
|
||
|
|
callData: data || "0x",
|
||
|
|
callGasLimit: "0x0",
|
||
|
|
verificationGasLimit: "0x0",
|
||
|
|
preVerificationGas: "0x0",
|
||
|
|
maxFeePerGas: "0x0",
|
||
|
|
maxPriorityFeePerGas: "0x0",
|
||
|
|
paymasterAndData: "0x",
|
||
|
|
signature: "0x",
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function sendUserOperation(
|
||
|
|
userOp: any,
|
||
|
|
bundlerUrl: string
|
||
|
|
): Promise<string> {
|
||
|
|
// Placeholder - full implementation would send to bundler
|
||
|
|
const response = await fetch(bundlerUrl, {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
},
|
||
|
|
body: JSON.stringify({
|
||
|
|
jsonrpc: "2.0",
|
||
|
|
id: 1,
|
||
|
|
method: "eth_sendUserOperation",
|
||
|
|
params: [userOp, "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"], // EntryPoint
|
||
|
|
}),
|
||
|
|
});
|
||
|
|
|
||
|
|
const result = await response.json();
|
||
|
|
if (result.error) {
|
||
|
|
throw new Error(result.error.message);
|
||
|
|
}
|
||
|
|
|
||
|
|
return result.result;
|
||
|
|
}
|