Skip to content

Commit 1d5b6ab

Browse files
new api for updating developer fees
1 parent fe8aea2 commit 1d5b6ab

File tree

5 files changed

+106
-64
lines changed

5 files changed

+106
-64
lines changed

apps/dashboard/src/@/api/universal-bridge/webhooks.ts renamed to apps/dashboard/src/@/api/universal-bridge/developer.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,59 @@ export async function deleteWebhook(props: {
9090

9191
return;
9292
}
93+
94+
export type Fee = {
95+
feeRecipient: string;
96+
feeBps: number;
97+
createdAt: string;
98+
updatedAt: string;
99+
};
100+
101+
export async function getFees(props: {
102+
clientId: string;
103+
}) {
104+
const authToken = await getAuthToken();
105+
const res = await fetch(`${UB_BASE_URL}/v1/developer/fees`, {
106+
method: "GET",
107+
headers: {
108+
"Content-Type": "application/json",
109+
"x-client-id-override": props.clientId,
110+
Authorization: `Bearer ${authToken}`,
111+
},
112+
});
113+
114+
if (!res.ok) {
115+
const text = await res.text();
116+
throw new Error(text);
117+
}
118+
119+
const json = await res.json();
120+
return json.data as Fee;
121+
}
122+
123+
export async function updateFee(props: {
124+
clientId: string;
125+
feeRecipient: string;
126+
feeBps: number;
127+
}) {
128+
const authToken = await getAuthToken();
129+
const res = await fetch(`${UB_BASE_URL}/v1/developer/fees`, {
130+
method: "PUT",
131+
headers: {
132+
"Content-Type": "application/json",
133+
"x-client-id-override": props.clientId,
134+
Authorization: `Bearer ${authToken}`,
135+
},
136+
body: JSON.stringify({
137+
feeRecipient: props.feeRecipient,
138+
feeBps: props.feeBps,
139+
}),
140+
});
141+
142+
if (!res.ok) {
143+
const text = await res.text();
144+
throw new Error(text);
145+
}
146+
147+
return;
148+
}

apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/universal-bridge/settings/page.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getProject } from "@/api/projects";
22
import { getTeamBySlug } from "@/api/team";
3+
import { getFees } from "@/api/universal-bridge/developer";
34
import { redirect } from "next/navigation";
45
import { PayConfig } from "../../../../../../../components/pay/PayConfig";
56

@@ -24,5 +25,32 @@ export default async function Page(props: {
2425
redirect(`/team/${team_slug}`);
2526
}
2627

27-
return <PayConfig project={project} teamId={team.id} teamSlug={team_slug} />;
28+
let fees = await getFees({
29+
clientId: project.publishableKey,
30+
}).catch(() => {
31+
return {
32+
feeRecipient: "",
33+
feeBps: 0,
34+
createdAt: "",
35+
updatedAt: "",
36+
};
37+
});
38+
39+
if (!fees) {
40+
fees = {
41+
feeRecipient: "",
42+
feeBps: 0,
43+
createdAt: "",
44+
updatedAt: "",
45+
};
46+
}
47+
48+
return (
49+
<PayConfig
50+
project={project}
51+
teamId={team.id}
52+
teamSlug={team_slug}
53+
fees={fees}
54+
/>
55+
);
2856
}

apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/universal-bridge/webhooks/components/webhooks.client.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
createWebhook,
55
deleteWebhook,
66
getWebhooks,
7-
} from "@/api/universal-bridge/webhooks";
7+
} from "@/api/universal-bridge/developer";
88
import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage";
99
import { CopyTextButton } from "@/components/ui/CopyTextButton";
1010
import { Spinner } from "@/components/ui/Spinner/Spinner";
@@ -109,7 +109,7 @@ export function PayWebhooksPage(props: PayWebhooksPageProps) {
109109
<TableHead>Label</TableHead>
110110
<TableHead>Url</TableHead>
111111
<TableHead>Created</TableHead>
112-
<TableHead>Webhook Version</TableHead>
112+
<TableHead>Version</TableHead>
113113
<TableHead>Delete</TableHead>
114114
</TableRow>
115115
</TableHeader>
@@ -249,7 +249,7 @@ function CreateWebhookButton(props: PropsWithChildren<PayWebhooksPageProps>) {
249249
name="version"
250250
render={({ field }) => (
251251
<FormItem>
252-
<FormLabel>Webhook Version</FormLabel>
252+
<FormLabel>Version</FormLabel>
253253
<Select {...field} onValueChange={field.onChange}>
254254
<SelectTrigger className="w-full">
255255
<SelectValue placeholder="v2" />

apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/universal-bridge/webhooks/page.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,5 @@ export default async function Page(props: {
1515
redirect(`/team/${params.team_slug}`);
1616
}
1717

18-
return (
19-
<PayWebhooksPage
20-
clientId={project.publishableKey}
21-
projectId={project.id}
22-
teamId={project.teamId}
23-
/>
24-
);
18+
return <PayWebhooksPage clientId={project.publishableKey} />;
2519
}

apps/dashboard/src/components/pay/PayConfig.tsx

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"use client";
22

33
import type { Project } from "@/api/projects";
4+
import { type Fee, updateFee } from "@/api/universal-bridge/developer";
45
import { SettingsCard } from "@/components/blocks/SettingsCard";
5-
import { UnderlineLink } from "@/components/ui/UnderlineLink";
6-
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
76
import {
87
Form,
98
FormControl,
@@ -12,15 +11,13 @@ import {
1211
FormLabel,
1312
} from "@/components/ui/form";
1413
import { Input } from "@/components/ui/input";
15-
import { updateProjectClient } from "@3rdweb-sdk/react/hooks/useApi";
1614
import { zodResolver } from "@hookform/resolvers/zod";
1715
import { useMutation } from "@tanstack/react-query";
1816
import {
1917
type ApiKeyPayConfigValidationSchema,
2018
apiKeyPayConfigValidationSchema,
2119
} from "components/settings/ApiKeys/validations";
2220
import { useTrack } from "hooks/analytics/useTrack";
23-
import { CircleAlertIcon } from "lucide-react";
2421
import Link from "next/link";
2522
import { useForm } from "react-hook-form";
2623
import { toast } from "sonner";
@@ -29,56 +26,41 @@ interface PayConfigProps {
2926
project: Project;
3027
teamId: string;
3128
teamSlug: string;
29+
fees: Fee;
3230
}
3331

3432
const TRACKING_CATEGORY = "pay";
3533

3634
export const PayConfig: React.FC<PayConfigProps> = (props) => {
37-
const payService = props.project.services.find(
38-
(service) => service.name === "pay",
39-
);
40-
4135
const form = useForm<ApiKeyPayConfigValidationSchema>({
4236
resolver: zodResolver(apiKeyPayConfigValidationSchema),
4337
values: {
44-
payoutAddress: payService?.payoutAddress ?? "",
45-
developerFeeBPS: payService?.developerFeeBPS ?? 0,
38+
payoutAddress: props.fees.feeRecipient ?? "",
39+
developerFeeBPS: props.fees.feeBps ?? 0,
4640
},
4741
});
4842

4943
const trackEvent = useTrack();
5044

51-
const updateProject = useMutation({
52-
mutationFn: async (projectValues: Partial<Project>) => {
53-
await updateProjectClient(
54-
{
55-
projectId: props.project.id,
56-
teamId: props.teamId,
57-
},
58-
projectValues,
59-
);
45+
const updateFeeMutation = useMutation({
46+
mutationFn: async (values: {
47+
payoutAddress: string;
48+
developerFeeBPS: number;
49+
}) => {
50+
await updateFee({
51+
clientId: props.project.publishableKey,
52+
feeRecipient: values.payoutAddress,
53+
feeBps: values.developerFeeBPS,
54+
});
6055
},
6156
});
6257

6358
const handleSubmit = form.handleSubmit(
6459
({ payoutAddress, developerFeeBPS }) => {
65-
const services = props.project.services;
66-
67-
const newServices = services.map((service) => {
68-
if (service.name !== "pay") {
69-
return service;
70-
}
71-
72-
return {
73-
...service,
60+
updateFeeMutation.mutate(
61+
{
7462
payoutAddress,
7563
developerFeeBPS: developerFeeBPS ? developerFeeBPS * 100 : 0,
76-
};
77-
});
78-
79-
updateProject.mutate(
80-
{
81-
services: newServices,
8264
},
8365
{
8466
onSuccess: () => {
@@ -110,24 +92,6 @@ export const PayConfig: React.FC<PayConfigProps> = (props) => {
11092
},
11193
);
11294

113-
if (!payService) {
114-
return (
115-
<Alert variant="warning">
116-
<CircleAlertIcon className="size-5" />
117-
<AlertTitle>Pay service is disabled</AlertTitle>
118-
<AlertDescription>
119-
Enable Pay service in{" "}
120-
<UnderlineLink
121-
href={`/team/${props.teamSlug}/${props.project.slug}/settings`}
122-
>
123-
project settings
124-
</UnderlineLink>{" "}
125-
to configure settings
126-
</AlertDescription>
127-
</Alert>
128-
);
129-
}
130-
13195
return (
13296
<Form {...form}>
13397
<form onSubmit={handleSubmit} autoComplete="off">
@@ -137,7 +101,7 @@ export const PayConfig: React.FC<PayConfigProps> = (props) => {
137101
saveButton={{
138102
type: "submit",
139103
disabled: !form.formState.isDirty,
140-
isPending: updateProject.isPending,
104+
isPending: updateFeeMutation.isPending,
141105
}}
142106
noPermissionText={undefined}
143107
>

0 commit comments

Comments
 (0)