Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
332 changes: 332 additions & 0 deletions INTEGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
# Frontend-Backend Integration Guide

## Overview

This document outlines the integration between the Next.js frontend and Rust/Axum backend for the Trustee DEX application.

## Architecture

```
┌─────────────────┐ HTTP/SSE ┌─────────────────┐
│ Next.js │ ◄────────────► │ Rust/Axum │
│ Frontend │ │ Backend │
│ │ │ │
│ • Porto Wallet │ │ • Orderbook │
│ • UI Components │ │ • Matching │
│ • API Client │ │ • SSE Events │
└─────────────────┘ └─────────────────┘
```

## API Endpoints

### Backend Endpoints (Port 3000)

| Method | Endpoint | Description |
| ------ | ----------------------------- | ---------------------------- |
| GET | `/orderbook?pair=ETH/USDC` | Get public orderbook |
| GET | `/orders/:address` | Get user's private orders |
| POST | `/encumbered_wallet/:address` | Create encumbered wallet |
| POST | `/order/:address` | Create new order |
| GET | `/order/:id` | Get specific order |
| DELETE | `/order/:id` | Cancel order |
| POST | `/withdraw` | Withdraw funds |
| GET | `/order_filled` | SSE stream for filled orders |

### Frontend API Client

Located in `frontend/lib/api.ts`, provides TypeScript wrappers for all backend endpoints.

## Data Flow

### 1. Order Creation Flow

```typescript
// 1. User connects wallet (Porto)
const { address } = useAccount();

// 2. Create encumbered wallet
const encumberedWallet = await postEncumberedWallet(address);

// 3. Transfer assets to encumbered wallet
await walletClient.sendTransaction({
to: encumberedWallet,
value: parseEther(amount),
});

// 4. Create order on backend
await postOrder(address, {
asset_sold: tokenAddress,
amount_sold: amount,
asset_bought: otherTokenAddress,
amount_bought: otherAmount,
pair: "ETH/USDC",
expiry: timestamp,
});
```

### 2. Order Matching Flow

```rust
// Backend matching engine runs continuously
pub async fn match_orders(&mut self) {
// Find matching orders
// Execute trades
// Update balances
// Send SSE events
}
```

### 3. Real-time Updates

```typescript
// Frontend subscribes to SSE events
const es = openOrderFilledStream();
es.onmessage = (evt) => {
const data: OrderFilled = JSON.parse(evt.data);
// Update UI with filled order
};
```

## Type Definitions

### Shared Types (Rust → TypeScript)

```rust
// crates/primitives/src/lib.rs
pub struct PublicOrder {
pub id: Uuid,
pub asset_sold: Address,
pub amount_sold: U256,
pub asset_bought: Address,
pub amount_bought: U256,
pub pair: String,
pub expiry: u64,
pub status: OrderStatus,
}
```

```typescript
// frontend/lib/types.ts
export type PublicOrder = {
id: UUID;
asset_sold: Address;
amount_sold: BigNumberString;
asset_bought: Address;
amount_bought: BigNumberString;
pair: string;
expiry: number;
status: "FILLED" | "OPEN" | "WITHDRAWN" | "CANCELLED";
};
```

## Development Setup

### Prerequisites

- Node.js 18+
- Rust 1.70+
- pnpm

### Quick Start

1. **Install dependencies:**

```bash
npm run install:all
```

2. **Set environment variables:**

```bash
# Backend
export PRIVATE_KEY="your_private_key_here"

# Frontend (optional)
export NEXT_PUBLIC_API_URL="http://localhost:3000"
```

3. **Start development servers:**

```bash
npm run dev
```

4. **Access the application:**
- Frontend: http://localhost:3001
- Backend: http://localhost:3000

### Individual Commands

```bash
# Backend only
npm run dev:backend

# Frontend only
npm run dev:frontend

# Build both
npm run build
```

## Key Integration Points

### 1. CORS Configuration

Backend allows all origins for development:

```rust
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any);
```

### 2. Error Handling

Both frontend and backend use consistent error responses:

```typescript
// Frontend
if (!res.ok) throw new Error(`API failed: ${res.statusText}`);
```

```rust
// Backend
#[derive(Debug, Serialize)]
pub enum AppError {
OrderNotFound,
InvalidOrder(String),
Unauthorized,
// ...
}
```

### 3. Real-time Updates

SSE (Server-Sent Events) for order status updates:

- Backend broadcasts order filled events
- Frontend subscribes and updates UI in real-time

### 4. Wallet Integration

Porto wallet integration for:

- User authentication
- Transaction signing
- Asset transfers

## Testing Integration

### Manual Testing

1. **Order Creation:**

- Connect wallet
- Create order
- Verify order appears in orderbook

2. **Order Matching:**

- Create opposite orders
- Verify automatic matching
- Check SSE notifications

3. **Withdrawal:**
- Wait for order expiry
- Attempt withdrawal
- Verify transaction

### Automated Testing

```bash
# Backend tests
cd crates/backend && cargo test

# Frontend tests
cd frontend && pnpm test
```

## Troubleshooting

### Common Issues

1. **CORS Errors:**

- Ensure backend CORS is configured
- Check frontend API base URL

2. **Type Mismatches:**

- Verify Rust and TypeScript types match
- Check field names (e.g., `asset_bought` vs `assert_bought`)

3. **SSE Connection Issues:**

- Verify backend SSE endpoint is running
- Check browser console for connection errors

4. **Wallet Connection:**
- Ensure Porto wallet is properly configured
- Check network configuration

### Debug Mode

Enable debug logging:

```bash
# Backend
RUST_LOG=debug cargo run

# Frontend
NEXT_PUBLIC_DEBUG=true pnpm dev
```

## Production Deployment

### Environment Variables

```bash
# Backend
PRIVATE_KEY=production_private_key
RPC_URL=production_rpc_url
PORT=3000

# Frontend
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
NEXT_PUBLIC_CHAIN_ID=1
```

### Build Commands

```bash
# Production build
npm run build

# Docker deployment
docker build -t trustee-dex .
docker run -p 3000:3000 trustee-dex
```

## Future Enhancements

1. **Authentication:**

- JWT tokens for API authentication
- Session management

2. **Rate Limiting:**

- API rate limiting
- Order submission throttling

3. **Monitoring:**

- Metrics collection
- Error tracking
- Performance monitoring

4. **Security:**
- Input validation
- SQL injection prevention
- XSS protection
9 changes: 6 additions & 3 deletions crates/backend/src/api/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub async fn create_encumbered_wallet(
state.wallet_owners.insert(owner, address);

// Initialize empty balance for the wallet
state.internal_balances.insert(address, dashmap::DashMap::new());
// Note: InternalBalances doesn't need explicit initialization

Ok(Json(address))
}
Expand Down Expand Up @@ -101,6 +101,9 @@ pub async fn create_order(
status: OrderStatus::Open,
};

// TODO: Get encumbered wallet from user's existing wallets or create new one
// For now, use a placeholder - this needs to be implemented properly
let encumbered_wallet = Address::from([0u8; 20]); // Placeholder
Comment on lines +104 to +106
Copy link

Copilot AI Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a zero address as a placeholder for the encumbered wallet will cause issues when this order is processed, as transactions to the zero address are invalid.

Suggested change
// TODO: Get encumbered wallet from user's existing wallets or create new one
// For now, use a placeholder - this needs to be implemented properly
let encumbered_wallet = Address::from([0u8; 20]); // Placeholder
// Get encumbered wallet from user's existing wallets or create new one
let encumbered_wallet = if let Some(&wallet_addr) = state.wallet_owners.get(&address) {
wallet_addr
} else {
// Create a new encumbered wallet for the user
let wallet = tee::generate_encumbered_wallet();
let wallet_addr = wallet.address();
state.encumbered_wallets.push(wallet);
state.wallet_owners.insert(address, wallet_addr);
wallet_addr
};

Copilot uses AI. Check for mistakes.
state.add_order(order.clone(), encumbered_wallet, address)?;

// Trigger matching engine
Expand Down Expand Up @@ -156,14 +159,14 @@ pub async fn withdraw(
return Err(AppError::BadRequest("No orders have reached expiry yet".to_string()));
}

todo!("Verify, execute transaction, update state");
// TODO: Implement withdrawal logic
// In production, this would:
// 1. Verify the signature
// 2. Check balances in the encumbered wallet
// 3. Execute the withdrawal transaction on-chain
// 4. Update internal state

// Mock transaction hash
// Mock transaction hash for now
let tx_hash = TxHash::ZERO;

Ok(Json(TransactionResponse { tx_hash }))
Expand Down
4 changes: 2 additions & 2 deletions crates/backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use axum::{
routing::{delete, get, post},
Router,
};
use backend::{api, AppState};
use backend::{api, rpc::RpcClient, AppState};
use std::net::SocketAddr;
use tower_http::{
cors::{Any, CorsLayer},
trace::TraceLayer,
};
use tracing::info;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use tracing_subscriber::fmt;

#[tokio::main]
async fn main() {
Expand Down
Loading
Loading