Skip to main content
Viem is a TypeScript interface for Ethereum. This guide shows how to integrate Para’s secure signing with both v2 (recommended) and v1 versions.

Prerequisites

To use Para, you need an API key. This key authenticates your requests to Para services and is essential for integration. Before integrating Para with your application, ensure you have:
  • Completed Para authentication setup in your application (see one of our Setup Guides)
  • A valid Para API key
  • An RPC endpoint for your desired network
Need an API key? Visit the Developer Portal to create API keys, manage billing, teams, and more.

Installation

Choose your package manager to install the Para Viem integration along with Viem:
  • Viem v2
  • Viem v1
npm install @getpara/viem-v2-integration viem@^2

Basic Setup

  • Viem v2
  • Viem v1
import { createParaViemClient, createParaAccount } from "@getpara/viem-v2-integration";
import { http, parseEther } from "viem";
import { sepolia } from "viem/chains";
import Para, { Environment } from "@getpara/web-sdk";

// Initialize Para (ensure authentication is completed before signing)
const para = new Para(Environment.BETA, YOUR_API_KEY);

// Create a Para Account
const account = await createParaAccount(para);

// Create the Para Viem WalletClient
const walletClient = createParaViemClient(para, {
  account: account,
  chain: sepolia,
  transport: http("https://ethereum-sepolia-rpc.publicnode.com"),
});

// Now you can use the client with Viem's API

Usage Examples

Once you’ve set up the Para Viem integration, you can leverage Viem’s API with Para’s secure signing. Para handles the secure signing process without changing how you construct transactions.

Sending ETH

  • Viem v2
  • Viem v1
import { parseEther, parseGwei } from "viem";

// Prepare transaction parameters
const transaction = {
  account: viemParaAccount,
  to: "0x1234567890123456789012345678901234567890" as `0x${string}`,
  value: parseEther("0.01"),
  gas: 21000n, // Or use parseGwei("21000")
};

// Send the transaction
try {
  const hash = await paraClient.sendTransaction(transaction);
  console.log("Transaction hash:", hash);
  
  // Wait for confirmation
  const receipt = await paraClient.waitForTransactionReceipt({ hash });
  console.log("Transaction confirmed in block:", receipt.blockNumber);
} catch (error) {
  console.error("Error sending transaction:", error);
}

Interacting with Smart Contracts

  • Viem v2
  • Viem v1
import { parseUnits } from "viem";

// ERC-20 contract ABI (simplified for transfer)
const abi = [{
  name: "transfer",
  type: "function",
  stateMutability: "nonpayable",
  inputs: [
    { name: "recipient", type: "address" },
    { name: "amount", type: "uint256" }
  ],
  outputs: [{ type: "bool" }]
}];

// Create contract instance
const contract = {
  address: "0xTokenContractAddress" as `0x${string}`,
  abi
};

// Prepare the transaction
const { request } = await paraClient.simulateContract({
  ...contract,
  functionName: "transfer",
  args: [
    "0xRecipientAddress" as `0x${string}`,
    parseUnits("10", 18) // Adjust decimals based on your token
  ],
  account: viemParaAccount
});

// Send the transaction
const hash = await paraClient.writeContract(request);
console.log("Transaction hash:", hash);

Raw Transaction Signing

In some cases, you might want to sign a transaction without sending it immediately:
  • Viem v2
  • Viem v1
// Prepare transaction parameters
const transaction = {
  account: viemParaAccount,
  to: "0x1234567890123456789012345678901234567890" as `0x${string}`,
  value: parseEther("0.01"),
  gas: 21000n,
};

// Sign the transaction (returns the signed transaction bytes)
try {
  const signedTx = await paraClient.signTransaction(transaction);
  console.log("Signed transaction:", signedTx);
  
  // You can later broadcast this signed transaction
  const hash = await paraClient.broadcastTransaction({
    serializedTransaction: signedTx
  });
  console.log("Transaction hash:", hash);
} catch (error) {
  console.error("Error signing transaction:", error);
}

Para Viem Client Methods

The Para Viem client provides methods that allow you to leverage Para’s secure signing capabilities:
createParaAccount(para)
function
signMessage(message)
function
signTransaction(transaction)
function
signTypedData(parameters)
function
Para handles only the signing process. It does not modify your transaction in any way. All transaction construction, including gas estimations and parameter settings, is your responsibility through the Viem API.

Important Considerations

When working with the Para Viem integration, keep in mind:
  1. Authentication requirement: The Para client must have an authenticated account before attempting any signing operations.
  2. Wallet availability: Ensure Para has wallets available for the EVM wallet type. If you encounter errors about missing wallets, check your developer portal settings to confirm your API key is configured for EVM wallet types.
  3. Transaction construction: Para only signs the raw bytes of the transaction you provide. Any issues related to transaction parameters (gas price, gas limit, etc.) or RPC interactions are not related to Para’s signing functionality.
  4. Viem version compatibility: Ensure you’re using the correct Para integration package that matches your Viem version (v1 or v2).

Server-Side Signing

Para’s signers can also be used on the server-side using pregen wallets or an active client side session. To learn more about using para on the server, check out these guides:

Examples

If you’d like to learn more about how to use the Para Viem WalletClient for different transaction types, check out this example in our Examples Hub:

Troubleshooting

If your transaction fails with an RPC error, the issue is likely related to transaction construction, not Para’s signing process. Common causes include:
  • Insufficient funds for the transaction
  • Incorrect nonce value
  • Inadequate gas limit
  • RPC endpoint connectivity issues
Try constructing a simpler transaction first to verify the signing process works correctly.
If you receive an error about no wallets being available:
  1. Ensure the user has completed Para’s authentication process
  2. Verify the user has created or imported an Ethereum wallet
  3. Check that you’re using the correct Para instance that was used during authentication
Viem v2 has stricter type requirements than v1, particularly around address formatting. Ensure you’re using the correct type annotations:
// Convert string addresses to the correct Viem type
const address = "0x1234..." as `0x${string}`;

// For v2, use BigInt values for gas limits
const gas = 21000n; // or parseGwei("21000")

Next Steps

Now that you’ve completed integrating Para with Viem, explore more advanced features and use cases.
I