Skip to content

Added Transactions model, Locking Mechanism #7

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
98 changes: 94 additions & 4 deletions apps/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import express from "express"
import { authMiddleware } from "./middleware";
import { prismaClient } from "db/client";
import {Prisma} from "db/client";
import cors from "cors";
import { Transaction, SystemProgram, Connection } from "@solana/web3.js";

import { Transaction, SystemProgram, Connection, Keypair, PublicKey, sendAndConfirmTransaction } from "@solana/web3.js";
const privateKey=process.env.PRIVATE_KEY;

const connection = new Connection("https://api.mainnet-beta.solana.com");
const app = express();
Expand Down Expand Up @@ -42,7 +43,9 @@ app.get("/api/v1/website/status", authMiddleware, async (req, res) => {
}
})

res.json(data)
res.json({
data
});

})

Expand Down Expand Up @@ -84,7 +87,94 @@ app.delete("/api/v1/website/", authMiddleware, async (req, res) => {
})

app.post("/api/v1/payout/:validatorId", async (req, res) => {

const validatorId=req.params.validatorId;

const txn=await prismaClient.$transaction(async (prisma)=>{
const validator=await prisma.validator.findUnique({
where:{
id: validatorId
},
select:{
id: true,
pendingPayouts: true,
publicKey: true,
lockedAt: true
}
})

if (!validator){
res.status(404).json({
message: "Validator not found"
});
return;
}

if (validator.lockedAt){
res.json({
message: "Payout is still in process"
});
return;
}

if (validator.pendingPayouts===0){
res.json({
message: "No payout left"
});
return;
}

await prisma.validator.update({
where:{
id: validatorId
},
data:{
lockedAt: new Date()
}
});
return validator;
});
if (!txn) return;

try{
const fromKeypair=Keypair.fromSecretKey(Uint8Array.from(JSON.parse(privateKey!)));
const toPublicKey= new PublicKey(txn.publicKey);
const amount=txn.pendingPayouts * 1000000;

const transaction=new Transaction().add(
SystemProgram.transfer({
fromPubkey: fromKeypair.publicKey,
toPubkey: toPublicKey,
lamports: amount
})
);

const signature=await sendAndConfirmTransaction(connection, transaction, [fromKeypair]);
await prismaClient.validator.update({
where:{id: validatorId},
data:{
pendingPayouts: 0,
isPaidOut: true,
lockedAt: null,
transactions:{
create:{
amount: amount,
signature: signature,
createdAt: new Date
} as Prisma.TransactionsCreateWithoutValidatorInput
}
}
});

res.json({
message: "Payout Successful with signature: ", signature
})
}catch(e){
console.log("Error processing payout", e);
res.status(500).json({
messsage: "Error processing payout"
});
}

})

app.listen(8080);
25 changes: 15 additions & 10 deletions apps/api/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import { JWT_PUBLIC_KEY } from "./config";
export function authMiddleware(req: Request, res: Response, next: NextFunction) {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
res.status(401).json({ error: 'Unauthorized' });
return;
}

const decoded = jwt.verify(token, JWT_PUBLIC_KEY);
console.log(decoded);
if (!decoded || !decoded.sub) {
return res.status(401).json({ error: 'Unauthorized' });
try{
const decoded = jwt.verify(token, JWT_PUBLIC_KEY);
console.log(decoded);
if (!decoded || !decoded.sub) {
res.status(401).json({ error: 'Unauthorized' });
return;
}
req.userId = decoded.sub as string;
next();
}catch(e){
res.status(401).json({
error: 'Invalid Token'
})
}

req.userId = decoded.sub as string;

next()
}
1 change: 0 additions & 1 deletion apps/api/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

declare namespace Express {
interface Request {
userId?: string
Expand Down
3 changes: 3 additions & 0 deletions apps/frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# clerk configuration (can include secrets)
/.clerk/
4 changes: 1 addition & 3 deletions apps/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,4 @@ async function signMessage(message: string, keypair: Keypair) {

main();

setInterval(async () => {

}, 10000);
setInterval(async () => {}, 10000);
3 changes: 3 additions & 0 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"packages/db": {
"name": "db",
"dependencies": {
"@prisma/client": "6.5.0",
"prisma": "^6.5.0",
},
"devDependencies": {
Expand Down Expand Up @@ -327,6 +328,8 @@

"@nolyfill/is-core-module": ["@nolyfill/[email protected]", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],

"@prisma/client": ["@prisma/[email protected]", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-M6w1Ql/BeiGoZmhMdAZUXHu5sz5HubyVcKukbLs3l0ELcQb8hTUJxtGEChhv4SVJ0QJlwtLnwOLgIRQhpsm9dw=="],

"@prisma/config": ["@prisma/[email protected]", "", { "dependencies": { "esbuild": ">=0.12 <1", "esbuild-register": "3.6.0" } }, "sha512-sOH/2Go9Zer67DNFLZk6pYOHj+rumSb0VILgltkoxOjYnlLqUpHPAN826vnx8HigqnOCxj9LRhT6U7uLiIIWgw=="],

"@prisma/debug": ["@prisma/[email protected]", "", {}, "sha512-fc/nusYBlJMzDmDepdUtH9aBsJrda2JNErP9AzuHbgUEQY0/9zQYZdNlXmKoIWENtio+qarPNe/+DQtrX5kMcQ=="],
Expand Down
1 change: 1 addition & 0 deletions packages/db/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"typescript": "^5.0.0"
},
"dependencies": {
"@prisma/client": "6.5.0",
"prisma": "^6.5.0"
},
"prisma": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- AlterTable
ALTER TABLE "Validator" ADD COLUMN "isPaidOut" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "lockedAt" TIMESTAMP(3);

-- CreateTable
CREATE TABLE "Transactions" (
"id" TEXT NOT NULL,
"amount" INTEGER NOT NULL,
"signature" TEXT NOT NULL,
"validatorId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "Transactions_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
ALTER TABLE "Transactions" ADD CONSTRAINT "Transactions_validatorId_fkey" FOREIGN KEY ("validatorId") REFERENCES "Validator"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
42 changes: 27 additions & 15 deletions packages/db/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,48 @@ datasource db {
}

model User {
id String @id @default(uuid())
id String @id @default(uuid())
email String
}

model Website {
id String @id @default(uuid())
url String
userId String
ticks WebsiteTick[]
disabled Boolean @default(false)
id String @id @default(uuid())
url String
userId String
ticks WebsiteTick[]
disabled Boolean @default(false)
}

model Validator {
id String @id @default(uuid())
publicKey String
location String
ip String
pendingPayouts Int @default(0)
ticks WebsiteTick[]
id String @id @default(uuid())
publicKey String
location String
ip String
pendingPayouts Int @default(0)
ticks WebsiteTick[]
transactions Transactions[]
isPaidOut Boolean @default(false)
lockedAt DateTime?
}

model WebsiteTick {
id String @id @default(uuid())
id String @id @default(uuid())
websiteId String
validatorId String
createdAt DateTime
status WebsiteStatus
latency Float
website Website @relation(fields: [websiteId], references: [id])
validator Validator @relation(fields: [validatorId], references: [id])
website Website @relation(fields: [websiteId], references: [id])
validator Validator @relation(fields: [validatorId], references: [id])
}

model Transactions{
id String @id @default(uuid())
amount Int
signature String
validatorId String
validator Validator @relation(fields: [validatorId], references: [id])
createdAt DateTime
}

enum WebsiteStatus {
Expand Down
3 changes: 1 addition & 2 deletions packages/db/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { PrismaClient } from "@prisma/client"
export { Prisma } from "@prisma/client"

export const prismaClient = new PrismaClient()