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

Feat/nillion bounty integration #17

Merged
merged 26 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5b97903
feat: integrate Nillion bounty service
romain-lfg Feb 8, 2025
30d5f69
feat: integrate Nillion data fetching with UI
romain-lfg Feb 8, 2025
cf5aa89
feat: implement Nillion integration
romain-lfg Feb 8, 2025
50c1335
chore: add Nillion configuration
romain-lfg Feb 8, 2025
6da5d91
fix: update Nillion integration to use correct SDK methods
romain-lfg Feb 8, 2025
e090e49
fix: correct Nillion SDK method calls
romain-lfg Feb 8, 2025
a699ae9
fix: update Nillion SDK integration
romain-lfg Feb 8, 2025
165e8f2
fix: align with original Nillion implementation
romain-lfg Feb 8, 2025
b7eb746
fix: add missing SCHEMA_IDS import in client
romain-lfg Feb 8, 2025
2588b89
fix: correct order of arguments in Nillion client initialization
romain-lfg Feb 8, 2025
863c5ac
fix: add nodes array type checking and logging
romain-lfg Feb 8, 2025
d8a5820
fix: align with original Nillion implementation
romain-lfg Feb 8, 2025
f779556
fix: align with original Nillion implementation
romain-lfg Feb 8, 2025
3b3840a
fix: update Nillion client and API
romain-lfg Feb 8, 2025
d1087d7
fix: use nillionClient directly for getCollection
romain-lfg Feb 8, 2025
b36e33c
fix: simplify client implementation
romain-lfg Feb 8, 2025
924e618
fix: add detailed logging for debugging
romain-lfg Feb 8, 2025
8916214
fix: update bounty fetching logic
romain-lfg Feb 8, 2025
56de8d1
fix: add collection initialization with test bounty
romain-lfg Feb 8, 2025
bcce7d2
feat: add schema initialization
romain-lfg Feb 8, 2025
e1bab2f
fix: update schema and data format
romain-lfg Feb 8, 2025
a44351b
fix: improve schema initialization
romain-lfg Feb 8, 2025
091c010
refactor: simplify nillion API
romain-lfg Feb 8, 2025
accf74d
fix: update nillion import path
romain-lfg Feb 8, 2025
6cc6b5f
fix: update nillion import path to use workspace path
romain-lfg Feb 8, 2025
909bf90
fix: use getBountyList directly from nillion package
romain-lfg Feb 8, 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
10 changes: 10 additions & 0 deletions frontend/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Feature Flags
NEXT_PUBLIC_ENABLE_NILLION=true

# Nillion Configuration (using demo credentials)
NEXT_PUBLIC_NILLION_SECRET_KEY=a786abe58f933e190d01d05b467838abb1e391007a674d8a3aef106e15a0bf5a
NEXT_PUBLIC_NILLION_ORG_DID=did:nil:testnet:nillion1vn49zpzgpagey80lp4xzzefaz09kufr5e6zq8c

# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_NETWORK=sepolia
7 changes: 7 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Feature Flags
NEXT_PUBLIC_ENABLE_NILLION=true

# Nillion Configuration
NEXT_PUBLIC_NILLION_SECRET_KEY=your_secret_key_here
NEXT_PUBLIC_NILLION_ORG_DID=your_org_did_here

# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_NETWORK=sepolia
Expand Down
6 changes: 6 additions & 0 deletions frontend/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Feature Flags
NEXT_PUBLIC_ENABLE_NILLION=true

# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_NETWORK=sepolia
46 changes: 46 additions & 0 deletions frontend/.github/PR_DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# API Integration Plan and Base Infrastructure

## Overview
This PR sets up the foundation for integrating our frontend with the backend API. It includes comprehensive documentation and base infrastructure for API integration.

## Changes
- Added detailed API integration plan (`docs/API_INTEGRATION.md`)
- Created base API client with error handling (`src/api/client.ts`)
- Set up directory structure for API integration

## API Integration Plan Highlights
1. **Phased Approach**
- Phase 1: API Contract Definition
- Phase 2: Environment Setup
- Phase 3: API Integration
- Phase 4: Testing & Validation
- Phase 5: Monitoring & Maintenance

2. **Documentation**
- Defined all required endpoints
- Documented data schemas
- Outlined integration testing strategy
- Added environment configuration guide

3. **Infrastructure**
- Base API client with axios
- Error handling with custom APIError class
- Authentication interceptors
- TypeScript types and interfaces

## Next Steps
- [ ] Review API contract with backend team
- [ ] Set up staging environment
- [ ] Begin endpoint implementation
- [ ] Create integration test suite

## Testing
- Base API client is set up with proper error handling
- Documentation has been reviewed for completeness
- Directory structure follows best practices

## Screenshots
N/A - Infrastructure and documentation changes only

## Additional Notes
This PR serves as a foundation for our API integration. It will help the team understand what endpoints are needed and how to implement them consistently.
39 changes: 36 additions & 3 deletions frontend/app/bounties/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,46 @@ import { useParams, useRouter } from 'next/navigation';
import { IconBrandGithub, IconClock, IconCalendar, IconTrophy, IconArrowLeft } from '@tabler/icons-react';
import Link from 'next/link';
import { FeatureGate } from '@/hooks/useFeature';
import { mockBounties } from '@/mocks/bounties';
import { Bounty } from '@/types/bounty';
import { useBounty } from '@/hooks/useBounty';
import BountySkeleton from '@/components/bounties/BountySkeleton';
import BountyError from '@/components/bounties/BountyError';

export default function BountyDetail() {
const { id } = useParams();
const bounty = mockBounties.find(b => b.id === id) as Bounty;
const {
data: bounty,
isLoading,
error,
refetch
} = useBounty(id as string);

// Show loading state
if (isLoading) {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white pt-24">
<div className="container mx-auto px-4">
<div className="max-w-4xl mx-auto">
<BountySkeleton />
</div>
</div>
</div>
);
}

// Show error state
if (error) {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white pt-24">
<div className="container mx-auto px-4">
<div className="max-w-4xl mx-auto">
<BountyError onRetry={() => refetch()} />
</div>
</div>
</div>
);
}

// Show not found state
if (!bounty) {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white flex items-center justify-center pt-24">
Expand Down
35 changes: 33 additions & 2 deletions frontend/app/bounties/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@

import { useState } from 'react';
import Link from 'next/link';
import { Bounty } from '@/types/bounty';
import { useBounties } from '@/hooks/useBounties';
import { useFeature } from '@/hooks/useFeature';
import { mockBounties } from '@/mocks/bounties';
import CreateBountyModal from '@/components/bounties/CreateBountyModal';
import BountySkeleton from '@/components/bounties/BountySkeleton';
import BountyError from '@/components/bounties/BountyError';

export default function BountyBoard() {
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const isNillionEnabled = useFeature('nillion.enabled');

const {
data: bountyData,
isLoading,
error,
refetch
} = useBounties();

// Use Nillion data if enabled, otherwise fall back to mock data
const bounties = isNillionEnabled ? bountyData?.items : mockBounties;
return (
<main className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white">
{/* Header Section */}
Expand Down Expand Up @@ -42,7 +56,24 @@ export default function BountyBoard() {
<section className="py-12">
<div className="container mx-auto px-4">
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{mockBounties.map((bounty) => (
{/* Loading State */}
{isLoading && (
<>
{[1, 2, 3, 4, 5, 6].map((i) => (
<BountySkeleton key={i} />
))}
</>
)}

{/* Error State */}
{error && (
<div className="col-span-full">
<BountyError onRetry={() => refetch()} />
</div>
)}

{/* Data State */}
{!isLoading && !error && bounties?.map((bounty) => (
<Link
key={bounty.id}
href={`/bounties/${bounty.id}`}
Expand Down
7 changes: 5 additions & 2 deletions frontend/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Metadata } from 'next'
import { Space_Grotesk } from 'next/font/google'
import './globals.css'
import Navbar from '@/components/Navbar'
import QueryProvider from '@/providers/QueryProvider'

const spaceGrotesk = Space_Grotesk({
subsets: ['latin'],
Expand Down Expand Up @@ -32,8 +33,10 @@ export default function RootLayout({
return (
<html lang="en" className={spaceGrotesk.variable}>
<body className={`${spaceGrotesk.className} antialiased`}>
<Navbar />
{children}
<QueryProvider>
<Navbar />
{children}
</QueryProvider>
</body>
</html>
)
Expand Down
22 changes: 22 additions & 0 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const nextJest = require('next/jest');

const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});

// Add any custom config to be passed to Jest
const customJestConfig = {
testTimeout: 10000,
testEnvironmentOptions: {
customExportConditions: [''],
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
14 changes: 14 additions & 0 deletions frontend/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '@testing-library/jest-dom';

// Mock next/navigation
jest.mock('next/navigation', () => ({
useRouter: () => ({
push: jest.fn(),
replace: jest.fn(),
prefetch: jest.fn(),
}),
useParams: () => ({}),
useSearchParams: () => ({
get: jest.fn(),
}),
}));
27 changes: 27 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,35 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
"dependencies": {
"@fontsource/space-grotesk": "^5.1.1",
"@next/font": "^14.2.15",
"@tabler/icons-react": "^3.29.0",
"@tanstack/react-query": "^5.66.0",
"next": "14.1.0",
"nillion-sv-wrappers": "^1.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"zod": "^3.24.1"
},
"devDependencies": {
"@tanstack/react-query-devtools": "^5.66.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.11.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"autoprefixer": "^10.4.17",
"eslint": "^8.56.0",
"eslint-config-next": "14.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3"
Expand Down
Loading