RISE Logo-Light

Wagmi Integration

Using RISE Wallet with Wagmi React hooks

This guide covers integrating RISE Wallet with Wagmi, the popular collection of React Hooks for Ethereum.

Overview

RISE Wallet implements a Wagmi connector and provides custom React hooks that map directly to the wallet's capabilities. The integration is designed to feel natural to developers already familiar with Wagmi.

Installation

npm i rise-wallet wagmi viem @tanstack/react-query
pnpm add rise-wallet wagmi viem @tanstack/react-query
yarn add rise-wallet wagmi viem @tanstack/react-query
bun add rise-wallet wagmi viem @tanstack/react-query

Basic Setup

1. Configure the Rise Wallet Connector

// config/wagmi.ts
import { Chains, RiseWallet } from "rise-wallet";
import { risewallet } from "rise-wallet/wagmi";
import { createConfig, http } from "wagmi";

// Export the connector for advanced usage
export const rwConnector = risewallet(RiseWallet.defaultConfig);

// Create wagmi config
export const config = createConfig({
  chains: [Chains.riseTestnet],
  connectors: [rwConnector],
  transports: {
    [Chains.riseTestnet.id]: http("https://testnet.riselabs.xyz"),
  },
});

2. Set Up Providers

// app/providers.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { config } from "@/config/wagmi";

const queryClient = new QueryClient();

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  );
}

Standard Wagmi Hooks

All standard Wagmi hooks work seamlessly with RISE Wallet:

Connection Management

import { useConnect, useAccount, useDisconnect } from "wagmi";

export function WalletButton() {
  const { address, isConnected } = useAccount();
  const { connect } = useConnect();
  const { disconnect } = useDisconnect();

  if (isConnected) {
    return (
      <div>
        <span>{address}</span>
        <button onClick={() => disconnect()}>Disconnect</button>
      </div>
    );
  }

  const rwConnector = config.connectors.find(c => c.id === "com.risechain.wallet");
  
  return (
    <button onClick={() => connect({ connector: rwConnector })}>
      Connect with Passkey
    </button>
  );
}

Sending Transactions

import { useSendCalls } from "wagmi";
import { parseEther } from "viem";

export function SendTransaction() {
  const { sendCallsAsync, isPending } = useSendCalls();

  const handleSend = async () => {
    const result = await sendCallsAsync({
      calls: [{
        to: "0x...",
        value: parseEther("0.001"),
      }],
    });
    
    console.log("Transaction sent:", result);
  };

  return (
    <button onClick={handleSend} disabled={isPending}>
      {isPending ? "Sending..." : "Send 0.001 ETH"}
    </button>
  );
}

RISE Wallet Specific Hooks

Import custom hooks via the Hooks namespace:

import { Hooks } from "rise-wallet/wagmi";
// or individually
import { useGrantPermissions } from "rise-wallet/wagmi/Hooks";

useGrantPermissions

Create session keys with specific permissions:

const grantPermissions = Hooks.useGrantPermissions();

const createSession = async () => {
  await grantPermissions.mutateAsync({
    key: { publicKey: "...", type: "p256" },
    expiry: Math.floor(Date.now() / 1000) + 3600, // 1 hour
    permissions: {
      calls: [{
        to: "0x...",
        signature: "0x...",
      }],
    },
  });
};

usePermissions

View current permissions for the connected account:

const { data: permissions } = Hooks.usePermissions();

if (permissions) {
  console.log("Active permissions:", permissions);
}

useRevokePermissions

Revoke previously granted permissions:

const revokePermissions = Hooks.useRevokePermissions();

const revokeSession = async (keyId: string) => {
  await revokePermissions.mutateAsync({
    keyId,
  });
};

useAssets

Get user's token balances and assets:

const { data: assets } = Hooks.useAssets();

return (
  <div>
    {assets?.map(asset => (
      <div key={asset.address}>
        {asset.symbol}: {asset.balance}
      </div>
    ))}
  </div>
);

Advanced Patterns

Batched Transactions

Execute multiple operations atomically:

const { sendCallsAsync } = useSendCalls();

// Approve and swap in one transaction
await sendCallsAsync({
  calls: [
    {
      to: TOKEN_ADDRESS,
      data: approveCalldata,
    },
    {
      to: DEX_ADDRESS,
      data: swapCalldata,
    },
  ],
  // Atomic execution - all succeed or all fail
  atomicRequired: true,
});

Reading Transaction Status

Monitor transaction progress:

import { useWaitForTransactionReceipt } from "wagmi";

const { data: receipt, isLoading } = useWaitForTransactionReceipt({
  hash: transactionHash,
});

if (receipt) {
  console.log("Transaction confirmed:", receipt);
}

Error Handling

Properly handle wallet errors:

import { BaseError } from "wagmi";

try {
  await sendCallsAsync({...});
} catch (error) {
  if (error instanceof BaseError) {
    // Handle specific error types
    if (error.shortMessage.includes("rejected")) {
      console.log("User rejected the request");
    }
  }
}

TypeScript Support

RISE Wallet provides full TypeScript support:

import type { RiseWallet } from "rise-wallet";
import type { Config } from "wagmi";

// Config is fully typed
const config: Config = createConfig({
  chains: [Chains.riseTestnet],
  connectors: [rwConnector],
  transports: {
    [Chains.riseTestnet.id]: http(),
  },
});

Best Practices

1. Check Connection State

Always verify the connection state before attempting transactions:

const { isConnected } = useAccount();

if (!isConnected) {
  return <ConnectButton />;
}

2. Handle Loading States

Provide feedback during async operations:

const { sendCallsAsync, isPending, isSuccess, isError } = useSendCalls();

3. Use Error Boundaries

Wrap your app with error boundaries to catch unexpected errors:

import { ErrorBoundary } from "react-error-boundary";

<ErrorBoundary fallback={<ErrorFallback />}>
  <App />
</ErrorBoundary>

Examples

For complete working examples, check out: