NFTゲートウェブサイト(NFTの所有に基づいてアクセスを制御するサイト)の作成について
※当記事はこちらの記事の翻訳版です。
このガイドでは、React を使用して、NFT の所有に基づいてコンテンツを制限する Web サイトを作成する方法を説明します。
このガイドでは、会員証としての機能に最適な、一つのアセットから多くのNFTを作成できるEdition Dropを使用します!
サンプルリポジトリの使用
はじめに、CLI を使用してスターターキットをクローンします。
npx thirdweb create --next --js
ThirdwebProvider のセットアップ
pages/_app.js
ページ内で、アプリケーションを ThirdwebProvider
コンポーネントでラップし、React SDK のすべてのフックにアプリケーション内のどこからでもアクセスできるようにします。
このファイルでは、プロジェクトが動作するdesiredChainId(希望するチェーンのId)
を設定する必要があります。
このプロジェクトでは、Edition DropのコントラクトがMumbai testnet上にあるため、Mumbai
を使用します。
import { ChainId, ThirdwebProvider } from "@thirdweb-dev/react";
// This is the chainId your dApp will work on.
const activeChainId = ChainId.Mumbai;
function MyApp({ Component, pageProps }) {
return (
<ThirdwebProvider
desiredChainId={activeChainId}
authConfig={{
domain: "example.org",
authUrl: "/api/auth",
loginRedirect: "/",
}}
>
<Component {...pageProps} />
</ThirdwebProvider>
);
}
export default MyApp;
Auth(認証)設定ファイルの作成
プロジェクトのルートに auth.config.js
というファイルを新規に作成します。
ここで、認証エンドポイントで使用する ThirdwebAuth
オブジェクトを設定します。
ThirdwebAuthオブジェクト
には、2つの設定オプションを渡す必要があります。
- ウォレットの
privateKey(秘密鍵)
:これはサーバ側で、ユーザがアプリケーションにサインインするための署名を生成するために使用されます。 -
domain(ドメイン名)
:これは任意の値を指定できますが、通常は thirdweb.com のようなウェブサイトの名前になります。
import { ThirdwebAuth } from "@thirdweb-dev/auth/next";
export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
privateKey: "<your-private-key-here>",
domain: "your-domain-name-here",
});
ウォレットから秘密鍵をエクスポートする方法はこのリンクを参考にしてください。
(日本語訳はまだ行っておりません。)
秘密鍵は安全に保管し、アクセスできるようにしてください。
秘密鍵に安全にアクセスする方法についてはこちらをご覧ください。
(日本語訳はまだ行っておりません。)
Auth(認証) APIエンドポイント
最後に、catch-all APIルートを用意します。
pages/api/auth/[...thirdweb].js
が呼ばれ、ThirdwebAuthHandler
をエクスポートして、ログインやログアウトなどの必要な認証エンドポイントすべてを管理します。
pages/api/auth
フォルダ(作成する必要があります)内に[...thirdweb].jsページを作成します。
このファイルから auth.config.js
ファイルで設定した ThirdwebAuthHandler
をエクスポートします。
import { ThirdwebAuthHandler } from "../../../auth.config";
export default ThirdwebAuthHandler();
ホームページのアクセス制限
ホームページでは、getServersideProps
内でサーバーサイドのコードを実行し、チェックしています。
- ユーザーが認証されていること
- ユーザーがthirdwebのコレクションから NFT を取得していること
ユーザーが認証されていない場合、またはNFTを持っていない場合、ホームページのコンテンツにアクセスする前に、/login
ページにリダイレクトされます。
それでは、このホームページのロジックを設定しましょう。
まず、これから使用する機能をインポートする必要があります。
import React from "react";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { useLogout } from "@thirdweb-dev/react";
import { getUser } from "../auth.config";
import checkBalance from "../util/checkBalance";
ホームページは認証されたNFT所有者しかアクセスできないので、ここにお礼のメッセージなど、任意のデータを表示することができます。
export default function Home() {
const logout = useLogout();
return (
<div>
<h1>Restricted Access Page</h1>
<p>Thanks for being a member of our NFT community!</p>
<button onClick={logout}>Logout</button>
</div>
);
}
上では、シンプルなお礼のメッセージとlogout
のボタンを表示し、ユーザーをログアウトさせて /login
ページにリダイレクトしています。
ここに到達する前に、getServersideProps関数の内部でロジックを実行します。
この関数では、ユーザーの認証状態とNFTの残高をチェックします。
ユーザーが認証されていない場合、または NFT を所有していない場合は、/login
ページにリダイレクトされます。
// This gets called on every request
export async function getServerSideProps(context) {
const user = await getUser(context.req);
if (!user) {
return {
redirect: {
destination: "/login",
permanent: false,
},
};
}
// Instantiate our SDK
const sdk = ThirdwebSDK.fromPrivateKey(
// Learn more about securely storing your private key: https://portal.thirdweb.com/web3-sdk/set-up-the-sdk/securing-your-private-key
"your-admin-private-key-here"
"mumbai",
);
// Check to see if the user has an NFT
const hasNft = await checkBalance(sdk, user.address);
// If they don't have an NFT, redirect them to the login page
console.log("User", user.address, "doesn't have an NFT! Redirecting...");
if (!hasNft) {
return {
redirect: {
destination: "/login",
permanent: false,
},
};
}
// Finally, return the props
return {
props: {},
};
}
NFTの残高を確認する
上記のスニペット(再利用可能なコードの断片)では、checkBalance
というユーティリティ関数(汎用的な処理を行う関数)を呼び出して、ユーザーがコレクションのNFTを持っているかどうかをチェックしています。
import { contractAddress } from "../const/yourDetails";
export default async function checkBalance(sdk, address) {
const editionDrop = sdk.getEditionDrop(
contractAddress, // replace this with your contract address
);
const balance = await editionDrop.balanceOf(address, 0);
// gt = greater than
return balance.gt(0);
}
素晴らしい これで、ユーザーが /
ページにアクセスしようとするたびに、アクセスを許可する前に NFT を持っているかどうかを確認することができます。
では、ユーザーがウォレットを使ってアプリケーションにサインインするための /login
ページを作成しましょう。
ログインページ
pages
フォルダに login.jsx
という名前の新しいページを作成します。
このページには、login
関数を呼び出すボタンが必要です。
まず、このファイルに必要なロジックをインポートしましょう。
import {
useAddress,
useMetamask,
useEditionDrop,
useClaimNFT,
useNetwork,
useNetworkMismatch,
useUser,
useLogin,
} from "@thirdweb-dev/react";
import { ChainId } from "@thirdweb-dev/sdk";
import { contractAddress } from "../const/yourDetails";
インポートの下に、address
変数(当サイトに接続されているウォレットのアドレスを検出)に基づくいくつかの条件付きロジックをレンダリングしています。
接続されたウォレットがある場合、Sign Inを表示し、useLogin
フックからインポートしたlogin
関数を呼び出します。
これはユーザーに、身元を証明するために自分のウォレットでメッセージに署名するよう求めます。
そして、ThirdwebProvider
のloginRedirect
フィールドに設定したURLにリダイレクトさせます。(ここでは/
を設定)
これは、ユーザーがメッセージを承認した後、/
ページにリダイレクトされ、そこで再びNFTを持っているかどうかがチェックされることを意味します。
export default function Login() {
// Wallet & Network Information
const address = useAddress();
const connectWithMetamask = useMetamask();
// Hooks to sign in with ethereum (auth SDK)
const login = useLogin(); // Sign in
return (
<div>
{address ? (
<>
<p>Welcome, {address.slice(0, 6)}...</p>
<button onClick={login}>Sign In</button>
</>
) : (
<>
<button onClick={() => connectWithMetamask()}>Connect Wallet</button>
</>
)}
</div>
);
}
このプロジェクトについて
このプロジェクトのコピーは、私たちのサンプルリポジトリから作成することができます。
このガイドにあるすべてのコードを含むプロジェクトを作成するには、以下を実行します。
npx thirdweb create --template nft-gated-website
Discordに参加して、チームからの最新情報を入手しましょう!
Discussion