execute
Submit one or more calls from a wallet. execute is overloaded: admin path takes (wallet, signer, calls), session path takes (session, calls).
Keystore impact
| Scenario | Touches Keystore? |
|---|---|
First admin execute on a fresh wallet | Yes (admin key registered) |
Subsequent admin execute calls | No |
Any session execute | No (session was registered at grant time) |
Admin path
The wallet's admin signs the intent. Use this for first-party operations.
const result = await execute(wallet, signer, {
to: "0xRecipient...",
value: 1_000_000_000_000_000n, // 0.001 ETH
});
console.log(result.status, result.transactionHash);Session path
A session signs the intent. Use this for agent-driven operations.
const result = await execute(session, [
{ to: "0xUniswapRouter...", data: "0x...", value: 0n },
]);Parameters
function execute(
wallet: Wallet,
signer: Signer,
calls: Call | readonly Call[],
opts?: ExecuteOptions,
): Promise<ExecuteResult>;
function execute(
session: Session,
calls: Call | readonly Call[],
opts?: ExecuteOptions,
): Promise<ExecuteResult>;
type Call = {
to: Address;
data?: Hex;
value?: bigint;
};
type ExecuteOptions = {
network?: NetworkConfig;
feeToken?: Address; // default: native (ETH)
noWait?: boolean; // return as soon as submitted, don't wait for confirmation
};Returns
type ExecuteResult = {
callsId: Hex;
status: "CONFIRMED" | "FAILED" | "PENDING";
transactionHash?: Hex;
};Notes
- First execute on a fresh wallet auto-registers the admin key in Keystore.
initialRegisterKeyis prepended transparently in the same userOp. - Empty calls is rejected.
execute(wallet, signer, [])errors. Pass at least one call. - Session execute is byte-exact. The on-chain validator matches the session's
permissions + expiry + role + publicKeyto the hash committed at grant. Persist theSessionobject verbatim. - With
noWait: true, you getstatus: "PENDING"and acallsIdto poll later.