Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ export function FaucetButton({

{canClaimFaucetQuery.data.type === "unsupported-chain" &&
"Faucet is empty right now"}

{canClaimFaucetQuery.data.type === "paid-plan-required" &&
"Faucet is only available on Starter, Growth and Pro plans."}
</Button>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ export type CanClaimResponseType =
| {
canClaim: false;
type: "unsupported-chain";
}
| {
canClaim: false;
type: "paid-plan-required";
};
20 changes: 20 additions & 0 deletions apps/dashboard/src/app/api/testnet-faucet/can-claim/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getTeams } from "@/api/team";
import {
DISABLE_FAUCET_CHAIN_IDS,
THIRDWEB_ACCESS_TOKEN,
Expand Down Expand Up @@ -46,6 +47,25 @@ export const GET = async (req: NextRequest) => {
} catch {}
}

// get the teams for the account
const teams = await getTeams();
if (!teams) {
const res: CanClaimResponseType = {
canClaim: false,
type: "paid-plan-required",
};
return NextResponse.json(res);
}

const hasPaidPlan = teams.some((team) => team.billingPlan !== "free");
if (!hasPaidPlan) {
const res: CanClaimResponseType = {
canClaim: false,
type: "paid-plan-required",
};
return NextResponse.json(res);
}

if (
!THIRDWEB_ENGINE_URL ||
!THIRDWEB_ENGINE_FAUCET_WALLET ||
Expand Down
86 changes: 56 additions & 30 deletions apps/dashboard/src/app/api/testnet-faucet/claim/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getTeams } from "@/api/team";
import { COOKIE_ACTIVE_ACCOUNT, COOKIE_PREFIX_TOKEN } from "@/constants/cookie";
import {
API_SERVER_URL,
Expand Down Expand Up @@ -53,36 +54,6 @@ export const POST = async (req: NextRequest) => {
);
}

// Make sure the connected wallet has a thirdweb account
const accountRes = await fetch(`${API_SERVER_URL}/v1/account/me`, {
method: "GET",
headers: {
Authorization: `Bearer ${authCookie.value}`,
},
});

if (accountRes.status !== 200) {
// Account not found on this connected address
return NextResponse.json(
{
error: "thirdweb account not found",
},
{ status: 400 },
);
}

const account: { data: Account } = await accountRes.json();

// Make sure the logged-in account has verified its email
if (!account.data.email) {
return NextResponse.json(
{
error: "Account owner hasn't verified email",
},
{ status: 400 },
);
}

const requestBody = (await req.json()) as RequestTestnetFundsPayload;
const { chainId, toAddress, turnstileToken } = requestBody;
if (Number.isNaN(chainId)) {
Expand Down Expand Up @@ -150,6 +121,61 @@ export const POST = async (req: NextRequest) => {
);
}

// Make sure the connected wallet has a thirdweb account
const accountRes = await fetch(`${API_SERVER_URL}/v1/account/me`, {
method: "GET",
headers: {
Authorization: `Bearer ${authCookie.value}`,
},
});

if (accountRes.status !== 200) {
// Account not found on this connected address
return NextResponse.json(
{
error: "thirdweb account not found",
},
{ status: 400 },
);
}

const account: { data: Account } = await accountRes.json();

// Make sure the logged-in account has verified its email
if (!account.data.email) {
return NextResponse.json(
{
error: "Account owner hasn't verified email",
},
{ status: 400 },
);
}

// get the teams for the account
const teams = await getTeams();
if (!teams) {
return NextResponse.json(
{
error: "No teams found for this account.",
},
{
status: 500,
},
);
}
// check if ANY of the customer's teams has "growth" or "pro" plan
const hasPaidPlan = teams.some((team) => team.billingPlan !== "free");
if (!hasPaidPlan) {
return NextResponse.json(
{
error: "Free plan cannot claim on this chain.",
},
{
status: 402,
},
);
}

const ipCacheKey = `testnet-faucet:${chainId}:${ip}`;
const addressCacheKey = `testnet-faucet:${chainId}:${toAddress}`;
const accountCacheKey = `testnet-faucet:${chainId}:${account.data.id}`;
Expand Down
Loading