diff --git a/.env.example b/.env.example index 67732b6..2256f21 100644 --- a/.env.example +++ b/.env.example @@ -44,12 +44,6 @@ INK_APP_SUBMISSION_TARGET_BRANCH= INK_APP_SUBMISSION_SLACK_NOTIFICATION_CHANNEL= INK_APP_SUBMISSION_SLACK_BOT_TOKEN= -# Smart Account Experiment -NEXT_PUBLIC_BUNDLER_URL= -NEXT_PUBLIC_PASSKEY_SERVER_URL= -NEXT_PUBLIC_PAYMASTER_URL= -NEXT_PUBLIC_GELATO_BRIDGE_URL= -NEXT_PUBLIC_FAUCET_API_URL= - # Testnet Faucet Experiment +NEXT_PUBLIC_FAUCET_API_URL= MULTIPLIER_JWT_SECRET= diff --git a/.github/workflows/ship.yml b/.github/workflows/ship.yml index ebe9e80..930f7f9 100644 --- a/.github/workflows/ship.yml +++ b/.github/workflows/ship.yml @@ -66,14 +66,8 @@ jobs: INK_APP_SUBMISSION_SLACK_NOTIFICATION_CHANNEL=${{ secrets.INK_APP_SUBMISSION_SLACK_NOTIFICATION_CHANNEL }} INK_APP_SUBMISSION_SLACK_BOT_TOKEN=${{ secrets.INK_APP_SUBMISSION_SLACK_BOT_TOKEN }} - # Smart Account Experiment - NEXT_PUBLIC_BUNDLER_URL=${{ secrets.NEXT_PUBLIC_BUNDLER_URL }} - NEXT_PUBLIC_PASSKEY_SERVER_URL=${{ secrets.NEXT_PUBLIC_PASSKEY_SERVER_URL }} - NEXT_PUBLIC_PAYMASTER_URL=${{ secrets.NEXT_PUBLIC_PAYMASTER_URL }} - NEXT_PUBLIC_GELATO_BRIDGE_URL=${{ secrets.NEXT_PUBLIC_GELATO_BRIDGE_URL }} - NEXT_PUBLIC_FAUCET_API_URL=${{ secrets.NEXT_PUBLIC_FAUCET_API_URL }} - # Testnet Faucet Experiment + NEXT_PUBLIC_FAUCET_API_URL=${{ secrets.NEXT_PUBLIC_FAUCET_API_URL }} MULTIPLIER_JWT_SECRET=${{ secrets.MULTIPLIER_JWT_SECRET }} EOF diff --git a/package.json b/package.json index 9ed5f4f..ae88983 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,6 @@ "@types/react-dom": "19.0.3", "@types/three": "0.170.0", "@walletconnect/ethereum-provider": "2.13.3", - "@zerodev/passkey-validator": "5.5.0-beta.0", - "@zerodev/sdk": "5.4.0-beta.0", "class-variance-authority": "0.7.1", "cookies-next": "4.2.1", "ethers": "6.13.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a57fe6c..3b2b381 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,12 +80,6 @@ importers: '@walletconnect/ethereum-provider': specifier: 2.13.3 version: 2.13.3(@types/react@19.0.7)(bufferutil@4.0.9)(react@19.0.0)(utf-8-validate@5.0.10) - '@zerodev/passkey-validator': - specifier: 5.5.0-beta.0 - version: 5.5.0-beta.0(@zerodev/sdk@5.4.0-beta.0(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)))(@zerodev/webauthn-key@5.4.2(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)))(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)) - '@zerodev/sdk': - specifier: 5.4.0-beta.0 - version: 5.4.0-beta.0(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)) class-variance-authority: specifier: 0.7.1 version: 0.7.1 @@ -194,7 +188,7 @@ importers: version: 9.1.0(eslint@9.14.0(jiti@2.4.2)) eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)) + version: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) eslint-plugin-simple-import-sort: specifier: 12.1.0 version: 12.1.0(eslint@9.14.0(jiti@2.4.2)) @@ -2205,16 +2199,6 @@ packages: peerDependencies: webpack: '>=4.40.0' - '@simplewebauthn/browser@8.3.7': - resolution: {integrity: sha512-ZtRf+pUEgOCvjrYsbMsJfiHOdKcrSZt2zrAnIIpfmA06r0FxBovFYq0rJ171soZbe13KmWzAoLKjSxVW7KxCdQ==} - - '@simplewebauthn/types@12.0.0': - resolution: {integrity: sha512-q6y8MkoV8V8jB4zzp18Uyj2I7oFp2/ONL8c3j8uT06AOWu3cIChc1au71QYHrP2b+xDapkGTiv+9lX7xkTlAsA==} - - '@simplewebauthn/typescript-types@8.3.4': - resolution: {integrity: sha512-38xtca0OqfRVNloKBrFB5LEM6PN5vzFbJG6rAutPVrtGHFYxPdiV3btYWq0eAZAZmP+dqFPYJxJWeJrGfmYHng==} - deprecated: This package has been renamed to @simplewebauthn/types. Please install @simplewebauthn/types instead to ensure you receive future updates. - '@slack/logger@4.0.0': resolution: {integrity: sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==} engines: {node: '>= 18', npm: '>= 8.6.0'} @@ -3216,23 +3200,6 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@zerodev/passkey-validator@5.5.0-beta.0': - resolution: {integrity: sha512-a18QOuQ3I8xE6UxHZ3/6WQfeat4RetroITfBlce61JKnMm1fgSfOg5DIHkxDIB6HI6OpTxmSueIulovEWprU0w==} - peerDependencies: - '@zerodev/sdk': ^5.4.0-beta.0 - '@zerodev/webauthn-key': ^5.4.0-beta.0 - viem: ^2.21.40 - - '@zerodev/sdk@5.4.0-beta.0': - resolution: {integrity: sha512-ei2NnSY1s1HJLvNn4QmdVCnSdyYyOJDb3jAg2ASVcWwIrZ1mJUbLYzSs3QqEqBF+zd50drklNbqmcWOmbMyZKg==} - peerDependencies: - viem: ^2.21.40 - - '@zerodev/webauthn-key@5.4.2': - resolution: {integrity: sha512-e/JKpV8SXmICZM0TVpiC05Q5eRdI9ECmsrRyc8PMO4qvZ7pJBV2dEdZjrFOmMSYLec59GHedsui6dHasqd50eA==} - peerDependencies: - viem: ^2.21.40 - abitype@1.0.7: resolution: {integrity: sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==} peerDependencies: @@ -9148,14 +9115,6 @@ snapshots: - encoding - supports-color - '@simplewebauthn/browser@8.3.7': - dependencies: - '@simplewebauthn/typescript-types': 8.3.4 - - '@simplewebauthn/types@12.0.0': {} - - '@simplewebauthn/typescript-types@8.3.4': {} - '@slack/logger@4.0.0': dependencies: '@types/node': 22.12.0 @@ -10879,26 +10838,6 @@ snapshots: '@xtuc/long@4.2.2': {} - '@zerodev/passkey-validator@5.5.0-beta.0(@zerodev/sdk@5.4.0-beta.0(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)))(@zerodev/webauthn-key@5.4.2(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)))(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1))': - dependencies: - '@noble/curves': 1.8.1 - '@simplewebauthn/browser': 8.3.7 - '@zerodev/sdk': 5.4.0-beta.0(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)) - '@zerodev/webauthn-key': 5.4.2(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1)) - viem: 2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1) - - '@zerodev/sdk@5.4.0-beta.0(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1))': - dependencies: - semver: 7.7.0 - viem: 2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1) - - '@zerodev/webauthn-key@5.4.2(viem@2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1))': - dependencies: - '@noble/curves': 1.8.1 - '@simplewebauthn/browser': 8.3.7 - '@simplewebauthn/types': 12.0.0 - viem: 2.22.11(bufferutil@4.0.9)(typescript@5.7.3)(utf-8-validate@5.0.10)(zod@3.24.1) - abitype@1.0.7(typescript@5.7.3)(zod@3.24.1): optionalDependencies: typescript: 5.7.3 @@ -11659,8 +11598,8 @@ snapshots: '@typescript-eslint/parser': 8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3) eslint: 9.14.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.14.0(jiti@2.4.2)) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.14.0(jiti@2.4.2)) eslint-plugin-react: 7.37.4(eslint@9.14.0(jiti@2.4.2)) eslint-plugin-react-hooks: 5.1.0(eslint@9.14.0(jiti@2.4.2)) @@ -11683,7 +11622,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.14.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -11695,22 +11634,22 @@ snapshots: is-glob: 4.0.3 stable-hash: 0.0.4 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3) eslint: 9.14.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.14.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -11721,7 +11660,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.14.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.14.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.23.0(eslint@9.14.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)))(eslint@9.14.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 diff --git a/src/app/[locale]/smart-wallet/_components/LoginButton.tsx b/src/app/[locale]/smart-wallet/_components/LoginButton.tsx deleted file mode 100644 index c79c20c..0000000 --- a/src/app/[locale]/smart-wallet/_components/LoginButton.tsx +++ /dev/null @@ -1,54 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { WebAuthnMode } from "@zerodev/passkey-validator"; - -import { useUsername } from "../context/UsernameContext"; -import { useZeroDev } from "../context/ZerodevContext"; -import { createAccountAndClient } from "../lib/zerodev"; - -import { Spinner } from "./Spinner"; - -export default function LoginButton() { - const [isLoggingIn, setIsLoggingIn] = useState(false); - const { username } = useUsername(); - const { - setKernelAccount, - setKernelClient, - setAccountAddress, - setIsKernelClientReady, - } = useZeroDev(); - - const handleLogin = async () => { - setIsLoggingIn(true); - - try { - const { kernelAccount, kernelClient } = await createAccountAndClient( - username || "", - WebAuthnMode.Login - ); - - setKernelAccount(kernelAccount); - setKernelClient(kernelClient); - setAccountAddress(kernelAccount.address); - setIsKernelClientReady(true); - - window.alert("Login done. Try sending UserOps."); - } catch (error) { - console.error("Login failed:", error); - window.alert("Login failed. Please try again."); - } finally { - setIsLoggingIn(false); - } - }; - - return ( - - ); -} diff --git a/src/app/[locale]/smart-wallet/_components/RegisterButton.tsx b/src/app/[locale]/smart-wallet/_components/RegisterButton.tsx deleted file mode 100644 index 6512b35..0000000 --- a/src/app/[locale]/smart-wallet/_components/RegisterButton.tsx +++ /dev/null @@ -1,55 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { WebAuthnMode } from "@zerodev/passkey-validator"; - -import { useUsername } from "../context/UsernameContext"; -import { useZeroDev } from "../context/ZerodevContext"; -import { createAccountAndClient } from "../lib/zerodev"; - -import { Spinner } from "./Spinner"; - -export default function RegisterButton() { - const [isRegistering, setIsRegistering] = useState(false); - const { username } = useUsername(); - const { - setKernelAccount, - setKernelClient, - setAccountAddress, - setIsKernelClientReady, - } = useZeroDev(); - - const handleRegister = async () => { - if (!username) return; - setIsRegistering(true); - - try { - const { kernelAccount, kernelClient } = await createAccountAndClient( - username, - WebAuthnMode.Register - ); - - setKernelAccount(kernelAccount); - setKernelClient(kernelClient); - setAccountAddress(kernelAccount.address); - setIsKernelClientReady(true); - - window.alert("Register done. Try sending UserOps."); - } catch (error) { - console.error("Registration failed:", error); - window.alert("Registration failed. Please try again."); - } finally { - setIsRegistering(false); - } - }; - - return ( - - ); -} diff --git a/src/app/[locale]/smart-wallet/_components/SendUserOp.tsx b/src/app/[locale]/smart-wallet/_components/SendUserOp.tsx deleted file mode 100644 index d710542..0000000 --- a/src/app/[locale]/smart-wallet/_components/SendUserOp.tsx +++ /dev/null @@ -1,133 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { encodeFunctionData, parseAbi } from "viem"; - -import { Button } from "@/components/Button/Button"; - -import { useZeroDev } from "../context/ZerodevContext"; -import { contractAddress } from "../utils/constants"; - -import { Spinner } from "./Spinner"; - -// Define the ABI directly in the component to ensure correct typing -const contractABI = parseAbi([ - "function mint(address _to) public", - "function balanceOf(address owner) external view returns (uint256 balance)", -]); - -export default function SendUserOp() { - const [isSendingUserOp, setIsSendingUserOp] = useState(false); - const [userOpStatus, setUserOpStatus] = useState(""); - const [lastMintTime, setLastMintTime] = useState(0); - const { kernelAccount, kernelClient, isKernelClientReady } = useZeroDev(); - - const MINT_COOLDOWN = 30000; // 30 seconds cooldown - - const handleSendUserOp = async () => { - if (!kernelAccount || !kernelClient) { - setUserOpStatus("Please connect your wallet first"); - return; - } - - // Check cooldown - const now = Date.now(); - const timeElapsed = now - lastMintTime; - if (timeElapsed < MINT_COOLDOWN) { - const remainingSeconds = Math.ceil((MINT_COOLDOWN - timeElapsed) / 1000); - setUserOpStatus( - `Please wait ${remainingSeconds} seconds before minting again` - ); - return; - } - - setIsSendingUserOp(true); - setUserOpStatus("Preparing transaction..."); - - try { - setUserOpStatus("Encoding transaction..."); - const callData = await kernelAccount.encodeCalls([ - { - to: contractAddress, - value: BigInt(0), - data: encodeFunctionData({ - abi: contractABI, - functionName: "mint", - args: [kernelAccount.address], - }), - }, - ]); - - setUserOpStatus("Sending transaction..."); - - const _userOpHash = await kernelClient.sendUserOperation({ - callData, - maxFeePerGas: BigInt(0), - maxPriorityFeePerGas: BigInt(0), - }); - - setUserOpStatus("Waiting for confirmation..."); - - await kernelClient.waitForUserOperationReceipt({ - hash: _userOpHash, - }); - - setLastMintTime(Date.now()); - setUserOpStatus( - `NFT Minted Successfully! View transaction` - ); - } catch (error) { - console.error("Detailed UserOp error:", error); - let errorMessage = "UserOp failed. Please try again."; - - if (error instanceof Error) { - if (error.message.includes("429")) { - errorMessage = - "Too many requests. Please wait a moment before trying again."; - } else { - errorMessage = `Error: ${error.message}`; - } - } - - setUserOpStatus(errorMessage); - } finally { - setIsSendingUserOp(false); - } - }; - - return ( -
- - - {/* Always show status messages */} - {userOpStatus && ( -
- )} -
- ); -} diff --git a/src/app/[locale]/smart-wallet/_components/SmartWallet.tsx b/src/app/[locale]/smart-wallet/_components/SmartWallet.tsx deleted file mode 100644 index e553ae4..0000000 --- a/src/app/[locale]/smart-wallet/_components/SmartWallet.tsx +++ /dev/null @@ -1,281 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { WebAuthnMode } from "@zerodev/passkey-validator"; -import Image from "next/image"; -import { useTranslations } from "next-intl"; - -import { Button } from "@/components/Button/Button"; -import { ColoredText } from "@/components/ColoredText"; - -import { useUsername } from "../context/UsernameContext"; -import { useZeroDev } from "../context/ZerodevContext"; -import { createAccountAndClient } from "../lib/zerodev"; - -import LoginButton from "./LoginButton"; -import RegisterButton from "./RegisterButton"; -import SendUserOp from "./SendUserOp"; -import { Spinner } from "./Spinner"; -import UsernameInput from "./UsernameInput"; - -export function SmartWallet() { - const t = useTranslations("SmartWallet"); - - const [mounted, setMounted] = useState(false); - const [isModalOpen, setIsModalOpen] = useState(false); - const [isRegistering, setIsRegistering] = useState(false); - const [isLoggingIn, setIsLoggingIn] = useState(false); - - const { - accountAddress, - setKernelAccount, - setKernelClient, - setAccountAddress, - setIsKernelClientReady, - } = useZeroDev(); - - const { username, setUsername } = useUsername(); - - useEffect(() => { - setMounted(true); - }, []); - - const handleCreateWallet = async () => { - if (!username) return; - setIsRegistering(true); - - try { - const { kernelAccount, kernelClient } = await createAccountAndClient( - username, - WebAuthnMode.Register - ); - - setKernelAccount(kernelAccount); - setKernelClient(kernelClient); - setAccountAddress(kernelAccount.address); - setIsKernelClientReady(true); - setIsModalOpen(false); - - window.alert("Smart wallet created successfully!"); - } catch (error) { - console.error("Registration failed:", error); - window.alert("Failed to create smart wallet. Please try again."); - } finally { - setIsRegistering(false); - } - }; - - const handleLogin = async () => { - setIsLoggingIn(true); - - try { - const { kernelAccount, kernelClient } = await createAccountAndClient( - username || "", - WebAuthnMode.Login - ); - - setKernelAccount(kernelAccount); - setKernelClient(kernelClient); - setAccountAddress(kernelAccount.address); - setIsKernelClientReady(true); - - window.alert("Login successful!"); - } catch (error) { - console.error("Login failed:", error); - window.alert("Login failed. Please try again."); - } finally { - setIsLoggingIn(false); - } - }; - - if (!mounted) return null; - - return ( -
- {/* Header */} - - Ink Labs - - - {/* Subtitle */} - - Give Ink chain a try by minting a mystery NFT into a smart wallet - - - {/* Cards Container */} -
- {/* Create Smart Wallet Card */} -
-
- Smart Wallet -
- - {/* Account Address Display */} - {accountAddress ? ( -
-

- Your Smart Wallet: -

- - {accountAddress} - -
- ) : ( - <> -
- -
- - {/* Login Button - Only shown when not connected */} - - - )} -
- - {/* Mint NFT Card */} -
-
- Mint NFT -
-
- -
-
-
- - {/* Footer Text */} -

- {t("noGas")} -

- -
-
-

- Ink Sepolia -

- -
- {/* Account Address Display */} - {accountAddress && ( -
- Account address:{" "} - - {accountAddress} - -
- )} - - {/* Username Input */} - - - {/* Register and Login Buttons */} -
- -
- -
-
- - {/* Send UserOp Button */} - -
-
-
- - {/* Create Wallet Modal - simplified to only handle creation */} - {isModalOpen && ( -
-
-

Create Smart Wallet

-
-
- - setUsername(e.target.value)} - className="p-2 border border-gray-300 rounded-lg w-full" - /> -
- -
- - -
-
-
-
- )} -
- ); -} diff --git a/src/app/[locale]/smart-wallet/_components/Spinner.tsx b/src/app/[locale]/smart-wallet/_components/Spinner.tsx deleted file mode 100644 index b6454ee..0000000 --- a/src/app/[locale]/smart-wallet/_components/Spinner.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export function Spinner() { - return ( - - - - - ); -} diff --git a/src/app/[locale]/smart-wallet/_components/UsernameInput.tsx b/src/app/[locale]/smart-wallet/_components/UsernameInput.tsx deleted file mode 100644 index 4727f17..0000000 --- a/src/app/[locale]/smart-wallet/_components/UsernameInput.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import { useUsername } from "../context/UsernameContext"; - -export default function UsernameInput() { - const { username, setUsername } = useUsername(); - - return ( - setUsername(e.target.value)} - className="p-2 border border-gray-300 rounded-lg w-full" - /> - ); -} diff --git a/src/app/[locale]/smart-wallet/context/UsernameContext.tsx b/src/app/[locale]/smart-wallet/context/UsernameContext.tsx deleted file mode 100644 index ad33cce..0000000 --- a/src/app/[locale]/smart-wallet/context/UsernameContext.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client"; - -import { createContext, ReactNode, useContext, useState } from "react"; - -interface UsernameContextType { - username: string; - setUsername: (username: string) => void; -} - -const UsernameContext = createContext( - undefined -); - -export function UsernameProvider({ children }: { children: ReactNode }) { - const [username, setUsername] = useState(""); - - return ( - - {children} - - ); -} - -export function useUsername() { - const context = useContext(UsernameContext); - if (context === undefined) { - throw new Error("useUsername must be used within a UsernameProvider"); - } - return context; -} diff --git a/src/app/[locale]/smart-wallet/context/ZerodevContext.tsx b/src/app/[locale]/smart-wallet/context/ZerodevContext.tsx deleted file mode 100644 index b660e1e..0000000 --- a/src/app/[locale]/smart-wallet/context/ZerodevContext.tsx +++ /dev/null @@ -1,53 +0,0 @@ -"use client"; - -import React, { createContext, ReactNode, useContext, useState } from "react"; -import { KernelSmartAccountImplementation } from "@zerodev/sdk"; -import { SmartAccount } from "viem/account-abstraction"; - -interface ZeroDevContextType { - kernelAccount: SmartAccount | null; - setKernelAccount: ( - account: SmartAccount - ) => void; - kernelClient: any; - setKernelClient: (client: any) => void; - accountAddress: string; - setAccountAddress: (address: string) => void; - isKernelClientReady: boolean; - setIsKernelClientReady: (ready: boolean) => void; -} - -const ZeroDevContext = createContext(undefined); - -export function ZeroDevProvider({ children }: { children: ReactNode }) { - const [kernelAccount, setKernelAccount] = - useState | null>(null); - const [kernelClient, setKernelClient] = useState(null); - const [accountAddress, setAccountAddress] = useState(""); - const [isKernelClientReady, setIsKernelClientReady] = useState(false); - - return ( - - {children} - - ); -} - -export function useZeroDev() { - const context = useContext(ZeroDevContext); - if (context === undefined) { - throw new Error("useZeroDev must be used within a ZeroDevProvider"); - } - return context; -} diff --git a/src/app/[locale]/smart-wallet/lib/viem.ts b/src/app/[locale]/smart-wallet/lib/viem.ts deleted file mode 100644 index 56a1456..0000000 --- a/src/app/[locale]/smart-wallet/lib/viem.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createPublicClient, http } from "viem"; - -import { BUNDLER_URL } from "../utils/constants"; - -export const publicClient = createPublicClient({ - transport: http(BUNDLER_URL), -}); diff --git a/src/app/[locale]/smart-wallet/lib/zerodev.ts b/src/app/[locale]/smart-wallet/lib/zerodev.ts deleted file mode 100644 index f088996..0000000 --- a/src/app/[locale]/smart-wallet/lib/zerodev.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - PasskeyValidatorContractVersion, - toPasskeyValidator, - toWebAuthnKey, - WebAuthnMode, -} from "@zerodev/passkey-validator"; -import { - createKernelAccount, - createKernelAccountClient, - KernelSmartAccountImplementation, -} from "@zerodev/sdk"; -import { KERNEL_V2_4 } from "@zerodev/sdk/constants"; -import { http } from "viem"; -import { SmartAccount } from "viem/account-abstraction"; - -import { - BUNDLER_URL, - CHAIN, - entryPoint, - PASSKEY_SERVER_URL, - publicClient, -} from "../utils/constants"; - -export async function createAccountAndClient( - username: string, - mode: WebAuthnMode -) { - try { - const webAuthnKey = await toWebAuthnKey({ - passkeyName: username, - passkeyServerUrl: PASSKEY_SERVER_URL, - mode: mode, - passkeyServerHeaders: {}, - }); - - const passkeyValidator = await toPasskeyValidator(publicClient, { - webAuthnKey, - entryPoint, - kernelVersion: KERNEL_V2_4, - validatorContractVersion: PasskeyValidatorContractVersion.V0_0_1, - }); - - const kernelAccount = (await createKernelAccount(publicClient, { - entryPoint, - plugins: { - sudo: passkeyValidator, - }, - kernelVersion: KERNEL_V2_4, - })) as SmartAccount; - - const kernelClient = createKernelAccountClient({ - account: kernelAccount, - chain: CHAIN, - bundlerTransport: http(BUNDLER_URL), - }); - - return { kernelAccount, kernelClient }; - } catch (error: any) { - throw error; - } -} diff --git a/src/app/[locale]/smart-wallet/page.tsx b/src/app/[locale]/smart-wallet/page.tsx deleted file mode 100644 index e83ff9b..0000000 --- a/src/app/[locale]/smart-wallet/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Metadata } from "next"; - -import { JsonLd } from "@/components/JsonLd"; -import { OnlyWithFeatureFlag } from "@/components/OnlyWithFeatureFlag"; -import { PageView } from "@/components/PageView"; -import { newLayoutContainerClasses } from "@/components/styles/container"; - -import { SmartWallet } from "./_components/SmartWallet"; -import { UsernameProvider } from "./context/UsernameContext"; -import { ZeroDevProvider } from "./context/ZerodevContext"; - -export const metadata: Metadata = { - title: "Ink Smart Wallet - DeFi unleashed by Kraken, built on the Superchain", - description: - "Experience the next generation of wallets with Ink Smart Wallet. Built on the Superchain, our smart wallet combines security, flexibility, and ease of use to enhance your DeFi experience.", -}; - -export default async function SmartWalletPage() { - return ( - - - - - -
- - - - - -
-
- ); -} diff --git a/src/app/[locale]/smart-wallet/utils/constants.ts b/src/app/[locale]/smart-wallet/utils/constants.ts deleted file mode 100644 index caece05..0000000 --- a/src/app/[locale]/smart-wallet/utils/constants.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createPublicClient, http } from "viem"; -import { Address } from "viem"; -import { - entryPoint06Address, - EntryPointVersion, -} from "viem/account-abstraction"; -import { inkSepolia } from "viem/chains"; - -import { clientEnv } from "@/env-client"; - -export const BUNDLER_URL = clientEnv.NEXT_PUBLIC_BUNDLER_URL; -export const PAYMASTER_URL = clientEnv.NEXT_PUBLIC_PAYMASTER_URL; -export const PASSKEY_SERVER_URL = clientEnv.NEXT_PUBLIC_PASSKEY_SERVER_URL; -export const CHAIN = inkSepolia; - -export const contractAddress = "0xA07F56aeeb535856FdEC39a9d685C62536150B1f"; -export const contractABI = [ - "function mint(address _to) public", - "function balanceOf(address owner) external view returns (uint256 balance)", -] as const; - -export const publicClient = createPublicClient({ - transport: http(BUNDLER_URL), - chain: CHAIN, -}); - -export const entryPoint = { - address: entryPoint06Address as Address, - version: "0.6" as EntryPointVersion, -}; diff --git a/src/env-client.ts b/src/env-client.ts index dbe3530..4ee2757 100644 --- a/src/env-client.ts +++ b/src/env-client.ts @@ -14,10 +14,6 @@ export const clientEnv = createEnv({ NEXT_PUBLIC_WC_PROJECT_ID: z.string().min(1), NEXT_PUBLIC_HCAPTCHA_SITEKEY: z.string().min(1), NEXT_PUBLIC_FAUCET_API_URL: z.string().url(), - NEXT_PUBLIC_GELATO_BRIDGE_URL: z.string().url(), - NEXT_PUBLIC_BUNDLER_URL: z.string().url(), - NEXT_PUBLIC_PAYMASTER_URL: z.string().url(), - NEXT_PUBLIC_PASSKEY_SERVER_URL: z.string().url(), }, runtimeEnv: { NEXT_PUBLIC_ENVIRONMENT: process.env.NEXT_PUBLIC_ENVIRONMENT, @@ -29,9 +25,5 @@ export const clientEnv = createEnv({ NEXT_PUBLIC_WC_PROJECT_ID: process.env.NEXT_PUBLIC_WC_PROJECT_ID, NEXT_PUBLIC_HCAPTCHA_SITEKEY: process.env.NEXT_PUBLIC_HCAPTCHA_SITEKEY, NEXT_PUBLIC_FAUCET_API_URL: process.env.NEXT_PUBLIC_FAUCET_API_URL, - NEXT_PUBLIC_GELATO_BRIDGE_URL: process.env.NEXT_PUBLIC_GELATO_BRIDGE_URL, - NEXT_PUBLIC_BUNDLER_URL: process.env.NEXT_PUBLIC_BUNDLER_URL, - NEXT_PUBLIC_PAYMASTER_URL: process.env.NEXT_PUBLIC_PAYMASTER_URL, - NEXT_PUBLIC_PASSKEY_SERVER_URL: process.env.NEXT_PUBLIC_PASSKEY_SERVER_URL, }, });