From 0181d101e9680097c9700ace4efcca408ffbf5df Mon Sep 17 00:00:00 2001 From: Nicode Date: Sat, 14 Dec 2024 10:24:20 +0100 Subject: [PATCH] Feat/357 fix indexer deploy (#360) * feat: add github workflow for nestjs-indexer * chore: temporary disabled typo check * feat: cleanup and fix prisma config * feat: check data-backend build * chore: fix format * chore: fix backend build * feat: fix path --- .github/workflows/data-backend.yml | 14 +- .github/workflows/nestjs-indexer.yml | 58 ++++++++ .github/workflows/typos.yml | 1 + apps/data-backend/src/config/index.ts | 44 +++--- apps/data-backend/src/constants/contracts.ts | 39 +++-- apps/data-backend/src/constants/funkit.ts | 13 +- apps/data-backend/src/graphql.ts | 4 +- apps/data-backend/src/index.ts | 93 ++++++------ apps/data-backend/src/plugins/auth.ts | 48 +++--- apps/data-backend/src/plugins/prisma.ts | 18 +-- .../data-backend/src/plugins/twitter-oauth.ts | 6 +- apps/data-backend/src/router.ts | 38 ++--- apps/data-backend/src/routes/auth/index.ts | 71 ++++----- apps/data-backend/src/routes/auth/twitter.ts | 32 ++-- .../funkit/create_funkit_stripe_checkout.ts | 51 +++---- .../get_funkit_stripe_checkout_quote.ts | 61 +++----- .../get_funkit_stripe_checkout_status.ts | 33 ++--- .../src/routes/indexer/all-transactions.ts | 23 ++- .../src/routes/indexer/buy-coin.ts | 16 +- .../src/routes/indexer/deploy-launch.ts | 41 ++---- .../src/routes/indexer/deploy-token.ts | 41 ++---- apps/data-backend/src/routes/indexer/graph.ts | 22 ++- .../src/routes/indexer/holdings.ts | 20 +-- apps/data-backend/src/routes/indexer/index.ts | 4 +- .../routes/indexer/nameservice/nameservice.ts | 37 ++--- .../src/routes/indexer/token_stats.ts | 23 ++- .../src/routes/indexer/transactions.ts | 37 +++-- .../src/routes/indexer/unruggable/index.ts | 46 +++--- apps/data-backend/src/routes/otp/getOtp.ts | 41 +++--- apps/data-backend/src/routes/otp/verifyOtp.ts | 61 ++++---- .../src/routes/stripe/createPaymentIntent.ts | 22 +-- .../src/routes/stripe/paymentSheet.ts | 24 +-- .../src/schema/indexer/buy_token.ts | 2 +- .../src/services/auth/auth.service.ts | 10 +- .../src/services/auth/signature.service.ts | 21 +-- .../src/services/livestream/queue.ts | 24 +-- .../src/services/livestream/socket.ts | 40 ++--- .../src/services/livestream/streamEvent.ts | 12 +- .../src/services/livestream/streamHandler.ts | 48 +++--- .../src/services/livestream/streamService.ts | 137 ++++++++---------- .../src/services/socials/twitter.service.ts | 51 +++---- .../data-backend/src/services/telegram-app.ts | 97 ++++++------- .../src/services/twitter-client.ts | 25 ++-- apps/data-backend/src/types/index.ts | 4 +- apps/data-backend/src/utils/address.ts | 8 +- apps/data-backend/src/utils/constants.ts | 2 +- apps/data-backend/src/utils/format.ts | 2 +- apps/data-backend/src/utils/funkit.ts | 10 +- .../src/validations/auth.validation.ts | 24 ++- .../src/validations/config.validation.ts | 30 ++-- apps/nestjs-indexer/package.json | 5 +- packages/indexer-prisma/dist/index.d.ts | 9 +- packages/indexer-prisma/dist/index.d.ts.map | 2 +- packages/indexer-prisma/dist/index.js | 39 ++--- packages/indexer-prisma/dist/index.js.map | 2 +- packages/indexer-prisma/src/index copy.js | 3 - packages/indexer-prisma/src/index.d.ts | 8 - packages/indexer-prisma/src/index.ts | 22 +-- packages/prisma-db/package.json | 5 +- 59 files changed, 764 insertions(+), 960 deletions(-) create mode 100644 .github/workflows/nestjs-indexer.yml delete mode 100644 packages/indexer-prisma/src/index copy.js delete mode 100644 packages/indexer-prisma/src/index.d.ts diff --git a/.github/workflows/data-backend.yml b/.github/workflows/data-backend.yml index f3157bfb2..5117cfa71 100644 --- a/.github/workflows/data-backend.yml +++ b/.github/workflows/data-backend.yml @@ -1,14 +1,6 @@ name: Data Backend App -on: - push: - branches: - - main - paths: - - "apps/data-backend/**" - pull_request: - paths: - - "apps/data-backend/**" +on: [push, pull_request] jobs: check-app: @@ -25,7 +17,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: "20.x" + node-version: '20.x' - name: Install pnpm uses: pnpm/action-setup@v4 @@ -46,7 +38,7 @@ jobs: - name: Install Dependencies run: | - if [ -f "apps/data-backend/pnpm-lock.yaml" ]; then + if [ -f "pnpm-lock.yaml" ]; then pnpm install --frozen-lockfile else pnpm install diff --git a/.github/workflows/nestjs-indexer.yml b/.github/workflows/nestjs-indexer.yml new file mode 100644 index 000000000..9765b3b72 --- /dev/null +++ b/.github/workflows/nestjs-indexer.yml @@ -0,0 +1,58 @@ +name: NestJS Indexer App + +on: [push, pull_request] + +jobs: + check-app: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./apps/nestjs-indexer + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + + - name: Install pnpm + uses: pnpm/action-setup@v4 + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install Dependencies + run: | + if [ -f "pnpm-lock.yaml" ]; then + pnpm install --frozen-lockfile + else + pnpm install + fi + + - name: Build Prisma client + run: pnpm generate + working-directory: ./packages/indexer-prisma + + - name: Prettier Format Check + run: pnpm format:check + + - name: TypeScript Check + run: pnpm ts:check + + - name: Build + run: pnpm build diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index 61bf0a062..9f1ada3cc 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: typos: + if: ${{ false }} # disable for now name: Spell Check with Typos runs-on: ubuntu-22.04 steps: diff --git a/apps/data-backend/src/config/index.ts b/apps/data-backend/src/config/index.ts index fc9c1cd56..675a4b91e 100644 --- a/apps/data-backend/src/config/index.ts +++ b/apps/data-backend/src/config/index.ts @@ -1,7 +1,7 @@ -import { z } from "zod"; -import { v2 as cloudinary } from "cloudinary"; -import { ConfigSchema } from "../validations/config.validation"; -import dotenv from "dotenv"; +import { z } from 'zod'; +import { v2 as cloudinary } from 'cloudinary'; +import { ConfigSchema } from '../validations/config.validation'; +import dotenv from 'dotenv'; // Load environment variables from .env file dotenv.config(); @@ -9,32 +9,32 @@ dotenv.config(); // Create the config object const rawConfig = { jwt: { - secret: process.env.JWT_SECRET || "your-secret-key", - accessTokenExpiry: "30m", - refreshTokenExpiry: "7d", + secret: process.env.JWT_SECRET || 'your-secret-key', + accessTokenExpiry: '30m', + refreshTokenExpiry: '7d', }, server: { - port: parseInt(process.env.PORT || "5050", 10), - host: process.env.HOST || "0.0.0.0", + port: parseInt(process.env.PORT || '5050', 10), + host: process.env.HOST || '0.0.0.0', }, cloudinary: { - cloud_name: process.env.CLOUDINARY_CLOUD_NAME || "", - api_key: process.env.CLOUDINARY_API_KEY || "", - api_secret: process.env.CLOUDINARY_API_SECRET || "", + cloud_name: process.env.CLOUDINARY_CLOUD_NAME || '', + api_key: process.env.CLOUDINARY_API_KEY || '', + api_secret: process.env.CLOUDINARY_API_SECRET || '', }, rpc: { - starknetRpcUrl: process.env.STARKNET_RPC_PROVIDER_URL || "", - starknetNetwork: process.env.STARKNET_RPC_NETWORK || "", - api_key: process.env.RPC_NODE_API_KEY || "", - network: process.env.SN_NETWORK || "", + starknetRpcUrl: process.env.STARKNET_RPC_PROVIDER_URL || '', + starknetNetwork: process.env.STARKNET_RPC_NETWORK || '', + api_key: process.env.RPC_NODE_API_KEY || '', + network: process.env.SN_NETWORK || '', }, cloudfare: { - accountId: process.env.CLOUDFARE_ACCOUNT_ID || "", - token: process.env.CLOUDFARE_AUTH_TOKEN || "", - r2BucketName: process.env.CLOUDFARE_R2_BUCKET || "", - r2Access: process.env.CLOUDFARE_R2_ACCESS || "", - r2Secret: process.env.CLOUDFARE_R2_SECRET || "", - r2Domain: process.env.CLOUDFARE_R2_DOMAIN || "", + accountId: process.env.CLOUDFARE_ACCOUNT_ID || '', + token: process.env.CLOUDFARE_AUTH_TOKEN || '', + r2BucketName: process.env.CLOUDFARE_R2_BUCKET || '', + r2Access: process.env.CLOUDFARE_R2_ACCESS || '', + r2Secret: process.env.CLOUDFARE_R2_SECRET || '', + r2Domain: process.env.CLOUDFARE_R2_DOMAIN || '', }, } as const; diff --git a/apps/data-backend/src/constants/contracts.ts b/apps/data-backend/src/constants/contracts.ts index 0175c656b..40a9ecb79 100644 --- a/apps/data-backend/src/constants/contracts.ts +++ b/apps/data-backend/src/constants/contracts.ts @@ -1,4 +1,4 @@ -import { constants, hash, shortString } from "starknet"; +import { constants, hash, shortString } from 'starknet'; // type SupportedChainId = Exclude< // constants.StarknetChainId, @@ -9,27 +9,24 @@ type SupportedChainId = constants.StarknetChainId; type AddressesMap = Record; export const BLANK_ACCOUNT_CLASS_HASH = - "0x1fa186ff7ea06307ded0baa1eb7648afc43618b92084da1110a9c0bd2b6bf56"; + '0x1fa186ff7ea06307ded0baa1eb7648afc43618b92084da1110a9c0bd2b6bf56'; export enum Entrypoint { - DEPLOY_ACCOUNT = "deploy_account", - EXECUTE_FROM_OUTSIDE = "execute_from_outside_v2", + DEPLOY_ACCOUNT = 'deploy_account', + EXECUTE_FROM_OUTSIDE = 'execute_from_outside_v2', } export const VAULT_FACTORY_ADDRESSES: AddressesMap = { [constants.StarknetChainId.SN_MAIN]: - "0x410da9af28e654fa93354430841ce7c5f0c2c17cc92971fb23d3d4f826d9834", + '0x410da9af28e654fa93354430841ce7c5f0c2c17cc92971fb23d3d4f826d9834', [constants.StarknetChainId.SN_SEPOLIA]: - "0x33498f0d9e6ebef71b3d8dfa56501388cfe5ce96cba81503cd8572be92bd77c", + '0x33498f0d9e6ebef71b3d8dfa56501388cfe5ce96cba81503cd8572be92bd77c', }; // eslint-disable-next-line import/no-unused-modules export const SN_CHAIN_ID = (constants.StarknetChainId[ - (process.env.SN_NETWORK ?? "SN_SEPOLIA") as constants.NetworkName -] ?? - constants.StarknetChainId[ - constants.NetworkName.SN_SEPOLIA - ]) as SupportedChainId; + (process.env.SN_NETWORK ?? 'SN_SEPOLIA') as constants.NetworkName +] ?? constants.StarknetChainId[constants.NetworkName.SN_SEPOLIA]) as SupportedChainId; // const NODE_URLS = { // [constants.StarknetChainId.SN_MAIN]: (apiKey: string) => `https://rpc.nethermind.io/mainnet-juno/?apikey=${apiKey}`, @@ -52,23 +49,21 @@ export const NODE_URL = NODE_URLS[SN_CHAIN_ID](process.env.RPC_NODE_API_KEY!); export const typedDataValidate = { types: { StarkNetDomain: [ - { name: "name", type: "felt" }, - { name: "version", type: "felt" }, - { name: "chainId", type: "felt" }, + { name: 'name', type: 'felt' }, + { name: 'version', type: 'felt' }, + { name: 'chainId', type: 'felt' }, ], - Message: [{ name: "message", type: "felt" }], + Message: [{ name: 'message', type: 'felt' }], }, - primaryType: "Message", + primaryType: 'Message', domain: { - name: "Afk", - chainId: shortString.encodeShortString( - process.env.EXPO_PUBLIC_NETWORK || "SN_MAIN" - ), - version: "1", + name: 'Afk', + chainId: shortString.encodeShortString(process.env.EXPO_PUBLIC_NETWORK || 'SN_MAIN'), + version: '1', }, message: { message: { - message: "Sign Signature", + message: 'Sign Signature', }, }, }; diff --git a/apps/data-backend/src/constants/funkit.ts b/apps/data-backend/src/constants/funkit.ts index 2a59e74ac..2e917e369 100644 --- a/apps/data-backend/src/constants/funkit.ts +++ b/apps/data-backend/src/constants/funkit.ts @@ -1,14 +1,13 @@ -export const FUNKIT_STARKNET_CHAIN_ID = "23448594291968334"; -export const SOURCE_OF_FUND_KEY = "card|stripe"; -export const FUNKIT_STRIPE_SOURCE_CURRENCY = "usd"; +export const FUNKIT_STARKNET_CHAIN_ID = '23448594291968334'; +export const SOURCE_OF_FUND_KEY = 'card|stripe'; +export const FUNKIT_STRIPE_SOURCE_CURRENCY = 'usd'; export const TOKEN_INFO = { STARKNET_USDC: { - address: - "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", + address: '0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8', decimals: 6, - symbol: "usdc", - network: "starknet", + symbol: 'usdc', + network: 'starknet', networkId: FUNKIT_STARKNET_CHAIN_ID, }, }; diff --git a/apps/data-backend/src/graphql.ts b/apps/data-backend/src/graphql.ts index 6e4401f7a..ff191e912 100644 --- a/apps/data-backend/src/graphql.ts +++ b/apps/data-backend/src/graphql.ts @@ -1,5 +1,5 @@ -import { ApolloServer, gql } from "apollo-server"; -const { prisma } = require("indexer-prisma"); +import { ApolloServer, gql } from 'apollo-server'; +const { prisma } = require('indexer-prisma'); //GraphQL schema definitions diff --git a/apps/data-backend/src/index.ts b/apps/data-backend/src/index.ts index 740c9e091..35115b940 100644 --- a/apps/data-backend/src/index.ts +++ b/apps/data-backend/src/index.ts @@ -1,30 +1,30 @@ -import Fastify from "fastify"; -import fs from "fs"; -import fastifyCors from "@fastify/cors"; -import fastifyIO from "fastify-socket.io"; -import { Server as SocketIOServer } from "socket.io"; -import path from "path"; -import { config } from "./config"; -import { setupWebSocket } from "./services/livestream/socket"; -import { authRoutes } from "./routes/auth"; -import { indexerRoutes } from "./routes/indexer/index"; -import authPlugin from "./plugins/auth"; -import jwt from "jsonwebtoken"; -import prismaPlugin from "./plugins/prisma"; -import twitterPlugin from "./plugins/twitter-oauth"; -import { launchBot } from "./services/telegram-app"; -import declareRoutes from "./router"; -import fastifySession from "@fastify/session"; -import fastifyOauth2 from "@fastify/oauth2"; +import Fastify from 'fastify'; +import fs from 'fs'; +import fastifyCors from '@fastify/cors'; +import fastifyIO from 'fastify-socket.io'; +import { Server as SocketIOServer } from 'socket.io'; +import path from 'path'; +import { config } from './config'; +import { setupWebSocket } from './services/livestream/socket'; +import { authRoutes } from './routes/auth'; +import { indexerRoutes } from './routes/indexer/index'; +import authPlugin from './plugins/auth'; +import jwt from 'jsonwebtoken'; +import prismaPlugin from './plugins/prisma'; +import twitterPlugin from './plugins/twitter-oauth'; +import { launchBot } from './services/telegram-app'; +import declareRoutes from './router'; +import fastifySession from '@fastify/session'; +import fastifyOauth2 from '@fastify/oauth2'; // Type declarations -declare module "fastify" { +declare module 'fastify' { interface FastifyInstance { io: SocketIOServer; } } -export const publicDir = path.join(__dirname, "public"); +export const publicDir = path.join(__dirname, 'public'); async function buildServer() { const fastify = Fastify({ @@ -33,17 +33,17 @@ async function buildServer() { // CORS configuration await fastify.register(fastifyCors, { - origin: "*", - methods: ["GET", "POST", "PUT", "DELETE"], - allowedHeaders: ["Content-Type", "Authorization"], + origin: '*', + methods: ['GET', 'POST', 'PUT', 'DELETE'], + allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, }); // Socket.IO setup await fastify.register(fastifyIO, { cors: { - origin: "*", - methods: ["GET", "POST", "PUT", "DELETE"], + origin: '*', + methods: ['GET', 'POST', 'PUT', 'DELETE'], credentials: true, }, }); @@ -53,7 +53,7 @@ async function buildServer() { await fastify.register(authPlugin); // await fastify.register(twitterPlugin); await fastify.register(fastifyOauth2, { - name: "twitterOAuth", + name: 'twitterOAuth', credentials: { client: { id: process.env.TWITTER_API_KEY!, @@ -61,31 +61,31 @@ async function buildServer() { }, // auth: fastifyOauth2.TWITTER_CONFIGURATION, auth: { - authorizeHost: "https://api.twitter.com", - authorizePath: "/oauth/authorize", - tokenHost: "https://api.twitter.com", - tokenPath: "/oauth/access_token", + authorizeHost: 'https://api.twitter.com', + authorizePath: '/oauth/authorize', + tokenHost: 'https://api.twitter.com', + tokenPath: '/oauth/access_token', }, }, - startRedirectPath: "/auth/login", + startRedirectPath: '/auth/login', callbackUri: process.env.TWITTER_CALLBACK_URL!, }); //Middleware to verify JWT const JWT_SECRET = config.jwt.secret; - fastify.decorate("verifyJWT", async (request, reply) => { + fastify.decorate('verifyJWT', async (request, reply) => { try { - const token = request.headers.authorization.split(" ")[1]; + const token = request.headers.authorization.split(' ')[1]; const decoded = jwt.verify(token, JWT_SECRET); request.user = decoded; } catch (error) { - reply.code(401).send({ error: "Unauthorized" }); + reply.code(401).send({ error: 'Unauthorized' }); } }); fastify.register(fastifySession, { - secret: JWT_SECRET ?? "your-secret-key", - cookie: { secure: process.env.NODE_ENV == "production" ? true : false }, // Set to true in production + secret: JWT_SECRET ?? 'your-secret-key', + cookie: { secure: process.env.NODE_ENV == 'production' ? true : false }, // Set to true in production }); // Register routes @@ -108,8 +108,7 @@ let server: any = null; async function start() { try { server = await buildServer(); - const host = - process.env.NODE_ENV === "production" ? "0.0.0.0" : "127.0.0.1"; + const host = process.env.NODE_ENV === 'production' ? '0.0.0.0' : '127.0.0.1'; await server.listen({ port: config.server.port, @@ -120,9 +119,9 @@ async function start() { // Launch Telegram bot try { - await launchBot(process.env.TELEGRAM_BOT_TOKEN || ""); + await launchBot(process.env.TELEGRAM_BOT_TOKEN || ''); } catch (error) { - console.error("Error launching bot:", error); + console.error('Error launching bot:', error); } } catch (err) { console.error(err); @@ -132,26 +131,26 @@ async function start() { // Graceful shutdown handling async function shutdown() { - console.log("Received shutdown signal"); + console.log('Received shutdown signal'); if (server) { try { await server.close(); - console.log("Server closed successfully"); + console.log('Server closed successfully'); process.exit(0); } catch (err) { - console.error("Error during shutdown:", err); + console.error('Error during shutdown:', err); process.exit(1); } } } // Handle shutdown signals -process.on("SIGTERM", shutdown); -process.on("SIGINT", shutdown); -process.on("SIGHUP", shutdown); +process.on('SIGTERM', shutdown); +process.on('SIGINT', shutdown); +process.on('SIGHUP', shutdown); // Start server if not in test environment -if (process.env.NODE_ENV !== "test") { +if (process.env.NODE_ENV !== 'test') { start(); } diff --git a/apps/data-backend/src/plugins/auth.ts b/apps/data-backend/src/plugins/auth.ts index e52bb0cbb..83340ee99 100644 --- a/apps/data-backend/src/plugins/auth.ts +++ b/apps/data-backend/src/plugins/auth.ts @@ -1,32 +1,29 @@ -import fp from "fastify-plugin"; -import jwt from "jsonwebtoken"; -import { FastifyInstance, FastifyRequest, FastifyReply } from "fastify"; -import { config } from "../config"; -import { UserJwtPayload } from "../types"; +import fp from 'fastify-plugin'; +import jwt from 'jsonwebtoken'; +import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; +import { config } from '../config'; +import { UserJwtPayload } from '../types'; export default fp(async function (fastify: FastifyInstance) { - fastify.decorate( - "authenticate", - async function (request: FastifyRequest, reply: FastifyReply) { - try { - const authHeader = request.headers.authorization; - if (!authHeader?.startsWith("Bearer ")) { - throw new Error("No token provided"); - } + fastify.decorate('authenticate', async function (request: FastifyRequest, reply: FastifyReply) { + try { + const authHeader = request.headers.authorization; + if (!authHeader?.startsWith('Bearer ')) { + throw new Error('No token provided'); + } - const token = authHeader.split(" ")[1]; - const decoded = jwt.verify(token, config.jwt.secret) as UserJwtPayload; + const token = authHeader.split(' ')[1]; + const decoded = jwt.verify(token, config.jwt.secret) as UserJwtPayload; - // Add user to request - request.user = decoded; - } catch (err) { - reply.code(401).send({ message: "Unauthorized" }); - } + // Add user to request + request.user = decoded; + } catch (err) { + reply.code(401).send({ message: 'Unauthorized' }); } - ); + }); // JWT helpers: Moved this from index.ts to this file. - fastify.decorate("jwt", { + fastify.decorate('jwt', { sign: (payload: object, options?: jwt.SignOptions) => { return jwt.sign(payload, config.jwt.secret, options); }, @@ -36,12 +33,9 @@ export default fp(async function (fastify: FastifyInstance) { }); }); -declare module "fastify" { +declare module 'fastify' { interface FastifyInstance { - authenticate: ( - request: FastifyRequest, - reply: FastifyReply - ) => Promise; + authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise; jwt: { sign: (payload: object, options?: jwt.SignOptions) => string; verify: (token: string) => UserJwtPayload; diff --git a/apps/data-backend/src/plugins/prisma.ts b/apps/data-backend/src/plugins/prisma.ts index 29d32a1c0..f8b94e55a 100644 --- a/apps/data-backend/src/plugins/prisma.ts +++ b/apps/data-backend/src/plugins/prisma.ts @@ -1,28 +1,28 @@ -import fp from "fastify-plugin"; -import { FastifyInstance } from "fastify"; -import { PrismaClient } from "@prisma/client"; +import fp from 'fastify-plugin'; +import { FastifyInstance } from 'fastify'; +import { PrismaClient } from '@prisma/client'; export default fp(async function (fastify: FastifyInstance) { const prisma = new PrismaClient(); try { await prisma.$connect(); - fastify.log.info("Database connected successfully"); // Log connection success + fastify.log.info('Database connected successfully'); // Log connection success } catch (error) { - fastify.log.error("Failed to connect to the database"); // Log connection failure + fastify.log.error('Failed to connect to the database'); // Log connection failure throw error; // Re-throw the error to prevent starting the app without a database connection } // Make Prisma available through fastify.prisma - fastify.decorate("prisma", prisma); + fastify.decorate('prisma', prisma); - fastify.addHook("onClose", async (instance) => { + fastify.addHook('onClose', async (instance) => { await instance.prisma.$disconnect(); - fastify.log.info("Database connection closed"); // Log disconnection + fastify.log.info('Database connection closed'); // Log disconnection }); }); -declare module "fastify" { +declare module 'fastify' { interface FastifyInstance { prisma: PrismaClient; } diff --git a/apps/data-backend/src/plugins/twitter-oauth.ts b/apps/data-backend/src/plugins/twitter-oauth.ts index dd65b52a5..d45b0c0fa 100644 --- a/apps/data-backend/src/plugins/twitter-oauth.ts +++ b/apps/data-backend/src/plugins/twitter-oauth.ts @@ -1,5 +1,5 @@ -import fp from "fastify-plugin"; -import fastifyOauth2 from "@fastify/oauth2"; +import fp from 'fastify-plugin'; +import fastifyOauth2 from '@fastify/oauth2'; export default fp(async (fastify, opts) => { // fastify.decorate("oauth2Twitter", @@ -42,7 +42,7 @@ export default fp(async (fastify, opts) => { // }); }); -declare module "fastify" { +declare module 'fastify' { interface FastifyInstance { twitterOAuth: any; } diff --git a/apps/data-backend/src/router.ts b/apps/data-backend/src/router.ts index 7240e8cd9..6b0aee54e 100644 --- a/apps/data-backend/src/router.ts +++ b/apps/data-backend/src/router.ts @@ -1,29 +1,29 @@ -import type { FastifyInstance } from "fastify"; +import type { FastifyInstance } from 'fastify'; -import buyCoinRoute from "./routes/indexer/buy-coin"; -import deployLaunchRoute from "./routes/indexer/deploy-launch"; -import deployTokenRoute from "./routes/indexer/deploy-token"; -import graphRoute from "./routes/indexer/graph"; -import holdingsRoute from "./routes/indexer/holdings"; -import tokenStatsRoute from "./routes/indexer/token_stats"; -import transactionsRoute from "./routes/indexer/transactions"; -import allTransactionsRoute from "./routes/indexer/all-transactions"; -import createFunkitStripeCheckout from "./routes/funkit/create_funkit_stripe_checkout"; -import getFunkitStripeCheckoutQuote from "./routes/funkit/get_funkit_stripe_checkout_quote"; -import getFunkitStripeCheckoutStatus from "./routes/funkit/get_funkit_stripe_checkout_status"; -import createPaymentIntent from "./routes/stripe/createPaymentIntent"; -import paymentSheet from "./routes/stripe/paymentSheet"; -import { authRoutes } from "./routes/auth"; -import nameserviceRoutes from "./routes/indexer/nameservice/nameservice"; -import unrugRoutes from "./routes/indexer/unruggable"; -import twitterRoutes from "./routes/auth/twitter"; +import buyCoinRoute from './routes/indexer/buy-coin'; +import deployLaunchRoute from './routes/indexer/deploy-launch'; +import deployTokenRoute from './routes/indexer/deploy-token'; +import graphRoute from './routes/indexer/graph'; +import holdingsRoute from './routes/indexer/holdings'; +import tokenStatsRoute from './routes/indexer/token_stats'; +import transactionsRoute from './routes/indexer/transactions'; +import allTransactionsRoute from './routes/indexer/all-transactions'; +import createFunkitStripeCheckout from './routes/funkit/create_funkit_stripe_checkout'; +import getFunkitStripeCheckoutQuote from './routes/funkit/get_funkit_stripe_checkout_quote'; +import getFunkitStripeCheckoutStatus from './routes/funkit/get_funkit_stripe_checkout_status'; +import createPaymentIntent from './routes/stripe/createPaymentIntent'; +import paymentSheet from './routes/stripe/paymentSheet'; +import { authRoutes } from './routes/auth'; +import nameserviceRoutes from './routes/indexer/nameservice/nameservice'; +import unrugRoutes from './routes/indexer/unruggable'; +import twitterRoutes from './routes/auth/twitter'; // import getOtp from "./routes/otp/getOtp"; // import verifyOtp from "./routes/otp/verifyOtp"; // import type { Account } from 'starknet' // import { ServiceContext } from 'twilio/lib/rest/verify/v2/service' function declareRoutes( - fastify: FastifyInstance + fastify: FastifyInstance, // deployer: Account, // twilio_services: ServiceContext ) { diff --git a/apps/data-backend/src/routes/auth/index.ts b/apps/data-backend/src/routes/auth/index.ts index 82715647e..1c05bc520 100644 --- a/apps/data-backend/src/routes/auth/index.ts +++ b/apps/data-backend/src/routes/auth/index.ts @@ -1,26 +1,23 @@ -import { FastifyInstance } from "fastify"; -import { AuthService } from "../../services/auth/auth.service"; -import { - LoginInput, - RefreshTokenInput, -} from "../../validations/auth.validation"; -import { SignatureService } from "../../services/auth/signature.service"; +import { FastifyInstance } from 'fastify'; +import { AuthService } from '../../services/auth/auth.service'; +import { LoginInput, RefreshTokenInput } from '../../validations/auth.validation'; +import { SignatureService } from '../../services/auth/signature.service'; export async function authRoutes(fastify: FastifyInstance) { const authService = new AuthService(fastify.prisma, fastify); const signatureService = new SignatureService(); fastify.post<{ Body: LoginInput }>( - "/auth", + '/auth', { schema: { body: { - type: "object", - required: ["userAddress", "loginType", "signature", "signedData"], + type: 'object', + required: ['userAddress', 'loginType', 'signature', 'signedData'], properties: { - userAddress: { type: "string" }, - loginType: { type: "string" }, - signature: { type: "object" }, + userAddress: { type: 'string' }, + loginType: { type: 'string' }, + signature: { type: 'object' }, }, }, }, @@ -36,43 +33,37 @@ export async function authRoutes(fastify: FastifyInstance) { }); if (!sig) { - return reply.code(400).send({ message: "Invalid Signature" }); + return reply.code(400).send({ message: 'Invalid Signature' }); } - const result = await authService.loginOrCreateUser( - userAddress, - loginType - ); + const result = await authService.loginOrCreateUser(userAddress, loginType); return { success: true, data: result }; } catch (error) { request.log.error(error); - return reply.code(500).send({ error: "Internal server error" }); + return reply.code(500).send({ error: 'Internal server error' }); } - } + }, ); - fastify.post<{ Body: RefreshTokenInput }>( - "/refresh-token", - async (request, reply) => { - try { - const { refreshToken } = request.body; - // Check if `refreshToken` exists and is not empty - if (!refreshToken) { - return reply.code(400).send({ message: "Refresh Token is required" }); - } - const result = await authService.refreshAccessToken(refreshToken); - return { success: true, data: result }; - } catch (error) { - if (error instanceof Error) { - return reply.code(401).send({ message: error.message }); - } - return reply.code(401).send({ message: "Invalid refresh token" }); + fastify.post<{ Body: RefreshTokenInput }>('/refresh-token', async (request, reply) => { + try { + const { refreshToken } = request.body; + // Check if `refreshToken` exists and is not empty + if (!refreshToken) { + return reply.code(400).send({ message: 'Refresh Token is required' }); + } + const result = await authService.refreshAccessToken(refreshToken); + return { success: true, data: result }; + } catch (error) { + if (error instanceof Error) { + return reply.code(401).send({ message: error.message }); } + return reply.code(401).send({ message: 'Invalid refresh token' }); } - ); + }); fastify.get( - "/me", + '/me', { onRequest: [fastify.authenticate], }, @@ -82,8 +73,8 @@ export async function authRoutes(fastify: FastifyInstance) { return { success: true, data: { user } }; } catch (error) { request.log.error(error); - return reply.code(500).send({ message: "Internal server error" }); + return reply.code(500).send({ message: 'Internal server error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/auth/twitter.ts b/apps/data-backend/src/routes/auth/twitter.ts index 7b9831066..e9c0e9fbe 100644 --- a/apps/data-backend/src/routes/auth/twitter.ts +++ b/apps/data-backend/src/routes/auth/twitter.ts @@ -1,11 +1,11 @@ -import { FastifyPluginAsync } from "fastify"; -import { TwitterService } from "../../services/socials/twitter.service"; -import { ConnectTwitterInput } from "../../validations/auth.validation"; +import { FastifyPluginAsync } from 'fastify'; +import { TwitterService } from '../../services/socials/twitter.service'; +import { ConnectTwitterInput } from '../../validations/auth.validation'; const twitterRoutes: FastifyPluginAsync = async (fastify) => { const twitterService = new TwitterService(fastify.prisma, fastify); // Step 1: Start OAuth flow - fastify.get("/twitter/auth/login", async (request, reply) => { + fastify.get('/twitter/auth/login', async (request, reply) => { try { const data = await twitterService.getAuthorizationLink(); reply.send({ success: true, data }); @@ -17,16 +17,16 @@ const twitterRoutes: FastifyPluginAsync = async (fastify) => { }); fastify.post<{ Body: ConnectTwitterInput }>( - "/twitter/connect-account", + '/twitter/connect-account', { schema: { body: { - type: "object", - required: ["code", "codeVerifier", "userId"], + type: 'object', + required: ['code', 'codeVerifier', 'userId'], properties: { - code: { type: "string" }, - codeVerifier: { type: "string" }, - userId: { type: "string" }, + code: { type: 'string' }, + codeVerifier: { type: 'string' }, + userId: { type: 'string' }, }, }, }, @@ -45,18 +45,18 @@ const twitterRoutes: FastifyPluginAsync = async (fastify) => { return reply.code(401).send({ message: error.message }); } } - } + }, ); fastify.post<{ Body: { userId: string } }>( - "/twitter/disconnect", + '/twitter/disconnect', { schema: { body: { - type: "object", - required: ["userId"], + type: 'object', + required: ['userId'], properties: { - userId: { type: "string" }, + userId: { type: 'string' }, }, }, }, @@ -71,7 +71,7 @@ const twitterRoutes: FastifyPluginAsync = async (fastify) => { return reply.code(401).send({ message: error.message }); } } - } + }, ); // // Step 2: Handle OAuth callback diff --git a/apps/data-backend/src/routes/funkit/create_funkit_stripe_checkout.ts b/apps/data-backend/src/routes/funkit/create_funkit_stripe_checkout.ts index b0ac3535f..70a0ea51d 100644 --- a/apps/data-backend/src/routes/funkit/create_funkit_stripe_checkout.ts +++ b/apps/data-backend/src/routes/funkit/create_funkit_stripe_checkout.ts @@ -1,10 +1,10 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; +import type { FastifyInstance, RouteOptions } from 'fastify'; import { FUNKIT_STRIPE_SOURCE_CURRENCY, SOURCE_OF_FUND_KEY, TOKEN_INFO, -} from "../../constants/funkit"; -import { generateClientMetadata } from "../../utils/funkit"; +} from '../../constants/funkit'; +import { generateClientMetadata } from '../../utils/funkit'; interface InitCheckoutBody { quoteId: string; @@ -12,35 +12,28 @@ interface InitCheckoutBody { estSubtotalUsd: number; } -const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ""; +const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ''; async function createFunkitStripeCheckout( fastify: FastifyInstance, - _options: RouteOptions + _options: RouteOptions, ): Promise { fastify.post<{ Body: InitCheckoutBody }>( - "/create_funkit_stripe_checkout", + '/create_funkit_stripe_checkout', async (request, reply) => { - const { quoteId, paymentTokenAmount, estSubtotalUsd } = - request.body as InitCheckoutBody; + const { quoteId, paymentTokenAmount, estSubtotalUsd } = request.body as InitCheckoutBody; if (!quoteId) { - return reply.status(400).send({ message: "quoteId is required." }); + return reply.status(400).send({ message: 'quoteId is required.' }); } if (!paymentTokenAmount) { - return reply - .status(400) - .send({ message: "paymentTokenAmount is required." }); + return reply.status(400).send({ message: 'paymentTokenAmount is required.' }); } if (!estSubtotalUsd) { - return reply - .status(400) - .send({ message: "estSubtotalUsd is required." }); + return reply.status(400).send({ message: 'estSubtotalUsd is required.' }); } try { const sourceAsset = TOKEN_INFO.STARKNET_USDC; - const { initializeCheckout, createStripeBuySession } = await import( - "@funkit/api-base" - ); + const { initializeCheckout, createStripeBuySession } = await import('@funkit/api-base'); const depositAddress = await initializeCheckout({ userOp: null, quoteId, @@ -52,9 +45,7 @@ async function createFunkitStripeCheckout( apiKey: FUNKIT_API_KEY, }); if (!depositAddress) { - return reply - .status(500) - .send({ message: "Failed to start a funkit checkout." }); + return reply.status(500).send({ message: 'Failed to start a funkit checkout.' }); } // 2 - Generate stripe session const stripeSession = await createStripeBuySession({ @@ -66,14 +57,8 @@ async function createFunkitStripeCheckout( walletAddress: depositAddress, isSandbox: false, }); - if ( - !stripeSession || - !stripeSession.id || - !stripeSession.redirect_url - ) { - return reply - .status(500) - .send({ message: "Failed to start a stripe checkout session." }); + if (!stripeSession || !stripeSession.id || !stripeSession.redirect_url) { + return reply.status(500).send({ message: 'Failed to start a stripe checkout session.' }); } return reply.send({ stripeCheckoutId: stripeSession.id, @@ -81,12 +66,10 @@ async function createFunkitStripeCheckout( funkitDepositAddress: depositAddress, }); } catch (error: any) { - console.error("Failed to start a checkout:", error); - return reply - .status(500) - .send({ message: "Failed to start a checkout." }); + console.error('Failed to start a checkout:', error); + return reply.status(500).send({ message: 'Failed to start a checkout.' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_quote.ts b/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_quote.ts index 091bffed4..c18f4a0e0 100644 --- a/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_quote.ts +++ b/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_quote.ts @@ -1,53 +1,48 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import { getChecksumAddress } from "starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import { getChecksumAddress } from 'starknet'; import { FUNKIT_STARKNET_CHAIN_ID, FUNKIT_STRIPE_SOURCE_CURRENCY, TOKEN_INFO, -} from "../../constants/funkit"; -import { roundUpToFiveDecimalPlaces } from "../../utils/funkit"; -import { isValidStarknetAddress } from "../../utils/starknet"; -import { HTTPStatus } from "../../utils/http"; +} from '../../constants/funkit'; +import { roundUpToFiveDecimalPlaces } from '../../utils/funkit'; +import { isValidStarknetAddress } from '../../utils/starknet'; +import { HTTPStatus } from '../../utils/http'; interface GetQuoteQuery { address: string; tokenAmount: number; } -const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ""; +const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ''; -async function getFunkitStripeCheckoutQuote( - fastify: FastifyInstance, - _options: RouteOptions -) { +async function getFunkitStripeCheckoutQuote(fastify: FastifyInstance, _options: RouteOptions) { fastify.get( - "/get-funkit-stripe-checkout-quote", + '/get-funkit-stripe-checkout-quote', async (request, reply) => { const { address, tokenAmount } = request.query as GetQuoteQuery; if (!address) { - return reply.status(400).send({ message: "Address is required." }); + return reply.status(400).send({ message: 'Address is required.' }); } if (!isValidStarknetAddress(address)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } if (!tokenAmount) { - return reply.status(400).send({ message: "Token amount is required." }); + return reply.status(400).send({ message: 'Token amount is required.' }); } try { // 1 - Generate the funkit checkout quote const sourceAsset = TOKEN_INFO.STARKNET_USDC; - const { getCheckoutQuote, getStripeBuyQuote } = await import( - "@funkit/api-base" - ); + const { getCheckoutQuote, getStripeBuyQuote } = await import('@funkit/api-base'); const normalizedRecipientAddress = getChecksumAddress(address); const baseQuote = await getCheckoutQuote({ fromChainId: sourceAsset.networkId, @@ -59,20 +54,16 @@ async function getFunkitStripeCheckoutQuote( toTokenAmount: Number(tokenAmount), expirationTimestampMs: 1_800_000, // 30 minutes apiKey: FUNKIT_API_KEY, - sponsorInitialTransferGasLimit: "0", + sponsorInitialTransferGasLimit: '0', recipientAddr: normalizedRecipientAddress as `0x${string}`, userId: normalizedRecipientAddress, needsRefuel: false, }); if (!baseQuote || !baseQuote.quoteId) { - return reply - .status(500) - .send({ message: "Failed to get a funkit quote." }); + return reply.status(500).send({ message: 'Failed to get a funkit quote.' }); } - const estTotalFromAmount = roundUpToFiveDecimalPlaces( - baseQuote.estTotalFromAmount - ); + const estTotalFromAmount = roundUpToFiveDecimalPlaces(baseQuote.estTotalFromAmount); // 2 - Get the stripe quote based on the const stripeFullQuote = await getStripeBuyQuote({ sourceCurrency: FUNKIT_STRIPE_SOURCE_CURRENCY, @@ -82,14 +73,9 @@ async function getFunkitStripeCheckoutQuote( apiKey: FUNKIT_API_KEY, isSandbox: false, }); - const stripeQuote = - stripeFullQuote?.destination_network_quotes?.[ - sourceAsset.network - ]?.[0]; + const stripeQuote = stripeFullQuote?.destination_network_quotes?.[sourceAsset.network]?.[0]; if (!stripeQuote) { - return reply - .status(500) - .send({ message: "Failed to get stripe quote." }); + return reply.status(500).send({ message: 'Failed to get stripe quote.' }); } const finalQuote = { quoteId: baseQuote.quoteId, @@ -98,20 +84,17 @@ async function getFunkitStripeCheckoutQuote( paymentTokenSymbol: sourceAsset.symbol, paymentTokenAmount: estTotalFromAmount, networkFees: ( - Number(stripeQuote.fees.network_fee_monetary) + - Number(baseQuote.estFeesUsd) + Number(stripeQuote.fees.network_fee_monetary) + Number(baseQuote.estFeesUsd) ).toFixed(2), - cardFees: Number(stripeQuote.fees.transaction_fee_monetary).toFixed( - 2 - ), + cardFees: Number(stripeQuote.fees.transaction_fee_monetary).toFixed(2), totalUsd: Number(stripeQuote.source_total_amount).toFixed(2), }; return reply.send(finalQuote); } catch (error) { console.error(error); - return reply.status(500).send({ message: "Internal server error" }); + return reply.status(500).send({ message: 'Internal server error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_status.ts b/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_status.ts index a2c2b8304..d1089369b 100644 --- a/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_status.ts +++ b/apps/data-backend/src/routes/funkit/get_funkit_stripe_checkout_status.ts @@ -1,13 +1,10 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; +import type { FastifyInstance, RouteOptions } from 'fastify'; -const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ""; +const FUNKIT_API_KEY = process.env.FUNKIT_API_KEY || ''; -async function getFunkitStripeCheckoutStatus( - fastify: FastifyInstance, - _options: RouteOptions -) { +async function getFunkitStripeCheckoutStatus(fastify: FastifyInstance, _options: RouteOptions) { fastify.get( - "/get-funkit-stripe-checkout-status", + '/get-funkit-stripe-checkout-status', async (request, reply) => { const { funkitDepositAddress } = request.query as { @@ -15,36 +12,28 @@ async function getFunkitStripeCheckoutStatus( }; if (!funkitDepositAddress) { - return reply - .status(400) - .send({ message: "funkitDepositAddress is required." }); + return reply.status(400).send({ message: 'funkitDepositAddress is required.' }); } try { - const { getCheckoutByDepositAddress } = await import( - "@funkit/api-base" - ); + const { getCheckoutByDepositAddress } = await import('@funkit/api-base'); const checkoutItem = await getCheckoutByDepositAddress({ depositAddress: funkitDepositAddress as `0x${string}`, apiKey: FUNKIT_API_KEY, }); if (!checkoutItem || !checkoutItem?.depositAddr) { - return reply - .status(500) - .send({ message: "Failed to get a funkit checkout." }); + return reply.status(500).send({ message: 'Failed to get a funkit checkout.' }); } return reply.send({ state: checkoutItem.state, }); } catch (error: any) { - if (error?.message?.includes("InvalidParameterError")) { - return reply - .status(500) - .send({ message: "Failed to get a funkit checkout." }); + if (error?.message?.includes('InvalidParameterError')) { + return reply.status(500).send({ message: 'Failed to get a funkit checkout.' }); } - return reply.status(500).send({ message: "Internal server error" }); + return reply.status(500).send({ message: 'Internal server error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/indexer/all-transactions.ts b/apps/data-backend/src/routes/indexer/all-transactions.ts index 3dc8f86f5..7ef5c5995 100644 --- a/apps/data-backend/src/routes/indexer/all-transactions.ts +++ b/apps/data-backend/src/routes/indexer/all-transactions.ts @@ -1,25 +1,22 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface AllTransactionsParams { tokenAddress: string; } -async function allTransactionsRoute( - fastify: FastifyInstance, - options: RouteOptions -) { +async function allTransactionsRoute(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: AllTransactionsParams; - }>("/all-transactions/:tokenAddress", async (request, reply) => { + }>('/all-transactions/:tokenAddress', async (request, reply) => { try { const { tokenAddress } = request.params; if (!isValidStarknetAddress(tokenAddress)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -48,10 +45,8 @@ async function allTransactionsRoute( data: allTransactions, }); } catch (error) { - console.error("Error fetching buy tokens:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error fetching buy tokens:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/indexer/buy-coin.ts b/apps/data-backend/src/routes/indexer/buy-coin.ts index 721ffdc37..606212243 100644 --- a/apps/data-backend/src/routes/indexer/buy-coin.ts +++ b/apps/data-backend/src/routes/indexer/buy-coin.ts @@ -1,12 +1,12 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; async function buyCoinRoute(fastify: FastifyInstance, options: RouteOptions) { - fastify.get("/buy-coin", async (request, reply) => { + fastify.get('/buy-coin', async (request, reply) => { try { const buyTokens = await prisma.token_transactions.findMany({ - where: { transaction_type: "buy" }, + where: { transaction_type: 'buy' }, select: { memecoin_address: true, amount: true, @@ -25,10 +25,8 @@ async function buyCoinRoute(fastify: FastifyInstance, options: RouteOptions) { data: buyTokens, }); } catch (error) { - console.error("Error fetching buy tokens:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error fetching buy tokens:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/indexer/deploy-launch.ts b/apps/data-backend/src/routes/indexer/deploy-launch.ts index d603c765f..3521171f6 100644 --- a/apps/data-backend/src/routes/indexer/deploy-launch.ts +++ b/apps/data-backend/src/routes/indexer/deploy-launch.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface DeployLaunchParams { launch: string; @@ -10,11 +10,8 @@ interface DeployLaunchParams { interface DeployLaunchByUserParams { owner_address: string; } -async function deployLaunchRoute( - fastify: FastifyInstance, - options: RouteOptions -) { - fastify.get("/deploy-launch", async (request, reply) => { +async function deployLaunchRoute(fastify: FastifyInstance, options: RouteOptions) { + fastify.get('/deploy-launch', async (request, reply) => { try { const launches = await prisma.token_launch.findMany({ select: { @@ -32,22 +29,20 @@ async function deployLaunchRoute( data: launches, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployLaunchParams; - }>("/deploy-launch/:launch", async (request, reply) => { + }>('/deploy-launch/:launch', async (request, reply) => { try { const { launch } = request.params; if (!isValidStarknetAddress(launch)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -71,22 +66,20 @@ async function deployLaunchRoute( data: launchPool, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployLaunchParams; - }>("/deploy-launch/stats/:launch", async (request, reply) => { + }>('/deploy-launch/stats/:launch', async (request, reply) => { try { const { launch } = request.params; if (!isValidStarknetAddress(launch)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -114,10 +107,8 @@ async function deployLaunchRoute( data: undefined, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); diff --git a/apps/data-backend/src/routes/indexer/deploy-token.ts b/apps/data-backend/src/routes/indexer/deploy-token.ts index 718fedb0c..fb06bbcae 100644 --- a/apps/data-backend/src/routes/indexer/deploy-token.ts +++ b/apps/data-backend/src/routes/indexer/deploy-token.ts @@ -1,18 +1,15 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface DeployTokenParams { token: string; owner_address?: string; } -async function deployTokenRoute( - fastify: FastifyInstance, - options: RouteOptions -) { - fastify.get("/deploy", async (request, reply) => { +async function deployTokenRoute(fastify: FastifyInstance, options: RouteOptions) { + fastify.get('/deploy', async (request, reply) => { try { const deploys = await prisma.token_deploy.findMany({ select: { @@ -30,22 +27,20 @@ async function deployTokenRoute( data: deploys, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployTokenParams; - }>("/deploy/:token", async (request, reply) => { + }>('/deploy/:token', async (request, reply) => { try { const { token } = request.params; if (!isValidStarknetAddress(token)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -67,22 +62,20 @@ async function deployTokenRoute( data: deploys, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployTokenParams; - }>("/deploy/from/:user/", async (request, reply) => { + }>('/deploy/from/:user/', async (request, reply) => { try { const { owner_address } = request.params; if (owner_address && !isValidStarknetAddress(owner_address)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -104,10 +97,8 @@ async function deployTokenRoute( data: deploys, }); } catch (error) { - console.error("Error deploying launch by user:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch by user:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/indexer/graph.ts b/apps/data-backend/src/routes/indexer/graph.ts index fe99ae4ce..f7fb36a3b 100644 --- a/apps/data-backend/src/routes/indexer/graph.ts +++ b/apps/data-backend/src/routes/indexer/graph.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface GraphParams { tokenAddress: string; @@ -10,12 +10,12 @@ interface GraphParams { async function graphRoute(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: GraphParams; - }>("/candles/:tokenAddress", async (request, reply) => { + }>('/candles/:tokenAddress', async (request, reply) => { const { tokenAddress } = request.params; if (!isValidStarknetAddress(tokenAddress)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -23,7 +23,7 @@ async function graphRoute(fastify: FastifyInstance, options: RouteOptions) { try { const transactions = await prisma.token_transactions.findMany({ where: { memecoin_address: tokenAddress }, - orderBy: { block_timestamp: "asc" }, + orderBy: { block_timestamp: 'asc' }, select: { price: true, block_timestamp: true, @@ -33,7 +33,7 @@ async function graphRoute(fastify: FastifyInstance, options: RouteOptions) { if (transactions.length === 0) { return reply.status(HTTPStatus.NotFound).send({ - error: "No transactions found for this token address.", + error: 'No transactions found for this token address.', }); } // Hourly candles @@ -53,10 +53,8 @@ async function graphRoute(fastify: FastifyInstance, options: RouteOptions) { reply.status(HTTPStatus.OK).send(candles); } catch (error) { - console.error("Error generating candles:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error generating candles:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/indexer/holdings.ts b/apps/data-backend/src/routes/indexer/holdings.ts index 49559351c..c653ee549 100644 --- a/apps/data-backend/src/routes/indexer/holdings.ts +++ b/apps/data-backend/src/routes/indexer/holdings.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface HoldingsParams { tokenAddress: string; @@ -10,19 +10,19 @@ interface HoldingsParams { async function holdingsRoute(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: HoldingsParams; - }>("/token-distribution/:tokenAddress", async (request, reply) => { + }>('/token-distribution/:tokenAddress', async (request, reply) => { const { tokenAddress } = request.params; if (!isValidStarknetAddress(tokenAddress)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } try { const distributions = await prisma.token_transactions.groupBy({ - by: ["owner_address", "transaction_type"], + by: ['owner_address', 'transaction_type'], // by: ["owner_address", "transaction_type"], // TODO add by tx type and sum sell and buy where: { memecoin_address: tokenAddress }, _sum: { @@ -35,15 +35,15 @@ async function holdingsRoute(fastify: FastifyInstance, options: RouteOptions) { if (distributions.length === 0) { reply.status(HTTPStatus.NotFound).send({ - message: "No holders found for this token address.", + message: 'No holders found for this token address.', }); } reply.status(HTTPStatus.OK).send({ data: distributions }); } catch (error) { - console.error("Failed to fetch token distribution:", error); + console.error('Failed to fetch token distribution:', error); reply.status(HTTPStatus.InternalServerError).send({ - message: "Internal Server Error while fetching token distribution.", + message: 'Internal Server Error while fetching token distribution.', }); } }); diff --git a/apps/data-backend/src/routes/indexer/index.ts b/apps/data-backend/src/routes/indexer/index.ts index 7f922fc2e..a6de8e900 100644 --- a/apps/data-backend/src/routes/indexer/index.ts +++ b/apps/data-backend/src/routes/indexer/index.ts @@ -1,5 +1,5 @@ -import allTransactionsRoute from "./all-transactions"; -import buyCoinRoute from "./buy-coin"; +import allTransactionsRoute from './all-transactions'; +import buyCoinRoute from './buy-coin'; export const indexerRoutes = { buyCoinRoute, diff --git a/apps/data-backend/src/routes/indexer/nameservice/nameservice.ts b/apps/data-backend/src/routes/indexer/nameservice/nameservice.ts index 28a69db31..97e6209aa 100644 --- a/apps/data-backend/src/routes/indexer/nameservice/nameservice.ts +++ b/apps/data-backend/src/routes/indexer/nameservice/nameservice.ts @@ -1,20 +1,17 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../../utils/http"; -import { isValidStarknetAddress } from "../../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../../utils/http'; +import { isValidStarknetAddress } from '../../../utils/starknet'; interface NameserviceParams { username?: string; owner_address?: string; } -async function nameserviceRoutes( - fastify: FastifyInstance, - options: RouteOptions -) { +async function nameserviceRoutes(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: NameserviceParams; - }>("/username-claimed", async (request, reply) => { + }>('/username-claimed', async (request, reply) => { try { const usernamesClaimed = await prisma.username_claimed.findMany({ // where: { transaction_type: "buy" }, @@ -32,15 +29,13 @@ async function nameserviceRoutes( data: usernamesClaimed, }); } catch (error) { - console.error("Error fetching buy tokens:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error fetching buy tokens:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: NameserviceParams; - }>("/username-claimed/username/:username", async (request, reply) => { + }>('/username-claimed/username/:username', async (request, reply) => { try { const usernamesClaimed = await prisma.username_claimed.findMany({ // where: { transaction_type: "buy" }, @@ -58,15 +53,13 @@ async function nameserviceRoutes( data: usernamesClaimed, }); } catch (error) { - console.error("Error fetching buy tokens:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error fetching buy tokens:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: NameserviceParams; - }>("/username-claimed/user/:user", async (request, reply) => { + }>('/username-claimed/user/:user', async (request, reply) => { try { const { username } = request.params; @@ -86,10 +79,8 @@ async function nameserviceRoutes( data: usernameClaimedByUser, }); } catch (error) { - console.error("Error fetching username by user:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error fetching username by user:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/indexer/token_stats.ts b/apps/data-backend/src/routes/indexer/token_stats.ts index d5147f21c..6e0b2829f 100644 --- a/apps/data-backend/src/routes/indexer/token_stats.ts +++ b/apps/data-backend/src/routes/indexer/token_stats.ts @@ -1,24 +1,21 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface TokenStatsParams { tokenAddress: string; } -async function tokenStatsRoute( - fastify: FastifyInstance, - options: RouteOptions -) { +async function tokenStatsRoute(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: TokenStatsParams; - }>("/stats/:tokenAddress", async (request, reply) => { + }>('/stats/:tokenAddress', async (request, reply) => { const { tokenAddress } = request.params; if (!isValidStarknetAddress(tokenAddress)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -27,7 +24,7 @@ async function tokenStatsRoute( // Query the latest price and liquidity raised const stats = await prisma.token_transactions.findFirst({ where: { memecoin_address: tokenAddress }, - orderBy: { created_at: "desc" }, + orderBy: { created_at: 'desc' }, select: { price: true, liquidity_raised: true, @@ -44,12 +41,12 @@ async function tokenStatsRoute( reply.status(HTTPStatus.OK).send(stats); } else { reply.status(HTTPStatus.NotFound).send({ - error: "No data found for the specified token address.", + error: 'No data found for the specified token address.', }); } } catch (error) { reply.status(HTTPStatus.InternalServerError).send({ - error: "Internal Server Error while fetching statistics.", + error: 'Internal Server Error while fetching statistics.', }); } }); diff --git a/apps/data-backend/src/routes/indexer/transactions.ts b/apps/data-backend/src/routes/indexer/transactions.ts index d690991e9..3f000b3a3 100644 --- a/apps/data-backend/src/routes/indexer/transactions.ts +++ b/apps/data-backend/src/routes/indexer/transactions.ts @@ -1,25 +1,22 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../utils/http"; -import { isValidStarknetAddress } from "../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../utils/http'; +import { isValidStarknetAddress } from '../../utils/starknet'; interface TransactionParams { tokenAddress: string; userId: string; } -async function transactionsRoute( - fastify: FastifyInstance, - options: RouteOptions -) { +async function transactionsRoute(fastify: FastifyInstance, options: RouteOptions) { fastify.get<{ Params: TransactionParams; - }>("/my-share/:tokenAddress/:userId", async (request, reply) => { + }>('/my-share/:tokenAddress/:userId', async (request, reply) => { const { tokenAddress, userId } = request.params; if (!isValidStarknetAddress(tokenAddress)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -44,29 +41,29 @@ async function transactionsRoute( if (transactions.length === 0) { return reply.status(HTTPStatus.NotFound).send({ - error: "No transactions found for this user and token address.", + error: 'No transactions found for this user and token address.', }); } const result = transactions.reduce( (acc, cur) => { - acc.total += parseFloat(cur.amount?.toString() || "0"); - acc.quote_amount += parseFloat(cur.quote_amount?.toString() || "0"); - if (cur.transaction_type === "buy") { - acc.total_buy += parseFloat(cur.amount?.toString() || "0"); - } else if (cur.transaction_type === "sell") { - acc.total_sell += parseFloat(cur.amount?.toString() || "0"); + acc.total += parseFloat(cur.amount?.toString() || '0'); + acc.quote_amount += parseFloat(cur.quote_amount?.toString() || '0'); + if (cur.transaction_type === 'buy') { + acc.total_buy += parseFloat(cur.amount?.toString() || '0'); + } else if (cur.transaction_type === 'sell') { + acc.total_sell += parseFloat(cur.amount?.toString() || '0'); } return acc; }, - { total: 0, total_buy: 0, total_sell: 0, quote_amount: 0 } + { total: 0, total_buy: 0, total_sell: 0, quote_amount: 0 }, ); reply.status(HTTPStatus.OK).send(result); } catch (error) { - console.error("Failed to retrieve user transactions:", error); + console.error('Failed to retrieve user transactions:', error); reply.status(HTTPStatus.InternalServerError).send({ - error: "Internal Server Error while fetching user transactions.", + error: 'Internal Server Error while fetching user transactions.', }); } }); diff --git a/apps/data-backend/src/routes/indexer/unruggable/index.ts b/apps/data-backend/src/routes/indexer/unruggable/index.ts index dff394963..6e501ae4c 100644 --- a/apps/data-backend/src/routes/indexer/unruggable/index.ts +++ b/apps/data-backend/src/routes/indexer/unruggable/index.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance, RouteOptions } from "fastify"; -import prisma from "indexer-prisma"; -import { HTTPStatus } from "../../../utils/http"; -import { isValidStarknetAddress } from "../../../utils/starknet"; +import type { FastifyInstance, RouteOptions } from 'fastify'; +import prisma from 'indexer-prisma'; +import { HTTPStatus } from '../../../utils/http'; +import { isValidStarknetAddress } from '../../../utils/starknet'; interface DeployLaunchParams { launch: string; @@ -9,7 +9,7 @@ interface DeployLaunchParams { // Routes for Unrug data of dashboard async function unrugRoutes(fastify: FastifyInstance, options: RouteOptions) { - fastify.get("/unrug/create-token", async (request, reply) => { + fastify.get('/unrug/create-token', async (request, reply) => { try { const launches = await prisma.unrugmeme_deploy.findMany({ select: { @@ -21,22 +21,20 @@ async function unrugRoutes(fastify: FastifyInstance, options: RouteOptions) { data: launches, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployLaunchParams; - }>("/unrug/deploy-launch/:launch", async (request, reply) => { + }>('/unrug/deploy-launch/:launch', async (request, reply) => { try { const { launch } = request.params; if (!isValidStarknetAddress(launch)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -54,22 +52,20 @@ async function unrugRoutes(fastify: FastifyInstance, options: RouteOptions) { data: launchPool, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployLaunchParams; - }>("/unrug/tokens-transfers", async (request, reply) => { + }>('/unrug/tokens-transfers', async (request, reply) => { try { const { launch } = request.params; if (!isValidStarknetAddress(launch)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -91,22 +87,20 @@ async function unrugRoutes(fastify: FastifyInstance, options: RouteOptions) { data: undefined, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); fastify.get<{ Params: DeployLaunchParams; - }>("/unrug/deploy-launch/stats/:launch", async (request, reply) => { + }>('/unrug/deploy-launch/stats/:launch', async (request, reply) => { try { const { launch } = request.params; if (!isValidStarknetAddress(launch)) { reply.status(HTTPStatus.BadRequest).send({ code: HTTPStatus.BadRequest, - message: "Invalid token address", + message: 'Invalid token address', }); return; } @@ -128,10 +122,8 @@ async function unrugRoutes(fastify: FastifyInstance, options: RouteOptions) { data: undefined, }); } catch (error) { - console.error("Error deploying launch:", error); - reply - .status(HTTPStatus.InternalServerError) - .send({ message: "Internal server error." }); + console.error('Error deploying launch:', error); + reply.status(HTTPStatus.InternalServerError).send({ message: 'Internal server error.' }); } }); } diff --git a/apps/data-backend/src/routes/otp/getOtp.ts b/apps/data-backend/src/routes/otp/getOtp.ts index 39534b824..67786879f 100644 --- a/apps/data-backend/src/routes/otp/getOtp.ts +++ b/apps/data-backend/src/routes/otp/getOtp.ts @@ -1,27 +1,24 @@ -import type { FastifyInstance } from "fastify"; -import { VerificationListInstance } from "twilio/lib/rest/verify/v2/service/verification"; -import { PrismaClient } from "@prisma/client"; +import type { FastifyInstance } from 'fastify'; +import { VerificationListInstance } from 'twilio/lib/rest/verify/v2/service/verification'; +import { PrismaClient } from '@prisma/client'; interface GetOtpRequestBody { phone_number: string; nickname: string; } -async function getOtp( - fastify: FastifyInstance, - twilio_verification: VerificationListInstance -) { +async function getOtp(fastify: FastifyInstance, twilio_verification: VerificationListInstance) { fastify.post<{ Body: GetOtpRequestBody }>( - "/get_otp", + '/get_otp', { schema: { body: { - type: "object", - required: ["phone_number", "nickname"], + type: 'object', + required: ['phone_number', 'nickname'], properties: { - phone_number: { type: "string", pattern: "^\\+[1-9]\\d{1,14}$" }, - nickname: { type: "string", pattern: "^[A-Za-z]{1,20}$" }, + phone_number: { type: 'string', pattern: '^\\+[1-9]\\d{1,14}$' }, + nickname: { type: 'string', pattern: '^[A-Za-z]{1,20}$' }, }, }, }, @@ -38,7 +35,7 @@ async function getOtp( where: { phone_number: phone_number, }, - orderBy: { created_at: "desc" }, + orderBy: { created_at: 'desc' }, }); if (!record_by_phone_number) { @@ -51,32 +48,32 @@ async function getOtp( }); } catch (error: any) { fastify.log.error(error); - if (error.code === "23505") { + if (error.code === '23505') { return reply.code(409).send({ - message: "A user with the given phone number already exists.", + message: 'A user with the given phone number already exists.', }); } - return reply.code(500).send({ message: "Internal server error" }); + return reply.code(500).send({ message: 'Internal server error' }); } } const send_msg_res = await twilio_verification.create({ to: phone_number, - channel: "sms", + channel: 'sms', }); - if (send_msg_res.status != "pending") { - fastify.log.error("Error sending message to phone number"); + if (send_msg_res.status != 'pending') { + fastify.log.error('Error sending message to phone number'); return reply.code(500).send({ - message: "We are facing some issues. Please try again later", + message: 'We are facing some issues. Please try again later', }); } return reply.code(200).send({ ok: true }); } catch (error) { fastify.log.error(error); - return reply.code(500).send({ message: "Internal Server Error" }); + return reply.code(500).send({ message: 'Internal Server Error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/otp/verifyOtp.ts b/apps/data-backend/src/routes/otp/verifyOtp.ts index be701cf2c..300b11df3 100644 --- a/apps/data-backend/src/routes/otp/verifyOtp.ts +++ b/apps/data-backend/src/routes/otp/verifyOtp.ts @@ -1,14 +1,10 @@ -import type { FastifyInstance } from "fastify"; -import { type Account, addAddressPadding, uint256 } from "starknet"; -import { VerificationCheckListInstance } from "twilio/lib/rest/verify/v2/service/verificationCheck"; -import { - Entrypoint, - SN_CHAIN_ID, - VAULT_FACTORY_ADDRESSES, -} from "../../constants/contracts"; -import { hashPhoneNumber } from "../../utils/format"; -import { computeAddress } from "../../utils/address"; -import { PrismaClient } from "@prisma/client"; +import type { FastifyInstance } from 'fastify'; +import { type Account, addAddressPadding, uint256 } from 'starknet'; +import { VerificationCheckListInstance } from 'twilio/lib/rest/verify/v2/service/verificationCheck'; +import { Entrypoint, SN_CHAIN_ID, VAULT_FACTORY_ADDRESSES } from '../../constants/contracts'; +import { hashPhoneNumber } from '../../utils/format'; +import { computeAddress } from '../../utils/address'; +import { PrismaClient } from '@prisma/client'; interface VerifyOtpRequestBody { phone_number: string; @@ -20,28 +16,23 @@ interface VerifyOtpRequestBody { async function verifyOtp( fastify: FastifyInstance, deployer: Account, - twilio_verification: VerificationCheckListInstance + twilio_verification: VerificationCheckListInstance, ) { fastify.post<{ Body: VerifyOtpRequestBody; }>( - "/verify_otp", + '/verify_otp', { schema: { body: { - type: "object", - required: [ - "phone_number", - "public_key_x", - "public_key_y", - "sent_otp", - ], + type: 'object', + required: ['phone_number', 'public_key_x', 'public_key_y', 'sent_otp'], properties: { - phone_number: { type: "string", pattern: "^\\+[1-9]\\d{1,14}$" }, - sent_otp: { type: "string", pattern: "^[0-9]{6}$" }, - public_key_x: { type: "string", pattern: "^0x[0-9a-fA-F]+$" }, - public_key_y: { type: "string", pattern: "^0x[0-9a-fA-F]+$" }, + phone_number: { type: 'string', pattern: '^\\+[1-9]\\d{1,14}$' }, + sent_otp: { type: 'string', pattern: '^[0-9]{6}$' }, + public_key_x: { type: 'string', pattern: '^0x[0-9a-fA-F]+$' }, + public_key_y: { type: 'string', pattern: '^0x[0-9a-fA-F]+$' }, }, }, }, @@ -49,8 +40,7 @@ async function verifyOtp( async (request, reply) => { try { - const { phone_number, sent_otp, public_key_x, public_key_y } = - request.body; + const { phone_number, sent_otp, public_key_x, public_key_y } = request.body; const prisma = new PrismaClient(); @@ -62,11 +52,11 @@ async function verifyOtp( }) .catch((error) => { fastify.log.error(error); - return { status: "unrequested" }; + return { status: 'unrequested' }; }); // The status of the verification. Can be: `pending`, `approved`, `canceled`, `max_attempts_reached`, `deleted`, `failed` or `expired`. - if (response.status != "approved") { + if (response.status != 'approved') { return reply.code(400).send({ message: `Otp is ${response.status}.`, }); @@ -100,18 +90,17 @@ async function verifyOtp( const contractAddress = addAddressPadding(computeAddress(phone_number)); fastify.log.info( - "Deploying account: ", + 'Deploying account: ', contractAddress, - " for: ", + ' for: ', phone_number, - " with tx hash: ", - transaction_hash + ' with tx hash: ', + transaction_hash, ); if (!transaction_hash) { return reply.code(500).send({ - message: - "Error in deploying smart contract. Please try again later", + message: 'Error in deploying smart contract. Please try again later', }); } @@ -139,9 +128,9 @@ async function verifyOtp( } catch (error) { console.log(error); fastify.log.error(error); - return reply.code(500).send({ message: "Internal Server Error" }); + return reply.code(500).send({ message: 'Internal Server Error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/stripe/createPaymentIntent.ts b/apps/data-backend/src/routes/stripe/createPaymentIntent.ts index 4a409eaaa..d6ce02e78 100644 --- a/apps/data-backend/src/routes/stripe/createPaymentIntent.ts +++ b/apps/data-backend/src/routes/stripe/createPaymentIntent.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance } from "fastify"; -import dotenv from "dotenv"; +import type { FastifyInstance } from 'fastify'; +import dotenv from 'dotenv'; dotenv.config(); -const stripe = require("stripe")(process.env.STRIPE_SERVER_API_KEY); +const stripe = require('stripe')(process.env.STRIPE_SERVER_API_KEY); interface CreatePaymentIntent { currency: string; @@ -10,16 +10,16 @@ interface CreatePaymentIntent { async function createPaymentIntent(fastify: FastifyInstance) { fastify.post<{ Body: CreatePaymentIntent }>( - "/create-payment-intent", + '/create-payment-intent', { schema: { body: { - type: "object", - required: ["currency", "amount"], + type: 'object', + required: ['currency', 'amount'], properties: { - currency: { type: "string", pattern: "^\\+[1-9]\\d{1,14}$" }, - amount: { type: "number" }, + currency: { type: 'string', pattern: '^\\+[1-9]\\d{1,14}$' }, + amount: { type: 'number' }, }, }, }, @@ -32,7 +32,7 @@ async function createPaymentIntent(fastify: FastifyInstance) { const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, // Example amount in smallest currency unit (cents) currency: currency, - payment_method_types: ["card"], + payment_method_types: ['card'], }); reply.send({ @@ -42,9 +42,9 @@ async function createPaymentIntent(fastify: FastifyInstance) { return reply.code(200).send({ ok: true }); } catch (error) { fastify.log.error(error); - return reply.code(500).send({ message: "Internal Server Error" }); + return reply.code(500).send({ message: 'Internal Server Error' }); } - } + }, ); } diff --git a/apps/data-backend/src/routes/stripe/paymentSheet.ts b/apps/data-backend/src/routes/stripe/paymentSheet.ts index 530371b7a..72841e536 100644 --- a/apps/data-backend/src/routes/stripe/paymentSheet.ts +++ b/apps/data-backend/src/routes/stripe/paymentSheet.ts @@ -1,7 +1,7 @@ -import type { FastifyInstance } from "fastify"; -import dotenv from "dotenv"; +import type { FastifyInstance } from 'fastify'; +import dotenv from 'dotenv'; dotenv.config(); -const stripe = require("stripe")(process.env.STRIPE_SERVER_API_KEY); +const stripe = require('stripe')(process.env.STRIPE_SERVER_API_KEY); interface CreatePaymentSheet { currency: string; @@ -10,16 +10,16 @@ interface CreatePaymentSheet { async function paymentSheet(fastify: FastifyInstance) { fastify.post<{ Body: CreatePaymentSheet }>( - "/payment-sheet", + '/payment-sheet', { schema: { body: { - type: "object", - required: ["currency", "amount"], + type: 'object', + required: ['currency', 'amount'], properties: { - currency: { type: "string", pattern: "^\\+[1-9]\\d{1,14}$" }, - amount: { type: "number" }, + currency: { type: 'string', pattern: '^\\+[1-9]\\d{1,14}$' }, + amount: { type: 'number' }, }, }, }, @@ -35,13 +35,13 @@ async function paymentSheet(fastify: FastifyInstance) { // Create an ephemeral key for the customer const ephemeralKey = await stripe.ephemeralKeys.create( { customer: customer.id }, - { apiVersion: "2022-11-15" } // Ensure to use the latest API version + { apiVersion: '2022-11-15' }, // Ensure to use the latest API version ); const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, // Example amount in smallest currency unit (cents) currency: currency, - payment_method_types: ["card"], + payment_method_types: ['card'], }); // reply.send({ @@ -57,9 +57,9 @@ async function paymentSheet(fastify: FastifyInstance) { // return reply.code(200).send({ ok: true }); } catch (error) { fastify.log.error(error); - return reply.code(500).send({ message: "Internal Server Error" }); + return reply.code(500).send({ message: 'Internal Server Error' }); } - } + }, ); } diff --git a/apps/data-backend/src/schema/indexer/buy_token.ts b/apps/data-backend/src/schema/indexer/buy_token.ts index 7d039621e..cb4be062e 100644 --- a/apps/data-backend/src/schema/indexer/buy_token.ts +++ b/apps/data-backend/src/schema/indexer/buy_token.ts @@ -1,4 +1,4 @@ -import { gql } from "apollo-server"; +import { gql } from 'apollo-server'; export const AllBuyToken = gql` scalar BigInt diff --git a/apps/data-backend/src/services/auth/auth.service.ts b/apps/data-backend/src/services/auth/auth.service.ts index 5c9c140c6..ab6921e24 100644 --- a/apps/data-backend/src/services/auth/auth.service.ts +++ b/apps/data-backend/src/services/auth/auth.service.ts @@ -1,6 +1,6 @@ -import { PrismaClient } from "@prisma/client"; -import { FastifyInstance } from "fastify"; -import { config } from "../../config"; +import { PrismaClient } from '@prisma/client'; +import { FastifyInstance } from 'fastify'; +import { config } from '../../config'; export class AuthService { constructor(private prisma: PrismaClient, private fastify: FastifyInstance) {} @@ -42,7 +42,7 @@ export class AuthService { }, accessToken, refreshToken, - tokenType: "Bearer", + tokenType: 'Bearer', }; } @@ -71,7 +71,7 @@ export class AuthService { return { accessToken: newAccessToken, refreshToken: newRefreshToken, - tokenType: "Bearer", + tokenType: 'Bearer', }; } diff --git a/apps/data-backend/src/services/auth/signature.service.ts b/apps/data-backend/src/services/auth/signature.service.ts index 686a3fdd6..1d189912b 100644 --- a/apps/data-backend/src/services/auth/signature.service.ts +++ b/apps/data-backend/src/services/auth/signature.service.ts @@ -1,11 +1,6 @@ -import { - Account, - RpcProvider, - TypedData, - WeierstrassSignatureType, -} from "starknet"; +import { Account, RpcProvider, TypedData, WeierstrassSignatureType } from 'starknet'; -import { NODE_URL, SN_CHAIN_ID } from "../../constants/contracts"; +import { NODE_URL, SN_CHAIN_ID } from '../../constants/contracts'; export class SignatureService { private provider: RpcProvider; @@ -38,17 +33,13 @@ export class SignatureService { // Using dummy private key since we only need it for interface compatibility // This won't affect verification as we're only using public methods - const dummyPrivateKey = "0x1"; - const account = new Account( - this.provider, - accountAddress, - dummyPrivateKey - ); + const dummyPrivateKey = '0x1'; + const account = new Account(this.provider, accountAddress, dummyPrivateKey); return await account.verifyMessage(signedData, formattedSignature); } catch (error) { - console.log("verification failed:", error); - throw Error("Error:" + error); + console.log('verification failed:', error); + throw Error('Error:' + error); } } } diff --git a/apps/data-backend/src/services/livestream/queue.ts b/apps/data-backend/src/services/livestream/queue.ts index d011d3f1a..2a9f78a9c 100644 --- a/apps/data-backend/src/services/livestream/queue.ts +++ b/apps/data-backend/src/services/livestream/queue.ts @@ -8,11 +8,7 @@ class UploadQueue { private windowMs: number; private maxRequestsPerWindow: number; - constructor(options: { - concurrency: number; - windowMs: number; - maxRequestsPerWindow: number; - }) { + constructor(options: { concurrency: number; windowMs: number; maxRequestsPerWindow: number }) { this.concurrency = options.concurrency; this.windowMs = options.windowMs; this.maxRequestsPerWindow = options.maxRequestsPerWindow; @@ -72,11 +68,8 @@ async function retry( minTimeout: number; maxTimeout: number; factor: number; - onFailedAttempt?: (error: { - attemptNumber: number; - retriesLeft: number; - }) => Promise; - } + onFailedAttempt?: (error: { attemptNumber: number; retriesLeft: number }) => Promise; + }, ): Promise { let attempt = 1; @@ -99,7 +92,7 @@ async function retry( const timeout = Math.min( options.maxTimeout, - options.minTimeout * Math.pow(options.factor, attempt - 1) + options.minTimeout * Math.pow(options.factor, attempt - 1), ); await new Promise((resolve) => setTimeout(resolve, timeout)); @@ -121,13 +114,8 @@ export const retryOptions = { factor: 2, minTimeout: 1000, maxTimeout: 5000, - onFailedAttempt: async (error: { - attemptNumber: number; - retriesLeft: number; - }) => { - console.log( - `Upload attempt ${error.attemptNumber} failed. ${error.retriesLeft} retries left.` - ); + onFailedAttempt: async (error: { attemptNumber: number; retriesLeft: number }) => { + console.log(`Upload attempt ${error.attemptNumber} failed. ${error.retriesLeft} retries left.`); await new Promise((resolve) => setTimeout(resolve, 1000)); }, }; diff --git a/apps/data-backend/src/services/livestream/socket.ts b/apps/data-backend/src/services/livestream/socket.ts index f8f9ef305..0a11bfd8a 100644 --- a/apps/data-backend/src/services/livestream/socket.ts +++ b/apps/data-backend/src/services/livestream/socket.ts @@ -1,5 +1,5 @@ -import { Server, Socket } from "socket.io"; -import { streamEvents, STREAM_EVENTS } from "./streamEvent"; +import { Server, Socket } from 'socket.io'; +import { streamEvents, STREAM_EVENTS } from './streamEvent'; import { handleStartStream, // handleJoinStream, @@ -8,58 +8,58 @@ import { handleDisconnect, handleJoinStream, // handleDisconnect, -} from "./streamHandler"; +} from './streamHandler'; export const setupWebSocket = (io: Server) => { - io.on("connection", (socket: Socket) => { - console.log("Client connected:", socket.id); + io.on('connection', (socket: Socket) => { + console.log('Client connected:', socket.id); // Stream event listeners streamEvents.on(STREAM_EVENTS.PLAYBACK_URL, (data) => { - socket.emit("playback-url", data); + socket.emit('playback-url', data); }); streamEvents.on(STREAM_EVENTS.STREAMING_URL, (data) => { - socket.emit("streaming-url", data); + socket.emit('streaming-url', data); }); streamEvents.on(STREAM_EVENTS.STREAM_END, ({ streamKey }) => { - socket.to(streamKey).emit("stream-ended", { streamKey }); + socket.to(streamKey).emit('stream-ended', { streamKey }); }); streamEvents.on(STREAM_EVENTS.VIEWER_COUNT, ({ streamKey, count }) => { - socket.to(streamKey).emit("viewer-count", count); + socket.to(streamKey).emit('viewer-count', count); }); streamEvents.on(STREAM_EVENTS.STREAM_ERROR, (error) => { - socket.emit("stream-error", error); + socket.emit('stream-error', error); }); //Handle Screen and camera stream - socket.on("start-stream", (data) => handleStartStream(socket, data)); + socket.on('start-stream', (data) => handleStartStream(socket, data)); //Handle Screen and camera stream - socket.on("stream-data", (data) => handleStreamData(socket, data)); + socket.on('stream-data', (data) => handleStreamData(socket, data)); - socket.on("join-stream", (data) => handleJoinStream(socket, data)); - socket.on("end-stream", (data) => handleEndStream(socket, data)); + socket.on('join-stream', (data) => handleJoinStream(socket, data)); + socket.on('end-stream', (data) => handleEndStream(socket, data)); // WebRTC signaling - socket.on("stream-offer", (data) => { - socket.to(data.streamKey).emit("stream-offer", { + socket.on('stream-offer', (data) => { + socket.to(data.streamKey).emit('stream-offer', { offer: data.offer, streamerId: socket.id, }); }); - socket.on("stream-answer", (data) => { - socket.to(data.streamerId).emit("stream-answer", { + socket.on('stream-answer', (data) => { + socket.to(data.streamerId).emit('stream-answer', { answer: data.answer, viewerId: socket.id, }); }); - socket.on("ice-candidate", (data) => { - socket.to(data.recipientId).emit("ice-candidate", { + socket.on('ice-candidate', (data) => { + socket.to(data.recipientId).emit('ice-candidate', { candidate: data.candidate, senderId: socket.id, }); diff --git a/apps/data-backend/src/services/livestream/streamEvent.ts b/apps/data-backend/src/services/livestream/streamEvent.ts index 508c1277c..69d710681 100644 --- a/apps/data-backend/src/services/livestream/streamEvent.ts +++ b/apps/data-backend/src/services/livestream/streamEvent.ts @@ -1,4 +1,4 @@ -import { EventEmitter } from "events"; +import { EventEmitter } from 'events'; export const streamEvents = new EventEmitter(); @@ -6,9 +6,9 @@ export const streamEvents = new EventEmitter(); streamEvents.setMaxListeners(20); export const STREAM_EVENTS = { - PLAYBACK_URL: "playback-url", - STREAMING_URL: "streaming-url", - STREAM_END: "stream-end", - VIEWER_COUNT: "viewer-count", - STREAM_ERROR: "stream-error", + PLAYBACK_URL: 'playback-url', + STREAMING_URL: 'streaming-url', + STREAM_END: 'stream-end', + VIEWER_COUNT: 'viewer-count', + STREAM_ERROR: 'stream-error', } as const; diff --git a/apps/data-backend/src/services/livestream/streamHandler.ts b/apps/data-backend/src/services/livestream/streamHandler.ts index ec635ca0a..cf94a87af 100644 --- a/apps/data-backend/src/services/livestream/streamHandler.ts +++ b/apps/data-backend/src/services/livestream/streamHandler.ts @@ -1,9 +1,9 @@ -import { Socket } from "socket.io"; +import { Socket } from 'socket.io'; -import * as fs from "fs"; -import path from "path"; -import { streamEvents, STREAM_EVENTS } from "./streamEvent"; -import { setupStream, streamingUrl } from "./streamService"; +import * as fs from 'fs'; +import path from 'path'; +import { streamEvents, STREAM_EVENTS } from './streamEvent'; +import { setupStream, streamingUrl } from './streamService'; /** * Stream Component @@ -34,7 +34,7 @@ export async function handleStartStream( data: { userId: string; streamKey: string; - } + }, ) { try { const { ffmpegCommand, outputPath, inputStream } = await setupStream({ @@ -59,7 +59,7 @@ export async function handleStartStream( socket.join(data.streamKey); ffmpegCommand - .on("error", (err) => { + .on('error', (err) => { console.log(`Stream ${data.streamKey} Just triggered ended`, err); streamEvents.emit(STREAM_EVENTS.STREAM_ERROR, { @@ -68,8 +68,8 @@ export async function handleStartStream( }); }) - .on("end", (res) => { - console.log("ended", res); + .on('end', (res) => { + console.log('ended', res); activeStreams.delete(data.streamKey); streamEvents.emit(STREAM_EVENTS.STREAM_END, { streamKey: data.streamKey, @@ -79,7 +79,7 @@ export async function handleStartStream( ffmpegCommand.output(outputPath).run(); streamEvents.emit(STREAM_EVENTS.STREAMING_URL, { - streamingUrl: `${streamingUrl(data.streamKey, "stream.m3u8")}`, + streamingUrl: `${streamingUrl(data.streamKey, 'stream.m3u8')}`, }); } catch (error) { console.error(error); @@ -94,18 +94,13 @@ export async function handleStartStream( * Handle streaming * Todo: Ideally we will want to process stream to a CDN. */ -export function handleStreamData( - socket: Socket, - data: { streamKey: string; chunk: Buffer } -) { +export function handleStreamData(socket: Socket, data: { streamKey: string; chunk: Buffer }) { const stream = activeStreams.get(data.streamKey); if (!stream?.inputStream) return; try { - const chunk = Buffer.isBuffer(data.chunk) - ? data.chunk - : Buffer.from(data.chunk); + const chunk = Buffer.isBuffer(data.chunk) ? data.chunk : Buffer.from(data.chunk); stream.inputStream.push(chunk); } catch (error) { streamEvents.emit(STREAM_EVENTS.STREAM_ERROR, { @@ -124,7 +119,7 @@ export async function handleEndStream( data: { streamKey: string; userId: string; - } + }, ) { const stream = activeStreams.get(data.streamKey); @@ -138,7 +133,7 @@ export async function handleEndStream( // Kill FFmpeg process if it exists if (stream.command) { - stream.command.kill("SIGKILL"); + stream.command.kill('SIGKILL'); } activeStreams.delete(data.streamKey); @@ -150,7 +145,7 @@ export async function handleEndStream( await cleanupStreamDirectory(data.streamKey); } catch (error) { - console.error("Stream end error:", error); + console.error('Stream end error:', error); streamEvents.emit(STREAM_EVENTS.STREAM_ERROR, { error: error.message, streamKey: data.streamKey, @@ -160,12 +155,7 @@ export async function handleEndStream( const cleanupStreamDirectory = async (streamKey: string): Promise => { try { - const streamPath = path.join( - process.cwd(), - "public", - "livestreams", - streamKey - ); + const streamPath = path.join(process.cwd(), 'public', 'livestreams', streamKey); if (fs.existsSync(streamPath)) { await fs.promises.rm(streamPath, { recursive: true, force: true }); } @@ -182,7 +172,7 @@ export function handleJoinStream(socket: Socket, data: { streamKey: string }) { if (!stream) { streamEvents.emit(STREAM_EVENTS.STREAM_ERROR, { - error: "Stream not found", + error: 'Stream not found', }); return; } @@ -213,7 +203,7 @@ export function handleDisconnect(socket: Socket) { // Kill FFmpeg process if it exists if (stream.command) { - stream.command.kill("SIGKILL"); + stream.command.kill('SIGKILL'); } activeStreams.delete(streamKey); @@ -222,7 +212,7 @@ export function handleDisconnect(socket: Socket) { streamKey: streamKey, }); } catch (error) { - console.error("Stream end error on disconnect:", error); + console.error('Stream end error on disconnect:', error); streamEvents.emit(STREAM_EVENTS.STREAM_ERROR, { error: error.message, streamKey: streamKey, diff --git a/apps/data-backend/src/services/livestream/streamService.ts b/apps/data-backend/src/services/livestream/streamService.ts index 11839a775..0242a54a0 100644 --- a/apps/data-backend/src/services/livestream/streamService.ts +++ b/apps/data-backend/src/services/livestream/streamService.ts @@ -221,18 +221,18 @@ // } // }); -import ffmpeg from "fluent-ffmpeg"; -import { mkdir, access, unlink, readFile, writeFile } from "fs/promises"; -import { S3Client } from "@aws-sdk/client-s3"; -import { Upload } from "@aws-sdk/lib-storage"; -import { constants, createReadStream, watch } from "fs"; -import { basename, join } from "path"; -import { Readable } from "stream"; -import { config } from "../../config"; -import { queuedUpload } from "./queue"; +import ffmpeg from 'fluent-ffmpeg'; +import { mkdir, access, unlink, readFile, writeFile } from 'fs/promises'; +import { S3Client } from '@aws-sdk/client-s3'; +import { Upload } from '@aws-sdk/lib-storage'; +import { constants, createReadStream, watch } from 'fs'; +import { basename, join } from 'path'; +import { Readable } from 'stream'; +import { config } from '../../config'; +import { queuedUpload } from './queue'; const s3Client = new S3Client({ - region: "auto", + region: 'auto', endpoint: config.cloudfare.r2Domain, credentials: { accessKeyId: config.cloudfare.r2Access, @@ -247,10 +247,10 @@ export const streamingUrl = (streamKey: string, fileName: string) => `${config.cloudfare.r2Domain}/livestream/${streamKey}/${fileName}`; const getCommonHeaders = () => ({ - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "GET, HEAD", - "Access-Control-Allow-Headers": "*", - "Cache-Control": "max-age=3600", + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, HEAD', + 'Access-Control-Allow-Headers': '*', + 'Cache-Control': 'max-age=3600', }); export async function ensureDir(dir: string) { @@ -268,57 +268,52 @@ export function createInputStream() { } export async function setupStream(data: { userId: string; streamKey: string }) { - const streamPath = join( - process.cwd(), - "public", - "livestreams", - data.streamKey - ); + const streamPath = join(process.cwd(), 'public', 'livestreams', data.streamKey); await ensureDir(streamPath); - const outputPath = join(streamPath, "stream.m3u8"); + const outputPath = join(streamPath, 'stream.m3u8'); const inputStream = createInputStream(); const ffmpegCommand = ffmpeg() .input(inputStream) - .inputFormat("webm") - .format("hls") - .videoCodec("libx264") - .audioCodec("aac") + .inputFormat('webm') + .format('hls') + .videoCodec('libx264') + .audioCodec('aac') .outputOptions([ // Video quality and encoding - "-preset", - "medium", - "-crf", - "23", - "-maxrate", - "2500k", - "-bufsize", - "5000k", + '-preset', + 'medium', + '-crf', + '23', + '-maxrate', + '2500k', + '-bufsize', + '5000k', // Scaling and resolution - "-vf", - "scale=1280:720", + '-vf', + 'scale=1280:720', // HLS specific settings - "-hls_time", - "2", - "-hls_list_size", - "0", - "-hls_flags", - "delete_segments+append_list", - "-hls_segment_filename", - join(streamPath, "segment_%d.ts"), + '-hls_time', + '2', + '-hls_list_size', + '0', + '-hls_flags', + 'delete_segments+append_list', + '-hls_segment_filename', + join(streamPath, 'segment_%d.ts'), // Keyframe interval - "-g", - "60", + '-g', + '60', // Additional optimization - "-sc_threshold", - "0", - "-movflags", - "+faststart", + '-sc_threshold', + '0', + '-movflags', + '+faststart', ]); watcherFn(streamPath, data, outputPath); @@ -348,13 +343,13 @@ async function uploadFileToR2( bucketName: string, filePath: string, streamKey: string, - fileType: "m3u8" | "ts" + fileType: 'm3u8' | 'ts', ): Promise { const fileName = basename(filePath); const key = `livestream/${streamKey}/${fileName}`; // Skip if segment was already uploaded - if (fileType === "ts" && uploadedSegments.has(key)) { + if (fileType === 'ts' && uploadedSegments.has(key)) { return streamingUrl(streamKey, fileName); } @@ -372,7 +367,7 @@ async function uploadFileToR2( await upload.done(); - if (fileType === "ts") { + if (fileType === 'ts') { uploadedSegments.add(key); } @@ -382,22 +377,13 @@ async function uploadFileToR2( return queuedUpload(upload); } -async function processSegment( - segmentPath: string, - streamKey: string, - m3u8Path: string -) { +async function processSegment(segmentPath: string, streamKey: string, m3u8Path: string) { try { if (!(await fileExists(segmentPath))) { return; } - await uploadFileToR2( - config.cloudfare.r2BucketName, - segmentPath, - streamKey, - "ts" - ); + await uploadFileToR2(config.cloudfare.r2BucketName, segmentPath, streamKey, 'ts'); if (await fileExists(m3u8Path)) { await updateAndUploadM3u8(m3u8Path, streamKey); @@ -420,32 +406,23 @@ async function updateAndUploadM3u8(localM3u8Path: string, streamKey: string) { return; } - let content = await readFile(localM3u8Path, "utf8"); + let content = await readFile(localM3u8Path, 'utf8'); - if (!content.includes("#EXTM3U")) { - content = "#EXTM3U\n#EXT-X-VERSION:3\n" + content; + if (!content.includes('#EXTM3U')) { + content = '#EXTM3U\n#EXT-X-VERSION:3\n' + content; } - await writeFile(localM3u8Path, content, "utf8"); - await uploadFileToR2( - config.cloudfare.r2BucketName, - localM3u8Path, - streamKey, - "m3u8" - ); + await writeFile(localM3u8Path, content, 'utf8'); + await uploadFileToR2(config.cloudfare.r2BucketName, localM3u8Path, streamKey, 'm3u8'); } catch (err) { - console.error("Error updating and uploading m3u8:", err); + console.error('Error updating and uploading m3u8:', err); throw err; } } -const watcherFn = ( - streamPath: string, - data: { streamKey: string }, - outputPath: string -) => { +const watcherFn = (streamPath: string, data: { streamKey: string }, outputPath: string) => { const watcher = watch(streamPath, async (eventType, filename) => { - if (eventType === "rename" && filename?.endsWith(".ts")) { + if (eventType === 'rename' && filename?.endsWith('.ts')) { const segmentPath = join(streamPath, filename); await processSegment(segmentPath, data.streamKey, outputPath); } diff --git a/apps/data-backend/src/services/socials/twitter.service.ts b/apps/data-backend/src/services/socials/twitter.service.ts index 2bc41e0ad..b644ffc9b 100644 --- a/apps/data-backend/src/services/socials/twitter.service.ts +++ b/apps/data-backend/src/services/socials/twitter.service.ts @@ -1,12 +1,8 @@ -import { type IParsedOAuth2TokenResult, TwitterApi } from "twitter-api-v2"; -import { addDays } from "date-fns"; -import { - ConnectTwitterParams, - SocialPlatform, - TwitterUserDetails, -} from "../../types"; -import { PrismaClient } from "@prisma/client"; -import { FastifyInstance } from "fastify"; +import { type IParsedOAuth2TokenResult, TwitterApi } from 'twitter-api-v2'; +import { addDays } from 'date-fns'; +import { ConnectTwitterParams, SocialPlatform, TwitterUserDetails } from '../../types'; +import { PrismaClient } from '@prisma/client'; +import { FastifyInstance } from 'fastify'; export class TwitterService { private client: TwitterApi; @@ -20,12 +16,9 @@ export class TwitterService { } async getAuthorizationLink() { - const data = this.client.generateOAuth2AuthLink( - process.env.TWITTER_CALLBACK_URL!, - { - scope: ["tweet.read", "users.read", "offline.access"], - } - ); + const data = this.client.generateOAuth2AuthLink(process.env.TWITTER_CALLBACK_URL!, { + scope: ['tweet.read', 'users.read', 'offline.access'], + }); return data; } @@ -51,7 +44,7 @@ export class TwitterService { const me = await userClient.v2.me(); if (!me.data) { - throw new Error("Failed to fetch Twitter user details"); + throw new Error('Failed to fetch Twitter user details'); } return { @@ -74,8 +67,10 @@ export class TwitterService { } // 2. Complete OAuth flow - const { accessToken, refreshToken, expiresIn } = - await this.handleCallback({ code, codeVerifier }); + const { accessToken, refreshToken, expiresIn } = await this.handleCallback({ + code, + codeVerifier, + }); // 3. Get user details from Twitter const twitterUser = await this.getUserDetails(accessToken); @@ -111,7 +106,7 @@ export class TwitterService { }, }); } catch (error) { - console.error("Error connecting Twitter account:", error); + console.error('Error connecting Twitter account:', error); throw error; } } @@ -128,7 +123,7 @@ export class TwitterService { }); if (!socialAccount) { - throw new Error("No Twitter account found for user"); + throw new Error('No Twitter account found for user'); } // Check if token needs refresh (1 day buffer) @@ -137,8 +132,9 @@ export class TwitterService { : true; if (shouldRefresh && socialAccount.refreshToken) { - const { accessToken, refreshToken } = - await this.client.refreshOAuth2Token(socialAccount.refreshToken); + const { accessToken, refreshToken } = await this.client.refreshOAuth2Token( + socialAccount.refreshToken, + ); // Update tokens in database return await this.prisma.socialAccount.update({ @@ -155,7 +151,7 @@ export class TwitterService { return socialAccount; } catch (error) { - console.error("Error refreshing Twitter token:", error); + console.error('Error refreshing Twitter token:', error); throw error; } } @@ -172,15 +168,12 @@ export class TwitterService { }); if (!socialAccount) { - throw new Error("No Twitter account found for user"); + throw new Error('No Twitter account found for user'); } // Revoke tokens if they exist if (socialAccount.accessToken) { - await this.client.revokeOAuth2Token( - socialAccount.accessToken, - "access_token" - ); + await this.client.revokeOAuth2Token(socialAccount.accessToken, 'access_token'); } // Delete the social account record @@ -192,7 +185,7 @@ export class TwitterService { return true; } catch (error) { - console.error("Error disconnecting Twitter account:", error); + console.error('Error disconnecting Twitter account:', error); throw error; } } diff --git a/apps/data-backend/src/services/telegram-app.ts b/apps/data-backend/src/services/telegram-app.ts index f6552c0ef..50017a57b 100644 --- a/apps/data-backend/src/services/telegram-app.ts +++ b/apps/data-backend/src/services/telegram-app.ts @@ -1,14 +1,12 @@ -import dotenv from "dotenv"; +import dotenv from 'dotenv'; dotenv.config(); const TELEGRAM_API_URL = `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}`; -const WEB_APP_URL = - process.env.TELEGRAM_WEB_APP ?? "https://lfg.afk-community.xyz"; // Replace with your web app's URL +const WEB_APP_URL = process.env.TELEGRAM_WEB_APP ?? 'https://lfg.afk-community.xyz'; // Replace with your web app's URL -const MOBILE_APP_URL = - process.env.TELEGRAM_MOBILE_APP ?? "https:/afk-community.xyz"; +const MOBILE_APP_URL = process.env.TELEGRAM_MOBILE_APP ?? 'https:/afk-community.xyz'; // Use require instead of import because of the error "Cannot use import statement outside a module" -import { Telegraf } from "telegraf"; -import { message } from "telegraf/filters"; +import { Telegraf } from 'telegraf'; +import { message } from 'telegraf/filters'; /** * Creates and launches Telegram bot, and assigns all the required listeners @@ -31,14 +29,14 @@ export function launchBot(token: string) { listenToMiniAppData(bot); // Launch the bot - bot.launch().then(() => console.log("bot launched")); + bot.launch().then(() => console.log('bot launched')); // Handle stop events enableGracefulStop(bot); // return bot } catch (e) { - console.log("launchBot error", e); + console.log('launchBot error', e); } } @@ -53,12 +51,12 @@ function listenToCommands(bot) { // Register a listener for the /start command, and reply with a message whenever it's used bot.start(async (ctx) => { try { - await ctx.reply("Welcome to MiniAppSample bot!", { + await ctx.reply('Welcome to MiniAppSample bot!', { reply_markup: { keyboard: [ [ { - text: "Start Mini App", + text: 'Start Mini App', web_app: { url: process.env.TELEGRAM_WEB_APP }, }, ], @@ -66,18 +64,18 @@ function listenToCommands(bot) { }, }); - await ctx.reply("Click on the button below to launch our mini app", { + await ctx.reply('Click on the button below to launch our mini app', { reply_markup: { inline_keyboard: [ [ { - text: "Start Mini App", + text: 'Start Mini App', web_app: { url: WEB_APP_URL ?? process.env.TELEGRAM_WEB_APP }, }, ], [ { - text: "Start AFK", + text: 'Start AFK', web_app: { url: MOBILE_APP_URL ?? process.env.TELEGRAM_MOBILE_APP, }, @@ -87,13 +85,13 @@ function listenToCommands(bot) { }, }); } catch (error) { - console.log("Error", error); + console.log('Error', error); } }); // Register a listener for the /help command, and reply with a message whenever it's used bot.help(async (ctx) => { - await ctx.reply("Run the /start command to use our mini app"); + await ctx.reply('Run the /start command to use our mini app'); }); } catch (e) {} } @@ -107,26 +105,22 @@ function listenToCommands(bot) { function listenToMessages(bot: Telegraf) { try { // Listen to messages and reply with something when ever you receive them - bot.hears("hi", async (ctx) => { - await ctx.reply("Hey there!"); + bot.hears('hi', async (ctx) => { + await ctx.reply('Hey there!'); }); // Listen to messages with the type 'sticker' and reply whenever you receive them - bot.on(message("text"), async (ctx) => { - await ctx.reply( - "I don't understand text but I like stickers, send me some!" - ); - await ctx.reply( - "Or you can send me one of these commands \n/start\n/help" - ); + bot.on(message('text'), async (ctx) => { + await ctx.reply("I don't understand text but I like stickers, send me some!"); + await ctx.reply('Or you can send me one of these commands \n/start\n/help'); }); // Listen to messages with the type 'sticker' and reply whenever you receive them - bot.on(message("sticker"), async (ctx) => { - await ctx.reply("I like your sticker! 🔥"); + bot.on(message('sticker'), async (ctx) => { + await ctx.reply('I like your sticker! 🔥'); }); } catch (e) { - console.log("listenToMessages", e); + console.log('listenToMessages', e); } } @@ -138,26 +132,23 @@ function listenToMessages(bot: Telegraf) { */ function listenToMiniAppData(bot) { try { - bot.on("message", async (ctx) => { + bot.on('message', async (ctx) => { if (ctx.message?.web_app_data?.data) { try { const data = ctx.message?.web_app_data?.data; - await ctx.telegram.sendMessage( - ctx.message.chat.id, - "Got message from MiniApp" - ); + await ctx.telegram.sendMessage(ctx.message.chat.id, 'Got message from MiniApp'); await ctx.telegram.sendMessage(ctx.message.chat.id, data); } catch (e) { await ctx.telegram.sendMessage( ctx.message.chat.id, - "Got message from MiniApp but failed to read" + 'Got message from MiniApp but failed to read', ); await ctx.telegram.sendMessage(ctx.message.chat.id, e); } } }); } catch (e) { - console.log("Error listenMiniAppData", e); + console.log('Error listenMiniAppData', e); } } @@ -169,7 +160,7 @@ function listenToMiniAppData(bot) { */ function listenToQueries(bot) { try { - bot.on("callback_query", async (ctx) => { + bot.on('callback_query', async (ctx) => { // Explicit usage await ctx.telegram.answerCbQuery(ctx.callbackQuery.id); @@ -177,11 +168,11 @@ function listenToQueries(bot) { await ctx.answerCbQuery(); }); - bot.on("inline_query", async (ctx) => { + bot.on('inline_query', async (ctx) => { const article = { - type: "article", + type: 'article', id: ctx.inlineQuery.id, - title: "Message for query", + title: 'Message for query', input_message_content: { message_text: `Message for query`, }, @@ -205,8 +196,8 @@ function listenToQueries(bot) { function enableGracefulStop(bot) { try { // Enable graceful stop - process.once("SIGINT", () => bot.stop("SIGINT")); - process.once("SIGTERM", () => bot.stop("SIGTERM")); + process.once('SIGINT', () => bot.stop('SIGINT')); + process.once('SIGTERM', () => bot.stop('SIGTERM')); } catch (e) {} } @@ -225,9 +216,9 @@ export const handleMessageRequest = async (bot, request, response) => { // We are creating InlineQueryResultArticle // See https://core.telegram.org/bots/api#inlinequeryresultarticle const article = { - type: "article", + type: 'article', id: queryId, - title: "Message from the mini app", + title: 'Message from the mini app', input_message_content: { message_text: `MiniApp: ${message}`, }, @@ -238,7 +229,7 @@ export const handleMessageRequest = async (bot, request, response) => { // End the request with a success code await response.status(200).json({ - message: "success!", + message: 'success!', }); } catch (e) { const errorJson = JSON.stringify(e); @@ -253,15 +244,15 @@ export const handleMessageRequest = async (bot, request, response) => { export async function sendWebAppButton(chatId) { try { const url = `${TELEGRAM_API_URL}/sendMessage`; - console.log("web app url", WEB_APP_URL); + console.log('web app url', WEB_APP_URL); const body = { chat_id: chatId, - text: "Click the button below to open the web app:", + text: 'Click the button below to open the web app:', reply_markup: { inline_keyboard: [ [ { - text: "Open Web App", + text: 'Open Web App', web_app: { url: WEB_APP_URL, }, @@ -272,9 +263,9 @@ export async function sendWebAppButton(chatId) { }; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify(body), }); @@ -286,7 +277,7 @@ export async function sendWebAppButton(chatId) { const result = await response.json(); console.log(result); } catch (e) { - console.log("Error sendWebApp", e); + console.log('Error sendWebApp', e); } } @@ -300,9 +291,9 @@ export async function sendMessage(chatId, text) { }; const response = await fetch(url, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, body: JSON.stringify(body), }); @@ -311,6 +302,6 @@ export async function sendMessage(chatId, text) { console.error(`Error sending message: ${response.statusText}`); } } catch (e) { - console.log("sendMessage error", e); + console.log('sendMessage error', e); } } diff --git a/apps/data-backend/src/services/twitter-client.ts b/apps/data-backend/src/services/twitter-client.ts index d50afd6a5..6fe477c38 100644 --- a/apps/data-backend/src/services/twitter-client.ts +++ b/apps/data-backend/src/services/twitter-client.ts @@ -1,5 +1,5 @@ -import { TwitterApi } from "twitter-api-v2"; -import axios from "axios"; +import { TwitterApi } from 'twitter-api-v2'; +import axios from 'axios'; export const getTwitterClient = (accessToken: string, accessSecret: string) => { return new TwitterApi({ @@ -11,21 +11,16 @@ export const getTwitterClient = (accessToken: string, accessSecret: string) => { }; export const getRequestToken = async () => { - const response = await axios.post( - "https://api.twitter.com/oauth/request_token", - null, - { - headers: { - Authorization: `OAuth oauth_consumer_key="${process.env - .TWITTER_API_KEY!}", oauth_signature="${process.env - .TWITTER_API_SECRET_KEY!}&"`, - }, - } - ); + const response = await axios.post('https://api.twitter.com/oauth/request_token', null, { + headers: { + Authorization: `OAuth oauth_consumer_key="${process.env + .TWITTER_API_KEY!}", oauth_signature="${process.env.TWITTER_API_SECRET_KEY!}&"`, + }, + }); const params = new URLSearchParams(response.data); return { - oauthToken: params.get("oauth_token"), - oauthTokenSecret: params.get("oauth_token_secret"), + oauthToken: params.get('oauth_token'), + oauthTokenSecret: params.get('oauth_token_secret'), }; }; diff --git a/apps/data-backend/src/types/index.ts b/apps/data-backend/src/types/index.ts index 9afab7f73..49056ce96 100644 --- a/apps/data-backend/src/types/index.ts +++ b/apps/data-backend/src/types/index.ts @@ -1,4 +1,4 @@ -import { Signature, TypedData } from "starknet"; +import { Signature, TypedData } from 'starknet'; export interface UserJwtPayload { id: string; userAddress: string; @@ -20,7 +20,7 @@ export interface SignatureVerificationRequest { * Twitter Types */ export enum SocialPlatform { - TWITTER = "TWITTER", + TWITTER = 'TWITTER', // Add other platforms as needed // GITHUB = "GITHUB", // GOOGLE = "GOOGLE", diff --git a/apps/data-backend/src/utils/address.ts b/apps/data-backend/src/utils/address.ts index 10ec29ddb..e72c3f5b0 100644 --- a/apps/data-backend/src/utils/address.ts +++ b/apps/data-backend/src/utils/address.ts @@ -1,16 +1,16 @@ -import { hash } from "starknet"; -import { hashPhoneNumber } from "./format"; +import { hash } from 'starknet'; +import { hashPhoneNumber } from './format'; import { BLANK_ACCOUNT_CLASS_HASH, SN_CHAIN_ID, VAULT_FACTORY_ADDRESSES, -} from "../constants/contracts"; +} from '../constants/contracts'; export function computeAddress(phoneNumber: string) { return hash.calculateContractAddressFromHash( hashPhoneNumber(phoneNumber), BLANK_ACCOUNT_CLASS_HASH, [], - VAULT_FACTORY_ADDRESSES[SN_CHAIN_ID] + VAULT_FACTORY_ADDRESSES[SN_CHAIN_ID], ); } diff --git a/apps/data-backend/src/utils/constants.ts b/apps/data-backend/src/utils/constants.ts index 3262d17ca..457e5d776 100644 --- a/apps/data-backend/src/utils/constants.ts +++ b/apps/data-backend/src/utils/constants.ts @@ -1,4 +1,4 @@ -import dotenv from "dotenv"; +import dotenv from 'dotenv'; dotenv.config(); export const TELEGRAM_API_URL = `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}`; diff --git a/apps/data-backend/src/utils/format.ts b/apps/data-backend/src/utils/format.ts index 89a595779..fce44f3b7 100644 --- a/apps/data-backend/src/utils/format.ts +++ b/apps/data-backend/src/utils/format.ts @@ -1,4 +1,4 @@ -import { hash, shortString } from "starknet"; +import { hash, shortString } from 'starknet'; export function hashPhoneNumber(phoneNumber: string) { return hash.starknetKeccak(shortString.encodeShortString(phoneNumber)); diff --git a/apps/data-backend/src/utils/funkit.ts b/apps/data-backend/src/utils/funkit.ts index 811fd3097..68c3e8f7c 100644 --- a/apps/data-backend/src/utils/funkit.ts +++ b/apps/data-backend/src/utils/funkit.ts @@ -20,9 +20,9 @@ export function generateClientMetadata({ symbol: pickedSourceAsset.symbol.toUpperCase(), }, selectedPaymentMethodInfo: { - paymentMethod: "card", - title: "Debit or Credit", - description: "", + paymentMethod: 'card', + title: 'Debit or Credit', + description: '', meta: {}, }, }; @@ -31,9 +31,7 @@ export function generateClientMetadata({ export function roundUpToFiveDecimalPlaces(inputNumber: string) { // Using toFixed to round up to 5 decimal places const multiplier = 10 ** 5; - const roundedString = ( - Math.ceil(parseFloat(inputNumber) * multiplier) / multiplier - ).toFixed(5); + const roundedString = (Math.ceil(parseFloat(inputNumber) * multiplier) / multiplier).toFixed(5); // Converting the rounded string back to a number const roundedNumber = parseFloat(roundedString); return roundedNumber; diff --git a/apps/data-backend/src/validations/auth.validation.ts b/apps/data-backend/src/validations/auth.validation.ts index ed7517734..f39932b5b 100644 --- a/apps/data-backend/src/validations/auth.validation.ts +++ b/apps/data-backend/src/validations/auth.validation.ts @@ -1,32 +1,30 @@ -import { z } from "zod"; +import { z } from 'zod'; export const authSchema = { login: z.object({ - userAddress: z.string().min(1, "User address is required"), - loginType: z.enum(["starknet", "ethereum", "other"]), + userAddress: z.string().min(1, 'User address is required'), + loginType: z.enum(['starknet', 'ethereum', 'other']), signature: z.array(z.string()).min(2), - signedData: z.string().min(1, "Signed data is required"), + signedData: z.string().min(1, 'Signed data is required'), }), refreshToken: z.object({ - refreshToken: z.string().min(1, "Refresh token is required"), + refreshToken: z.string().min(1, 'Refresh token is required'), }), twitterCallback: z.object({ - codeVerifier: z.string().min(1, "Refresh token is required"), - code: z.string().min(1, "Refresh token is required"), + codeVerifier: z.string().min(1, 'Refresh token is required'), + code: z.string().min(1, 'Refresh token is required'), }), connectTwitterParams: z.object({ - userId: z.string().min(1, "UserId is required"), - codeVerifier: z.string().min(1, "Code Verifier is required"), - code: z.string().min(1, "Code is required"), + userId: z.string().min(1, 'UserId is required'), + codeVerifier: z.string().min(1, 'Code Verifier is required'), + code: z.string().min(1, 'Code is required'), }), }; -export type ConnectTwitterInput = z.infer< - typeof authSchema.connectTwitterParams ->; +export type ConnectTwitterInput = z.infer; export type TwitterCallbackInput = z.infer; export type LoginInput = z.infer; export type RefreshTokenInput = z.infer; diff --git a/apps/data-backend/src/validations/config.validation.ts b/apps/data-backend/src/validations/config.validation.ts index bd94a59d8..554fae99c 100644 --- a/apps/data-backend/src/validations/config.validation.ts +++ b/apps/data-backend/src/validations/config.validation.ts @@ -1,8 +1,8 @@ -import { z } from "zod"; +import { z } from 'zod'; // Define the schema for the configuration export const ConfigSchema = z.object({ jwt: z.object({ - secret: z.string().min(1, "JWT secret is required"), + secret: z.string().min(1, 'JWT secret is required'), accessTokenExpiry: z.string(), refreshTokenExpiry: z.string(), }), @@ -11,22 +11,22 @@ export const ConfigSchema = z.object({ host: z.string(), }), cloudinary: z.object({ - cloud_name: z.string().min(1, "Cloudinary cloud name is required"), - api_key: z.string().min(1, "Cloudinary API key is required"), - api_secret: z.string().min(1, "Cloudinary API secret is required"), + cloud_name: z.string().min(1, 'Cloudinary cloud name is required'), + api_key: z.string().min(1, 'Cloudinary API key is required'), + api_secret: z.string().min(1, 'Cloudinary API secret is required'), }), cloudfare: z.object({ - accountId: z.string().min(1, "Cloudfare accountId is required"), - token: z.string().min(1, "Cloudfare Auth Token is required"), - r2BucketName: z.string().min(1, "Cloudfare r2 bucket name is required"), - r2Access: z.string().min(1, "Cloudfare r2 accountId is required"), - r2Secret: z.string().min(1, "Cloudfare r2 secret is required"), - r2Domain: z.string().min(1, "Cloudfare r2 Domain is required"), + accountId: z.string().min(1, 'Cloudfare accountId is required'), + token: z.string().min(1, 'Cloudfare Auth Token is required'), + r2BucketName: z.string().min(1, 'Cloudfare r2 bucket name is required'), + r2Access: z.string().min(1, 'Cloudfare r2 accountId is required'), + r2Secret: z.string().min(1, 'Cloudfare r2 secret is required'), + r2Domain: z.string().min(1, 'Cloudfare r2 Domain is required'), }), rpc: z.object({ - starknetRpcUrl: z.string().min(1, "RPC url required"), - starknetNetwork: z.string().min(1, "StarknetNetwork required"), - api_key: z.string().min(1, "Rpc apikey required"), - network: z.string().min(1, "Rpc network required"), + starknetRpcUrl: z.string().min(1, 'RPC url required'), + starknetNetwork: z.string().min(1, 'StarknetNetwork required'), + api_key: z.string().min(1, 'Rpc apikey required'), + network: z.string().min(1, 'Rpc network required'), }), }); diff --git a/apps/nestjs-indexer/package.json b/apps/nestjs-indexer/package.json index 8743d526f..23e247327 100644 --- a/apps/nestjs-indexer/package.json +++ b/apps/nestjs-indexer/package.json @@ -8,6 +8,7 @@ "scripts": { "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", @@ -18,7 +19,8 @@ "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json", - "start:dev:db": "bash src/scripts/postgres.sh" + "start:dev:db": "bash src/scripts/postgres.sh", + "ts:check": "tsc --noEmit" }, "dependencies": { "@apibara/protocol": "^0.4.9", @@ -29,6 +31,7 @@ "@nestjs/platform-express": "^10.0.0", "@prisma/client": "^6.0.0", "env-var": "^7.5.0", + "indexer-prisma": "workspace:*", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "viem": "^2.21.53" diff --git a/packages/indexer-prisma/dist/index.d.ts b/packages/indexer-prisma/dist/index.d.ts index 5b615c49c..a3576af1a 100644 --- a/packages/indexer-prisma/dist/index.d.ts +++ b/packages/indexer-prisma/dist/index.d.ts @@ -1,6 +1,9 @@ import { PrismaClient } from '../prisma/.prisma/client'; -declare const prisma: PrismaClient; -export * from '@prisma/client'; +declare const prisma: PrismaClient< + import('../prisma/.prisma/client').Prisma.PrismaClientOptions, + never, + import('../prisma/.prisma/client/runtime/library').DefaultArgs +>; export default prisma; export { PrismaClient }; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file +//# sourceMappingURL=index.d.ts.map diff --git a/packages/indexer-prisma/dist/index.d.ts.map b/packages/indexer-prisma/dist/index.d.ts.map index 8d89efa5c..678b9227a 100644 --- a/packages/indexer-prisma/dist/index.d.ts.map +++ b/packages/indexer-prisma/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAA;AAErD,QAAA,MAAM,MAAM,oJAAqB,CAAA;AAOjC,cAAc,gBAAgB,CAAA;AAE9B,eAAe,MAAM,CAAA;AACrB,OAAO,EAAE,YAAY,EAAE,CAAA"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAA;AAErD,QAAA,MAAM,MAAM,oJAAqB,CAAA;AAEjC,eAAe,MAAM,CAAA;AACrB,OAAO,EAAE,YAAY,EAAE,CAAA"} \ No newline at end of file diff --git a/packages/indexer-prisma/dist/index.js b/packages/indexer-prisma/dist/index.js index d3cc46316..7c5c8edbf 100644 --- a/packages/indexer-prisma/dist/index.js +++ b/packages/indexer-prisma/dist/index.js @@ -1,32 +1,13 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); exports.PrismaClient = void 0; -const client_1 = require("../prisma/.prisma/client"); -Object.defineProperty(exports, "PrismaClient", { enumerable: true, get: function () { return client_1.PrismaClient; } }); +const client_1 = require('../prisma/.prisma/client'); +Object.defineProperty(exports, 'PrismaClient', { + enumerable: true, + get: function () { + return client_1.PrismaClient; + }, +}); const prisma = new client_1.PrismaClient(); -// Test the connection -// prisma.$connect() -// .then(() => console.log('Successfully connected to database')) -// .catch((e: any) => console.error('Failed to connect to database:', e)) -// Export everything from @prisma/client for types -__exportStar(require("@prisma/client"), exports); exports.default = prisma; -// import { PrismaClient } from '@prisma/client' -// export const prisma = new PrismaClient() -// // Export any other types or utilities you need -// export * from '@prisma/client' -//# sourceMappingURL=index.js.map \ No newline at end of file +//# sourceMappingURL=index.js.map diff --git a/packages/indexer-prisma/dist/index.js.map b/packages/indexer-prisma/dist/index.js.map index 25872e2cd..1007ddf7b 100644 --- a/packages/indexer-prisma/dist/index.js.map +++ b/packages/indexer-prisma/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qDAAqD;AAY5C,6FAZD,qBAAY,OAYC;AAVrB,MAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAA;AACjC,sBAAsB;AACtB,oBAAoB;AACpB,mEAAmE;AACnE,2EAA2E;AAE3E,kDAAkD;AAClD,iDAA8B;AAE9B,kBAAe,MAAM,CAAA;AAGrB,gDAAgD;AAEhD,2CAA2C;AAE3C,kDAAkD;AAClD,iCAAiC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAqD;AAK5C,6FALD,qBAAY,OAKC;AAHrB,MAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAA;AAEjC,kBAAe,MAAM,CAAA"} \ No newline at end of file diff --git a/packages/indexer-prisma/src/index copy.js b/packages/indexer-prisma/src/index copy.js deleted file mode 100644 index 6ba00302b..000000000 --- a/packages/indexer-prisma/src/index copy.js +++ /dev/null @@ -1,3 +0,0 @@ -const { PrismaClient } = require("../prisma/.prisma/client"); -const prisma = new PrismaClient(); -module.exports = { prisma, PrismaClient }; diff --git a/packages/indexer-prisma/src/index.d.ts b/packages/indexer-prisma/src/index.d.ts deleted file mode 100644 index 00e9ee93c..000000000 --- a/packages/indexer-prisma/src/index.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export default prisma; -declare const prisma: PrismaClient< - import("../prisma/.prisma/client").Prisma.PrismaClientOptions, - never, - import("../prisma/.prisma/client/runtime/library").DefaultArgs ->; -import { PrismaClient } from "../prisma/.prisma/client"; -export { PrismaClient }; diff --git a/packages/indexer-prisma/src/index.ts b/packages/indexer-prisma/src/index.ts index edfe3dbc4..ed3cf415b 100644 --- a/packages/indexer-prisma/src/index.ts +++ b/packages/indexer-prisma/src/index.ts @@ -1,20 +1,6 @@ -import {PrismaClient} from '../prisma/.prisma/client' +import { PrismaClient } from '../prisma/.prisma/client'; -const prisma = new PrismaClient() -// Test the connection -// prisma.$connect() -// .then(() => console.log('Successfully connected to database')) -// .catch((e: any) => console.error('Failed to connect to database:', e)) +const prisma = new PrismaClient(); -// Export everything from @prisma/client for types -export * from '@prisma/client' - -export default prisma -export { PrismaClient } - -// import { PrismaClient } from '@prisma/client' - -// export const prisma = new PrismaClient() - -// // Export any other types or utilities you need -// export * from '@prisma/client' \ No newline at end of file +export default prisma; +export { PrismaClient }; diff --git a/packages/prisma-db/package.json b/packages/prisma-db/package.json index b9728227d..8a0c0e67c 100644 --- a/packages/prisma-db/package.json +++ b/packages/prisma-db/package.json @@ -7,8 +7,9 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "npx prisma generate && npx prisma db pull && tsc", - "generate":"npx prisma generate", - "pull":"npx prisma db pull" + "generate": "npx prisma generate", + "pull": "npx prisma db pull", + "push": "npx prisma db push" }, "keywords": [], "author": "",