+ npm create wagmi@latest
+
+
+ yarn create wagmi
+
+
+
+```typescript
+import { http, createConfig } from "wagmi";
+import { mainnet, sepolia } from "wagmi/chains";
+import { coinbaseWallet, injected, walletConnect } from "wagmi/connectors";
+
+export const config = createConfig({
+ chains: [mainnet, sepolia],
+ connectors: [
+ injected(),
+ coinbaseWallet(),
+ walletConnect({ projectId: import.meta.env.VITE_WC_PROJECT_ID }),
+ ],
+ transports: {
+ [mainnet.id]: http(),
+ [sepolia.id]: http(),
+ },
+});
+
+declare module "wagmi" {
+ interface Register {
+ config: typeof config;
+ }
+}
+```
+
+
+
+
+```javascript
+import { useAccount, useConnect, useDisconnect } from "wagmi";
+
+function App() {
+ const account = useAccount();
+ const { connectors, connect, status, error } = useConnect();
+ const { disconnect } = useDisconnect();
+
+ return (
+ <>
+
+ Account
+
+
+ status: {account.status}
+
+ addresses: {JSON.stringify(account.addresses)}
+
+ chainId: {account.chainId}
+
+
+ {account.status === "connected" && (
+
+ )}
+
+
+
+ Connect
+ {connectors.map((connector) => (
+
+ ))}
+ {status}
+ {error?.message}
+
+ >
+ );
+}
+
+export default App;
+```
+
+
+
+
+```typescript
+import { Buffer } from "buffer";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { WagmiProvider } from "wagmi";
+
+import App from "./App.tsx";
+import { config } from "./wagmi.ts";
+
+import "./index.css";
+
+globalThis.Buffer = Buffer;
+
+const queryClient = new QueryClient();
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+
+
+
+
+
+);
+```
+
+
+
+
+```javascript
+import { http, createConfig } from "wagmi";
+import {
+ anvil,
+ arbitrum,
+ arbitrumGoerli,
+ base,
+ baseSepolia,
+ mainnet,
+ optimism,
+ optimismGoerli,
+ sepolia,
+} from "wagmi/chains";
+import { coinbaseWallet, injected, walletConnect } from "wagmi/connectors";
+import { createClient } from "viem";
+
+export const config = createConfig({
+ chains: [
+ anvil,
+ mainnet,
+ sepolia,
+ arbitrum,
+ arbitrumGoerli,
+ optimismGoerli,
+ optimism,
+ base,
+ baseSepolia,
+ ],
+ connectors: [
+ injected(),
+ coinbaseWallet(),
+ walletConnect({ projectId: import.meta.env.VITE_WC_PROJECT_ID }),
+ ],
+ client({ chain }) {
+ return createClient({ chain, transport: http() });
+ },
+});
+
+declare module "wagmi" {
+ interface Register {
+ config: typeof config;
+ }
+}
+
+```
+
+
+
+
+```javascript
+import { useAccount, useConnect, useDisconnect, useSwitchChain } from "wagmi";
+import { useState } from "react";
+
+const Account = () => {
+ const account = useAccount();
+ const { connectors, connect, status, error } = useConnect();
+ const { disconnect } = useDisconnect();
+ const { chains, switchChain } = useSwitchChain();
+ const [isChainDropdownOpen, setIsChainDropdownOpen] = useState(false);
+
+ return (
+
+
+ Account
+
+
+
+ Status: {account.status.toLocaleUpperCase()}
+
+
+ Address:{" "}
+ {account.addresses?.[0]}
+
+
+ Chain ID: {account.chain?.name} | {account.chainId}
+
+
+
+ {/* Display chain switching and disconnect options when connected */}
+ {account.status === "connected" && (
+
+ {/* Chain switching dropdown */}
+
+
+ {/* Dropdown menu for chain options */}
+ {isChainDropdownOpen && (
+
+ {chains.map((chainOption) => (
+
+ ))}
+
+ )}
+
+ {/* Disconnect button */}
+
+
+ )}
+
+
+ {/* Connect section */}
+
+ Connect
+
+ {connectors.map((connector) => (
+
+ ))}
+
+ Status: {status.toLocaleUpperCase()}
+ {error?.message}
+
+
+ );
+};
+
+export default Account;
+```
+
+
+
+
+```javascript
+import Account from "./components/Account";
+
+function App() {
+ return (
+ <>
+
+ >
+ );
+}
+
+export default App;
+
+```
+
+
+
+
+```javascript
+export const contractAddresses = {
+ InputBox: "0x59b22D57D4f067708AB0c00552767405926dc768",
+ EtherPortal: "0xFfdbe43d4c855BF7e0f105c400A50857f53AB044",
+ Erc20Portal: "0x9C21AEb2093C32DDbC53eEF24B873BDCd1aDa1DB",
+ Erc721Portal: "0x237F8DD094C0e47f4236f12b4Fa01d6Dae89fb87",
+ Erc1155SinglePortal: "0x7CFB0193Ca87eB6e48056885E026552c3A941FC4",
+ Erc1155BatchPortal: "0xedB53860A6B52bbb7561Ad596416ee9965B055Aa",
+ DAppAddressRelay: "0xF5DE34d6BbC0446E2a45719E718efEbaaE179daE"
+};
+```
+
+
+
+
+```typescript
+export const ABIs = {
+ DAppAddressRelayABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ {
+ inputs: [{ internalType: "address", name: "_dapp", type: "address" }],
+ name: "relayDAppAddress",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ ],
+
+ ERC1155BatchPortalABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [
+ { internalType: "contract IERC1155", name: "_token", type: "address" },
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "uint256[]", name: "_tokenIds", type: "uint256[]" },
+ { internalType: "uint256[]", name: "_values", type: "uint256[]" },
+ { internalType: "bytes", name: "_baseLayerData", type: "bytes" },
+ { internalType: "bytes", name: "_execLayerData", type: "bytes" },
+ ],
+ name: "depositBatchERC1155Token",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+
+ ERC1155SinglePortalABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [
+ { internalType: "contract IERC1155", name: "_token", type: "address" },
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "uint256", name: "_tokenId", type: "uint256" },
+ { internalType: "uint256", name: "_value", type: "uint256" },
+ { internalType: "bytes", name: "_baseLayerData", type: "bytes" },
+ { internalType: "bytes", name: "_execLayerData", type: "bytes" },
+ ],
+ name: "depositSingleERC1155Token",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+
+ ERC20PortalABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [
+ { internalType: "contract IERC20", name: "_token", type: "address" },
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "uint256", name: "_amount", type: "uint256" },
+ { internalType: "bytes", name: "_execLayerData", type: "bytes" },
+ ],
+ name: "depositERC20Tokens",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+
+ ERC721PortalABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [
+ { internalType: "contract IERC721", name: "_token", type: "address" },
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "uint256", name: "_tokenId", type: "uint256" },
+ { internalType: "bytes", name: "_baseLayerData", type: "bytes" },
+ { internalType: "bytes", name: "_execLayerData", type: "bytes" },
+ ],
+ name: "depositERC721Token",
+ outputs: [],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+
+ EtherPortalABI: [
+ {
+ inputs: [
+ {
+ internalType: "contract IInputBox",
+ name: "_inputBox",
+ type: "address",
+ },
+ ],
+ stateMutability: "nonpayable",
+ type: "constructor",
+ },
+ {
+ inputs: [],
+ name: "EtherTransferFailed",
+ type: "error",
+ },
+ {
+ inputs: [
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "bytes", name: "_execLayerData", type: "bytes" },
+ ],
+ name: "depositEther",
+ outputs: [],
+ stateMutability: "payable",
+ type: "function",
+ },
+ {
+ inputs: [],
+ name: "getInputBox",
+ outputs: [
+ { internalType: "contract IInputBox", name: "", type: "address" },
+ ],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+
+ InputBoxABI: [
+ {
+ inputs: [],
+ name: "InputSizeExceedsLimit",
+ type: "error",
+ },
+ {
+ anonymous: false,
+ inputs: [
+ { indexed: true, internalType: "address", name: "dapp", type: "address" },
+ {
+ indexed: true,
+ internalType: "uint256",
+ name: "inputIndex",
+ type: "uint256",
+ },
+ {
+ indexed: false,
+ internalType: "address",
+ name: "sender",
+ type: "address",
+ },
+ { indexed: false, internalType: "bytes", name: "input", type: "bytes" },
+ ],
+ name: "InputAdded",
+ type: "event",
+ },
+ {
+ inputs: [
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "bytes", name: "_input", type: "bytes" },
+ ],
+ name: "addInput",
+ outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
+ stateMutability: "nonpayable",
+ type: "function",
+ },
+ {
+ inputs: [
+ { internalType: "address", name: "_dapp", type: "address" },
+ { internalType: "uint256", name: "_index", type: "uint256" },
+ ],
+ name: "getInputHash",
+ outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
+ stateMutability: "view",
+ type: "function",
+ },
+ {
+ inputs: [{ internalType: "address", name: "_dapp", type: "address" }],
+ name: "getNumberOfInputs",
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
+ stateMutability: "view",
+ type: "function",
+ },
+ ],
+};
+```
+
+
+Transaction Sent
+ )} + + {error && ( +
+
+```typescript
+import React, { useState } from "react";
+import { BaseError, useWriteContract } from "wagmi";
+import { ABIs } from "../utils/abi";
+import { contractAddresses } from "../utils/addresses";
+import { Hex, stringToHex } from "viem";
+
+const SimpleInput = () => {
+ const dAppAddress = `0xab7528bb862fb57e8a2bcd567a2e929a0be56a5e`;
+ const [inputValue, setInputValue] = useState("");
+
+ const { isPending, isSuccess, error, writeContractAsync } =
+ useWriteContract();
+
+ async function submit(event: React.FormEvent) {
+ event.preventDefault();
+ await writeContractAsync({
+ address: contractAddresses.InputBox as Hex,
+ abi: ABIs.InputBoxABI,
+ functionName: "addInput",
+ args: [dAppAddress, stringToHex(inputValue)],
+ });
+ }
+
+ return (
+
+ Send Generic Input
+
+
+ {isSuccess && (
+ Transaction Sent
+ )}
+
+ {error && (
+
+ Error: {(error as BaseError).shortMessage || error.message}
+
+ )}
+
+ );
+};
+
+export default SimpleInput;
+
+```
+
+
+
+
+```typescript
+import Account from "./components/Account";
+import SimpleInput from "./components/SimpleInput";
+
+function App() {
+ return (
+ <>
+
+
+ >
+ );
+}
+
+export default App;
+
+```
+
+
+
+
+```typescript
+import React, { useState } from "react";
+import { BaseError, useWriteContract } from "wagmi";
+import { ABIs } from "../utils/abi";
+import { contractAddresses } from "../utils/addresses";
+
+import { Hex, parseEther, stringToHex } from "viem";
+
+const SendEther = () => {
+ const dAppAddress = `0xab7528bb862fb57e8a2bcd567a2e929a0be56a5e`;
+ const [etherValue, setEtherValue] = useState("");
+
+ const { isPending, isSuccess, error, writeContractAsync } = useWriteContract();
+
+ async function submit(event: React.FormEvent) {
+ event.preventDefault();
+ const data = stringToHex(`Deposited (${etherValue}) ether.`);
+ await writeContractAsync({
+ address: contractAddresses.EtherPortal as Hex,
+ abi: ABIs.EtherPortalABI,
+ functionName: "depositEther",
+ args: [dAppAddress, data],
+ value: parseEther(etherValue),
+ });
+ }
+
+ return (
+
+ Deposit Ether
+
+
+ {isSuccess && (
+ {etherValue} ETH sent!
+ )}
+
+ {error && (
+
+ Error: {(error as BaseError).shortMessage || error.message}
+
+ )}
+
+ );
+};
+
+export default SendEther;
+
+```
+
+
+
+
+```typescript
+import Account from "./components/Account";
+import SimpleInput from "./components/SimpleInput";
+import SendEther from "./components/SendEther";
+
+function App() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
+
+export default App;
+
+
+```
+
+
+
+
+```typescript
+iimport React, { useState } from "react";
+import { BaseError, useWriteContract } from "wagmi";
+import { ABIs } from "../utils/abi";
+import { contractAddresses } from "../utils/addresses";
+import { Address, erc20Abi, parseEther, stringToHex, Hex } from "viem";
+
+const SendERC20 = () => {
+ const dAppAddress = `0xab7528bb862fb57e8a2bcd567a2e929a0be56a5e`;
+ const [erc20Value, setErc20Value] = useState("");
+ const [tokenAddress, setTokenAddress] = useState();
+
+ const { isPending, isSuccess, error, writeContractAsync } =
+ useWriteContract();
+
+ const approveERC20 = async (tokenAddress: Address, amount: string) => {
+ try {
+ await writeContractAsync({
+ address: tokenAddress,
+ abi: erc20Abi, // this type is imported from viem
+ functionName: "approve",
+ args: [contractAddresses.Erc20Portal as Hex, parseEther(amount)],
+ });
+ console.log("ERC20 Approval successful");
+ } catch (error) {
+ console.error("Error in approving ERC20:", error);
+ throw error;
+ }
+ };
+
+ async function submit(event: React.FormEvent) {
+ event.preventDefault();
+ const data = stringToHex(`Deposited (${erc20Value}).`);
+ await approveERC20(tokenAddress as Address, erc20Value);
+ await writeContractAsync({
+ address: contractAddresses.Erc20Portal as Hex,
+ abi: ABIs.ERC20PortalABI,
+ functionName: "depositERC20Tokens",
+ args: [tokenAddress, dAppAddress, parseEther(erc20Value), data],
+ });
+ }
+
+ return (
+
+ Deposit ERC20
+
+
+ {isSuccess && (
+
+ {erc20Value} tokens sent!
+
+ )}
+
+ {error && (
+
+ Error: {(error as BaseError).shortMessage || error.message}
+
+ )}
+
+ );
+};
+
+export default SendERC20;
+
+
+```
+
+
+
+
+```typescript
+import Account from "./components/Account";
+import SimpleInput from "./components/SimpleInput";
+import SendEther from "./components/SendEther";
+import SendERC20 from "./components/SendERC20";
+
+function App() {
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
+
+export default App;
+
+
+```
+
+
+
+
+```typescript
+import React, { useState } from "react";
+import { BaseError, useWriteContract } from "wagmi";
+import { ABIs } from "../utils/abi";
+import { contractAddresses } from "../utils/addresses";
+import { stringToHex, erc721Abi, Address, Hex } from "viem";
+
+const SendERC721 = () => {
+ const dAppAddress = `0xab7528bb862fb57e8a2bcd567a2e929a0be56a5e`;
+ const [tokenId, setTokenId] = useState("");
+ const [tokenAddress, setTokenAddress] = useState("");
+
+ const { isPending, isSuccess, error, writeContractAsync } = useWriteContract();
+
+ const approveERC721 = async (tokenAddress: Address, tokenId: bigint) => {
+ try {
+ await writeContractAsync({
+ address: tokenAddress,
+ abi: erc721Abi,
+ functionName: "approve",
+ args: [contractAddresses.Erc721Portal as Hex, tokenId],
+ });
+
+ console.log("Approval successful");
+ } catch (error) {
+ console.error("Error in approving ERC721:", error);
+ throw error; // Re-throw the error to be handled by the caller
+ }
+ };
+
+ async function submit(event: React.FormEvent) {
+ event.preventDefault();
+
+ const bigIntTokenId = BigInt(tokenId);
+ const data = stringToHex(`Deposited NFT of token id:(${bigIntTokenId}).`);
+
+ await approveERC721(tokenAddress as Address, bigIntTokenId);
+
+ writeContractAsync({
+ address: contractAddresses.Erc721Portal as Hex,
+ abi: ABIs.ERC721PortalABI,
+ functionName: "depositERC721Token",
+ args: [tokenAddress, dAppAddress, bigIntTokenId, "0x", data],
+ });
+ }
+
+ return (
+
+ Deposit ERC721 Token
+
+
+ {isSuccess && (
+ NFT of Token number: {tokenId} sent!
+ )}
+
+ {error && (
+
+ Error: {(error as BaseError).shortMessage || error.message}
+
+ )}
+
+ );
+};
+
+export default SendERC721;
+
+```
+
+
+
+
+```typescript
+import Account from "./components/Account";
+import SendERC20 from "./components/SendERC20";
+import SendERC721 from "./components/SendERC721";
+import SendEther from "./components/SendEther";
+import SimpleInput from "./components/SimpleInput";
+
+function App() {
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+}
+
+export default App;
+
+
+
+```
+
+
+
+
+```typescript
+// queries.ts
+
+export const NOTICES_QUERY = `
+ query notices {
+ notices {
+ edges {
+ node {
+ index
+ input {
+ index
+ }
+ payload
+ }
+ }
+ }
+ }
+`;
+
+export const REPORTS_QUERY = `
+ query reports {
+ reports {
+ edges {
+ node {
+ index
+ input {
+ index
+ }
+ payload
+ }
+ }
+ }
+ }
+`;
+
+export const VOUCHERS_QUERY = `
+ query vouchers {
+ vouchers {
+ edges {
+ node {
+ index
+ input {
+ index
+ }
+ destination
+ payload
+ }
+ }
+ }
+ }
+`;
+```
+
+
+
+
+```typescript
+// types.ts
+
+export type Notice = {
+ index: number;
+ input: {
+ index: number;
+ };
+ payload: string;
+};
+
+export type Report = {
+ index: number;
+ input: {
+ index: number;
+ };
+ payload: string;
+};
+
+export type Voucher = {
+ index: number;
+ input: {
+ index: number;
+ };
+ destination: string;
+ payload: string;
+};
+
+export type GraphQLResponse = {
+ data: T;
+};
+```
+
+
+
+
+```typescript
+// api.ts
+
+import axios from 'axios'; // install axios by running `npm i axios`
+import { GraphQLResponse } from './types';
+
+export const fetchGraphQLData = async (query: string) => {
+ const response = await axios.post>('http://localhost:8080/graphql', {
+ query,
+ });
+ return response.data.data;
+};
+```
+
+
+
+
+```typescript
+
+import { useEffect, useState } from 'react';
+import { fetchGraphQLData } from '../utils/api';
+import { Notice } from '../utils/types';
+import { NOTICES_QUERY } from '../utils/queries';
+
+const Notices = () => {
+ const [notices, setNotices] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchNotices = async () => {
+ try {
+ const data = await fetchGraphQLData<{ notices: { edges: { node: Notice }[] } }>(NOTICES_QUERY);
+ setNotices(data.notices.edges.map(edge => edge.node));
+ } catch (err) {
+ setError('Error fetching notices.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchNotices();
+ }, []);
+
+ if (loading) return Loading...;
+ if (error) return {error};
+
+ return (
+
+ Notices
+
+
+
+ Index
+ Input Index
+ Payload
+
+
+
+ {notices.map((notice, idx) => (
+
+ {notice.index}
+ {notice.input.index}
+ {notice.payload}
+
+ ))}
+
+
+
+ );
+};
+
+export default Notices;
+```
+
+
+
+
+```typescript
+
+
+import { useEffect, useState } from 'react';
+import { fetchGraphQLData } from '../utils/api';
+import { Report } from '../utils/types';
+import { REPORTS_QUERY } from '../utils/queries';
+
+
+const Reports = () => {
+ const [reports, setReports] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchReports = async () => {
+ try {
+ const data = await fetchGraphQLData<{ reports: { edges: { node: Report }[] } }>(REPORTS_QUERY);
+ setReports(data.reports.edges.map(edge => edge.node));
+ } catch (err) {
+ setError('Error fetching reports.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchReports();
+ }, []);
+
+ if (loading) return Loading...;
+ if (error) return {error};
+
+ return (
+
+ Reports
+
+
+
+ Index
+ Input Index
+ Payload
+
+
+
+ {reports.map((report, idx) => (
+
+ {report.index}
+ {report.input.index}
+ {report.payload}
+
+ ))}
+
+
+
+ );
+};
+
+export default Reports;
+```
+
+
+
+
+```typescript
+
+
+import { useEffect, useState } from 'react';
+import { fetchGraphQLData } from '../utils/api';
+import { Voucher } from '../utils/types';
+import { VOUCHERS_QUERY } from '../utils/queries';
+
+const Vouchers = () => {
+ const [vouchers, setVouchers] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchVouchers = async () => {
+ try {
+ const data = await fetchGraphQLData<{ vouchers: { edges: { node: Voucher }[] } }>(VOUCHERS_QUERY);
+ setVouchers(data.vouchers.edges.map(edge => edge.node));
+ } catch (err) {
+ setError('Error fetching vouchers.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchVouchers();
+ }, []);
+
+ if (loading) return Loading...;
+ if (error) return {error};
+
+ return (
+
+ Vouchers
+
+
+
+ Index
+ Input Index
+ Destination
+ Payload
+
+
+
+ {vouchers.map((voucher, idx) => (
+
+ {voucher.index}
+ {voucher.input.index}
+ {voucher.destination}
+ {voucher.payload}
+
+ ))}
+
+
+
+ );
+};
+
+export default Vouchers;
+```
+
+
+