Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
kien-ngo committed Oct 17, 2024
1 parent f8f90fd commit f2ba43a
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 18 deletions.
6 changes: 5 additions & 1 deletion apps/dashboard/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,8 @@ UNTHREAD_PRO_TIER_ID=""
NEXT_PUBLIC_DEMO_ENGINE_URL=""

# API server secret (required for thirdweb.com SIWE login). Copy from Vercel.
API_SERVER_SECRET=""
API_SERVER_SECRET=""

# Used for the Faucet page (/<chain_id>)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
TURNSTILE_SECRET_KEY=""
1 change: 1 addition & 0 deletions apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@hookform/resolvers": "^3.9.0",
"@marsidev/react-turnstile": "^1.0.2",
"@n8tb1t/use-scroll-position": "^2.0.3",
"@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-avatar": "^1.1.1",
Expand Down
3 changes: 3 additions & 0 deletions apps/dashboard/src/@/constants/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ export const DASHBOARD_STORAGE_URL =

export const API_SERVER_URL =
process.env.NEXT_PUBLIC_THIRDWEB_API_HOST || "https://api.thirdweb.com";

export const TURNSTILE_SITE_KEY =
process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || "";
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
import { THIRDWEB_ENGINE_FAUCET_WALLET } from "@/constants/env";
import {
THIRDWEB_ENGINE_FAUCET_WALLET,
TURNSTILE_SITE_KEY,
} from "@/constants/env";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet";
import { Turnstile } from "@marsidev/react-turnstile";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { CanClaimResponseType } from "app/api/testnet-faucet/can-claim/CanClaimResponseType";
import { mapV4ChainToV5Chain } from "contexts/map-chains";
import { useTrack } from "hooks/analytics/useTrack";
import { useState } from "react";
import { toast } from "sonner";
import { toUnits } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
Expand Down Expand Up @@ -67,6 +72,7 @@ export function FaucetButton({
body: JSON.stringify({
chainId: chainId,
toAddress: address,
turnstileToken,
}),
});

Expand Down Expand Up @@ -117,6 +123,8 @@ export function FaucetButton({
faucetWalletBalanceQuery.data !== undefined &&
faucetWalletBalanceQuery.data.value < toUnits("1", 17);

const [turnstileToken, setTurnstileToken] = useState("");

// loading state
if (faucetWalletBalanceQuery.isPending || canClaimFaucetQuery.isPending) {
return (
Expand Down Expand Up @@ -190,6 +198,11 @@ export function FaucetButton({
{faucetWalletBalanceQuery.data.symbol} left in the faucet
</p>
)}

<Turnstile
siteKey={TURNSTILE_SITE_KEY}
onSuccess={(token) => setTurnstileToken(token)}
/>
</div>
);
}
32 changes: 31 additions & 1 deletion apps/dashboard/src/app/api/testnet-faucet/claim/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ const THIRDWEB_ACCESS_TOKEN = process.env.THIRDWEB_ACCESS_TOKEN;
interface RequestTestnetFundsPayload {
chainId: number;
toAddress: string;

// Cloudflare Turnstile token received from the client-side
turnstileToken: string;
}

// Note: This handler cannot use "edge" runtime because of Redis usage.
export const POST = async (req: NextRequest) => {
const requestBody = (await req.json()) as RequestTestnetFundsPayload;
const { chainId, toAddress } = requestBody;
const { chainId, toAddress, turnstileToken } = requestBody;
if (Number.isNaN(chainId)) {
throw new Error("Invalid chain ID.");
}
Expand Down Expand Up @@ -46,6 +49,33 @@ export const POST = async (req: NextRequest) => {
);
}

// https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
// Validate the token by calling the "/siteverify" API endpoint.
const result = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
body: JSON.stringify({
secret: process.env.TURNSTILE_SECRET_KEY,
response: turnstileToken,
remoteip: ipAddress,
}),
method: "POST",
headers: {
"Content-Type": "application/json",
},
},
);

const outcome = await result.json();
if (!outcome.success) {
return NextResponse.json(
{
error: "Could not validate captcha.",
},
{ status: 400 },
);
}

const ipCacheKey = `testnet-faucet:${chainId}:${ipAddress}`;
const addressCacheKey = `testnet-faucet:${chainId}:${toAddress}`;

Expand Down
34 changes: 19 additions & 15 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f2ba43a

Please sign in to comment.