Skip to content

Commit 9611a17

Browse files
committed
Add support for chain filtering in webhook creation (#7209)
## [Dashboard] Feature: Add Chain Filtering for Webhooks ## Notes for the reviewer This PR adds support for filtering available chains in the webhook creation flow. It fetches supported chains from the Insight API and restricts the chain selection in the UI to only those chains that are supported for webhooks. ## How to test 1. Navigate to the webhooks page for a project 2. Verify that the chain selector in the webhook creation modal only shows supported chains 3. Confirm that the API call to fetch supported chains works correctly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added support for dynamically fetching and displaying supported blockchain networks when creating or managing webhooks. - The network selector now only shows networks that are currently supported for webhooks. - Users are notified if no supported blockchain networks are available for webhooks. - **Bug Fixes** - Improved error handling and messaging when no supported blockchain networks are available. <!-- end of auto-generated comment: release notes by coderabbit.ai --> <!-- start pr-codex --> --- ## PR-Codex overview This PR primarily focuses on enhancing the `NetworkSelectors` and webhook components by introducing support for `chainIds`. It adds functionality to filter chains based on the provided IDs and ensures that the `CreateWebhookModal` and `WebhooksTable` components utilize these IDs. ### Detailed summary - Added `chainIds` prop to `NetworkSelectors`. - Modified `useAllChainsData` to filter `allChains` based on `chainIds`. - Updated `CreateWebhookModal` to accept `supportedChainIds`. - Updated `WebhooksTable` to accept `supportedChainIds`. - Introduced `getSupportedWebhookChains` API function to fetch supported chains. - Updated `FilterDetailsStep` to use `supportedChainIds`. - Modified `WebhooksPage` to fetch and handle `supportedChainIds` from the API. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 3b1e16c commit 9611a17

File tree

6 files changed

+82
-8
lines changed

6 files changed

+82
-8
lines changed

apps/dashboard/src/@/api/insight/webhooks.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ interface TestWebhookResponse {
6767
error?: string;
6868
}
6969

70+
type SupportedWebhookChainsResponse =
71+
| { chains: Array<number> }
72+
| { error: string };
73+
7074
export async function createWebhook(
7175
payload: CreateWebhookPayload,
7276
clientId: string,
@@ -205,3 +209,31 @@ export async function testWebhook(
205209
};
206210
}
207211
}
212+
213+
export async function getSupportedWebhookChains(): Promise<SupportedWebhookChainsResponse> {
214+
try {
215+
const response = await fetch(
216+
`https://${THIRDWEB_INSIGHT_API_DOMAIN}/service/chains`,
217+
{
218+
method: "GET",
219+
headers: {
220+
"x-service-api-key": process.env.INSIGHT_SERVICE_API_KEY || "",
221+
},
222+
},
223+
);
224+
225+
if (!response.ok) {
226+
const errorText = await response.json();
227+
return { error: `Failed to fetch supported chains: ${errorText.error}` };
228+
}
229+
230+
const data = await response.json();
231+
if (Array.isArray(data.data)) {
232+
return { chains: data.data };
233+
}
234+
return { error: "Unexpected response format" };
235+
} catch (error) {
236+
console.error("Error fetching supported chains:", error);
237+
return { error: `Failed to fetch supported chains: ${error}` };
238+
}
239+
}

apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,15 @@ export function MultiNetworkSelector(props: {
2727
side?: "left" | "right" | "top" | "bottom";
2828
showSelectedValuesInModal?: boolean;
2929
client: ThirdwebClient;
30+
chainIds?: number[];
3031
}) {
31-
const { allChains, idToChain } = useAllChainsData();
32+
let { allChains, idToChain } = useAllChainsData();
33+
34+
if (props.chainIds && props.chainIds.length > 0) {
35+
allChains = allChains.filter((chain) =>
36+
props.chainIds?.includes(chain.chainId),
37+
);
38+
}
3239

3340
const options = useMemo(() => {
3441
let sortedChains = allChains;

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/CreateWebhookModal.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ import {
4141

4242
interface CreateWebhookModalProps {
4343
clientId: string;
44+
supportedChainIds: Array<number>;
4445
}
4546

46-
export function CreateWebhookModal({ clientId }: CreateWebhookModalProps) {
47+
export function CreateWebhookModal({
48+
clientId,
49+
supportedChainIds,
50+
}: CreateWebhookModalProps) {
4751
const router = useDashboardRouter();
4852
const thirdwebClient = useThirdwebClient();
4953
const [isOpen, setIsOpen] = useState(false);
@@ -270,6 +274,7 @@ export function CreateWebhookModal({ clientId }: CreateWebhookModalProps) {
270274
goToNextStep={goToNextStep}
271275
goToPreviousStep={goToPreviousStep}
272276
isLoading={isLoading}
277+
supportedChainIds={supportedChainIds}
273278
/>
274279
)}
275280

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/FilterDetailsStep.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
22

3-
import { MultiNetworkSelector } from "@/components/blocks/NetworkSelectors";
43
import { Spinner } from "@/components/ui/Spinner/Spinner";
54
import { Badge } from "@/components/ui/badge";
65
import { Button } from "@/components/ui/button";
@@ -24,6 +23,7 @@ import { useThirdwebClient } from "@/constants/thirdweb.client";
2423
import { useQueryClient } from "@tanstack/react-query";
2524
import type { UseFormReturn } from "react-hook-form";
2625

26+
import { MultiNetworkSelector } from "@/components/blocks/NetworkSelectors";
2727
import { truncateMiddle } from "../utils/abiUtils";
2828
import type {
2929
AbiData,
@@ -45,6 +45,7 @@ interface FilterDetailsStepProps {
4545
goToNextStep: () => void;
4646
goToPreviousStep: () => void;
4747
isLoading: boolean;
48+
supportedChainIds: Array<number>;
4849
}
4950

5051
export function FilterDetailsStep({
@@ -60,6 +61,7 @@ export function FilterDetailsStep({
6061
goToNextStep,
6162
goToPreviousStep,
6263
isLoading,
64+
supportedChainIds,
6365
}: FilterDetailsStepProps) {
6466
const thirdwebClient = useThirdwebClient();
6567
const queryClient = useQueryClient();
@@ -106,6 +108,7 @@ export function FilterDetailsStep({
106108
}
107109
onChange={(chainIds) => field.onChange(chainIds.map(String))}
108110
client={thirdwebClient}
111+
chainIds={supportedChainIds}
109112
/>
110113
</FormControl>
111114
<FormMessage />

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/components/WebhooksTable.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ function getEventType(filters: WebhookFilters): string {
3232
interface WebhooksTableProps {
3333
webhooks: WebhookResponse[];
3434
clientId: string;
35+
supportedChainIds: number[];
3536
}
3637

37-
export function WebhooksTable({ webhooks, clientId }: WebhooksTableProps) {
38+
export function WebhooksTable({
39+
webhooks,
40+
clientId,
41+
supportedChainIds,
42+
}: WebhooksTableProps) {
3843
const [isDeleting, setIsDeleting] = useState<Record<string, boolean>>({});
3944
const { testWebhookEndpoint, isTestingMap } = useTestWebhook(clientId);
4045
const router = useDashboardRouter();
@@ -210,7 +215,10 @@ export function WebhooksTable({ webhooks, clientId }: WebhooksTableProps) {
210215
return (
211216
<div className="w-full">
212217
<div className="mb-4 flex items-center justify-end">
213-
<CreateWebhookModal clientId={clientId} />
218+
<CreateWebhookModal
219+
clientId={clientId}
220+
supportedChainIds={supportedChainIds}
221+
/>
214222
</div>
215223
<TWTable
216224
data={sortedWebhooks}

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/page.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { type WebhookResponse, getWebhooks } from "@/api/insight/webhooks";
1+
import {
2+
type WebhookResponse,
3+
getSupportedWebhookChains,
4+
getWebhooks,
5+
} from "@/api/insight/webhooks";
26
import { getProject } from "@/api/projects";
37
import { TrackedUnderlineLink } from "@/components/ui/tracked-link";
48
import { notFound } from "next/navigation";
@@ -11,6 +15,7 @@ export default async function WebhooksPage({
1115
let webhooks: WebhookResponse[] = [];
1216
let clientId = "";
1317
let errorMessage = "";
18+
let supportedChainIds: number[] = [];
1419

1520
try {
1621
// Await params before accessing properties
@@ -32,6 +37,13 @@ export default async function WebhooksPage({
3237
} else if (webhooksRes.data) {
3338
webhooks = webhooksRes.data;
3439
}
40+
41+
const supportedChainsRes = await getSupportedWebhookChains();
42+
if ("chains" in supportedChainsRes) {
43+
supportedChainIds = supportedChainsRes.chains;
44+
} else {
45+
errorMessage = supportedChainsRes.error;
46+
}
3547
} catch (error) {
3648
errorMessage = "Failed to load webhooks. Please try again later.";
3749
console.error("Error loading project or webhooks", error);
@@ -71,7 +83,11 @@ export default async function WebhooksPage({
7183
</div>
7284
</div>
7385
) : webhooks.length > 0 ? (
74-
<WebhooksTable webhooks={webhooks} clientId={clientId} />
86+
<WebhooksTable
87+
webhooks={webhooks}
88+
clientId={clientId}
89+
supportedChainIds={supportedChainIds}
90+
/>
7591
) : (
7692
<div className="flex flex-col items-center justify-center gap-4 rounded-lg border border-border p-12 text-center">
7793
<div>
@@ -80,7 +96,10 @@ export default async function WebhooksPage({
8096
Create a webhook to get started.
8197
</p>
8298
</div>
83-
<CreateWebhookModal clientId={clientId} />
99+
<CreateWebhookModal
100+
clientId={clientId}
101+
supportedChainIds={supportedChainIds}
102+
/>
84103
</div>
85104
)}
86105
</div>

0 commit comments

Comments
 (0)