Module Reference
Complete API documentation for all functions and hooks used in the Compose SDK.
React Hooks
useSmartAccount
Hook to create and access a smart account. Returns a React Query result with the smart account data.
import { useSmartAccount } from '@ssv-labs/compose-sdk/react';
function useSmartAccount({
chainId,
multiChainIds
}: {
chainId: number;
multiChainIds?: number[];
}): UseQueryResult<SmartAccountResult>;
Parameters
chainId(number): Chain ID for the primary chainmultiChainIds?(number[]): Optional array of chain IDs for multi-chain support. When provided, the smart account will be configured to work across all specified chains with the same address.
Returns
UseQueryResult<SmartAccountResult>: React Query result object with:
data:SmartAccountResult | undefined- Smart account object containing:account: Smart account instance withaddressproperty andcreateUserOp()methodpublicClient: Public client for the chain
isLoading:boolean- True while the account is being createdisError:boolean- True if an error occurrederror:Error | null- Error object if creation failed
Important Notes
- The hook returns a React Query result object, not
{ data, isLoading } - Always access properties via
smartAccountQuery.data,smartAccountQuery.isLoading, etc. - The
multiChainIdsparameter is required for cross-chain functionality - Access the address via
smartAccountQuery.data?.account?.address - The smart account address will be the same across all chains when using
multiChainIds
Example
import { useSmartAccount } from '@ssv-labs/compose-sdk/react';
import { rollupA, rollupB } from '@ssv-labs/compose-sdk';
import { useAccount } from 'wagmi';
function MyComponent() {
const { isConnected } = useAccount();
// Hook returns a query object
const smartAccountQuery = useSmartAccount({
chainId: rollupA.id,
multiChainIds: [rollupA.id, rollupB.id]
});
if (!isConnected) return <div>Please connect your wallet</div>;
if (smartAccountQuery.isLoading) return <div>Creating smart account...</div>;
// Access account via query.data?.account
const smartAccount = smartAccountQuery.data?.account;
const publicClient = smartAccountQuery.data?.publicClient;
return (
<div>
<p>Address: {smartAccount?.address}</p>
</div>
);
}
Core Functions
composePreparedUserOps
Composes multiple prepared user operations for atomic cross-chain execution. User operations must be prepared using prepareUserOperation from viem/account-abstraction before composing.
import { composePreparedUserOps } from '@ssv-labs/compose-sdk';
import { prepareUserOperation } from 'viem/account-abstraction';
function composePreparedUserOps(
operations: PreparedUserOpInput[]
): Promise<ComposedUserOps>;
Parameters
operations(PreparedUserOpInput[]): Array of objects, each containing:account: Smart account instance (fromuseSmartAccount().data?.account)publicClient: Public client for the chain (fromuseSmartAccount().data?.publicClient)userOp: Prepared user operation (fromprepareUserOperation)
Returns
Promise<ComposedUserOps>: Object with:
send():() => Promise<SendResult>- Function that sends the transactions and returns:wait():() => Promise<TransactionReceipt[]>- Function that waits for all transaction receipts
builds:TransactionBuild[]- Array of transaction builds with.hashpropertyexplorerUrls:string[]- Array of explorer URLs for each transaction
Example - Single Chain
import { composePreparedUserOps } from '@ssv-labs/compose-sdk';
import { prepareUserOperation } from 'viem/account-abstraction';
import { encodeFunctionData, erc20Abi } from 'viem';
// Step 1: Create user operation with multiple calls
const { userOp } = await smartAccount.createUserOp([
{
to: tokenAddress,
value: 0n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: [spenderAddress, amount]
})
},
{
to: tokenAddress,
value: 0n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: 'transfer',
args: [recipientAddress, amount]
})
}
]);
// Step 2: Prepare the user operation
const preparedUserOp = await prepareUserOperation(publicClient, userOp);
// Step 3: Compose and send
const { send, explorerUrls } = await composePreparedUserOps([{
account: smartAccount,
publicClient: publicClient,
userOp: preparedUserOp,
}]);
// Step 4: Send and wait for receipts
const { wait } = await send();
const receipts = await wait();
Example - Multiple Chains
// Create user operations for both chains
const { userOp: userOpA } = await smartAccountA.createUserOp([/* calls */]);
const { userOp: userOpB } = await smartAccountB.createUserOp([/* calls */]);
// Prepare user operations
const preparedUserOpA = await prepareUserOperation(publicClientA, userOpA);
const preparedUserOpB = await prepareUserOperation(publicClientB, userOpB);
// Compose operations from both chains
const { send, builds, explorerUrls } = await composePreparedUserOps([
{
account: smartAccountA,
publicClient: publicClientA,
userOp: preparedUserOpA,
},
{
account: smartAccountB,
publicClient: publicClientB,
userOp: preparedUserOpB,
},
]);
// Send to sequencer and wait for receipts
const { wait } = await send();
const [receiptA, receiptB] = await wait();
// Get transaction hashes
const hashes = builds.map(b => b.hash);
Smart Account Methods
account.createUserOp
Creates a user operation from an array of calls. This method is available on the smart account instance returned by useSmartAccount().data?.account.
account.createUserOp(calls: Call[]): Promise<{ userOp: UserOperation }>;
Parameters
calls(Call[]): Array of call objects, each containing:to:Address- Target contract addressvalue:bigint- ETH value to send (in wei)data:Hex- Encoded function call data (useencodeFunctionDatafrom viem)
Returns
Promise<{ userOp: UserOperation }>: Object containing:
userOp:UserOperation- The user operation data (must be prepared before composing)
Example
import { encodeFunctionData, erc20Abi } from 'viem';
// Create user operation with multiple calls
const { userOp } = await smartAccount.createUserOp([
{
to: '0x...', // Token address
value: 0n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: ['0x...', 10000000000000000000n]
})
},
{
to: '0x...', // Another token
value: 0n,
data: encodeFunctionData({
abi: erc20Abi,
functionName: 'transfer',
args: ['0x...', 5000000000000000000n]
})
}
]);
// Then prepare the user operation before composing
import { prepareUserOperation } from 'viem/account-abstraction';
const preparedUserOp = await prepareUserOperation(publicClient, userOp);
Chain Exports
The SDK exports predefined chain configurations for Compose rollups:
import { rollupA, rollupB } from '@ssv-labs/compose-sdk';
// Use in useSmartAccount
const smartAccountQuery = useSmartAccount({
chainId: rollupA.id,
multiChainIds: [rollupA.id, rollupB.id]
});
Available Chains
rollupA: Chain ID 11113rollupB: Chain ID 22224
Helper Functions
Encoding Function Calls
Use encodeFunctionData from viem to encode function calls for user operations:
import { encodeFunctionData, erc20Abi } from 'viem';
// Encode an approval
const approveData = encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: ['0x...', 10000000000000000000n]
});
// Encode a transfer
const transferData = encodeFunctionData({
abi: erc20Abi,
functionName: 'transfer',
args: ['0x...', 5000000000000000000n]
});
Preparing User Operations
Use prepareUserOperation from viem/account-abstraction to prepare user operations before composing:
import { prepareUserOperation } from 'viem/account-abstraction';
// After creating a user operation
const { userOp } = await smartAccount.createUserOp([/* calls */]);
// Prepare it before composing
const preparedUserOp = await prepareUserOperation(publicClient, userOp);