Skip to content

Commit

Permalink
chore: merge develop and resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
martines3000 committed Apr 8, 2024
2 parents e080735 + 541ad5b commit d3654d7
Show file tree
Hide file tree
Showing 70 changed files with 1,696 additions and 594 deletions.
5 changes: 5 additions & 0 deletions .changeset/five-poets-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blockchain-lab-um/dapp": patch
---

Adds reclaim option for campaigns.
5 changes: 5 additions & 0 deletions .changeset/rich-pandas-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blockchain-lab-um/dapp": patch
---

Adds campaign issue checks.
3 changes: 1 addition & 2 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
"patches/**",
"assets/**",
".changeset/**",
".nx/**",
"post-process.js"
".nx/**"
]
},
"organizeImports": {
Expand Down
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,16 @@
"cross-fetch@4.0.0": "patches/cross-fetch@4.0.0.patch",
"@ceramicnetwork/common@2.30.0": "patches/@ceramicnetwork__common@2.30.0.patch",
"@metamask/snaps-sdk@1.2.0": "patches/@metamask__snaps-sdk@1.2.0.patch",
"@changesets/assemble-release-plan@6.0.0": "patches/@changesets__assemble-release-plan@6.0.0.patch"
"@changesets/assemble-release-plan@6.0.0": "patches/@changesets__assemble-release-plan@6.0.0.patch",
"@iden3/js-iden3-core@1.2.1": "patches/@iden3__js-iden3-core@1.2.1.patch",
"@iden3/js-crypto@1.0.3": "patches/@iden3__js-crypto@1.0.3.patch",
"@iden3/js-jwz@1.3.0": "patches/@iden3__js-jwz@1.3.0.patch",
"@iden3/js-merkletree@1.1.2": "patches/@iden3__js-merkletree@1.1.2.patch",
"ffjavascript@0.2.63": "patches/ffjavascript@0.2.63.patch",
"did-jwt@6.11.6": "patches/did-jwt@6.11.6.patch",
"web-worker@1.3.0": "patches/web-worker@1.3.0.patch",
"@iden3/js-jsonld-merklization@1.1.2": "patches/@iden3__js-jsonld-merklization@1.1.2.patch"
},
"allowNonAppliedPatches": true
"allowNonAppliedPatches": false
}
}
2 changes: 1 addition & 1 deletion packages/dapp/src/app/[locale]/(public)/ecosystem/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const projectsDark: ProjectIconProps[] = [

export default function Page() {
return (
<div className="flex flex-col items-center pt-20">
<div className="flex flex-col">
<div>
<h1 className="font-ubuntu dark:text-orange-accent-dark mb-4 text-center text-2xl font-medium text-pink-500">
Applications
Expand Down
6 changes: 4 additions & 2 deletions packages/dapp/src/app/[locale]/(public)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ export default async function PublicLayout({
children: React.ReactNode;
}) {
return (
<div className="flex min-h-screen flex-col px-4 sm:px-12">
<PublicNavbar />
<div className="flex flex-col h-screen px-4 sm:px-12">
<div className="m-0 p-6 sm:px-12">
<PublicNavbar />
</div>
<div className="flex flex-1">
<div className="flex flex-1 items-center justify-center overflow-auto">
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const metadata: Metadata = {

export default function Page() {
return (
<div className="flex flex-1 items-center justify-center">
<div className="flex w-full pt-12 h-auto items-center justify-center">
<div className="dark:bg-navy-blue-800 dark:text-navy-blue-400 w-full rounded-3xl bg-white shadow-lg md:max-w-4xl">
<SettingsCard />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const metadata: Metadata = {

export default function Page() {
return (
<div className="flex h-full flex-1 justify-center">
<div className="flex h-full justify-center w-full">
<CampaignsDisplay />
</div>
);
Expand Down
20 changes: 11 additions & 9 deletions packages/dapp/src/app/[locale]/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AppNavbar from '@/components/AppNavbar';
import { SignInModal } from '@/components/SignInModal';
import ToastWrapper from '@/components/ToastWrapper';
import { Providers } from '@/components/Providers';
import { ScrollShadow } from '@nextui-org/react';

export default async function AppLayout({
children,
Expand All @@ -13,16 +14,17 @@ export default async function AppLayout({
}) {
return (
<Providers>
<AppNavbar />
<div
className={clsx(
'flex min-h-screen flex-col justify-center pt-24',
'main-bg'
)}
>
<div className="flex h-full w-full flex-1 flex-col px-2 pb-20 pt-12 sm:px-6 md:px-12">
{children}
<div className="flex flex-col h-screen px-4 pb-6 sm:px-12">
<div className="p-6 m-0 sm:px-2 max-sm:py-2">
<AppNavbar />
</div>
<ScrollShadow
className="flex h-full w-full flex-col py-6 px-2 main-bg max-sm:mb-12"
hideScrollBar
size={8}
>
{children}
</ScrollShadow>
</div>
<AppBottomBar />
<SignInModal />
Expand Down
58 changes: 58 additions & 0 deletions packages/dapp/src/app/api/campaigns/claims/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { type NextRequest, NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
import { supabaseServiceRoleClient } from '@/utils/supabase/supabaseServiceRoleClient';
import { supabaseClient } from '@/utils/supabase/supabaseClient';

const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};

export const dynamic = 'force-dynamic';

export async function GET(request: NextRequest) {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return new NextResponse('Unauthorized', {
status: 401,
headers: {
...CORS_HEADERS,
},
});
}
const user = jwt.verify(token, process.env.SUPABASE_JWT_SECRET!) as {
sub: string;
address: string;
aud: string;
role: string;
iat: number;
exp: number;
};

const supabase = supabaseServiceRoleClient();
const { data: userId } = await supabase
.from('users')
.select('id')
.eq('address', user.address.toLowerCase())
.single();
if (!userId) {
return NextResponse.json({ claims: [] }, { headers: { ...CORS_HEADERS } });
}
const { data: claims, error } = await supabase
.from('claims')
.select('*')
.eq('user_id', userId.id);

if (error) {
console.error('Error getting claims', error);
return new NextResponse('Error getting claims', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}

return NextResponse.json({ claims }, { headers: { ...CORS_HEADERS } });
}
130 changes: 86 additions & 44 deletions packages/dapp/src/app/api/campaigns/issue/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,40 +59,13 @@ export async function POST(request: NextRequest) {
});
}

const agent = await getAgent();
const didResolution = await agent.resolveDid({ didUrl: did });

if (
!didResolution.didDocument ||
!didResolution.didDocument.verificationMethod
) {
return new NextResponse('Error resolving did', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}

if (
didResolution.didDocument.verificationMethod[0].blockchainAccountId
?.split(':')[2]
.toLowerCase() !== user.address.toLowerCase()
) {
return new NextResponse('Unauthorized', {
status: 401,
headers: {
...CORS_HEADERS,
},
});
}

const supabase = supabaseServiceRoleClient();

const { data: campaign, error: campaignError } = await supabase
.from('campaigns')
.select('*')
.select('*, requirements(id, *)')
.eq('id', campaignId)
.order('created_at', { ascending: false })
.single()
.throwOnError();

Expand All @@ -105,15 +78,6 @@ export async function POST(request: NextRequest) {
});
}

if (campaign.total && campaign.claimed >= campaign.total) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}

const { data: claim, error: claimError } = await supabase
.from('claims')
.select('*')
Expand All @@ -129,6 +93,89 @@ export async function POST(request: NextRequest) {
});
}

let claimDate = new Date().toISOString();
let alreadyClaimed = false;
if (claim.length > 0) {
claimDate = claim[0].claimed_at;
alreadyClaimed = true;
}

if (!alreadyClaimed) {
const now = new Date();
const notYetStarted =
campaign.start_date && new Date(campaign.start_date) > now;
const alreadyFinished =
campaign.end_date && new Date(campaign.end_date) < now;
const isCampaignInactive = notYetStarted || alreadyFinished;
const isCampaignFullyClaimed =
campaign.total && campaign.claimed >= campaign.total;

if (isCampaignInactive) {
return new NextResponse('Campaign is not active', {
status: 400,
headers: { ...CORS_HEADERS },
});
}

if (isCampaignFullyClaimed) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: { ...CORS_HEADERS },
});
}

const { data: completedRequirements, error: completedRequirementsError } =
await supabase.rpc('get_num_of_users_requirements_by_campaign', {
input_campaign_id: campaignId,
input_user_id: user.sub,
});

if (completedRequirementsError) {
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}
if (completedRequirements !== campaign.requirements.length) {
return new NextResponse('User has not completed all requirements', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}
}

const agent = await getAgent();
const didResolution = await agent.resolveDid({ didUrl: did });

if (
!didResolution.didDocument ||
!didResolution.didDocument.verificationMethod
) {
return new NextResponse('Error resolving did', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}

if (
didResolution.didDocument.verificationMethod[0].blockchainAccountId
?.split(':')[2]
.toLowerCase() !== user.address.toLowerCase()
) {
return new NextResponse('Unauthorized', {
status: 401,
headers: {
...CORS_HEADERS,
},
});
}

const controllerKeyId = 'key-1';

const issuerDid = await agent.didManagerImport({
Expand All @@ -145,12 +192,8 @@ export async function POST(request: NextRequest) {
],
});

let claimDate = new Date().toISOString();
if (claim.length > 0) {
claimDate = claim[0].claimed_at;
}
let credentialId = claim[0]?.credential_id;
if (claim.length === 0) {
if (!alreadyClaimed) {
const { data: insertedClaimData, error: updatedClaimError } =
await supabase
.from('claims')
Expand All @@ -173,7 +216,6 @@ export async function POST(request: NextRequest) {
});
}

console.error('Error updating claim', updatedClaimError);
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,15 @@ export async function POST(
let credentials: VerifiableCredential[];

try {
credentials = presentation.verifiableCredential.map((credential) =>
normalizeCredential(credential)
credentials = presentation.verifiableCredential.reduce(
(result, credential) => {
const normalized = normalizeCredential(credential);
if (normalized?.credentialSubject?.id === did) {
result.push(normalized);
}
return result;
},
[] as VerifiableCredential[]
);
} catch (error) {
console.error('Error decoding credentials', error);
Expand Down
6 changes: 3 additions & 3 deletions packages/dapp/src/components/AppNavbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export default function AppNavbar() {
const { isConnected } = useAccount();

return (
<div className="main-bg fixed top-0 z-50 m-0 flex h-24 w-screen items-center">
<div className="flex flex-1 items-center px-4 sm:px-12">
<div className="z-50 items-center">
<div className="flex flex-1 items-center">
<Link href="/" className="focus-visible:outline-none">
<div className="flex">
<MascaLogo />
Expand All @@ -45,7 +45,7 @@ export default function AppNavbar() {
</h1>
</div>
</Link>
<div className="mx-2 hidden flex-1 items-center justify-center md:flex">
<div className="hidden flex-1 items-center justify-center md:flex">
{MAIN_LINKS.map(({ name, href, requiresConnection }) => {
if ((requiresConnection && isConnected) || !requiresConnection) {
return (
Expand Down
Loading

0 comments on commit d3654d7

Please sign in to comment.