SDK Package (@humanwallet/sdk)
The @humanwallet/sdk package provides a high-level, class-based client interface for HumanWallet. Built on top of @humanwallet/core, it offers a simplified API that makes it easy to integrate passkey-based authentication and account abstraction into your Web3 applications.
Overview
The SDK abstracts away the complexity of the core functions by providing:
- Simple Client Interface: Easy-to-use class-based API for all wallet operations
- Automatic State Management: Built-in session handling and account state tracking
- Streamlined Configuration: Minimal setup required compared to core functions
- Comprehensive Operations: Support for authentication, contract interactions, and transaction management
- TypeScript First: Excellent developer experience with full type safety
When to Use SDK vs Core
Use SDK When:
- You want a simple, high-level interface
- You're building a new application from scratch
- You prefer class-based APIs
- You want automatic state management
- You need quick prototyping capabilities
Use Core When:
- You need fine-grained control over the authentication flow
- You're integrating into existing state management systems
- You want to implement custom session handling
- You're building a framework or library on top of HumanWallet
Installation
npm install @humanwallet/sdkBrowser Compatibility
When using the SDK in browser environments, you need to configure Buffer:
npm install bufferCreate a polyfills file:
// src/polyfills.ts
import { Buffer } from "buffer"
// Make Buffer available globally
window.Buffer = BufferImport it at the beginning of your main entry file:
import "./polyfills"
// ... rest of your importsAnd add to your index.html <head>:
<script>
var global = global || window
</script>For more details, see the React Integration Guide.
Quick Start
import { HumanWallet } from "@humanwallet/sdk"
import { sepolia } from "viem/chains"
// Initialize the client
const client = new HumanWallet(
"your-project-id", // projectId
sepolia, // chain
)
// Connect with existing passkey
const address = await client.connect()
console.log("Connected:", address)
// Or register a new user
// const address = await client.register("alice")
// Check connection status
if (client.address) {
console.log("User address:", client.address)
// Execute a contract transaction
const hash = await client.writeContract({
address: "0x...",
abi: contractAbi,
functionName: "transfer",
args: ["0x742d35Cc6634C0532925a3b8D52ECC5c5e9fA008", BigInt("1000000000000000000")],
})
console.log("Transaction hash:", hash)
}
// Disconnect when done
await client.disconnect()HumanWallet Class
The main SDK interface is the HumanWallet class that encapsulates all HumanWallet functionality.
Constructor
new HumanWallet(
projectId: string,
chain: Chain
)Parameters
projectId: Your ZeroDev project ID for accessing bundler and paymaster serviceschain: Viem chain configuration object (e.g.,sepolia,mainnet)
Example
import { sepolia, polygon, mainnet } from "viem/chains"
// Sepolia testnet client
const sepoliaClient = new HumanWallet(
"your-project-id",
sepolia,
)
// Mainnet client
const mainnetClient = new HumanWallet(
"your-project-id",
mainnet,
)Properties
address: Address | undefined
The current user's wallet address. Returns undefined if no user is authenticated.
if (client.address) {
console.log("Current address:", client.address)
} else {
console.log("No user authenticated")
}chain: Chain
The current blockchain network the client is connected to.
console.log("Current chain:", client.chain.name) // "Sepolia"
console.log("Chain ID:", client.chain.id) // 11155111API Reference
Authentication Methods
connect()- Connect with existing passkeyregister()- Create new passkey-based accountsreconnect()- Restore previous sessionsdisconnect()- End sessions and clear datahasAccount()- Check if user has existing account
Contract Interaction Methods
writeContract()- Execute contract transactionswriteContracts()- Execute batch transactionsreadContract()- Read contract statesignTypedData()- Sign structured data
Transaction Management Methods
waitForTransaction()- Wait for transaction confirmationwaitForUserOperation()- Wait for user operation completion
Usage Patterns
Single Page Application (SPA)
class WalletService {
private client: HumanWallet
constructor() {
this.client = new HumanWallet(
process.env.VITE_PROJECT_ID!,
sepolia,
)
}
async initializeSession() {
// Try to restore previous session
const address = await this.client.reconnect()
if (address) {
console.log("Session restored for:", address)
return true
}
return false
}
async authenticateUser(username: string, isNewUser: boolean = false) {
if (isNewUser) {
return await this.client.register(username)
} else {
return await this.client.connect()
}
}
async transferTokens(to: string, amount: bigint) {
if (!this.client.address) {
throw new Error("User not authenticated")
}
return await this.client.writeContract({
address: TOKEN_CONTRACT_ADDRESS,
abi: ERC20_ABI,
functionName: "transfer",
args: [to, amount],
})
}
async signOut() {
await this.client.disconnect()
}
get userAddress() {
return this.client.address
}
get isAuthenticated() {
return !!this.client.address
}
}React Integration
import { createContext, useContext, useState, useEffect } from 'react'
import { HumanWallet } from '@humanwallet/sdk'
const WalletContext = createContext<{
client: HumanWallet
address?: string
isConnected: boolean
connect: () => Promise<string>
register: (username: string) => Promise<string>
disconnect: () => Promise<void>
}>()
export function WalletProvider({ children }: { children: React.ReactNode }) {
const [client] = useState(() => new HumanWallet(
process.env.VITE_PROJECT_ID!,
sepolia
))
const [address, setAddress] = useState<string>()
const [isConnected, setIsConnected] = useState(false)
useEffect(() => {
// Try to restore session on mount
client.reconnect().then(addr => {
if (addr) {
setAddress(addr)
setIsConnected(true)
}
})
}, [client])
const connect = async () => {
const addr = await client.connect()
setAddress(addr)
setIsConnected(true)
return addr
}
const register = async (username: string) => {
const addr = await client.register(username)
setAddress(addr)
setIsConnected(true)
return addr
}
const disconnect = async () => {
await client.disconnect()
setAddress(undefined)
setIsConnected(false)
}
return (
<WalletContext.Provider value={{
client,
address,
isConnected,
connect,
register,
disconnect
}}>
{children}
</WalletContext.Provider>
)
}
export const useWallet = () => {
const context = useContext(WalletContext)
if (!context) {
throw new Error('useWallet must be used within WalletProvider')
}
return context
}Error Handling
The SDK methods can throw various errors that should be handled appropriately:
try {
const address = await client.register("username")
console.log("Registration successful:", address)
} catch (error) {
if (error.message.includes("User rejected")) {
console.log("User cancelled passkey creation")
} else if (error.message.includes("not supported")) {
console.log("Passkeys not supported in this browser")
} else if (error.message.includes("already exists")) {
console.log("Username already taken")
} else {
console.error("Registration failed:", error)
}
}Common Error Patterns
class ErrorHandler {
static handleAuthError(error: Error) {
if (error.message.includes("User rejected")) {
return "Authentication cancelled by user"
} else if (error.message.includes("not supported")) {
return "Passkeys not supported in this browser"
} else if (error.message.includes("Account not created")) {
return "Failed to create account"
} else {
return "Authentication failed"
}
}
static handleTransactionError(error: Error) {
if (error.message.includes("User not authenticated")) {
return "Please login to perform transactions"
} else if (error.message.includes("insufficient funds")) {
return "Insufficient balance for transaction"
} else if (error.message.includes("execution reverted")) {
return "Contract execution failed"
} else {
return "Transaction failed"
}
}
}Best Practices
1. Environment Configuration
// config.ts
const getSDKConfig = () => {
const requiredEnvVars = ["VITE_PROJECT_ID"]
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`)
}
}
return {
projectId: process.env.VITE_PROJECT_ID!,
}
}
export const createWalletClient = (chain: Chain) => {
const config = getSDKConfig()
return new HumanWallet(config.projectId, chain)
}2. Session Management
// Always try to reconnect on app startup
async function initializeApp() {
const client = createWalletClient(sepolia)
try {
const address = await client.reconnect()
if (address) {
console.log("User session restored:", address)
return { client, address }
}
} catch (error) {
console.log("No previous session found")
}
return { client, address: null }
}3. Type Safety
// Define your contract interfaces
interface TokenContract {
address: `0x${string}`
abi: typeof ERC20_ABI
}
class TokenService {
constructor(
private client: ClientRepository,
private tokenContract: TokenContract,
) {}
async getBalance(): Promise<bigint> {
return await this.client.readContract({
address: this.tokenContract.address,
abi: this.tokenContract.abi,
functionName: "balanceOf",
args: [this.client.address!],
})
}
async transfer(to: `0x${string}`, amount: bigint): Promise<string> {
return await this.client.writeContract({
address: this.tokenContract.address,
abi: this.tokenContract.abi,
functionName: "transfer",
args: [to, amount],
})
}
}Migration from Core
If you're currently using @humanwallet/core, migrating to the SDK is straightforward:
Before (Core)
import { createConfig, register, login, writeContract } from "@humanwallet/core"
const config = createConfig({
passkeyUrl: "https://passkeys.example.com/api/v3/your-project-id",
bundlerRpc: "https://rpc.example.com/api/v3/your-project-id/chain/11155111",
paymasterRpc: "https://rpc.example.com/api/v3/your-project-id/chain/11155111",
chain: sepolia,
})
const { sessionKeyAccount, kernelClient } = await register("username", config)
// Update config with authenticated clients
const authenticatedConfig = { ...config, sessionKeyAccount, kernelClient }
const hash = await writeContract(authenticatedConfig, contractParams)After (SDK)
import { HumanWallet } from "@humanwallet/sdk"
const client = new HumanWallet("your-project-id", sepolia)
await client.register("username")
const hash = await client.writeContract(contractParams)Next Steps
- Authentication Methods - Learn about user authentication flows
- Contract Interactions - Execute and read smart contract operations
- Transaction Management - Monitor and manage blockchain transactions
- React Integration Examples - See SDK in action with React