Transaction Management
HumanWallet provides functions for monitoring and managing blockchain transactions and user operations. These functions help you track transaction status and wait for confirmations.
Functions Overview
waitForTransaction()- Wait for regular transaction confirmationwaitForUserOperation()- Wait for user operation completion
waitForTransaction()
Waits for a regular blockchain transaction to be confirmed and included in a block.
Function Signature
function waitForTransaction(
config: Config,
hash: string,
options?: WaitForTransactionOptions,
): Promise<TransactionReceipt>Parameters
config
- Type:
Config - Description: Configuration object from
createConfig()
hash
- Type:
string - Description: Transaction hash to wait for
options (optional)
- Type:
WaitForTransactionOptions - Properties:
timeout: Maximum time to wait in milliseconds (default: 60000)confirmations: Number of confirmations to wait for (default: 1)
Usage Example
import { writeContract, waitForTransaction } from "@humanwallet/core"
// Execute a transaction
const hash = await writeContract(authenticatedConfig, {
address: "0x...",
abi: tokenAbi,
functionName: "transfer",
args: ["0x742d35Cc6634C0532925a3b8D52ECC5c5e9fA008", BigInt("1000000000000000000")],
})
console.log("Transaction submitted:", hash)
try {
// Wait for confirmation
const receipt = await waitForTransaction(config, hash)
console.log("Transaction confirmed!")
console.log("Block number:", receipt.blockNumber)
console.log("Gas used:", receipt.gasUsed.toString())
console.log("Status:", receipt.status) // 'success' or 'reverted'
} catch (error) {
console.error("Transaction failed or timed out:", error)
}Advanced Usage
With Custom Timeout and Confirmations
// Wait for 3 confirmations with 2 minute timeout
const receipt = await waitForTransaction(config, hash, {
timeout: 120000, // 2 minutes
confirmations: 3,
})
console.log("Transaction confirmed with 3 confirmations")Error Handling
try {
const receipt = await waitForTransaction(config, hash)
if (receipt.status === "reverted") {
console.log("Transaction was reverted")
// Handle revert case
} else {
console.log("Transaction successful")
}
} catch (error) {
if (error.message.includes("timeout")) {
console.log("Transaction timed out - may still be pending")
} else if (error.message.includes("not found")) {
console.log("Transaction not found")
} else {
console.error("Unexpected error:", error)
}
}waitForUserOperation()
Waits for an account abstraction user operation to be completed. This is used for gasless transactions executed through HumanWallet.
Function Signature
function waitForUserOperation(
config: Config,
hash: string,
options?: WaitForUserOperationOptions,
): Promise<UserOperationReceipt>Parameters
config
- Type:
Config - Description: Configuration object from
createConfig()
hash
- Type:
string - Description: User operation hash to wait for
options (optional)
- Type:
WaitForUserOperationOptions - Properties:
timeout: Maximum time to wait in milliseconds (default: 60000)
Usage Example
import { writeContract, waitForUserOperation } from "@humanwallet/core"
// Execute a gasless transaction (returns user operation hash)
const userOpHash = await writeContract(authenticatedConfig, {
address: "0x...",
abi: contractAbi,
functionName: "mint",
args: [sessionKeyAccount.address, 1],
})
console.log("User operation submitted:", userOpHash)
try {
// Wait for user operation completion
const receipt = await waitForUserOperation(config, userOpHash)
console.log("User operation completed!")
console.log("Actual transaction hash:", receipt.transactionHash)
console.log("Block number:", receipt.blockNumber)
console.log("Success:", receipt.success)
} catch (error) {
console.error("User operation failed:", error)
}User Operation Receipt
The UserOperationReceipt contains:
interface UserOperationReceipt {
transactionHash: string // The actual on-chain transaction hash
blockNumber: bigint // Block number where it was included
success: boolean // Whether the operation succeeded
gasUsed: bigint // Gas consumed by the operation
logs: Log[] // Event logs emitted
}Transaction Flow Examples
Complete Transaction Flow
async function executeAndWaitForTransaction(contractParams: WriteContractParameters) {
try {
// 1. Submit transaction
console.log("Submitting transaction...")
const hash = await writeContract(authenticatedConfig, contractParams)
// 2. Show pending state to user
console.log("Transaction pending:", hash)
// 3. Wait for confirmation
console.log("Waiting for confirmation...")
const receipt = await waitForUserOperation(config, hash)
// 4. Handle result
if (receipt.success) {
console.log("✅ Transaction successful!")
console.log("Transaction hash:", receipt.transactionHash)
return receipt
} else {
console.log("❌ Transaction failed")
throw new Error("Transaction reverted")
}
} catch (error) {
console.error("Transaction error:", error)
throw error
}
}Batch Transaction Monitoring
async function executeBatchAndMonitor(operations: WriteContractParameters[]) {
try {
// Execute batch
const batchHash = await writeContracts(authenticatedConfig, operations)
console.log("Batch submitted:", batchHash)
// Monitor progress
const receipt = await waitForUserOperation(config, batchHash, {
timeout: 120000, // 2 minutes for batch operations
})
if (receipt.success) {
console.log("All operations in batch succeeded")
// Parse logs to see individual operation results
receipt.logs.forEach((log, index) => {
console.log(`Operation ${index + 1} log:`, log)
})
} else {
console.log("Batch failed - some operations reverted")
}
return receipt
} catch (error) {
console.error("Batch execution failed:", error)
throw error
}
}React Integration Examples
Transaction Status Hook
import { useState, useEffect } from "react"
import { waitForUserOperation } from "@humanwallet/core"
export function useTransactionStatus(config: Config, hash: string | null) {
const [status, setStatus] = useState<"pending" | "confirmed" | "failed" | null>(null)
const [receipt, setReceipt] = useState(null)
useEffect(() => {
if (!hash) return
setStatus("pending")
waitForUserOperation(config, hash)
.then((receipt) => {
setReceipt(receipt)
setStatus(receipt.success ? "confirmed" : "failed")
})
.catch((error) => {
console.error("Transaction monitoring failed:", error)
setStatus("failed")
})
}, [config, hash])
return { status, receipt }
}Transaction Component
import React from 'react'
import { useTransactionStatus } from './useTransactionStatus'
interface TransactionStatusProps {
config: Config
hash: string
onComplete?: (receipt: any) => void
}
export function TransactionStatus({ config, hash, onComplete }: TransactionStatusProps) {
const { status, receipt } = useTransactionStatus(config, hash)
useEffect(() => {
if (status === 'confirmed' && receipt && onComplete) {
onComplete(receipt)
}
}, [status, receipt, onComplete])
return (
<div className="transaction-status">
{status === 'pending' && (
<div>
<span>⏳ Transaction pending...</span>
<div>Hash: {hash}</div>
</div>
)}
{status === 'confirmed' && (
<div>
<span>✅ Transaction confirmed!</span>
<div>Block: {receipt?.blockNumber.toString()}</div>
</div>
)}
{status === 'failed' && (
<div>
<span>❌ Transaction failed</span>
<div>Please try again</div>
</div>
)}
</div>
)
}Error Handling
Timeout Handling
async function waitWithTimeout(hash: string, timeoutMs: number = 60000) {
try {
const receipt = await waitForUserOperation(config, hash, {
timeout: timeoutMs,
})
return receipt
} catch (error) {
if (error.message.includes("timeout")) {
// Transaction might still be pending
console.log("Transaction timed out but may still complete")
// Optionally, continue monitoring with longer timeout
return waitForUserOperation(config, hash, {
timeout: timeoutMs * 2,
})
}
throw error
}
}Network Error Recovery
async function waitWithRetry(hash: string, maxRetries: number = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await waitForUserOperation(config, hash)
} catch (error) {
console.log(`Attempt ${attempt} failed:`, error.message)
if (attempt === maxRetries) {
throw new Error(`Failed to confirm transaction after ${maxRetries} attempts`)
}
// Wait before retry
await new Promise((resolve) => setTimeout(resolve, 5000 * attempt))
}
}
}Best Practices
Progress Feedback
async function executeWithProgress(contractParams: WriteContractParameters) {
// 1. Show submission state
console.log("🚀 Submitting transaction...")
const hash = await writeContract(authenticatedConfig, contractParams)
// 2. Show pending state
console.log("⏳ Transaction submitted, waiting for confirmation...")
console.log("Hash:", hash)
// 3. Monitor with timeout
const receipt = await waitForUserOperation(config, hash, {
timeout: 90000, // 1.5 minutes
})
// 4. Show final result
if (receipt.success) {
console.log("✅ Transaction confirmed!")
} else {
console.log("❌ Transaction failed")
}
return receipt
}Batch Monitoring
async function monitorBatchExecution(batchHash: string) {
console.log("Monitoring batch execution...")
const startTime = Date.now()
const receipt = await waitForUserOperation(config, batchHash, {
timeout: 180000, // 3 minutes for complex batches
})
const duration = Date.now() - startTime
console.log(`Batch completed in ${duration}ms`)
if (receipt.success) {
console.log(`✅ All ${receipt.logs.length} operations succeeded`)
} else {
console.log("❌ Batch failed - check individual operations")
}
return receipt
}Gas Usage Tracking
async function trackGasUsage(operations: WriteContractParameters[]) {
const startTime = Date.now()
// Execute operations
const hashes = await Promise.all(operations.map((op) => writeContract(authenticatedConfig, op)))
// Wait for all confirmations
const receipts = await Promise.all(hashes.map((hash) => waitForUserOperation(config, hash)))
// Calculate metrics
const totalGasUsed = receipts.reduce((sum, receipt) => sum + receipt.gasUsed, 0n)
const successfulOps = receipts.filter((r) => r.success).length
const duration = Date.now() - startTime
console.log("Gas usage summary:", {
totalOperations: operations.length,
successfulOperations: successfulOps,
totalGasUsed: totalGasUsed.toString(),
averageGasPerOp: (totalGasUsed / BigInt(receipts.length)).toString(),
executionTime: `${duration}ms`,
})
return receipts
}