# JAW Wagmi Integration > Wagmi connector and React hooks for integrating JAW smart accounts into React/Next.js applications. **This file is self-contained.** You have everything needed to help with this topic. Do NOT fetch other llms-*.txt files unless the user explicitly asks about a different topic. ## Key Info - **Package:** `@jaw.id/wagmi` - **Install:** `npm install @jaw.id/wagmi wagmi @tanstack/react-query` - **Dashboard:** https://dashboard.jaw.id - **Docs:** https://docs.jaw.id ## Quick Example ```typescript import { jaw } from '@jaw.id/wagmi'; import { createConfig, http } from 'wagmi'; import { base } from 'wagmi/chains'; const config = createConfig({ chains: [base], connectors: [ jaw({ apiKey: 'YOUR_API_KEY', appName: 'My App', }), ], transports: { [base.id]: http() }, }); ``` --- ## Wagmi Integration Source: https://docs.jaw.id/wagmi/index ## Wagmi Integration The `@jaw.id/wagmi` package provides a Wagmi-compatible connector and React hooks for integrating JAW smart accounts into your dApp. ### Installation :::code-group ```bash [npm] npm install @jaw.id/wagmi wagmi @tanstack/react-query ``` ```bash [pnpm] pnpm add @jaw.id/wagmi wagmi @tanstack/react-query ``` ```bash [yarn] yarn add @jaw.id/wagmi wagmi @tanstack/react-query ``` ```bash [bun] bun add @jaw.id/wagmi wagmi @tanstack/react-query ``` ::: ### Quick Start #### 1. Configure the Connector ```typescript import { createConfig, http } from 'wagmi'; import { mainnet, base, baseSepolia } from 'wagmi/chains'; import { jaw } from '@jaw.id/wagmi'; export const config = createConfig({ chains: [mainnet, base, baseSepolia], connectors: [ jaw({ apiKey: 'YOUR_API_KEY', appName: 'My App', appLogoUrl: 'https://example.com/logo.png', }), ], transports: { [mainnet.id]: http(), [base.id]: http(), [baseSepolia.id]: http(), }, }); ``` #### 2. Set Up Providers ```tsx import { WagmiProvider } from 'wagmi'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const queryClient = new QueryClient(); function App({ children }) { return ( {children} ); } ``` #### 3. Use the Hooks ```tsx import { useAccount, useSendTransaction } from 'wagmi'; import { useConnect, useDisconnect } from '@jaw.id/wagmi'; function WalletButton() { const { address, isConnected } = useAccount(); const { mutate: connect, isPending } = useConnect(); const { mutate: disconnect } = useDisconnect(); if (isConnected) { return (

Connected: {address}

); } return ( ); } ``` ### Standard Wagmi Hooks All standard wagmi hooks work with the JAW connector. Use them directly from `wagmi`: ```typescript import { useAccount, useSendTransaction, useSignMessage, useSignTypedData, useSwitchChain, useSendCalls, useWriteContract, useBalance, } from 'wagmi'; ``` \| Hook | Description | \|------|-------------| \| `useAccount` | Get connected account address and status | \| `useSendTransaction` | Send a single transaction | \| `useSignMessage` | Sign a personal message (EIP-191) | \| `useSignTypedData` | Sign typed data (EIP-712) | \| `useSwitchChain` | Switch to a different chain | \| `useSendCalls` | Send atomic batch transactions (EIP-5792) | \| `useWriteContract` | Call a contract write function | \| `useBalance` | Get ETH or token balance | :::info When a paymaster is configured, transactions sent via `useSendTransaction`, `useSendCalls`, and `useWriteContract` are automatically sponsored (gasless). ::: ### JAW Hooks For JAW-specific features, import hooks directly from `@jaw.id/wagmi`: ```typescript // Direct import (recommended) import { useConnect, useDisconnect, useGrantPermissions } from '@jaw.id/wagmi'; // Alternative: namespace import import { Hooks } from '@jaw.id/wagmi'; const { mutate } = Hooks.useConnect(); ``` \| Hook | Description | \|------|-------------| \| [useConnect](/wagmi/useConnect) | Connect with optional capabilities (SIWE, subnames) | \| [useDisconnect](/wagmi/useDisconnect) | Disconnect and clean up session | \| [useSign](/wagmi/useSign) | Unified signing (personal + typed data) with chain support | \| [useGrantPermissions](/wagmi/useGrantPermissions) | Grant permissions to a spender | \| [usePermissions](/wagmi/usePermissions) | Query current permissions | \| [useRevokePermissions](/wagmi/useRevokePermissions) | Revoke a permission | \| [useGetAssets](/wagmi/useGetAssets) | Query token balances across chains | \| [useCapabilities](/wagmi/useCapabilities) | Query wallet capabilities per chain | ### Connector \| Function | Description | \|----------|-------------| \| [jaw()](/wagmi/jaw) | Create a JAW connector for Wagmi | ### Why Use JAW Hooks? #### useConnect vs wagmi's useConnect \| Feature | `wagmi.useConnect` | `@jaw.id/wagmi.useConnect` | \|---------|-------------------|------------------------| \| Basic connection | Yes | Yes | \| Request SIWE signature | No | Yes | \| Request subname issuance | No | Yes | \| Uses `wallet_connect` RPC | No | When capabilities provided | Use `@jaw.id/wagmi`'s `useConnect` when you need capabilities like Sign-In with Ethereum or ENS subnames during connection. #### useDisconnect vs wagmi's useDisconnect Both work the same way. `@jaw.id/wagmi`'s version is provided for consistency. ### Actions (Non-React) For vanilla JavaScript or other frameworks, use actions directly: ```typescript import { connect, disconnect, grantPermissions } from '@jaw.id/wagmi'; // Use with your wagmi config await connect(config, { connector: jawConnector }); ``` ### Related * [Configuration](/configuration) - Full configuration options * [Provider API](/api-reference) - Direct provider methods * [Account API](/account) - Low-level Account class ## Connector Source: https://docs.jaw.id/wagmi/jaw ## Connector Create a JAW connector for your [Wagmi Config](https://wagmi.sh/core/api/createConfig). ```typescript import { createConfig, http } from 'wagmi'; import { mainnet } from 'wagmi/chains'; import { jaw } from '@jaw.id/wagmi'; const config = createConfig({ chains: [mainnet], connectors: [ jaw({ apiKey: 'YOUR_API_KEY' }), ], transports: { [mainnet.id]: http(), }, }); ``` ### Signature ```typescript function jaw(parameters: JawParameters): Connector ``` ### Parameters #### apiKey Type: `string` (required) Your JAW API key. Get one at [JAW Dashboard](https://dashboard.jaw.id/). #### appName Type: `string` Display name for your application. Shown in the authentication UI. #### appLogoUrl Type: `string | null` URL to your application's logo. Used in authentication UI. #### defaultChainId Type: `number` Default chain ID to use on first connection. #### ens Type: `string` ENS domain for issuing subnames (e.g., `'myapp.eth'`). When configured, users can receive a subname during account creation. #### preference Type: `JawProviderPreference` Configuration for authentication behavior. ```typescript interface JawProviderPreference { /** Authentication mode (default: Mode.CrossPlatform) */ mode?: Mode.CrossPlatform | Mode.AppSpecific; /** Whether to show testnet chains (default: false) */ showTestnets?: boolean; /** UI handler for app-specific mode */ uiHandler?: UIHandler; } ``` #### paymasters Type: `Record }>` Custom paymaster configuration by chain ID for gas sponsorship. See [paymasters](/configuration/paymasters) for details. ### Returns `Connector` - A Wagmi-compatible connector instance. ### Connector Properties The returned connector has these Wagmi-standard properties: \| Property | Value | \|----------|-------| \| `id` | `'jaw'` | \| `name` | `'JAW'` | \| `type` | `'jaw'` | \| `rdns` | `'keys.jaw.id'` | ### Example ```typescript import { createConfig, http } from 'wagmi'; import { mainnet, base, baseSepolia } from 'wagmi/chains'; import { jaw } from '@jaw.id/wagmi'; const config = createConfig({ chains: [mainnet, base, baseSepolia], connectors: [ jaw({ apiKey: 'YOUR_API_KEY', appName: 'My DApp', appLogoUrl: 'https://example.com/logo.png', defaultChainId: 8453, // Base ens: 'myapp.eth', preference: { showTestnets: true, }, paymasters: { 8453: { url: 'https://my-paymaster.com/base' }, 84532: { url: 'https://my-paymaster.com/base-sepolia' }, }, }), ], transports: { [mainnet.id]: http(), [base.id]: http(), [baseSepolia.id]: http(), }, }); ``` ### Related * [Configuration](/configuration) - Full configuration reference * [useConnect](/wagmi/useConnect) - Connect with capabilities * [mode](/configuration/mode) - Authentication mode and UI handler options ## useCapabilities Source: https://docs.jaw.id/wagmi/useCapabilities ## useCapabilities Hook to get wallet capabilities for supported chains. Implements EIP-5792 for capability discovery. **Type:** `hook` ### Import ```typescript import { useCapabilities } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useCapabilities(parameters?: { address?: Address; chainId?: number; connector?: Connector; chainFilter?: Hex[]; config?: Config; query?: UseQueryParameters; }): UseQueryResult ``` ### Parameters #### address Type: `Address` (optional) Specific account address to get capabilities for. When provided, allows querying capabilities without a connected wallet. #### chainId Type: `number` (optional) Specific chain ID. Defaults to current chain. #### connector Type: `Connector` (optional) Specific connector to use. Defaults to active connector. #### chainFilter Type: `Hex[]` (optional) Array of chain IDs (hex format) to filter capabilities. If not provided, returns capabilities for all supported chains. #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### query Type: `UseQueryParameters` (optional) TanStack React Query options (excluding `gcTime` and `staleTime` which are managed internally). ### Returns Returns a TanStack React Query result: \| Property | Type | Description | \|----------|------|-------------| \| `data` | `Record>` | Capabilities keyed by chain ID (hex) | \| `isLoading` | `boolean` | Whether initial load is in progress | \| `isFetching` | `boolean` | Whether any fetch is in progress | \| `isSuccess` | `boolean` | Whether query succeeded | \| `isError` | `boolean` | Whether query failed | \| `error` | `Error` | Error if query failed | \| `refetch` | `function` | Manually refetch capabilities | #### data When successful, `data` is an object of capabilities keyed by chain ID (hex): ```typescript type WalletGetCapabilitiesResponse = Record>; // Example structure: { "0x1": { "atomicBatch": { "supported": true }, "atomic": { "status": "supported" }, "paymasterService": { "supported": true }, "permissions": { "supported": true }, "feeToken": { "supported": true, "tokens": [...] } }, "0x2105": { // Base chain capabilities } } ``` ### Behavior 1. **Works without connection** when `address` parameter is provided 2. **Auto-enables** when wallet is connected or address is provided 3. **Caches results** for optimal performance 4. **Returns all chains** by default, use `chainFilter` to limit ### Examples #### Basic Usage ```tsx import { useAccount } from 'wagmi'; import { useCapabilities } from '@jaw.id/wagmi'; function CapabilitiesDisplay() { const { isConnected } = useAccount(); const { data: capabilities, isLoading } = useCapabilities(); if (!isConnected) return

Connect wallet to view capabilities

; if (isLoading) return

Loading capabilities...

; return (
{Object.entries(capabilities || {}).map(([chainId, caps]) => (

Chain {chainId}

    {Object.entries(caps).map(([name, value]) => (
  • {name}: {JSON.stringify(value)}
  • ))}
))}
); } ``` #### Without Wallet Connection ```tsx import { useCapabilities } from '@jaw.id/wagmi'; function CapabilitiesForAddress({ address }: { address: `0x${string}` }) { // Works without wallet connection when address is provided const { data: capabilities, isLoading } = useCapabilities({ address }); if (isLoading) return

Loading...

; return
{JSON.stringify(capabilities, null, 2)}
; } ``` #### Filter by Chain ```tsx import { useCapabilities } from '@jaw.id/wagmi'; function BaseCapabilities() { const { data: capabilities } = useCapabilities({ chainFilter: ['0x2105'], // Base mainnet only }); // ... } ``` #### Check Specific Capability ```tsx import { useCapabilities } from '@jaw.id/wagmi'; function PaymasterSupport() { const { data: capabilities } = useCapabilities(); const supportsPaymaster = (chainId: string) => { const chainCaps = capabilities?.[chainId as `0x${string}`]; return (chainCaps?.paymasterService as { supported?: boolean })?.supported === true; }; return (

Ethereum paymaster: {supportsPaymaster('0x1') ? 'Yes' : 'No'}

Base paymaster: {supportsPaymaster('0x2105') ? 'Yes' : 'No'}

); } ``` ### Available Capabilities \| Capability | Description | \|------------|-------------| \| `atomicBatch` | Support for `wallet_sendCalls` (EIP-5792) | \| `atomic` | Atomic transaction execution | \| `paymasterService` | Gasless transactions via ERC-7677 | \| `permissions` | Permission system support | \| `feeToken` | Supported fee tokens for gas | ### Related * [useGetAssets](/wagmi/useGetAssets) - Query token balances * [usePermissions](/wagmi/usePermissions) - Query permissions * [wallet\_getCapabilities](/api-reference/wallet_getCapabilities) - RPC method reference ## useConnect Source: https://docs.jaw.id/wagmi/useConnect ## useConnect Hook to connect to the wallet with optional capabilities. **Type:** `hook` ### Import ```typescript import { useConnect } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useConnect(parameters?: { config?: Config; mutation?: UseMutationParameters; }): UseMutationResult ``` ### Parameters #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### mutation Type: `UseMutationParameters` (optional) TanStack React Query mutation options. ### Returns Returns a TanStack React Query mutation result: \| Property | Type | Description | \|----------|------|-------------| \| `mutate` | `function` | Function to trigger connection | \| `mutateAsync` | `function` | Async version of mutate | \| `data` | `{ accounts, chainId }` | Connection result | \| `isPending` | `boolean` | Whether connection is in progress | \| `isSuccess` | `boolean` | Whether connection succeeded | \| `isError` | `boolean` | Whether connection failed | \| `error` | `Error` | Error if connection failed | #### data When successful, `data` contains: ```typescript { accounts: Address[] | AccountWithCapabilities[]; chainId: number; } ``` If capabilities were requested, accounts include capability information. ### Mutation Variables When calling `mutate()`, you can pass: #### connector Type: `Connector` (required) The connector to use for connection. #### chainId Type: `number` (optional) Chain ID to connect to. #### capabilities Type: `WalletConnectCapabilities` (optional) Capabilities to request during connection. When provided, uses `wallet_connect` instead of `eth_requestAccounts`. ```typescript interface WalletConnectCapabilities { /** SIWE parameters for authentication */ signInWithEthereum?: { nonce: string; chainId: string; domain?: string; uri?: string; statement?: string; }; /** Text records for subname issuance */ subnameTextRecords?: { key: string; value: string }[]; } ``` ### Examples #### Basic Connection ```tsx import { useAccount } from 'wagmi'; import { useConnect, jaw } from '@jaw.id/wagmi'; function ConnectButton() { const { isConnected } = useAccount(); const { mutate: connect, isPending } = useConnect(); if (isConnected) return

Connected!

; return ( ); } ``` #### Using Config Connector ```tsx import { useConnect } from '@jaw.id/wagmi'; import { config } from './config'; function ConnectButton() { const { mutate: connect, isPending } = useConnect(); return ( ); } ``` #### Connection with SIWE Request a Sign-In with Ethereum signature during connection: ```tsx import { useConnect, jaw } from '@jaw.id/wagmi'; function ConnectWithSIWE() { const { mutate: connect, data, isPending } = useConnect(); const handleConnect = () => { connect({ connector: jaw({ apiKey: '...' }), capabilities: { signInWithEthereum: { nonce: crypto.randomUUID(), chainId: '0x1', domain: window.location.host, uri: window.location.origin, statement: 'Sign in to My DApp', }, }, }); }; return (
{data && (

Connected: {data.accounts[0].address}

SIWE Signature: {data.accounts[0].capabilities?.signInWithEthereum?.signature}

)}
); } ``` #### Connection with Subname Issue an ENS subname during connection (requires `ens` config option): ```tsx import { useConnect, jaw } from '@jaw.id/wagmi'; function ConnectWithSubname() { const { mutate: connect, isPending } = useConnect(); const handleConnect = () => { connect({ connector: jaw({ apiKey: '...', ens: 'myapp.eth' }), capabilities: { subnameTextRecords: [ { key: 'avatar', value: 'https://example.com/avatar.png' }, { key: 'description', value: 'My profile' }, ], }, }); }; return ( ); } ``` #### With Mutation Callbacks ```tsx import { useConnect } from '@jaw.id/wagmi'; function ConnectWithCallbacks() { const { mutate: connect } = useConnect({ mutation: { onSuccess: (data) => { console.log('Connected:', data.accounts); }, onError: (error) => { console.error('Connection failed:', error); }, }, }); return ; } ``` ### Difference from wagmi useConnect \| Feature | `wagmi.useConnect` | `@jaw.id/wagmi.useConnect` | \|---------|-------------------|------------------------| \| Basic connection | Yes | Yes | \| Capabilities parameter | No | Yes | \| Uses `wallet_connect` | No | When capabilities provided | \| Returns account capabilities | No | Yes (when requested) | Use `@jaw.id/wagmi`'s `useConnect` when you need to request capabilities during connection. For basic connections without capabilities, either hook works. ### Related * [useDisconnect](/wagmi/useDisconnect) - Disconnect from wallet * [jaw()](/wagmi/jaw) - Create the connector * [wallet\_connect](/api-reference/wallet_connect) - RPC method reference ## useDisconnect Source: https://docs.jaw.id/wagmi/useDisconnect ## useDisconnect Hook to disconnect from the wallet. **Type:** `hook` ### Import ```typescript import { useDisconnect } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useDisconnect(parameters?: { config?: Config; mutation?: UseMutationParameters; }): UseMutationResult ``` ### Parameters #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### mutation Type: `UseMutationParameters` (optional) TanStack React Query mutation options. ### Returns Returns a TanStack React Query mutation result: \| Property | Type | Description | \|----------|------|-------------| \| `mutate` | `function` | Function to trigger disconnection | \| `mutateAsync` | `function` | Async version of mutate | \| `isPending` | `boolean` | Whether disconnection is in progress | \| `isSuccess` | `boolean` | Whether disconnection succeeded | \| `isError` | `boolean` | Whether disconnection failed | \| `error` | `Error` | Error if disconnection failed | ### Mutation Variables When calling `mutate()`, you can optionally pass: #### connector Type: `Connector` (optional) Specific connector to disconnect from. If omitted, disconnects the active connector. ### Examples #### Basic Usage ```tsx import { useAccount } from 'wagmi'; import { useDisconnect } from '@jaw.id/wagmi'; function DisconnectButton() { const { isConnected } = useAccount(); const { mutate: disconnect, isPending } = useDisconnect(); if (!isConnected) return null; return ( ); } ``` #### With Callback ```tsx import { useDisconnect } from '@jaw.id/wagmi'; function DisconnectButton() { const { mutate: disconnect } = useDisconnect({ mutation: { onSuccess: () => { console.log('Disconnected successfully'); // Redirect to login page, clear local state, etc. }, }, }); return ; } ``` #### Disconnect Specific Connector ```tsx import { useDisconnect, jaw } from '@jaw.id/wagmi'; function DisconnectButton() { const { mutate: disconnect } = useDisconnect(); const connector = jaw({ apiKey: '...' }); // Disconnect only this specific connector return ( ); } ``` #### Full Wallet Component ```tsx import { useAccount } from 'wagmi'; import { useConnect, useDisconnect, jaw } from '@jaw.id/wagmi'; function WalletButton() { const { address, isConnected } = useAccount(); const { mutate: connect, isPending: isConnecting } = useConnect(); const { mutate: disconnect, isPending: isDisconnecting } = useDisconnect(); if (isConnected) { return (
{address?.slice(0, 6)}...{address?.slice(-4)}
); } return ( ); } ``` ### Related * [useConnect](/wagmi/useConnect) - Connect to wallet * [jaw()](/wagmi/jaw) - Create the connector ## useGetAssets Source: https://docs.jaw.id/wagmi/useGetAssets ## useGetAssets Hook to get the assets for the connected account. Fetches token balances across supported chains. **Type:** `hook` ### Import ```typescript import { useGetAssets } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useGetAssets(parameters?: { address?: Address; chainId?: number; connector?: Connector; chainFilter?: string[]; assetTypeFilter?: AssetType[]; assetFilter?: AssetFilter; config?: Config; query?: UseQueryParameters; }): UseQueryResult ``` ### Parameters #### address Type: `Address` (optional) Specific account address to get assets for. Defaults to connected account. #### chainId Type: `number` (optional) Specific chain ID. Defaults to current chain. #### connector Type: `Connector` (optional) Specific connector to use. Defaults to active connector. #### chainFilter Type: `string[]` (optional) Array of chain IDs in hex format (e.g., `['0x1', '0xa']`) to filter results. If not provided, returns assets from all supported chains. #### assetTypeFilter Type: `AssetType[]` (optional) Filter by asset type. Options: `'native'`, `'erc20'`. ```typescript // Only get ERC-20 tokens useGetAssets({ assetTypeFilter: ['erc20'] }); // Only get native tokens (ETH, etc.) useGetAssets({ assetTypeFilter: ['native'] }); ``` #### assetFilter Type: `AssetFilter` (optional) Filter by specific assets per chain. Maps chain ID (hex) to an array of assets to filter by. ```typescript type AssetFilter = Record<`0x${string}`, AssetFilterEntry[]>; type AssetFilterEntry = { address: `0x${string}`; type: 'native' | 'erc20'; }; // Example: Get only USDC on mainnet and Base useGetAssets({ assetFilter: { '0x1': [{ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', type: 'erc20' }], '0x2105': [{ address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', type: 'erc20' }], }, }); ``` #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### query Type: `UseQueryParameters` (optional) TanStack React Query options (excluding `gcTime` and `staleTime` which are managed internally). ### Returns Returns a TanStack React Query result: \| Property | Type | Description | \|----------|------|-------------| \| `data` | `WalletGetAssetsResponse` | Assets grouped by chain ID | \| `isLoading` | `boolean` | Whether initial load is in progress | \| `isFetching` | `boolean` | Whether any fetch is in progress | \| `isSuccess` | `boolean` | Whether query succeeded | \| `isError` | `boolean` | Whether query failed | \| `error` | `Error` | Error if query failed | \| `refetch` | `function` | Manually refetch assets | #### data When successful, `data` is an object mapping chain IDs to asset arrays: ```typescript type WalletGetAssetsResponse = { [chainId: string]: Asset[]; }; interface Asset { /** Token contract address, null for native tokens */ address: string | null; /** Balance in hex format */ balance: string; /** Asset metadata */ metadata: { decimals: number; name: string; symbol: string; } | null; /** Asset type: 'native' or 'erc20' */ type: 'native' | 'erc20'; } ``` ### Behavior 1. **Auto-enables** when wallet is connected 2. **Listens for changes** via `assetsChanged` event 3. **Auto-refetches** when assets change (e.g., after transactions) 4. **Caches for 30 seconds** before becoming stale ### Examples #### Basic Usage ```tsx import { useAccount } from 'wagmi'; import { useGetAssets } from '@jaw.id/wagmi'; import { formatUnits } from 'viem'; function Portfolio() { const { isConnected } = useAccount(); const { data: assets, isLoading } = useGetAssets(); if (!isConnected) return

Connect wallet to view assets

; if (isLoading) return

Loading assets...

; return (
{Object.entries(assets || {}).map(([chainId, chainAssets]) => (

Chain {parseInt(chainId, 16)}

    {chainAssets.map((asset, i) => (
  • {asset.metadata?.symbol || 'Unknown'}: {' '} {formatUnits( BigInt(asset.balance), asset.metadata?.decimals || 18 )}
  • ))}
))}
); } ``` #### Filter by Chain ```tsx import { useGetAssets } from '@jaw.id/wagmi'; function MainnetAssets() { const { data: assets } = useGetAssets({ chainFilter: ['0x1'], // Mainnet only }); // ... } ``` #### Filter by Asset Type ```tsx import { useGetAssets } from '@jaw.id/wagmi'; function TokenBalances() { // Only get ERC-20 tokens, exclude native ETH const { data: assets } = useGetAssets({ assetTypeFilter: ['erc20'], }); // ... } ``` #### Manual Refresh ```tsx import { useGetAssets } from '@jaw.id/wagmi'; function RefreshablePortfolio() { const { data, refetch, isFetching } = useGetAssets(); return (
{/* Render assets */}
); } ``` #### Disable Auto-Fetch ```tsx import { useGetAssets } from '@jaw.id/wagmi'; function ManualAssets() { const { data, refetch } = useGetAssets({ query: { enabled: false, // Don't fetch automatically }, }); return (
{data &&

{Object.keys(data).length} chains with assets

}
); } ``` ### Related * [wallet\_getAssets](/api-reference/wallet_getAssets) - RPC method reference * [usePermissions](/wagmi/usePermissions) - Query permissions ## useGetCallsHistory Source: https://docs.jaw.id/wagmi/useGetCallsHistory ## useGetCallsHistory Hook to get the call history for an account. Can be called with or without a connected wallet. **Type:** `hook` ### Import ```typescript import { useGetCallsHistory } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useGetCallsHistory(parameters?: { address?: Address; chainId?: number; connector?: Connector; index?: number; limit?: number; sort?: 'asc' | 'desc'; config?: Config; query?: UseQueryParameters; }): UseQueryResult ``` ### Parameters #### address Type: `Address` (optional) Specific account address to get history for. If not provided when connected, uses the connected account's address. **Required when not connected.** #### chainId Type: `number` (optional) Chain ID to filter results by. When provided, only returns history items for that chain. #### connector Type: `Connector` (optional) Specific connector to use. Defaults to active connector or JAW connector if available. #### index Type: `number` (optional) Index cursor for pagination. Use the `index` from the last item in the previous response to fetch the next page. #### limit Type: `number` (optional) Maximum number of bundles to return. Defaults to 20. #### sort Type: `'asc' | 'desc'` (optional) Sort direction based on index. Defaults to `'desc'` (newest first). #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### query Type: `UseQueryParameters` (optional) TanStack React Query options (excluding `gcTime` and `staleTime` which are managed internally). ### Returns Returns a TanStack React Query result: \| Property | Type | Description | \|----------|------|-------------| \| `data` | `CallsHistoryItem[]` | Array of call history items | \| `isLoading` | `boolean` | Whether initial load is in progress | \| `isFetching` | `boolean` | Whether any fetch is in progress | \| `isSuccess` | `boolean` | Whether query succeeded | \| `isError` | `boolean` | Whether query failed | \| `error` | `Error` | Error if query failed | \| `refetch` | `function` | Manually refetch history | #### data When successful, `data` is an array of call history items: ```typescript interface CallsHistoryItem { /** userOpHash */ id: `0x${string}`; /** Auto-incrementing index per address (for cursor pagination) */ index: number; /** Wallet address */ address: `0x${string}`; /** 100=Pending, 200=Completed, 500=Onchain Revert */ status: number; /** Unix timestamp in seconds */ timestamp: number; /** Chain ID */ chainId: number; /** Transaction hash (null when pending) */ transactionHash: `0x${string}` | null; } ``` ### Behavior 1. **Works without connection** when `address` is provided 2. **Uses connected address** automatically when wallet is connected 3. **Caches for 30 seconds** before becoming stale 4. **Supports pagination** via `index` cursor ### Examples #### Basic Usage (Connected) ```tsx import { useAccount } from 'wagmi'; import { useGetCallsHistory } from '@jaw.id/wagmi'; function TransactionHistory() { const { isConnected } = useAccount(); const { data: history, isLoading } = useGetCallsHistory(); if (!isConnected) return

Connect wallet to view history

; if (isLoading) return

Loading history...

; return (
    {history?.map((item) => (
  • {new Date(item.timestamp * 1000).toLocaleDateString()} -{' '} {item.status === 200 ? 'Success' : item.status === 100 ? 'Pending' : 'Failed'}
  • ))}
); } ``` #### Without Connection (Address Required) ```tsx import { useGetCallsHistory } from '@jaw.id/wagmi'; function AddressHistory({ address }: { address: `0x${string}` }) { // Works without wallet connection! const { data: history, isLoading } = useGetCallsHistory({ address }); if (isLoading) return

Loading...

; return (

History for {address}

{history?.length || 0} transactions found

); } ``` #### With Pagination ```tsx import { useState } from 'react'; import { useGetCallsHistory } from '@jaw.id/wagmi'; function PaginatedHistory({ address }: { address: `0x${string}` }) { const [cursor, setCursor] = useState(); const { data: history, isLoading, isFetching } = useGetCallsHistory({ address, index: cursor, limit: 10, sort: 'desc', }); const loadMore = () => { if (history && history.length > 0) { setCursor(history[history.length - 1].index); } }; return (
{history?.map((item) => (
{item.status === 200 ? 'Completed' : 'Pending'}
))}
); } ``` #### Filtering by Status ```tsx import { useGetCallsHistory } from '@jaw.id/wagmi'; function PendingTransactions() { const { data: history } = useGetCallsHistory(); const pending = history?.filter((item) => item.status === 100) || []; return (

Pending Transactions ({pending.length})

{pending.map((item) => (
Submitted: {new Date(item.timestamp * 1000).toLocaleString()}
))}
); } ``` #### Manual Refresh ```tsx import { useGetCallsHistory } from '@jaw.id/wagmi'; function RefreshableHistory() { const { data, refetch, isFetching } = useGetCallsHistory(); return (

{data?.length || 0} transactions

); } ``` ### Related * [wallet\_getCallsHistory](/api-reference/wallet_getCallsHistory) - RPC method reference * [wallet\_getCallsStatus](/api-reference/wallet_getCallsStatus) - Get status of specific batch * [useGetAssets](/wagmi/useGetAssets) - Query asset balances ## useGrantPermissions Source: https://docs.jaw.id/wagmi/useGrantPermissions ## useGrantPermissions Hook to grant permissions to a spender address, enabling session keys, subscriptions, and automated transactions. **Type:** `hook` ### Import ```typescript import { useGrantPermissions } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useGrantPermissions(parameters?: { config?: Config; mutation?: UseMutationParameters; }): UseMutationResult ``` ### Parameters #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### mutation Type: `UseMutationParameters` (optional) TanStack React Query mutation options. ### Returns Returns a TanStack React Query mutation result: \| Property | Type | Description | \|----------|------|-------------| \| `mutate` | `function` | Function to grant permissions | \| `mutateAsync` | `function` | Async version of mutate | \| `data` | `WalletGrantPermissionsResponse` | Granted permission details | \| `isPending` | `boolean` | Whether granting is in progress | \| `isSuccess` | `boolean` | Whether granting succeeded | \| `isError` | `boolean` | Whether granting failed | \| `error` | `Error` | Error if granting failed | #### data When successful, `data` contains: ```typescript interface WalletGrantPermissionsResponse { /** Smart account this permission is valid for */ account: Address; /** Entity that can use this permission */ spender: Address; /** Timestamp when permission becomes valid */ start: number; /** Timestamp when permission expires */ end: number; /** Salt for uniqueness */ salt: Hex; /** Array of call permissions */ calls: CallPermissionDetail[]; /** Array of spend permissions */ spends: SpendPermissionDetail[]; /** Permission identifier (hash) */ permissionId: Hex; /** Chain ID in hex */ chainId: Hex; } ``` ### Mutation Variables When calling `mutate()`, pass an object with the following properties: #### expiry (required) Type: `number` Unix timestamp (in seconds) when the permission expires. The permission becomes invalid after this time. ```typescript // Permission valid for 1 week const expiry = Math.floor(Date.now() / 1000) + 86400 * 7; ``` #### spender (required) Type: `Address` The address that will be granted permission to execute calls on behalf of the account. This is typically: * A session key address * A backend service address * An automation bot address ```typescript const spender = '0x1234...'; // The address that can use this permission ``` #### permissions (required) Type: `PermissionsDetail` The permissions to grant. Contains two optional arrays: `calls` (what functions can be called) and `spends` (token spending limits). ```typescript interface PermissionsDetail { /** Call permissions - which contracts and functions can be called */ calls?: CallPermissionDetail[]; /** Spend permissions - token spending limits */ spends?: SpendPermissionDetail[]; } ``` ##### permissions.calls Type: `CallPermissionDetail[]` (optional) Array of call permissions specifying which contract functions the spender can call. ```typescript interface CallPermissionDetail { /** Target contract address */ target: Address; /** Function selector (4 bytes hex). Optional if functionSignature is provided. */ selector?: Hex; /** Human-readable function signature. Selector is computed from this if not provided. */ functionSignature?: string; } ``` \| Field | Type | Required | Description | \|-------|------|----------|-------------| \| `target` | `Address` | Yes | Contract address the spender can call | \| `selector` | `Hex` | No\* | 4-byte function selector (e.g., `'0xa9059cbb'`) | \| `functionSignature` | `string` | No\* | Human-readable signature (e.g., `'transfer(address,uint256)'`) | \*Either `selector` or `functionSignature` must be provided. :::tip Use `functionSignature` for readability - the SDK computes the selector automatically: ```typescript // These are equivalent: { target: USDC, selector: '0xa9059cbb' } { target: USDC, functionSignature: 'transfer(address,uint256)' } ``` ::: ##### permissions.spends Type: `SpendPermissionDetail[]` (optional) Array of spend permissions specifying token spending limits per time period. ```typescript interface SpendPermissionDetail { /** Token address. Use NATIVE_TOKEN constant for ETH. */ token: Address; /** Maximum amount per period (in wei, as string) */ allowance: string; /** Time period unit for the limit */ unit: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year' | 'forever'; /** Multiplier for the period (1-255). Defaults to 1. */ multiplier?: number; } ``` \| Field | Type | Required | Description | \|-------|------|----------|-------------| \| `token` | `Address` | Yes | Token contract address. Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for native ETH. | \| `allowance` | `string` | Yes | Maximum spend amount per period in wei (as string, supports large numbers) | \| `unit` | `SpendPeriod` | Yes | Time period: `'minute'`, `'hour'`, `'day'`, `'week'`, `'month'`, `'year'`, or `'forever'` | \| `multiplier` | `number` | No | Period multiplier (1-255). E.g., `unit: 'day', multiplier: 3` = every 3 days. Defaults to 1. | :::info For native ETH spending limits, use the ERC-7528 native token address: ```typescript const NATIVE_TOKEN = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; ``` ::: #### address (optional) Type: `Address` Specific account address to grant permissions for. Defaults to the connected account. #### chainId (optional) Type: `number` Target chain ID. Defaults to the connected chain. #### connector (optional) Type: `Connector` Specific connector to use. Defaults to the active connector. ### Examples #### Basic Usage - Allow Token Transfers ```tsx import { useGrantPermissions } from '@jaw.id/wagmi'; import { parseUnits } from 'viem'; const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; function GrantPermissionButton() { const { mutate: grant, isPending, data } = useGrantPermissions(); const handleGrant = () => { grant({ expiry: Math.floor(Date.now() / 1000) + 86400 * 7, // 1 week spender: '0xYourBackendService...', permissions: { calls: [ { target: USDC, functionSignature: 'transfer(address,uint256)', }, ], spends: [ { token: USDC, allowance: parseUnits('100', 6).toString(), // 100 USDC unit: 'day', }, ], }, }); }; return (
{data &&

Permission ID: {data.permissionId}

}
); } ``` #### Subscription Service - Monthly Limit ```tsx import { useGrantPermissions } from '@jaw.id/wagmi'; import { parseUnits } from 'viem'; function SubscriptionButton() { const { mutate: grant, isPending } = useGrantPermissions(); const handleSubscribe = () => { grant({ expiry: Math.floor(Date.now() / 1000) + 86400 * 365, // 1 year spender: '0xSubscriptionService...', permissions: { calls: [ { target: USDC_ADDRESS, functionSignature: 'transfer(address,uint256)', }, ], spends: [ { token: USDC_ADDRESS, allowance: parseUnits('9.99', 6).toString(), // $9.99/month unit: 'month', }, ], }, }); }; return ( ); } ``` #### DeFi Automation - Swap Permission ```tsx import { useGrantPermissions } from '@jaw.id/wagmi'; const UNISWAP_ROUTER = '0x...'; function AutomatedTradingSetup() { const { mutate: grant, isPending } = useGrantPermissions(); const handleSetup = () => { grant({ expiry: Math.floor(Date.now() / 1000) + 86400 * 30, // 30 days spender: '0xTradingBot...', permissions: { calls: [ { target: UNISWAP_ROUTER, functionSignature: 'swapExactTokensForTokens(uint256,uint256,address[],address,uint256)', }, { target: UNISWAP_ROUTER, functionSignature: 'swapTokensForExactTokens(uint256,uint256,address[],address,uint256)', }, ], spends: [ { token: USDC_ADDRESS, allowance: parseUnits('1000', 6).toString(), // 1000 USDC per week unit: 'week', }, { token: WETH_ADDRESS, allowance: parseUnits('0.5', 18).toString(), // 0.5 WETH per week unit: 'week', }, ], }, }); }; return ( ); } ``` #### Native ETH Spending Limit ```tsx import { useGrantPermissions } from '@jaw.id/wagmi'; import { parseEther } from 'viem'; const NATIVE_TOKEN = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; function NativeSpendingLimit() { const { mutate: grant, isPending } = useGrantPermissions(); const handleGrant = () => { grant({ expiry: Math.floor(Date.now() / 1000) + 86400 * 7, spender: '0xGamingContract...', permissions: { spends: [ { token: NATIVE_TOKEN, allowance: parseEther('0.1').toString(), // 0.1 ETH per day unit: 'day', }, ], }, }); }; return ( ); } ``` #### With Period Multiplier ```tsx // Allow 500 USDC every 2 weeks grant({ expiry: Math.floor(Date.now() / 1000) + 86400 * 90, // 90 days spender: '0xPayrollService...', permissions: { spends: [ { token: USDC_ADDRESS, allowance: parseUnits('500', 6).toString(), unit: 'week', multiplier: 2, // Every 2 weeks }, ], }, }); ``` #### With Callbacks ```tsx import { useGrantPermissions } from '@jaw.id/wagmi'; function GrantWithCallbacks() { const { mutate: grant } = useGrantPermissions({ mutation: { onSuccess: (data) => { console.log('Permission granted:', data.permissionId); // Store permission ID for later revocation savePermissionId(data.permissionId); }, onError: (error) => { console.error('Failed to grant permission:', error); }, }, }); // ... } ``` ### Use Cases * **Session Keys** - Allow a temporary key to perform specific actions without full wallet access * **Subscription Services** - Grant recurring spending permissions for SaaS, content, or services * **Automated Trading** - Allow a bot to execute specific trades within spending limits * **Gaming** - Let a game contract execute moves without transaction prompts * **DeFi Automation** - Enable auto-compounding, limit orders, or rebalancing * **Payroll** - Allow scheduled payments to employees ### Related * [usePermissions](/wagmi/usePermissions) - Get current permissions * [useRevokePermissions](/wagmi/useRevokePermissions) - Revoke a permission * [wallet\_grantPermissions](/api-reference/wallet_grantPermissions) - RPC method reference ## usePermissions Source: https://docs.jaw.id/wagmi/usePermissions ## usePermissions Hook to get the current permissions for the connected account. Automatically updates when permissions change. **Type:** `hook` ### Import ```typescript import { usePermissions } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function usePermissions(parameters?: { address?: Address; chainId?: number; connector?: Connector; config?: Config; query?: UseQueryParameters; }): UseQueryResult ``` ### Parameters #### address Type: `Address` (optional) Specific account address to get permissions for. Defaults to connected account. #### chainId Type: `number` (optional) Specific chain ID. Defaults to current chain. #### connector Type: `Connector` (optional) Specific connector to use. Defaults to active connector. #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### query Type: `UseQueryParameters` (optional) TanStack React Query options (excluding `gcTime` and `staleTime` which are managed internally). ### Returns Returns a TanStack React Query result: \| Property | Type | Description | \|----------|------|-------------| \| `data` | `WalletGetPermissionsResponse` | Array of permissions | \| `isLoading` | `boolean` | Whether initial load is in progress | \| `isFetching` | `boolean` | Whether any fetch is in progress | \| `isSuccess` | `boolean` | Whether query succeeded | \| `isError` | `boolean` | Whether query failed | \| `error` | `Error` | Error if query failed | \| `refetch` | `function` | Manually refetch permissions | #### data When successful, `data` is an array of permissions: ```typescript type WalletGetPermissionsResponse = Permission[]; interface Permission { /** Permission identifier (hash) */ id: Hex; /** Smart account address */ account: Address; /** Spender address */ spender: Address; /** Start timestamp */ start: number; /** Expiry timestamp */ expiry: number; /** Call permissions */ calls: CallPermissionDetail[]; /** Spend permissions */ spends: SpendPermissionDetail[]; } ``` ### Behavior 1. **Auto-enables** when wallet is connected 2. **Listens for changes** via `permissionsChanged` event 3. **Auto-refetches** when permissions change on-chain 4. **Caches indefinitely** until invalidated by events ### Examples #### Basic Usage ```tsx import { useAccount } from 'wagmi'; import { usePermissions } from '@jaw.id/wagmi'; function PermissionsList() { const { isConnected } = useAccount(); const { data: permissions, isLoading } = usePermissions(); if (!isConnected) return

Connect wallet to view permissions

; if (isLoading) return

Loading permissions...

; if (!permissions?.length) { return

No active permissions

; } return (
    {permissions.map((permission) => (
  • Spender: {permission.spender}

    Expires: {new Date(permission.expiry * 1000).toLocaleString()}

    Calls: {permission.calls.length}

    Spends: {permission.spends.length}

  • ))}
); } ``` #### For Specific Address ```tsx import { usePermissions } from '@jaw.id/wagmi'; function PermissionsForAddress({ address }: { address: `0x${string}` }) { const { data: permissions } = usePermissions({ address }); // ... } ``` #### Disable Auto-Fetch ```tsx import { usePermissions } from '@jaw.id/wagmi'; function ManualPermissions() { const { data, refetch } = usePermissions({ query: { enabled: false, // Don't fetch automatically }, }); return (
{data &&

{data.length} permissions found

}
); } ``` ### Related * [useGrantPermissions](/wagmi/useGrantPermissions) - Grant new permissions * [useRevokePermissions](/wagmi/useRevokePermissions) - Revoke a permission * [wallet\_getPermissions](/api-reference/wallet_getPermissions) - RPC method reference ## useRevokePermissions Source: https://docs.jaw.id/wagmi/useRevokePermissions ## useRevokePermissions Hook to revoke an active permission by its ID. This permanently disables the permission, preventing the spender from executing any further calls. **Type:** `hook` ### Import ```typescript import { useRevokePermissions } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useRevokePermissions(parameters?: { config?: Config; mutation?: UseMutationParameters; }): UseMutationResult ``` ### Parameters #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### mutation Type: `UseMutationParameters` (optional) TanStack React Query mutation options. ### Returns Returns a TanStack React Query mutation result: \| Property | Type | Description | \|----------|------|-------------| \| `mutate` | `function` | Function to revoke permission | \| `mutateAsync` | `function` | Async version of mutate | \| `data` | `RevokePermissionApiResponse` | Revocation result | \| `isPending` | `boolean` | Whether revocation is in progress | \| `isSuccess` | `boolean` | Whether revocation succeeded | \| `isError` | `boolean` | Whether revocation failed | \| `error` | `Error` | Error if revocation failed | #### data When successful, `data` contains: ```typescript interface RevokePermissionApiResponse { /** Indicates if the permission was revoked successfully */ success: boolean; } ``` ### Mutation Variables When calling `mutate()`, pass an object with the following properties: #### id (required) Type: `Hex` (e.g., `` `0x${string}` ``) The permission ID (hash) to revoke. You can obtain this from: * The `permissionId` field returned when granting a permission * The `permissionId` field from permissions returned by `usePermissions()` ```typescript // From grant response const { data } = useGrantPermissions(); const permissionId = data.permissionId; // '0x1234...' // From permissions list const { data: permissions } = usePermissions(); const permissionId = permissions[0].permissionId; // '0x1234...' ``` #### address (optional) Type: `Address` Specific account address to revoke the permission for. Defaults to the connected account. ```typescript revoke({ id: '0x1234...', address: '0xSpecificAccount...', // Optional: specify which account }); ``` #### chainId (optional) Type: `number` Target chain ID where the permission exists. Defaults to the connected chain. :::warning **Chain-Specific**: Permissions are chain-specific. Make sure you're revoking on the correct chain where the permission was granted. ::: ```typescript revoke({ id: '0x1234...', chainId: 8453, // Revoke on Base }); ``` #### connector (optional) Type: `Connector` Specific connector to use. Defaults to the active connector. #### capabilities (optional) Type: `RequestCapabilities` Optional capabilities for the revocation transaction, such as paymaster service for sponsored (gasless) revocation. ```typescript interface RequestCapabilities { /** Paymaster service for sponsored transactions */ paymasterService?: { /** URL of the paymaster service (ERC-7677 compliant) */ url: string; /** Optional context for the paymaster */ context?: Record; }; } ``` ```typescript // Sponsored revocation (gasless) revoke({ id: '0x1234...', capabilities: { paymasterService: { url: 'https://paymaster.example.com', }, }, }); ``` ### Examples #### Basic Usage ```tsx import { useRevokePermissions } from '@jaw.id/wagmi'; function RevokeButton({ permissionId }: { permissionId: `0x${string}` }) { const { mutate: revoke, isPending } = useRevokePermissions(); return ( ); } ``` #### With Confirmation Dialog ```tsx import { useState } from 'react'; import { useRevokePermissions } from '@jaw.id/wagmi'; function RevokeWithConfirmation({ permission }) { const { mutate: revoke, isPending } = useRevokePermissions(); const [showConfirm, setShowConfirm] = useState(false); const handleRevoke = () => { revoke( { id: permission.permissionId }, { onSuccess: () => { setShowConfirm(false); // Permission list will auto-update via usePermissions }, } ); }; if (showConfirm) { return (

Revoke permission for {permission.spender}?

This action cannot be undone.

); } return ; } ``` #### With Callbacks ```tsx import { useRevokePermissions } from '@jaw.id/wagmi'; import { toast } from 'sonner'; function RevokeWithCallbacks() { const { mutate: revoke } = useRevokePermissions({ mutation: { onSuccess: () => { toast.success('Permission revoked successfully'); }, onError: (error) => { toast.error(`Failed to revoke: ${error.message}`); }, }, }); // ... } ``` #### Full Permissions Manager ```tsx import { usePermissions, useRevokePermissions } from '@jaw.id/wagmi'; function PermissionsManager() { const { data: permissions, isLoading } = usePermissions(); const { mutate: revoke, isPending, variables } = useRevokePermissions(); if (isLoading) return

Loading permissions...

; if (!permissions?.length) return

No active permissions

; return (

Active Permissions

{permissions.map((permission) => { const isRevoking = isPending && variables?.id === permission.permissionId; return (

Spender: {permission.spender}

Expires: {new Date(permission.end * 1000).toLocaleDateString()}

Call Permissions: {permission.calls.length}

Spend Limits: {permission.spends.length}

); })}
); } ``` #### Revoke on Specific Chain ```tsx import { useRevokePermissions } from '@jaw.id/wagmi'; import { base } from 'wagmi/chains'; function RevokeOnBase({ permissionId }) { const { mutate: revoke, isPending } = useRevokePermissions(); const handleRevoke = () => { revoke({ id: permissionId, chainId: base.id, // Revoke on Base chain }); }; return ( ); } ``` #### Sponsored Revocation (Gasless) ```tsx import { useRevokePermissions } from '@jaw.id/wagmi'; function SponsoredRevoke({ permissionId }) { const { mutate: revoke, isPending } = useRevokePermissions(); const handleRevoke = () => { revoke({ id: permissionId, capabilities: { paymasterService: { url: 'https://your-paymaster.com/api', }, }, }); }; return ( ); } ``` ### Important Notes :::warning **Revocation is Permanent**: Once a permission is revoked, it cannot be restored. The spender will immediately lose the ability to execute calls using that permission. To re-enable access, you must grant a new permission. ::: :::info **Transaction Required**: Revoking a permission requires an on-chain transaction. The user will need to pay gas for the transaction (unless using a paymaster for gasless revocation). ::: ### Related * [usePermissions](/wagmi/usePermissions) - Get current permissions * [useGrantPermissions](/wagmi/useGrantPermissions) - Grant new permissions * [wallet\_revokePermissions](/api-reference/wallet_revokePermissions) - RPC method reference ## useSign Source: https://docs.jaw.id/wagmi/useSign ## useSign Hook to sign messages using the unified `wallet_sign` method (ERC-7871). This combines the functionality of `useSignMessage` and `useSignTypedData` into a single hook, with support for specifying a target chain. **Type:** `hook` ### Import ```typescript import { useSign } from '@jaw.id/wagmi'; ``` ### Signature ```typescript function useSign(parameters?: { config?: Config; mutation?: UseMutationParameters; }): UseMutationResult ``` ### Parameters #### config Type: `Config` (optional) Wagmi config. If not provided, uses the config from `WagmiProvider`. #### mutation Type: `UseMutationParameters` (optional) TanStack React Query mutation options. ### Returns Returns a TanStack React Query mutation result: \| Property | Type | Description | \|----------|------|-------------| \| `mutate` | `function` | Function to sign a message | \| `mutateAsync` | `function` | Async version of mutate | \| `data` | `Hex` | The signature | \| `isPending` | `boolean` | Whether signing is in progress | \| `isSuccess` | `boolean` | Whether signing succeeded | \| `isError` | `boolean` | Whether signing failed | \| `error` | `Error` | Error if signing failed | ### Mutation Variables When calling `mutate()`, pass: #### request Type: `PersonalSignRequestData | TypedDataRequestData` (required) The signing request, which can be one of two types: ##### Personal Sign (EIP-191) ```typescript { type: '0x45', data: { message: string; } } ``` ##### Typed Data (EIP-712) ```typescript { type: '0x01', data: { types: Record; primaryType: string; domain: TypedDataDomain; message: Record; } } ``` #### Optional Parameters \| Parameter | Type | Description | \|-----------|------|-------------| \| `address` | `Address` | Specific account address | \| `chainId` | `number` | Target chain ID for signing | \| `connector` | `Connector` | Specific connector | ### Why Use useSign? #### Unified API Instead of choosing between `useSignMessage` and `useSignTypedData`, use a single hook that handles both: \| Signature Type | Type Code | Standard | \|---------------|-----------|----------| \| Personal Sign | `0x45` | EIP-191 | \| Typed Data | `0x01` | EIP-712 | #### Chain-Specific Signing Smart accounts can produce different signatures depending on which chain they're deployed on. The `chainId` parameter lets you sign for a specific chain without calling `wallet_switchEthereumChain` first: ```typescript // Sign for Base without switching chains signMessage({ chainId: 8453, request: { type: '0x45', data: { message: 'Hello from Base' }, }, }); ``` :::info The `chainId` parameter specifies which chain's smart account to use for signing. This is separate from any chain ID that might be included in the message content itself (like in EIP-712's domain). ::: ### Examples #### Personal Sign ```tsx import { useSign } from '@jaw.id/wagmi'; function SignMessageButton() { const { mutate: signMessage, data: signature, isPending } = useSign(); const handleSign = () => { signMessage({ request: { type: '0x45', data: { message: 'Hello, World!' }, }, }); }; return (
{signature &&

Signature: {signature}

}
); } ``` #### Typed Data (EIP-712) ```tsx import { useSign } from '@jaw.id/wagmi'; function SignTypedDataButton() { const { mutate: signMessage, data: signature, isPending } = useSign(); const handleSign = () => { signMessage({ request: { type: '0x01', data: { types: { EIP712Domain: [ { name: 'name', type: 'string' }, { name: 'version', type: 'string' }, { name: 'chainId', type: 'uint256' }, ], Mail: [ { name: 'from', type: 'string' }, { name: 'to', type: 'string' }, { name: 'contents', type: 'string' }, ], }, primaryType: 'Mail', domain: { name: 'My dApp', version: '1', chainId: 1, }, message: { from: 'Alice', to: 'Bob', contents: 'Hello!', }, }, }, }); }; return ( ); } ``` #### Cross-Chain Signing ```tsx import { useSign } from '@jaw.id/wagmi'; import { base, mainnet } from 'wagmi/chains'; function CrossChainSign() { const { mutate: signMessage, isPending } = useSign(); const signForBase = () => { signMessage({ chainId: base.id, request: { type: '0x45', data: { message: 'Signed using Base smart account' }, }, }); }; const signForMainnet = () => { signMessage({ chainId: mainnet.id, request: { type: '0x45', data: { message: 'Signed using Mainnet smart account' }, }, }); }; return (
); } ``` #### With Callbacks ```tsx import { useSign } from '@jaw.id/wagmi'; function SignWithCallbacks() { const { mutate: signMessage } = useSign({ mutation: { onSuccess: (signature) => { console.log('Signature:', signature); // Send signature to your backend }, onError: (error) => { console.error('Signing failed:', error); }, }, }); // ... } ``` ### Comparison with Wagmi Hooks \| Feature | `useSignMessage` | `useSignTypedData` | `useSign` | \|---------|------------------|-------------------|-----------| \| Personal sign (EIP-191) | Yes | No | Yes | \| Typed data (EIP-712) | No | Yes | Yes | \| Target chain parameter | No | No | Yes | \| Smart account aware | No | No | Yes | ### Use Cases * **Authentication** - Sign messages to prove account ownership * **Gasless Signatures** - Sign data without sending a transaction * **Multi-chain dApps** - Sign for different chains without switching * **Permit Signatures** - Sign EIP-2612 permit messages * **Off-chain Orders** - Sign trading orders for DEX aggregators ### Related * [wallet\_sign](/api-reference/wallet_sign) - RPC method reference * [personal\_sign](/api-reference/personal_sign) - Standard personal sign * [eth\_signTypedData\_v4](/api-reference/eth_signTypedData_v4) - Standard typed data signing