Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/privy wagmi #111

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f759f10
Update README.md
baumstern Jun 4, 2024
87d966a
Merge pull request #99 from VoiceDeck/baumstern-patch-1
0xRowdy Sep 22, 2024
db3efb7
Merge branch 'main' into cc-integration
dipanshuhappy Oct 21, 2024
1b772f6
Merge branch 'main' of https://github.com/VoiceDeck/app into cc-integ…
dipanshuhappy Oct 30, 2024
980bc14
privy initialization
Nithin-Varma Oct 30, 2024
38e0b92
merged nithin changes
dipanshuhappy Oct 31, 2024
e5e5712
privy api to pre generate a wallet
Nithin-Varma Oct 31, 2024
da7898a
Merge branch 'cc-integration' of https://github.com/VoiceDeck/app int…
Nithin-Varma Oct 31, 2024
3214941
feat: integrate Privy authentication and update wallet generation API
dipanshuhappy Nov 3, 2024
d6dd546
feat: add Privy wallet generation API and integrate Privy context pro…
dipanshuhappy Nov 3, 2024
7f0b2a1
refactor: clean up commented code and improve API client configuration
dipanshuhappy Nov 3, 2024
52f6681
fix: correct environment variable name for API key in checkout request
dipanshuhappy Nov 3, 2024
dcb2a66
build fix
dipanshuhappy Nov 3, 2024
be18af5
refactor: remove deprecated wallet generation API and clean up relate…
dipanshuhappy Nov 3, 2024
7bf5deb
Recreate issue of privy wagmi
dipanshuhappy Nov 4, 2024
43dd34e
refactor: clean up wallet generation code and improve login/logout ha…
dipanshuhappy Nov 5, 2024
32aee01
refactor: streamline fiat-without-login handling in buy fraction hook
dipanshuhappy Nov 5, 2024
f65a47c
feat: add User import from privy-io for enhanced user handling in buy…
dipanshuhappy Nov 5, 2024
26a480c
Merge branch 'main' of https://github.com/VoiceDeck/app into issue/pr…
dipanshuhappy Nov 7, 2024
a3d3abb
feat: add nanoid for unique transaction IDs and enhance contribution …
dipanshuhappy Nov 7, 2024
ef46324
feat: add payment success page and integrate transaction handling
dipanshuhappy Nov 7, 2024
705bc2f
chore: update @privy-io/server-auth to version 1.16.1 and comment out…
dipanshuhappy Nov 7, 2024
92dbaa7
feat: add Suspense component for loading state in ReportsPage
dipanshuhappy Nov 7, 2024
8d1b588
feat: update API base URL for normieTechClient to use the new endpoint
dipanshuhappy Nov 7, 2024
6fb8b6e
Refactor payment handling and integrate PayButton component in SignIn
dipanshuhappy Nov 7, 2024
71c1c91
feat: enhance wallet integration in ConnectButton and update PrivyCon…
dipanshuhappy Nov 11, 2024
b660e9e
feat: set defaultChain to optimism in PrivyContextProvider
dipanshuhappy Nov 11, 2024
d45c7e0
feat: implement chain switching in ConnectButton and set defaultChain…
dipanshuhappy Nov 11, 2024
7d65e64
feat: add CORS header and update type assertion in useHandleBuyFracti…
dipanshuhappy Nov 12, 2024
4013dd6
feat: improve wallet handling in ConnectButton and ensure proper logo…
dipanshuhappy Nov 12, 2024
13387fc
feat: improve wallet and order handling in SupportReportForm
dipanshuhappy Feb 15, 2025
c78e20e
Merge branch 'main' into issue/privy-wagmi
dipanshuhappy Feb 15, 2025
a1e3e4b
feat: improve error handling and wallet disconnection in ConnectButton
dipanshuhappy Feb 18, 2025
98f99a1
Merge branch 'issue/privy-wagmi' of https://github.com/VoiceDeck/app …
dipanshuhappy Feb 18, 2025
502123d
chore: minor formatting adjustment in PrivyContextProvider configuration
dipanshuhappy Feb 18, 2025
f9df8c5
Merge branch 'main' into issue/privy-wagmi
baumstern Mar 3, 2025
ba1414a
feat: improve wallet connection and loading states in SupportReportForm
dipanshuhappy Mar 4, 2025
4109c20
Merge branch 'issue/privy-wagmi' of https://github.com/VoiceDeck/app …
dipanshuhappy Mar 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ VoiceDeck is a platform that allows users to contribute retroactive funding for
- Contribute funds with embedded crypto wallet
- Track personal contribution activity and metrics

## Data Flow

This diagram provide a high level overview of data flow:
<img width="1632" alt="VD-sequential diagram_20240229" src="https://github.com/VoiceDeck/app/assets/1610146/53bdf97e-da9d-449f-b178-bbe2be67a1f0">

## Tech Stack

Expand Down
32 changes: 32 additions & 0 deletions app/api/wallet-generate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// import { PrivyClient } from "@privy-io/server-auth";
// import { type NextRequest, NextResponse } from "next/server";

// export async function POST(req: NextRequest) {
// const privy = new PrivyClient(
// process.env.PRIVY_APP_ID ?? "",
// process.env.PRIVY_APP_SECRET ?? "",
// );

// const { address } = await req.json();
// console.log("address", address);

// if (!address) {
// console.log("Missing required fields");
// return NextResponse.json(
// { error: "Missing required fields" },
// { status: 400 },
// );
// }

// const wallet = await privy.importUser({
// linkedAccounts: [
// {
// type: "email",
// address: address,
// },
// ],
// createEthereumWallet: true,
// });

// return NextResponse.json({ wallet }, { status: 200 });
// }
145 changes: 145 additions & 0 deletions app/checkout/success/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { notFound } from 'next/navigation'
import Link from 'next/link'
import { ArrowLeft, ExternalLink } from 'lucide-react'

import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { normieTechClient } from '@/lib/normie-tech'

import { processNewContribution } from '@/lib/directus'

async function getTransactionData(transactionId: string) {
const transactionData = (await normieTechClient.GET('/v1/{projectId}/transactions/{transactionId}',{
params:{
header:{
"x-api-key":process.env.NEXT_PUBLIC_NORMIE_TECH_API_KEY ?? "",

},
path:{
projectId:"voice-deck",
transactionId:transactionId
}

}
}))
return transactionData
}



export default async function PaymentSuccessPage({
searchParams
}: {
searchParams: { transactionId?: string }
}) {
if (!searchParams.transactionId) {
notFound()
}
const res = await getTransactionData(searchParams.transactionId)



if (res.error) {
return (
<div className="min-h-screen bg-slate-50 p-4 md:p-6 lg:p-8">
<div className="mx-auto max-w-2xl">
<Card className="overflow-hidden rounded-lg border-0 bg-white shadow-lg">
<div className="flex flex-col items-center p-6 text-center">
<h1 className="mb-2 text-2xl font-bold text-slate-900">Payment Processing Error</h1>
<p className="mb-6 text-slate-600">{JSON.stringify(res.error)}</p>
<Link href="/reports" className="w-full">
<Button className="w-full">Return to Reports</Button>
</Link>
</div>
</Card>
</div>
</div>
)
}
if(!res.data){
return "Error"
}
const { amountInFiat,blockchainTransactionId,extraMetadataJson} = res.data
const extraMetadata = JSON.parse(JSON.stringify(extraMetadataJson))

if(!extraMetadata || !extraMetadata.sender || !blockchainTransactionId || !extraMetadata.hypercertId || !amountInFiat){
return (
<h1>Error some data not defined</h1>
)
}
await processNewContribution(
extraMetadata.sender,
blockchainTransactionId as `0x${string}`,
extraMetadata.hypercertId,
amountInFiat,
extraMetadata.comment
)




return (
<div className="min-h-screen bg-slate-50 p-4 md:p-6 lg:p-8">
<div className="mx-auto max-w-2xl">
<Link
href="/reports"
className="mb-6 inline-flex items-center text-sm text-slate-600 hover:text-slate-900"
>
<ArrowLeft className="mr-2 h-4 w-4" />
ALL REPORTS
</Link>

<Card className="overflow-hidden rounded-lg border-0 bg-white shadow-lg">
<div className="flex flex-col items-center p-6 text-center">
<div className="mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-green-100">
{/* biome-ignore lint/a11y/noSvgWithoutTitle: <explanation> */}
<svg
className="h-8 w-8 text-green-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 13l4 4L19 7"
/>
</svg>
</div>

<h1 className="mb-2 text-2xl font-bold text-slate-900">Payment Successful!</h1>
<p className="mb-6 text-slate-600">
Thank you for supporting this important cause. Your contribution will make a real difference.
</p>

<div className="mb-6 w-full rounded-lg bg-slate-50 p-4">
<div className="text-sm text-slate-600">Transaction Amount</div>
<div className="text-2xl font-bold text-slate-900">${amountInFiat.toFixed(2)}</div>
</div>

<div className="flex w-full flex-col gap-3">
<Link href={`${extraMetadata.redirectUrl}`} className="w-full">
<Button className="w-full" variant="outline">
Return to Report
</Button>
</Link>

<Link
href={`https://optimistic.etherscan.io/tx/${blockchainTransactionId}`}
target="_blank"
rel="noopener noreferrer"
className="w-full"
>
<Button className="w-full">
View on Optimism
<ExternalLink className="ml-2 h-4 w-4" />
</Button>
</Link>
</div>
</div>
</Card>
</div>
</div>
)
}
16 changes: 10 additions & 6 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { Footer } from "@/components/global/footer";
import { NavMenu } from "@/components/global/nav-menu";
import { siteConfig } from "@/config/site";
import { config } from "@/config/wagmi";
import { PrivyContextProvider } from "@/contexts/privy";
import { WagmiContextProvider } from "@/contexts/wagmi";
import { PrivyProvider } from "@privy-io/react-auth";
import { headers } from "next/headers";

export const metadata: Metadata = {
Expand Down Expand Up @@ -43,19 +45,21 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
const initialState = cookieToInitialState(config, headers().get("cookie"));
const initialState = undefined;
return (
<html lang="en">
<body
className={cn(
"min-h-screen bg-background font-sans antialiased flex flex-col",
)}
>
<WagmiContextProvider initialState={initialState}>
<NavMenu />
<div className="flex-1">{children}</div>
<Footer />
</WagmiContextProvider>
<PrivyContextProvider>
<WagmiContextProvider initialState={initialState}>
<NavMenu />
<div className="flex-1">{children}</div>
<Footer />
</WagmiContextProvider>
</PrivyContextProvider>
</body>
</html>
);
Expand Down
18 changes: 15 additions & 3 deletions app/reports/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
import { Badge } from "@/components/ui/badge";
import { DynamicCategoryIcon } from "@/components/ui/dynamic-category-icon";
import { Separator } from "@/components/ui/separator";
import { getContributionsByHCId } from "@/lib/directus";
import {
getContributionsByHCId,
processNewCryptoContribution,

Check failure on line 12 in app/reports/[slug]/page.tsx

View workflow job for this annotation

GitHub Actions / test (typecheck)

'"@/lib/directus"' has no exported member named 'processNewCryptoContribution'. Did you mean 'processNewContribution'?
} from "@/lib/directus";
import { fetchReportBySlug } from "@/lib/impact-reports";
import { normieTechClient } from "@/lib/normie-tech";
import type { Report } from "@/types";
import parse from "html-react-parser";
import { ChevronLeft, MapPin } from "lucide-react";
import type { Metadata } from "next";
import Image from "next/image";
import Link from "next/link";
import { comment } from "postcss";

interface ReportPageProps {
params: { slug: string };
searchParams?: { [key: string]: string | string[] | undefined };
}

const getReportData = async (slug?: string | string[]) => {
Expand All @@ -35,6 +41,7 @@
if (!hypercertId) return null;
try {
const contributionsData = await getContributionsByHCId(hypercertId);

return contributionsData || [];
} catch (error) {
throw new Error(
Expand All @@ -59,12 +66,17 @@
return metadata;
}

export default async function ReportPage({ params }: ReportPageProps) {
export default async function ReportPage({
params,
searchParams,
}: ReportPageProps) {
const { slug } = params;
const report = await getReportData(slug);
const contributions = await getContributionsByHypercertId(report.hypercertId);
const htmlParsedStory = report.story ? parse(report.story) : null;
// console.log({ report });
console.log({ searchParams });
console.log({ hypercertId: report.hypercertId }, "hypercertId", report.title);

return (
<main className="flex flex-col justify-between h-svh md:h-fit md:px-12 pt-6">
{/* 192px is added to account for the funding progress on mobile */}
Expand Down
3 changes: 3 additions & 0 deletions app/reports/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { FilterProvider } from "@/contexts/filter";
import { getNumberOfContributors } from "@/lib/directus";
import { fetchReports } from "@/lib/impact-reports";
import type { Report } from "@/types";
import { Suspense } from "react";

export default async function ReportsPage() {
let uniqueReports: Report[];
Expand All @@ -32,6 +33,7 @@ export default async function ReportsPage() {
}

return (
<Suspense fallback={<div>Loading...</div>}>
<main className="flex flex-col gap-4 pb-[64px] md:pb-0">
<section className="flex flex-col items-center p-4 md:p-8 gap-4">
<header className="relative overflow-hidden w-full flex flex-col justify-end max-w-screen-xl min-[2560px]:max-w-screen-2xl h-[420px] 2xl:h-[520px] min-[2560px]:h-[720px] text-vd-beige-100 rounded-3xl p-4 md:p-8 2xl:p-16">
Expand Down Expand Up @@ -74,5 +76,6 @@ export default async function ReportsPage() {
</section>
)}
</main>
</Suspense>
);
}
Binary file modified bun.lockb
Binary file not shown.
57 changes: 55 additions & 2 deletions components/global/connect-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,63 @@
import { useWeb3Modal } from "@web3modal/wagmi/react";

import { Button } from "@/components/ui/button";
import { DEFAULT_CHAIN_ID } from "@/config/constants";
import { config } from "@/config/wagmi";
import { useLogin, useLogout, useWallets } from "@privy-io/react-auth";
import { useSetActiveWallet } from "@privy-io/wagmi";
import { disconnect } from "@wagmi/core";
import { UserPlus } from "lucide-react";
import { useState } from "react";

const ConnectButton = () => {
const { open } = useWeb3Modal();
return <Button onClick={() => open()}>Connect Wallet</Button>;
// const { open } = useWeb3Modal();
const [isLogin, setIsLogin] = useState(false);

const { logout } = useLogout({
onSuccess: () => {
console.log("User logged out");
setIsLogin(false);
},
});
const { wallets, ready } = useWallets();
const { setActiveWallet } = useSetActiveWallet();

const { login } = useLogin({
onComplete: async (user) => {
console.log("user logged in...", user);
const wallet = user.linkedAccounts.filter((a) => a.type === "wallet")[0];
console.log("wallet", wallet);
if (wallet.address) {
console.log("wallets", wallets);
const newActiveWallet = wallets.find(
(wallet) => wallet.address === user.wallet?.address,
);
if (newActiveWallet) {
console.log("newActiveWallet", newActiveWallet);
console.log("chainId", newActiveWallet.chainId);

await setActiveWallet(newActiveWallet);
const chainId = newActiveWallet.chainId;
if (chainId !== DEFAULT_CHAIN_ID.toString()) {
await newActiveWallet.switchChain(DEFAULT_CHAIN_ID);
}
}
}
setIsLogin(true);
},

onError: async (error) => {
console.log("error while logging in...", error);
await disconnect(config);
setIsLogin(false);
},
});

return (
<div>
<Button onClick={login}>Connect Wallet</Button>
</div>
);
};
ConnectButton.displayName = "ConnectButton";

Expand Down
Loading
Loading