Skip to content

Commit

Permalink
Merge branch 'develop' into feat/user-dashboard-page
Browse files Browse the repository at this point in the history
  • Loading branch information
evgongora authored Feb 2, 2025
2 parents 859bd0e + 295b720 commit 7771bb7
Show file tree
Hide file tree
Showing 18 changed files with 961 additions and 110 deletions.
215 changes: 215 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
You are an expert developer in TypeScript, Node.js, Next.js 15 App Router, React, Supabase, GraphQL, Genql, DrizzleORM, HuggingFace Models, Tailwind CSS, Radix UI, and Shadcn UI.

---

## Coding Philosophy

Our coding philosophy revolves around writing **semantic, idiomatic, functional, and declarative code**. Follow these key principles:

- **Modern JavaScript & TypeScript:**
Leverage the latest features for expressive, maintainable code with an emphasis on TypeScript's type safety.
- **Declarative React:**
Describe UI structure and state, avoiding imperative code.
- **Readable Naming:**
Use self-explanatory names for variables, functions, and components.
- **Single Responsibility Principle:**
Keep components focused and reusable.
- **Favor Composition Over Inheritance:**
Build components and functions that promote modularity and reusability.
- **File Organization:**
Structure code logically, keeping readability and scalability in mind.
- **Utility-First Styling:**
Use TailwindCSS for rapid and consistent UI development.

---

## General Conventions

- **Project Structure:**

- Organize components in a well-structured manner.
- Separate concerns with clear folder structures.
- Follow monorepo best practices (`apps/`, `packages/`,`services/`, `config/`).

- **Filenames:**

- Use lowercase with dash separators (e.g., `auth-wizard.tsx`).
- File extensions should indicate file types (e.g., `.config.ts`, `.test.ts`, `.hook.tsx`).

- **Exporting:**
- Prefer named exports over default exports.

---

## JavaScript/TypeScript Best Practices

- **Naming Variables:**

- Use meaningful names that reflect purpose.
- Prefix booleans with auxiliary verbs (e.g., `isLoading`, `hasPermission`).

- **Functional Programming:**

- Prefer `function` declarations for components.
- Use the RORO (Receive an Object, Return an Object) pattern.

- **TypeScript Usage:**
- Use `interface` for objects and class definitions.
- Use `type` for unions, tuples, and aliases.
- Avoid `any`; prefer explicit types and inference when possible.
- Use `as` for type assertions when necessary.
- Explicitly annotate function parameters and return types.

---

## React/Next.js Conventions

- **Component Declaration Order:**

1. Imports
2. Component declaration
3. Styled components (if any)
4. TypeScript types and interfaces

- **Component Structure:**

- Small, focused components following single responsibility.
- Use hooks for state management; avoid unnecessary re-renders.
- Follow the `use client` directive judiciously.

- **State Management & Fetching:**

- Prefer React Server Components (RSC) for data-heavy operations.
- Use `next-safe-action` for secure server actions.
- Leverage Supabase for real-time data synchronization.

- **Performance Optimization:**
- Lazy load non-critical components.
- Use Suspense with fallbacks for client-side components.
- Optimize image loading with `next/image`.

---

## AI SDK Integration (Vercel AI SDK)

- Use **Vercel AI SDK UI** for chat interfaces.
- Use **Vercel AI SDK Core** for model interactions.
- Handle rate limits and fallback gracefully.
- Sanitize user inputs before sending to models.
- Store API keys securely using environment variables.

---

## HuggingFace Models

- Use `@huggingface/inference` for model interactions.
- Cache frequent model responses to reduce latency.
- Handle model switching and errors gracefully.
- Optimize queries for efficient token usage.

---

## DrizzleORM Best Practices

- Use DrizzleORM for database interactions with Supabase.
- Leverage migrations for schema evolution.
- Follow the repository pattern to encapsulate database logic.
- Optimize queries with proper indexing.
- Adhere to Supabase RLS policies.

---

## Supabase & GraphQL Guidelines

- Use Genql for type-safe GraphQL queries.
- Follow Supabase best practices for authentication and authorization.
- Implement efficient data fetching by requesting only required fields.

---

## Naming Conventions

- **Booleans:** Prefix with `does`, `has`, `is`, `should` (e.g., `isValid`, `hasError`).
- **Files:** Use lowercase with dash separators (e.g., `project-detail.tsx`).
- **Extensions:** Follow the convention:
- `.config.ts` for configurations
- `.test.ts` for tests
- `.context.tsx` for context files
- `.type.ts` for types
- `.hook.ts` for hooks

---

## Styling with Tailwind CSS

- Follow utility-first principles.
- Use CVA (Class Variance Authority) for managing component variants.
- Maintain a mobile-first responsive approach.

---

## Testing Guidelines

- **Unit Tests:** Use Jest for utility functions and hooks.
- **Integration Tests:** Validate component interactions.
- **End-to-End Tests:** Use Cypress for key user flows.
- Ensure code coverage meets project standards.

---

## Accessibility Guidelines

- Ensure all interactive elements are keyboard accessible.
- Use ARIA roles and attributes for screen readers.
- Maintain WCAG compliance for color contrast and readability.

---

## Documentation Standards

- Provide clear and concise comments for complex logic.
- Use JSDoc comments to improve IDE intellisense.
- Maintain up-to-date README files with setup instructions.
- Document Supabase schemas and edge functions where applicable.

---

## Key Conventions

1. Rely on Next.js App Router for routing and state changes.
2. Prioritize Web Vitals (LCP, CLS, FID) for performance.
3. Use a monorepo structure with shared code in `packages/` and app-specific code in `apps/`.
4. Use Taskfile for automation of development and deployment workflows.
5. Adhere to the defined database schema with enum tables for predefined values.

---

## Security Practices

- Store sensitive data in environment variables.
- Validate all incoming API requests for security compliance.
- Implement Role-Based Access Control (RBAC) using Supabase policies.
- Set security headers (CSP, HSTS, etc.) using Next.js config
- Implement rate limiting for API routes
- Use prepared statements for database queries
- Enable audit logging for sensitive operations
- Implement session management best practices
- Regular security dependency updates

---

## Performance Optimization

- Minimize client-side dependencies.
- Use streaming and suspense features in Next.js.
- Leverage Incremental Static Regeneration (ISR) where applicable.
- Optimize bundle size using code splitting.

---

Refer to the official documentation for best practices in:

- **Next.js** (Data Fetching, Routing, Rendering)
- **Vercel AI SDK** (AI Integration)
- **Supabase** (Database and Authentication)
- **TailwindCSS** (Styling)
8 changes: 7 additions & 1 deletion apps/web/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@
# Update these with your Supabase details from your project settings > API
# https://app.supabase.com/project/_/settings/api
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=supabase-service-key
STELLAR_NETWORK_URL=stellar-network-url



128 changes: 128 additions & 0 deletions apps/web/app/api/escrow/initialize/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { createClient } from "@supabase/supabase-js";
import { validateEscrowInitialization } from "~/lib/validators/escrow";
import { initializeEscrowContract } from "~/lib/stellar/escrow";
import type { EscrowInitialization } from "~/lib/types/escrow";
import { AppError } from "~/lib/errors";

const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);

export async function POST(req: NextRequest) {
try {
const initializationData: EscrowInitialization = await req.json();
const validationResult =
validateEscrowInitialization(initializationData);

if (!validationResult.success) {
return NextResponse.json(
{
error: "Invalid escrow initialization",
details: validationResult.errors
},
{ status: 400 }
);
}

const contractResult = await initializeEscrowContract(
initializationData.contractParams,
initializationData.contractParams.parties.payerSecretKey
);

if (!contractResult.success) {
return NextResponse.json(
{
error: "Failed to initialize escrow contract",
details: contractResult.error
},
{ status: 500 }
);
}

const { data: dbResult, error: dbError } = await supabase
.from("escrow_contracts")
.insert({
engagement_id: contractResult.engagementId,
contract_id: contractResult.contractAddress,
project_id: initializationData.metadata.projectId,
contribution_id: contractResult.contributionId,
payer_address: initializationData.contractParams.parties.payer,
receiver_address:
initializationData.contractParams.parties.receiver,
amount: contractResult.totalAmount,
platform_fee: initializationData.contractParams.platformFee,
current_state: "PENDING",
metadata: initializationData.metadata
})
.select("id")
.single();

if (dbError) {
return NextResponse.json(
{
error: "Failed to track escrow contract",
details: dbError
},
{ status: 500 }
);
}

// If successful, update the state to INITIALIZED
await supabase
.from("escrow_contracts")
.update({ current_state: "INITIALIZED" })
.eq("id", dbResult.id);

return NextResponse.json(
{
escrowId: dbResult.id,
contractAddress: contractResult.contractAddress,
status: "INITIALIZED"
},
{ status: 201 }
);
} catch (error) {
if (error instanceof AppError) {
console.error("Escrow initialization error:", error);
return NextResponse.json(
{
error: error.message,
details: error.details // Include additional details for troubleshooting
},
{ status: error.statusCode }
);
}

console.error("Internal server error during escrow initialization:", error);
return NextResponse.json(
{
error: "Internal server error during escrow initialization"
},
{ status: 500 }

);
}
}

const initializeEscrow = async (data: EscrowInitialization) => {
const response = await fetch("/api/escrow/initialize", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});

if (!response.ok) {
const error = await response.json();
throw {
error: error.error || "Failed to initialize escrow",
details: error.details || null
};
}

return response.json();
};
Loading

0 comments on commit 7771bb7

Please sign in to comment.