> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dfns.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate with viem

> Using viem with Dfns for EVM transactions

[viem](https://viem.sh) is a popular TypeScript library for interacting with EVM chains. This guide shows how to use viem with Dfns wallets.

<Tip>
  See complete working examples in the [dfns-sdk-ts repository](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem), including account abstraction integrations with Alchemy, Biconomy, Pimlico, and ZeroDev.
</Tip>

## Setup

Install the required packages:

```bash theme={null}
npm install viem @dfns/sdk @dfns/lib-viem
```

## Creating a Dfns-backed viem account

Use `DfnsWallet` and `toAccount` from the SDK to create a viem-compatible account:

```typescript theme={null}
import { DfnsWallet } from '@dfns/lib-viem'
import { DfnsApiClient } from '@dfns/sdk'
import { AsymmetricKeySigner } from '@dfns/sdk-keysigner'
import { createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { toAccount } from 'viem/accounts'

// Initialize Dfns client
const signer = new AsymmetricKeySigner({
  credId: process.env.DFNS_CRED_ID!,
  privateKey: process.env.DFNS_PRIVATE_KEY!,
})

const dfnsClient = new DfnsApiClient({
  authToken: process.env.DFNS_AUTH_TOKEN!,
  baseUrl: process.env.DFNS_API_URL!,
  signer,
})

// Initialize Dfns wallet
const dfnsWallet = await DfnsWallet.init({
  walletId: process.env.DFNS_WALLET_ID!,
  dfnsClient,
})

// Create viem wallet client
const walletClient = createWalletClient({
  account: toAccount(dfnsWallet),
  chain: mainnet,
  transport: http(),
})
```

## Sending transactions

### Simple ETH transfer

```typescript theme={null}
import { parseEther } from 'viem'

const hash = await walletClient.sendTransaction({
  to: '0x...',
  value: parseEther('0.1'),
})

// Wait for confirmation
const receipt = await publicClient.waitForTransactionReceipt({ hash })
```

### Contract interaction

```typescript theme={null}
import { parseAbi, parseUnits } from 'viem'

const hash = await walletClient.writeContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  abi: parseAbi(['function transfer(address to, uint256 amount) returns (bool)']),
  functionName: 'transfer',
  args: ['0xRecipient...', parseUnits('100', 6)], // 100 USDC
})
```

### EIP-712 typed data signing

```typescript theme={null}
const signature = await walletClient.signTypedData({
  domain: {
    name: 'My App',
    version: '1',
    chainId: 1,
    verifyingContract: '0x...',
  },
  types: {
    Order: [
      { name: 'maker', type: 'address' },
      { name: 'amount', type: 'uint256' },
    ],
  },
  primaryType: 'Order',
  message: {
    maker: walletAddress,
    amount: 1000000n,
  },
})
```

## Account abstraction (gasless transactions)

Dfns wallets work with account abstraction providers for gasless transactions. The SDK includes examples for:

| Provider                                                                                      | Use case                           |
| --------------------------------------------------------------------------------------------- | ---------------------------------- |
| [Alchemy](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/alchemy-aa-gasless)   | Modular accounts with gas policies |
| [Biconomy](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/biconomy-aa-gasless) | Smart accounts with paymasters     |
| [Pimlico](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/pimlico-aa-gasless)   | Bundler and paymaster services     |
| [ZeroDev](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/zerodev-aa-gasless)   | Kernel smart accounts              |

### Example with Alchemy

```typescript theme={null}
import { createModularAccountAlchemyClient } from '@alchemy/aa-alchemy'
import { LocalAccountSigner } from '@alchemy/aa-core'
import { sepolia } from 'viem/chains'

const smartAccountClient = await createModularAccountAlchemyClient({
  apiKey: process.env.ALCHEMY_API_KEY!,
  chain: sepolia,
  signer: new LocalAccountSigner(toAccount(dfnsWallet)),
  gasManagerConfig: {
    policyId: process.env.ALCHEMY_GAS_POLICY_ID!,
  },
})

// Transactions are now gasless for your users
const hash = await smartAccountClient.sendTransaction({
  to: '0x...',
  data: '0x...',
})
```

## Multicall (batch transactions)

Batch multiple contract calls in a single transaction:

```typescript theme={null}
import { encodeFunctionData, parseAbi } from 'viem'

const multiCallAddress = '0x...' // Multicall3 contract

const hash = await walletClient.sendTransaction({
  to: multiCallAddress,
  data: encodeFunctionData({
    abi: multicallAbi,
    functionName: 'aggregate3',
    args: [[
      { target: token1, callData: transferData1 },
      { target: token2, callData: transferData2 },
    ]],
  }),
})
```

See the [multicall example](https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem/multicall) for complete implementation.

## Reading contract data

Use a public client for read operations (no signing needed):

```typescript theme={null}
import { createPublicClient, http, parseAbi } from 'viem'
import { mainnet } from 'viem/chains'

const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
})

// Read ERC-20 balance
const balance = await publicClient.readContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  abi: parseAbi(['function balanceOf(address) view returns (uint256)']),
  functionName: 'balanceOf',
  args: [walletAddress],
})
```

## Using Dfns Broadcast API instead

For better policy integration, you may prefer using the Dfns Broadcast API directly:

```typescript theme={null}
import { encodeFunctionData, parseAbi } from 'viem'

// Encode the contract call with viem
const data = encodeFunctionData({
  abi: parseAbi(['function transfer(address to, uint256 amount) returns (bool)']),
  functionName: 'transfer',
  args: [recipient, amount],
})

// Broadcast via Dfns
const result = await dfnsClient.wallets.broadcastTransaction({
  walletId,
  body: {
    kind: 'Evm',
    to: tokenAddress,
    data,
  },
})
```

This approach integrates with Dfns policies and provides consistent transaction tracking.

## Related

<CardGroup cols={2}>
  <Card title="viem examples" icon="github" href="https://github.com/dfns/dfns-sdk-ts/tree/m/examples/libs/viem">
    Complete working examples
  </Card>

  <Card title="TypeScript SDK" icon="code" href="/sdks/typescript">
    Dfns TypeScript SDK documentation
  </Card>

  <Card title="EVM Signing" icon="signature" href="/api-reference/sign/evm">
    EVM signature types reference
  </Card>

  <Card title="EVM Broadcast" icon="tower-broadcast" href="/api-reference/broadcast/evm">
    EVM transaction broadcast reference
  </Card>
</CardGroup>
