Layer LogoLayer AVS Docs
GuidesFrontend example guide

Add More AVS Types

Adding New AVS Service Types to the App

This guide explains how to add new AVS (Actively Validated Service) service types to the application, based on the existing Squaring Service example. Follow these steps to integrate additional services that interact with the task queue system.

Step 1: Create a New Service Component

Start by creating a new service component similar to the existing Service component for the Squaring Service example. The new component will be responsible for fetching tasks from the task queue and submitting new tasks. Here's a general structure for a new service:

  1. Create a new file in the components directory:

    src/components/NewService.tsx
  2. Set up the component similar to the Square AVS:

    "use client";
    import TaskQueue from "@/components/TaskQueue/TaskQueue";
    import { useEffect, useState } from "react";
    import { TaskQueueEntryProps } from "@/types";
    import { fetchTasks } from "@/utils/tasks";
    import SubmitTask from "@/components/AddTask/AddTask";
    export default function NewService({ address }: { address: string }) {
    const [taskQueue, setTaskQueue] = useState<TaskQueueEntryProps[]>([]);
    const getTasks = async () => {
    const allTasks = await fetchTasks(address);
    setTaskQueue(allTasks);
    };
    useEffect(() => {
    getTasks();
    const intervalId = setInterval(() => {
    getTasks();
    }, 3000);
    return () => clearInterval(intervalId);
    }, []);
    return (
    <div>
    <section>
    <h1 className="font-bold text-text-primary text-[26px] mb-4">New Service</h1>
    <div className="grid grid-cols-4 gap-4 pb-[40px] mb-[40px] border-b border-border-primary">
    <SubmitTask taskQueueAddressCustom={address} />
    </div>
    </section>
    <section>
    <h1 className="font-bold text-text-primary text-[26px] mb-4">Task Queue</h1>
    <TaskQueue entries={taskQueue} />
    </section>
    </div>
    );
    }

This component should:

  • Fetch tasks from the task queue based on the address prop.
  • Display the tasks using the TaskQueue component.
  • Allow new task submissions through the SubmitTask component.

Step 2: Implement Task Submission Logic

You need to implement the logic for submitting tasks to the new service. The SubmitTask component will handle task creation, similar to the Square AVS example.

  1. Modify the existing SubmitTask component if necessary, or create a new component that accepts custom task inputs for your new service:
    const SubmitTask = ({ taskQueueAddressCustom }: { taskQueueAddressCustom?: string }) => {
    const [taskInput, setTaskInput] = useState<string>("");
    const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
    const appStore = useAppStore();
    if (!appStore.wallet.address || !appStore.cosmWasmSigningClient) {
    return null;
    }
    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const taskValue = parseInt(taskInput, 10);
    const taskQueueClient = new TaskQueueClient(
    appStore.cosmWasmSigningClient!,
    appStore.wallet.address,
    taskQueueAddressCustom || taskQueueAddress
    );
    try {
    setIsSubmitting(true);
    await taskQueueClient.createTask(
    {
    description: "New Task",
    timeout: undefined,
    payload: { x: taskValue }, // Update payload according to your service needs
    },
    "auto",
    undefined,
    [{ amount: "1000000", denom: "ulayer" }]
    );
    setTaskInput("");
    } catch (error) {
    console.error("Error submitting task:", error);
    } finally {
    setIsSubmitting(false);
    }
    };
    return (
    <form onSubmit={handleSubmit}>
    {/* Form structure for task input */}
    <input
    type="text"
    value={taskInput}
    onChange={(e) => setTaskInput(e.target.value)}
    disabled={isSubmitting}
    />
    <button type="submit" disabled={isSubmitting || taskInput === ""}>
    {isSubmitting ? "Submitting..." : "Submit"}
    </button>
    </form>
    );
    };

Step 3: Update fetchTasks Utility

If your new service handles different kinds of tasks, update the fetchTasks function to correctly handle the data for the new service type. You may need to add custom logic for handling task payloads or results.

  1. Modify the fetchTasks utility:
    export const fetchTasks = async (taskQueueAddressCustom?: string) => {
    const cosmWasmClient = await CosmWasmClient.connect(TestnetConfig.rpc_endpoint);
    const taskQueueQueryClient = new LayerTaskQueue.TaskQueueQueryClient(
    cosmWasmClient,
    taskQueueAddressCustom || taskQueueAddress
    );
    const tasksCompleted = await taskQueueQueryClient.listCompleted({});
    const tasksOpen = await taskQueueQueryClient.listOpen({});
    return [
    ...convertTasksToTaskQueueEntryProps(tasksOpen.tasks),
    ...convertTasksToTaskQueueEntryProps(tasksCompleted.tasks),
    ];
    };

Step 4: Add the New Service to the UI

To make the new service available in the app, you need to render it in the appropriate part of the UI, such as a route or a section of the dashboard.

  1. Add a route for the new service:

    • Create a new page in the app directory for your service:
      // src/app/new-service/page.tsx
      import NewService from "@/components/NewService";
      const NewServicePage = () => (
      <div>
      <NewService address="new-service-address" />
      </div>
      );
      export default NewServicePage;
  2. Update the navigation to include a link to your new service if necessary.

Connect the frontend to your contracts

Follow the frontend connection guide to learn how to connect the frontend to your contract. You'll need to edit the frontend code to add your task queue address.

Conclusion

By following the steps above, you can easily add new AVS service types to the app. This structure ensures that new services can interact with the task queue in a modular way while maintaining consistency with existing components like the Square AVS service. Make sure to customize task submission and handling logic according to the requirements of each new service type.

On this page