diff --git a/.env.example b/.env.example index 4fad3ca..cc2c0ec 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,15 @@ ID_HUB_ADDR= SELF_SCOPE= SELF_CONFIG_ID= -NEXT_PUBLIC_SELF_APP_NAME= +NODE_ENV = "development" +# this env is read in packages/contract and packages/web NEXT_PUBLIC_VERIFICATION_DEPLOYED_ADDR= -NEXT_PUBLIC_SELF_SCOPE_SEED= + +NEXT_PUBLIC_SELF_SCOPE_SEED="dhkdao-self-prototype" +NEXT_PUBLIC_ALCHEMY_ID= +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID= + +# DHK Token deployed on op mainnet: +# https://optimistic.etherscan.io/token/0xe85d2c93f7e26b99a46a8bb9350cbfb965fa4f82 +NEXT_PUBLIC_DHKTOKEN_ADDR="0xe85d2c93f7e26b99a46a8bb9350cbfb965fa4f82" +NEXT_PUBLIC_DHKTOKEN_THRESHOLD="1" diff --git a/packages/web/src/app/api/verify-successful/route.ts b/packages/web/src/app/api/verify-successful/route.ts index 0745cba..087ceed 100644 --- a/packages/web/src/app/api/verify-successful/route.ts +++ b/packages/web/src/app/api/verify-successful/route.ts @@ -7,7 +7,7 @@ import { type Abi, } from "viem"; import { optimism } from "viem/chains"; -import { erc20Abi } from "@/config"; +import { erc20Abi, thresholdTokenAmt } from "@/config"; export async function POST(req: NextRequest) { const body = await req.json(); @@ -40,8 +40,7 @@ export async function POST(req: NextRequest) { const balance = BigInt( (await dhkTokenContract.read.balanceOf([sender])) as bigint, ); - const voteThreshold = - BigInt(process.env.NEXT_PUBLIC_DHKTOKEN_THRESHOLD || "1") * decimals; + const voteThreshold = thresholdTokenAmt * decimals; // TODO: 3. check user has a DHK subname in https://app.namespace.ninja const senderHasSubname = true; @@ -53,6 +52,7 @@ export async function POST(req: NextRequest) { status: "success", sender, result, + txHash, aboveTokenThreshold, hasSubname: senderHasSubname, }); diff --git a/packages/web/src/app/result/page.tsx b/packages/web/src/app/result/page.tsx new file mode 100644 index 0000000..c30010a --- /dev/null +++ b/packages/web/src/app/result/page.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { useEffect, useState } from "react"; +import type { VerificationResult } from "@/types"; +import { + appName, + alfajoresTxUrlPrefix, + thresholdTokenAmt, + opMainnetAddrUrlPrefix, +} from "@/config"; + +export default function VerificationResultPage() { + const linkClasses = + "mt-4 bg-transparent text-blue-600 underline hover:text-blue-800 hover:underline p-0 border-0 font-normal"; + + const [verificationResult, setVerificationResult] = + useState(); + + useEffect(() => { + const _verificationResult = JSON.parse( + localStorage.getItem("verificationResult") || "", + ) as VerificationResult; + setVerificationResult(_verificationResult); + }, []); + + return ( +
+

{appName}

+ +
+

Result

+
    +
  • + User address:{" "} + {verificationResult?.sender && ( + + + {verificationResult?.sender} + + + )} +
  • +
  • + User is self.xyz verified?{" "} + {verificationResult?.txHash ? ( + + + true + + + ) : ( + false + )} +
  • +
  • + User has threshold amount of DHK token ( + {thresholdTokenAmt.toString()})?{" "} + + {verificationResult?.aboveTokenThreshold ? "true" : "false"} + +
  • +
  • + User has DHK ID Subname (mocked)?{" "} + {verificationResult?.hasSubname ? "true" : "false"} +
  • +
+
+
+ ); +} diff --git a/packages/web/src/components/VerificationComponent.tsx b/packages/web/src/components/VerificationComponent.tsx index c68ba26..f22e728 100644 --- a/packages/web/src/components/VerificationComponent.tsx +++ b/packages/web/src/components/VerificationComponent.tsx @@ -3,13 +3,14 @@ import React, { useState, useEffect } from "react"; import { getUniversalLink } from "@selfxyz/core"; import { ConnectKitButton } from "connectkit"; +import { useRouter } from "next/navigation"; import { SelfAppBuilder, SelfQRcodeWrapper, type SelfApp, } from "@selfxyz/qrcode"; import { clsx } from "clsx"; -import type { Log, Hash } from "viem"; +import type { Log } from "viem"; import { useAccount, useConfig, useWatchContractEvent } from "wagmi"; import { watchContractEvent } from "wagmi/actions"; import { @@ -22,21 +23,12 @@ import { } from "@headlessui/react"; import { appName, selfVerificationContract } from "@/config"; -import type { Address } from "viem"; - -type VerificationCompletedEventArgs = { - txHash: Hash; - sender: Address; - nationality: string; - times: number; - userData: string; -}; - -type EventLog = Log & { args: any }; +import type { VerificationCompletedEventArgs, EventLog } from "@/types"; export default function VerificationComponent() { const account = useAccount(); const config = useConfig(); + const router = useRouter(); const [selfApp, setSelfApp] = useState(); const [universalLink, setUniversalLink] = useState(""); @@ -144,17 +136,21 @@ export default function VerificationComponent() { if (!res.ok) throw new Error("API request failed"); - console.log("result:", await res.json()); + localStorage.setItem( + "verificationResult", + JSON.stringify(await res.json()), + ); + router.push("/result"); } catch (err) { console.error("Error calling verify-successful API:", err); } })(); - }, [isFNCallback, evReceived]); + }, [isFNCallback, evReceived, router]); return ( <>
-

DHK dao Self Prototype

+

{appName}

1. Sign in with your wallet

diff --git a/packages/web/src/components/Web3Provider.tsx b/packages/web/src/components/Web3Provider.tsx index 50917bc..8d4b554 100644 --- a/packages/web/src/components/Web3Provider.tsx +++ b/packages/web/src/components/Web3Provider.tsx @@ -7,15 +7,28 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ConnectKitProvider, getDefaultConfig } from "connectkit"; import { appName } from "@/config"; +const chains = + process.env.NODE_ENV === "development" + ? [foundry, celoAlfajores] + : [celoAlfajores]; +const transports = + process.env.NODE_ENV === "development" + ? { + [foundry.id]: webSocket("http://localhost:8545"), + [celoAlfajores.id]: webSocket( + `https://celo-alfajores.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, + ), + } + : { + [celoAlfajores.id]: webSocket( + `https://celo-alfajores.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, + ), + }; + export const ckConfig = getDefaultConfig({ // Your dApps chains - chains: [foundry, celoAlfajores], - transports: { - [foundry.id]: webSocket("http://localhost:8545"), - [celoAlfajores.id]: webSocket( - `https://celo-alfajores.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_ID}`, - ), - }, + chains, + transports, // Required API Keys walletConnectProjectId: diff --git a/packages/web/src/config.ts b/packages/web/src/config.ts index 734d648..b66e8c9 100644 --- a/packages/web/src/config.ts +++ b/packages/web/src/config.ts @@ -9,5 +9,13 @@ export const selfVerificationContract = { }; export const erc20Abi = ERC20ABI_JSON.abi as Abi; - export const appName = "DHK dao Identity Verification"; +export const thresholdTokenAmt = BigInt( + process.env.NEXT_PUBLIC_DHKTOKEN_THRESHOLD || "1", +); + +export const alfajoresTxUrlPrefix = "https://celo-alfajores.blockscout.com/tx/"; +export const alfajoresAddrUrlPrefix = + "https://celo-alfajores.blockscout.com/address/"; +export const opMainnetAddrUrlPrefix = + "https://optimistic.etherscan.io/address/"; diff --git a/packages/web/src/types.ts b/packages/web/src/types.ts new file mode 100644 index 0000000..e1540a4 --- /dev/null +++ b/packages/web/src/types.ts @@ -0,0 +1,20 @@ +import type { Address, Log, Hash } from "viem"; + +export type VerificationCompletedEventArgs = { + txHash: Hash; + sender: Address; + nationality: string; + times: number; + userData: string; +}; + +export type EventLog = Log & { args: any }; + +export type VerificationResult = { + status: string; + sender: Address; + result: boolean; + txHash: Hash; + aboveTokenThreshold: boolean; + hasSubname: boolean; +};