Skip to content

Commit

Permalink
fix: merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
Praashh committed Oct 9, 2024
2 parents a1a45bc + c82961d commit 1c6c57d
Show file tree
Hide file tree
Showing 18 changed files with 231 additions and 70 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/client.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Deploy Client

on:
push:
paths:
- "apps/client/**"
- "packages/db/**"
- "packages/order-queue/**"
branches:
- master

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: SSH and deploy
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
echo "$SSH_PRIVATE_KEY" > keyfile
chmod 600 keyfile
ssh -o StrictHostKeyChecking=no -t -i keyfile [email protected] "sudo bash /home/ubuntu/offchain-orderbook/apps/client/deploy.sh"
26 changes: 26 additions & 0 deletions .github/workflows/server.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Deploy Express Backend

on:
push:
paths:
- "apps/server/**"
- "packages/db/**"
- "packages/order-queue/**"
branches:
- master

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: SSH and deploy
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
echo "$SSH_PRIVATE_KEY" > keyfile
chmod 600 keyfile
ssh -o StrictHostKeyChecking=no -t -i keyfile [email protected] "sudo bash /home/ubuntu/offchain-orderbook/apps/server/deploy.sh"
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This project is a real-time opinion trading platform where users can place bets
- [Components:](#components)
- [Current Features](#current-features)
- [Future Steps](#future-steps)
- [](#)

---

Expand Down Expand Up @@ -66,16 +67,15 @@ The system is designed to handle real-time updates and asynchronous order proces
## Future Steps


1. **Order Queuing:**
- A Redis-backed queue system will be introduced for handling order submissions and matching efficiently.

2. **Payment Integration:**
- Add Stripe or Razorpay to enable secure and seamless payments within the platform.
1. **Payment Integration:**
- Add Stripe, Juspay or Razorpay to enable secure and seamless payments within the platform.

3. **Authentication:**
- Implement user authentication using NextAuth.js to allow users to create accounts and manage their portfolios securely.

4. **Worker-based Architecture:**
2. **Worker-based Architecture:**
- A worker system handles adding and matching orders in the order book, ensuring smooth operation and avoiding race conditions.

**Working on this architecture**

![User Diagram](https://utfs.io/f/40G0kRMDo8Ybl88nziDdG6QCSrVvFodOTgceNxm81943jJbA)
---
20 changes: 20 additions & 0 deletions apps/client/actions/Payout/Recharge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use server";
import prisma from "@repo/db/client"
import { error } from "console";

export const DepositeMoneyInWallet = async (userId: string, amount: number) => {
try {
Expand All @@ -22,3 +23,22 @@ export const DepositeMoneyInWallet = async (userId: string, amount: number) => {
return { success: false, message: "Error while depositing money." };
}
};

export async function getBalance(userId :string){
try {
const user = await prisma.user.findUnique({
where: {
id: userId,
},
});
if (!user) {
return error("no user found")
}
return user.balance


} catch (e) {
console.error("Error fetching money:", e);

}
}
19 changes: 10 additions & 9 deletions apps/client/app/(lobby)/event/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
"use client"
"use client";

import OrderBook from '@/components/landing/Orderbook';
import { useParams } from 'next/navigation'
import OrderBook from "@/components/landing/Orderbook";
import { useParams } from "next/navigation";
/*
TODO:
1. server actiosn to fetch the event from the event id (not sure but for now).
2. Add sources of truth.
3. Add event details like name and all.
*/
export default function Page() {
const {id} = useParams()
const { id } = useParams();
console.log(id);
const eventId = Array.isArray(id) ? id[id.length - 1] : id;


if (!eventId) {
return <div>Error: Event ID not found</div>;
}
return <div>
<OrderBook eventId = {eventId}/>
</div>
}
return (
<div>
<OrderBook eventId={eventId} />
</div>
);
}
47 changes: 31 additions & 16 deletions apps/client/app/(lobby)/portfolio/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"use client";
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { useSession } from "next-auth/react";
import { redirect } from "next/navigation";
import { getTrades } from "@/actions/Trade/getTrades";
import Portfolio from "../../../components/landing/Portfolio";
import { getEventDetails } from "@/actions/Event/getEventDetails";
import axios from "axios";
import { toast, Toaster } from "react-hot-toast";

export interface Trade {
id: string;
createdAt: Date;
Expand All @@ -16,7 +18,7 @@ export interface Trade {
side: "YES" | "NO";
title?: string;
gainloss: number | null;
status : "ACTIVE"|"PAST"
status: "ACTIVE" | "PAST";
}
export interface Portfolio {
id: string;
Expand All @@ -30,6 +32,7 @@ const Page = () => {
const [loading, setLoading] = useState<boolean>(true);
const [portfolioData, setPortfolioData] = useState<Portfolio | null>(null);
const [tradesWithTitles, setTradesWithTitles] = useState<Trade[]>([]);

const { data } = useSession();
console.log(data?.user);

Expand All @@ -38,32 +41,43 @@ const Page = () => {
redirect("/api/auth/signin");
}
}, [data?.user]);
const userId = "cm1r277l500178uzhh6kiewxa"; //data?.user.id;
const userId = data?.user.id;

useEffect(() => {
if (userId) {
getPortfolioDetails(userId);
}
}, [userId]);

async function getPortfolioDetails(userId: string) {
const { status } = useSession();

const getPortfolioDetails = useCallback(async (userId: string) => {
setLoading(true);
try {
const portfolio = await getTrades(userId);
console.log(portfolio);
console.log("portfolio", portfolio);

setPortfolioData(portfolio);
if (!portfolio) {
return;
if (portfolio) {
const updatedTrades = await fetchTitles(portfolio.trades);
setTradesWithTitles(updatedTrades);
}
const updatedTrades = await fetchTitles(portfolio.trades);
setTradesWithTitles(updatedTrades);
} catch (e) {
console.log("Error fetching portfolio", e);
} finally {
setLoading(false);
}
}
}, []);

useEffect(() => {
if (status === "unauthenticated") {
redirect("/api/auth/signin");
}
if (status === "authenticated" && userId) {
getPortfolioDetails(userId);
}
}, [status, userId, getPortfolioDetails]);

async function fetchTitles(trades: Trade[]) {
const titles = await Promise.all(
trades.map(async (trade) => {
Expand All @@ -84,7 +98,7 @@ const Page = () => {
);
if (tradeToSell) {
const response = await axios.post(
"http://localhost:3001/v1/order/sell-order",
`${process.env.NEXT_PUBLIC_API_PREFIX_URL}/v1/order/sell-order`,
{
tradeId: tradeToSell.id,
eventId: tradeToSell.eventId,
Expand All @@ -93,13 +107,13 @@ const Page = () => {
side: tradeToSell.side == "YES" ? "yes" : "no",
}
);
window.alert(response.data.message || "Order sold successfully!");
toast.success(response.data.message || "Order sold successfully!");
} else {
window.alert("Trade not found.");
toast.error("Trade not found.");
}
} catch (error) {
console.error("Error selling order", error);
window.alert("Failed to sell order.");
toast.error("Failed to sell order.");
}
}
};
Expand All @@ -122,10 +136,11 @@ const Page = () => {
price: trade.price,
quantity: trade.quantity,
type: trade.side,
gainloss : trade.gainloss,
status :trade.status
gainloss: trade.gainloss,
status: trade.status,
}))}
/>
<Toaster position="top-center" />
</div>
);
};
Expand Down
14 changes: 11 additions & 3 deletions apps/client/components/landing/Appbar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
"use client";
import Link from "next/link";
import React from "react";
import React, { useEffect, useState } from "react";
import { NavigationMenu } from "./Navmenu";
import ProfileHeader from "./ProfileHeader";
import { Wallet } from "lucide-react";
import { useSession } from "next-auth/react";
import { getBalance } from "@/actions/Payout/Recharge";

interface navMenutItemType {
title: string;
link: string;
}

export default function Appbar() {
const[balance,setBalance] = useState(0);
const { data } = useSession();

useEffect(() => {
if (data?.user.id) {
const bal = getBalance(data?.user.id);
// @ts-expect-error promise <nmber></nmber>
setBalance(bal);
}
}, [data?.user.id]);
const navMenutItem: Array<navMenutItemType> = [
{ title: "Events", link: "/event" },
{ title: "Portfolio", link: "/portfolio" },
Expand Down Expand Up @@ -43,7 +51,7 @@ export default function Appbar() {
<div className="flex gap-3 items-center">
<button className="bg-gray-800 text-white border-gray-700 hover:bg-gray-700 hover:text-white border rounded pr-4 pf-4 pt-2 pb-2 flex items-center space-x-2">
<Wallet className="h-5 w-5 ml-3" />
<span className="font-mono">{data?.user.balance}</span>
<span className="font-mono"> {balance}</span>
</button>
<ProfileHeader />
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/client/components/landing/DepositForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const DepositForm = () => {

async function handleRechageClick(){
if(!data?.user)redirect("/api/auth/signin");
const userid = "cm1r277l500178uzhh6kiewxa"//data.user.id;
const userid = data.user.id;
const isRechargeDone = await DepositeMoneyInWallet(userid!, depositAmount);
if(isRechargeDone?.success){
toast.success("Recharge Success");
Expand Down
18 changes: 12 additions & 6 deletions apps/client/components/landing/Orderbook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import LineChart from "../ui/line-chart";
import { getEventDetails } from "@/actions/Event/getEventDetails";
import { ArrowUpDown } from "lucide-react";

import { useSession } from "next-auth/react";

import {toast, Toaster} from "react-hot-toast"



interface OrderBookItem {
id: string;
Expand All @@ -41,6 +46,7 @@ interface OrderBookProps {
}

export default function OrderBook({ eventId }: OrderBookProps) {
const {data} = useSession();
const [orderBookData, setOrderBookData] = useState<OrderBookData | null>(
null
);
Expand Down Expand Up @@ -77,12 +83,12 @@ export default function OrderBook({ eventId }: OrderBookProps) {
}
}
fetchInitialData();

}, [eventId]);

useEffect(() => {
const ws = new WebSocket("ws://localhost:3001");
ws.onopen = () => {
console.log("Connected to server");
ws.send(JSON.stringify({ eventId }));
};
ws.onmessage = (event: MessageEvent) => {
Expand All @@ -107,20 +113,19 @@ export default function OrderBook({ eventId }: OrderBookProps) {
};
async function handleTrade() {
const response = await axios.post(
"http://localhost:3001/v1/order/place-order",
`${process.env.NEXT_PUBLIC_API_PREFIX_URL}/v1/order/place-order`,
{
userId: "cm1r277l500178uzhh6kiewxa",
userId: data?.user.id,
eventId : eventId,
side: side,
quantity: tradeQuantity,
price: tradePrice,
}
);
console.log(response);
if(response.status === 200){
window.alert("Order placed successfully!")
toast.success("Order placed successfully!")
}else{
window.alert("Error placing order!")
toast.error("Error placing order!")
}
}

Expand Down Expand Up @@ -348,6 +353,7 @@ export default function OrderBook({ eventId }: OrderBookProps) {
<p className="text-gray-300">{description}</p>
</CardContent>
</Card>
<Toaster position="top-center"/>
</div>
);
}
8 changes: 8 additions & 0 deletions apps/client/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
export PATH=$PATH:/home/ubuntu/.nvm/versions/node/v18.20.4/bin

cd /home/ubuntu/offchain-orderbook
git pull origin master
npm run build
pm2 stop client
pm2 start npm --name "client" -- run "start:client"
Loading

0 comments on commit 1c6c57d

Please sign in to comment.