UNPKG

@fastlane-labs/shbundler-sdk

Version:

SDK for interacting with Fastlane's 4337 ShBundler

188 lines (185 loc) 5.38 kB
// src/client.ts import { createPublicClient, createWalletClient, http } from "viem"; import { createBundlerClient, createPaymasterClient, entryPoint07Address, entryPoint08Address, sendUserOperation as sendUserOperationViem } from "viem/account-abstraction"; import { toSimpleSmartAccount, toSafeSmartAccount } from "permissionless/accounts"; import { toAccount } from "viem/accounts"; import { createSmartAccountClient } from "permissionless"; // src/utils/gas.ts import { hexToBigInt } from "viem"; async function getUserOperationGasPrice(bundlerClient) { const resultEncoded = await bundlerClient.request({ method: "gas_getUserOperationGasPrice", params: [] }); return { maxFeePerGas: hexToBigInt(resultEncoded.standard.maxFeePerGas), maxPriorityFeePerGas: hexToBigInt(resultEncoded.standard.maxPriorityFeePerGas) }; } // src/utils/networks.ts async function fetchNetworkDefaults(chainId) { const url = "https://raw.githubusercontent.com/FastLane-Labs/shbundler-sdk/main/configs/networks.json"; const res = await fetch(url); const data = await res.json(); return data[chainId] || null; } // src/client.ts async function buildShBundlerSDK({ smartAccount, rpcUrl, chain, bundlerUrl, paymasterUrl, paymasterAddress }) { const publicClient = createPublicClient({ transport: http(rpcUrl), chain }); const walletClient = createWalletClient({ transport: http(rpcUrl), account: smartAccount }); const paymasterClient = createPaymasterClient({ transport: http(paymasterUrl) }); let bundlerClient; bundlerClient = createBundlerClient({ transport: http(bundlerUrl), name: "shBundler", account: smartAccount, client: publicClient, paymaster: paymasterClient, userOperation: { estimateFeesPerGas: async () => getUserOperationGasPrice(bundlerClient) } }); const sendUserOperation = async ({ to, data, chain: chain2, paymasterContext }) => { const dynamicSmartAccountClient = createSmartAccountClient({ client: publicClient, chain: chain2, bundlerTransport: http(bundlerUrl), account: smartAccount, userOperation: { estimateFeesPerGas: async () => getUserOperationGasPrice(bundlerClient) }, paymaster: paymasterClient, paymasterContext }); return sendUserOperationViem(dynamicSmartAccountClient, { account: smartAccount, calls: [{ to, data }] }); }; return { publicClient, walletClient, smartAccount, paymasterClient, bundlerClient, sendUserOperation }; } async function createShBundlerClient(opts) { const { signer, rpcUrl, chain, bundlerUrl: inputBundlerUrl, paymasterUrl: inputPaymasterUrl, paymasterAddress: inputPaymasterAddress, entryPointVersion = "0.8" } = opts; if (!signer || !rpcUrl || !chain) { throw new Error("signer, rpcUrl, and chain are required"); } const publicClient = createPublicClient({ transport: http(rpcUrl), chain }); const chainId = await publicClient.getChainId(); const defaults = await fetchNetworkDefaults(chainId) || {}; const bundlerUrl = inputBundlerUrl || defaults.bundlerUrl; const paymasterUrl = inputPaymasterUrl || defaults.paymasterUrl; const paymasterAddress = inputPaymasterAddress || defaults.paymasterAddress; if (!bundlerUrl || !paymasterUrl || !paymasterAddress) { throw new Error("Missing bundlerUrl, paymasterUrl, or paymasterAddress and no defaults found"); } const entryPointAddress = entryPointVersion === "0.7" ? entryPoint07Address : entryPoint08Address; const smartAccountSimple = await toSimpleSmartAccount({ client: publicClient, entryPoint: { address: entryPointAddress, version: entryPointVersion }, owner: toAccount(signer) }); const smartAccountV08MonadTestnet = await toSafeSmartAccount({ client: publicClient, entryPoint: { address: entryPoint08Address, version: "0.7" }, owners: [signer], version: "1.4.1", safe4337ModuleAddress: "0x02b336F533F2de3F221540eF56583e9cb8E65203", safeProxyFactoryAddress: "0xd9d2Ba03a7754250FDD71333F444636471CACBC4", safeSingletonAddress: "0x639245e8476E03e789a244f279b5843b9633b2E7", safeModuleSetupAddress: "0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47", multiSendAddress: "0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C", multiSendCallOnlyAddress: "0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC" }); const smartAccount = chainId !== 10143 ? smartAccountSimple : entryPointVersion === "0.7" ? smartAccountSimple : smartAccountV08MonadTestnet; return buildShBundlerSDK({ smartAccount, rpcUrl, chain, bundlerUrl, paymasterUrl, paymasterAddress }); } async function createShBundlerClientFromSmartAccount(opts) { const { smartAccount, rpcUrl, chain, bundlerUrl, paymasterUrl, paymasterAddress } = opts; if (!rpcUrl || !chain || !bundlerUrl || !paymasterUrl || !paymasterAddress) { throw new Error("All fields are required to use a precomputed smartAccount"); } return buildShBundlerSDK({ smartAccount, rpcUrl, chain, bundlerUrl, paymasterUrl, paymasterAddress }); } export { createShBundlerClient, createShBundlerClientFromSmartAccount }; //# sourceMappingURL=index.mjs.map