Skip to Content

Transactions

Hooks for sending UserOperations, tracking transaction status, and viewing transaction history.

The useSendTransaction hook builds and submits a UserOperation through the account abstraction bundler. Combine it with useUserOpStatus to track confirmation state.

Import

import { useSendTransaction, useUserOpStatus } from '@embarkai/ui-kit'

Basic Usage

import { useSendTransaction } from '@embarkai/ui-kit' function SendForm() { const { sendTransaction, isLoading, error, userOpHash } = useSendTransaction() const handleSend = async () => { await sendTransaction({ to: '0x1234567890abcdef1234567890abcdef12345678', value: '0.1', }) } return ( <div> <button onClick={handleSend} disabled={isLoading}> {isLoading ? 'Sending...' : 'Send 0.1 LUMIA'} </button> {error && <p className="error">{error}</p>} {userOpHash && <p>UserOp: {userOpHash}</p>} </div> ) }

SendTransactionParams

ParameterTypeRequiredDescription
to`0x${string}`YesRecipient address.
valuestringYesAmount to send (human-readable, e.g., '1.5').
data`0x${string}`NoCalldata for contract interactions.
assetType'native' | 'erc20' | 'erc721' | 'erc1155' | 'erc3643'NoToken standard. Defaults to 'native'.
tokenAddress`0x${string}`NoContract address of the token (required for non-native).
tokenIdstringNoToken ID for ERC-721 and ERC-1155 transfers.
decimalsnumberNoToken decimals (required for ERC-20 if not auto-detected).

Return Value

PropertyTypeDescription
sendTransaction(params: SendTransactionParams) => Promise<string | null>Submit a UserOperation. Returns the UserOp hash on success.
isLoadingbooleantrue while the operation is being signed and submitted.
errorstring | nullError message if the operation failed.
userOpHashstring | nullThe hash of the submitted UserOperation.
reset() => voidClear the current error and userOpHash state.

Asset Type Examples

Native Token Transfer

await sendTransaction({ to: '0xRecipientAddress...', value: '1.0', })

ERC-20 Transfer

await sendTransaction({ to: '0xRecipientAddress...', value: '100', assetType: 'erc20', tokenAddress: '0xTokenContractAddress...', decimals: 18, })

ERC-721 (NFT) Transfer

await sendTransaction({ to: '0xRecipientAddress...', value: '1', assetType: 'erc721', tokenAddress: '0xNFTContractAddress...', tokenId: '42', })

ERC-1155 Transfer

await sendTransaction({ to: '0xRecipientAddress...', value: '5', assetType: 'erc1155', tokenAddress: '0xMultiTokenAddress...', tokenId: '7', })

Tracking with useUserOpStatus

After submitting a transaction, use useUserOpStatus to poll for confirmation:

import { useSendTransaction, useUserOpStatus } from '@embarkai/ui-kit' function TrackedSend() { const { sendTransaction, userOpHash, isLoading } = useSendTransaction() const { state, txHash, receipt } = useUserOpStatus({ userOpHash, pollMs: 1000, maxPollTimeMs: 60000, onStateChange: (state) => console.log('State:', state), onTxHash: (hash) => console.log('Tx hash:', hash), onReceipt: (receipt) => console.log('Confirmed:', receipt), }) return ( <div> <button onClick={() => sendTransaction({ to: '0x...', value: '0.01' })} disabled={isLoading} > Send </button> {state !== 'waiting' && <p>Status: {state}</p>} {txHash && <p>Transaction: {txHash}</p>} </div> ) }

useUserOpStatus Options

OptionTypeDefaultDescription
userOpHashstring | nullThe UserOperation hash to track.
pollMsnumber1000Polling interval in milliseconds.
maxPollTimeMsnumber60000Maximum time to poll before timeout.
enabledbooleantrueSet to false to pause polling.
onStateChange(state: UserOpState) => voidCallback fired on every state transition.
onReceipt(receipt) => voidCallback fired when the operation is included on-chain.
onTxHash(txHash: string) => voidCallback fired when the transaction hash is available.

UserOpState Values

StateDescription
'waiting'No userOpHash provided or polling not started.
'pending'UserOp is in the mempool, waiting for inclusion.
'included'Transaction has been included in a block.
'failed'Transaction reverted on-chain.
'rejected'UserOp was rejected by the bundler.
'timeout'Polling exceeded maxPollTimeMs.

useTransactions

Returns the recent transaction history for the connected account, including both UserOperations and direct transactions.

import { useTransactions } from '@embarkai/ui-kit' function TransactionHistory() { const transactions = useTransactions() if (!transactions?.length) return <p>No transactions yet.</p> return ( <ul> {transactions.map((tx) => ( <li key={tx.hash}> {tx.type} — {tx.status} — {tx.value} {tx.symbol} </li> ))} </ul> ) }

Transaction Object

PropertyTypeDescription
hashstringTransaction or UserOp hash.
type'send' | 'receive' | 'contract'Transaction type.
status'pending' | 'confirmed' | 'failed'Current status.
valuestringTransfer amount (human-readable).
symbolstringToken symbol.
tostringRecipient address.
fromstringSender address.
timestampnumberUnix timestamp.

useSmartAccountTransactions

Similar to useTransactions, but scoped exclusively to the smart account. Excludes direct wallet transactions when in linked mode.

import { useSmartAccountTransactions } from '@embarkai/ui-kit' function SmartAccountHistory() { const transactions = useSmartAccountTransactions() return ( <div> <h3>Smart Account Activity</h3> {transactions?.map((tx) => ( <div key={tx.hash}> <span>{tx.type}</span> <span>{tx.value} {tx.symbol}</span> </div> ))} </div> ) }

useErc3643Compliance

Check ERC-3643 compliance status for regulated (security) tokens. Returns whether the connected wallet is eligible to hold and transfer a given token.

import { useErc3643Compliance } from '@embarkai/ui-kit' function ComplianceCheck({ tokenAddress }: { tokenAddress: `0x${string}` }) { const { isCompliant, isLoading, error } = useErc3643Compliance(tokenAddress) if (isLoading) return <p>Checking compliance...</p> if (error) return <p className="error">{error}</p> return ( <p> {isCompliant ? 'Your wallet is eligible to hold this token.' : 'Your wallet is not eligible for this regulated token.'} </p> ) }

Return Value

PropertyTypeDescription
isCompliantboolean | nullWhether the wallet passes compliance checks. null while loading.
isLoadingbooleantrue while the compliance check is in progress.
errorstring | nullError message if the check failed.

Error Handling

Always check for errors and provide a way to retry:

function SendWithRetry() { const { sendTransaction, isLoading, error, reset } = useSendTransaction() const handleSend = async () => { reset() const hash = await sendTransaction({ to: '0xRecipientAddress...', value: '0.1', }) if (!hash) { console.error('Transaction was not submitted') } } return ( <div> <button onClick={handleSend} disabled={isLoading}>Send</button> {error && ( <div className="error"> <p>{error}</p> <button onClick={reset}>Dismiss</button> </div> )} </div> ) }

Next Steps

  • useBalance — check balances before sending
  • Components — use the UserOpStatus component for a built-in status display
  • useSession — verify the user is connected before sending
Last updated on