Privy와 Pimlico를 사용해 이메일 로그인과 트랜잭션 스폰서십을 구현하는 방법을 알아봅니다.
완성된 코드
이 튜토리얼의 완성된 코드를 확인하세요.
이 튜토리얼을 읽고 있다면 다음 중 하나 또는 둘 다를 하고 싶을 가능성이 큽니다:
지갑이 없는 사용자가 이메일로 로그인할 수 있게 하기(“Embedded Wallets”)
사용자의 트랜잭션을 스폰서하여 가스비를 지불하지 않게 하기(“Smart Wallets”)
Privy는 이 둘을 다음과 같이 설명합니다:
Embedded wallets는 Privy 자체가 프로비저닝한 자체 수탁(self-custodial) 지갑으로, 애플리케이션에 직접 내장된 지갑 경험을 제공합니다. Embedded wallets는 브라우저 확장 프로그램이나 모바일 앱과 같은 별도의 지갑 클라이언트가 필요 없으며, 제품에서 직접 접근할 수 있습니다. 이는 외부 지갑을 아직 가지고 있지 않거나 외부 지갑을 연결하고 싶지 않은 앱 사용자를 위해 주로 설계되었습니다.Smart wallets는 account abstraction의 기능을 포함하는, 프로그래밍 가능한 온체인 계정입니다. 몇 줄의 코드만으로 사용자를 위한 smart wallet을 만들어 가스비를 스폰서하고, 배치 트랜잭션을 전송하는 등 다양한 기능을 사용할 수 있습니다.
Privy 문서의 이 부분
여기는
Embedded Wallets를 자동으로 설정하는 방법을 설명합니다. 이는 이메일 로그인을
지원하여 사용자가 이메일로 로그인할 때 자동으로 지갑을 생성한다는 의미입니다.
아래 예제에서는 단순히 모든 사용자에 대해 embedded wallet을 만들지만, 더 많은
커스터마이징을 원한다면 해당 튜토리얼을 참고하세요.
embedded/smart wallets를 사용하는 모든 컴포넌트를 PrivyProvider와 SmartWalletsProvider로 감싸야 합니다. providers.tsx(원하는 이름으로) 파일에 다음 코드를 추가합니다:
providers.tsx
"use client";import { PrivyProvider } from "@privy-io/react-auth";import { SmartWalletsProvider } from "@privy-io/react-auth/smart-wallets";import { aeneid } from "@story-protocol/core-sdk";export default function Providers({ children }: { children: React.ReactNode }) { return ( <PrivyProvider appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID as string} config={{ // Customize Privy's appearance in your app appearance: { theme: "light", accentColor: "#676FFF", logo: "/story-logo.jpg", }, // Create embedded wallets for users who don't have a wallet // when they sign in with email embeddedWallets: { createOnLogin: "all-users", }, defaultChain: aeneid, supportedChains: [aeneid], }} > <SmartWalletsProvider>{children}</SmartWalletsProvider> </PrivyProvider> );}
그런 다음 다음과 같이 layout.tsx에 추가할 수 있습니다:
layout.tsx
import Providers from "@/providers/providers";/* other code here... */export default function RootLayout({ children,}: Readonly<{ children: React.ReactNode,}>) { return ( <html lang="en"> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} > <Providers>{children}</Providers> </body> </html> );}
생성된 smart wallet을 사용해 🛠️ TypeScript SDK에서 트랜잭션을 전송할 수도 있습니다. 일부 함수는 encodedTxData를 반환하는 옵션이 있어서, 이를 Privy의 smart wallet에 전달할 수 있습니다. 어떤 함수가 이를 지원하는지는 SDK Reference에서 확인할 수 있습니다.
page.tsx
import { useSmartWallets } from "@privy-io/react-auth/smart-wallets";import { EncodedTxData, StoryClient, StoryConfig,} from "@story-protocol/core-sdk";import { http } from "viem";export default function Home() { const { client: smartWalletClient } = useSmartWallets(); /* previous code here */ async function setupStoryClient() { const config: StoryConfig = { account: smartWalletClient!.account, transport: http("https://aeneid.datarpc.io"), chainId: "aeneid", }; const client = StoryClient.newClient(config); return client; } async function registerIp() { const storyClient = await setupStoryClient(); const response = await storyClient.ipAsset.registerIpAsset({ nft: { type: "mint", spgNftContract: "0xc32A8a0FF3beDDDa58393d022aF433e78739FAbc", }, }); const uiOptions = { title: "Register IP", description: "This is an example transaction that registers an IP.", buttonText: "Register", }; const txHash = await smartWalletClient?.sendTransaction( response.encodedTxData as EncodedTxData, { uiOptions } ); console.log(`View Tx: https://aeneid.datanetscan.io/tx/${txHash}`); } return ( <div> {/* previous code here */} <button onClick={registerIp}>Register IP</button> </div> );}