buildUserOperationFromTx
Converts a traditional Ethereum transaction and builds an unsigned UserOperation
(UO) struct with all middleware of the SmartAccountClient
run through the client middleware pipeline.
Learn more about ClientMiddleware
to learn more about the internals of SmartAccountClient
middleware pipeline that builds the user operation request given the user transaction call data and the operating account data.
Note
Note that to
, data
, value
, maxFeePerGas
, maxPriorityFeePerGas
fields of the transaction request type are considered and used to build the user operation from the transaction, while other fields are not used.
Usage
import type { RpcTransactionRequest } from "viem";
import { smartAccountClient } from "./smartAccountClient";
// buildUserOperationFromTx converts a traditional Ethereum transaction and returns
// the unsigned user operation struct after constructing the user operation struct
// through the middleware pipeline
const tx: RpcTransactionRequest = {
from, // ignored
to,
data: encodeFunctionData({
abi: ContractABI.abi,
functionName: "func",
args: [arg1, arg2, ...],
}),
};
const uoStruct = await smartAccountClient.buildUserOperationFromTx(tx);
// signUserOperation signs the above unsigned user operation struct built
// using the account connected to the smart account client
const request = await smartAccountClient.signUserOperation({ uoStruct });
// You can use the BundlerAction `sendRawUserOperation` (packages/core/src/actions/bundler/sendRawUserOperation.ts)
// to send the signed user operation request to the bundler, requesting the bundler to send the signed uo to the
// EntryPoint contract pointed at the entryPoint address parameter
const entryPointAddress = client.account.getEntryPoint().address;
const uoHash = await smartAccountClient.sendRawUserOperation({ request, entryPoint: entryPointAddress });
import { createMultiOwnerModularAccount } from "@alchemy/aa-accounts";
import {
LocalAccountSigner,
SmartAccountSigner,
createSmartAccountClient,
polygonMumbai,
} from "@alchemy/aa-core";
import { http } from "viem";
const chain = polygonMumbai;
const signer: SmartAccountSigner = LocalAccountSigner.mnemonicToAccountSigner(
"YOUR_OWNER_MNEMONIC"
);
const rpcTransport = http("https://polygon-mumbai.g.alchemy.com/v2/demo");
export const smartAccountClient = createSmartAccountClient({
transport: rpcTransport,
chain,
account: await createMultiOwnerModularAccount({
transport: rpcTransport,
chain,
signer,
}),
});
Returns
Promise<BuildUserOperationFromTransactionsResult>
A Promise
containing the unsigned UO struct converted from the input transaction with all the middleware run on the resulting UO
Parameters
SendTransactionParameters
Same as viem
TransactionRequest
, but with the from
field excluded
export type SendTransactionParameters<
TChain extends Chain | undefined = Chain | undefined,
TAccount extends Account | undefined = Account | undefined,
TChainOverride extends Chain | undefined = Chain | undefined,
///
derivedChain extends Chain | undefined = DeriveChain<TChain, TChainOverride>
> = UnionOmit<FormattedTransactionRequest<derivedChain>, "from"> &
GetAccountParameter<TAccount> &
GetChainParameter<TChain, TChainOverride>;
overrides?:
UserOperationOverrides
Optional parameter where you can specify override values for maxFeePerGas
, maxPriorityFeePerGas
, callGasLimit
, preVerificationGas
, verificationGasLimit
, paymasterAndData
, or nonceKey
for the user operation request. You can also specify a stateOverride
to be passed into eth_estimateUserOperationGas
during gas estimation.
account?: TAccount extends SmartContractAccount | undefined
When using this action, if the SmartContractAccount
has not been connected to the SmartAccountClient
(e.g. SmartAccountClient
not instantiated with your SmartContractAccount
during createSmartAccountClient
). If the account is not connected, you can specify the SmartContractAccount
instance to use for the function call.