@biconomy/ecosystem
Version:
Testing infrastructure for abstractjs with ephemeral networks
130 lines (113 loc) • 3.13 kB
text/typescript
import {
EntrypointAbi,
createSmartAccountClient,
toNexusAccount
} from "@biconomy/abstractjs"
import {
http,
type Address,
encodeFunctionData,
erc20Abi,
parseEther
} from "viem"
import { toPackedUserOperation } from "viem/account-abstraction"
import {
ENTRYPOINT_V07_ADDRESS,
FREE_MINT_ERC20,
NEXUS_IMPLEMENTATION_ADDRESS,
getBalance,
toClients
} from "../src"
import type { Infra } from "../src/toEcosystem"
export const benchmark7702 = async ({
bundler,
network: { rpcUrl, chain }
}: Infra) => {
const { publicClient, walletClients, testClient, accounts } = await toClients(
{
rpcUrl,
chain
}
)
const nexusAccount = await toNexusAccount({
signer: accounts[0],
chain,
transport: http(rpcUrl)
})
const nexusAccountClient = createSmartAccountClient({
account: nexusAccount,
chain,
transport: http(bundler.url),
mock: true
})
await testClient.setBalance({
address: nexusAccount.address,
value: parseEther("10")
})
const eip7702Account = accounts[8]
const someWallet = accounts[9]
const eip7702AccountClient = walletClients[8]
const someWalletClient = walletClients[9]
const userOp = await nexusAccountClient.prepareUserOperation({
calls: [
{
to: FREE_MINT_ERC20,
value: 0n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: [someWallet.address, parseEther("1")]
})
}
]
})
// update sender to be the eip7702Account address
userOp.sender = eip7702Account.address
userOp.factory = "0x"
userOp.factoryData = "0x"
const updatedHash = nexusAccount.getUserOpHash(userOp)
const sig = await eip7702Account.signMessage({
message: { raw: updatedHash }
})
userOp.signature = sig
const nonce = await publicClient.getTransactionCount({
address: eip7702Account.address
})
// sign eip7702 authorization with viem
const authorization = await eip7702AccountClient.prepareAuthorization({
account: eip7702Account,
contractAddress: NEXUS_IMPLEMENTATION_ADDRESS,
chainId: 0,
nonce: nonce
})
const signedAuthorization =
await eip7702AccountClient.signAuthorization(authorization)
const packedUserOp = toPackedUserOperation(userOp)
const balanceBefore = await getBalance(
publicClient,
someWallet.address,
FREE_MINT_ERC20
)
const handleOpsHash = await someWalletClient.sendTransaction({
authorizationList: [signedAuthorization],
data: encodeFunctionData({
abi: EntrypointAbi,
functionName: "handleOps",
args: [[packedUserOp], eip7702Account.address]
}),
to: ENTRYPOINT_V07_ADDRESS
})
// get the receipt
const receipt = await publicClient.waitForTransactionReceipt({
hash: handleOpsHash
})
const balanceAfter = await getBalance(
publicClient,
someWallet.address,
FREE_MINT_ERC20
)
if (balanceAfter - balanceBefore !== parseEther("1")) {
throw new Error("Balance has not changed properly")
}
console.log("Delegate EOA to Nexus via 7702 + send ERC20", receipt.gasUsed)
}