From 9980969f5b8295625dc0f35b0461b348cfe595ee Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 14:19:17 +0530 Subject: [PATCH 01/20] dummy service --- docs/fly.prod.toml | 1 + docs/fly.toml | 1 + .../src/alerts/alerts.controller.spec.ts | 18 ++++++++++++++++++ .../backend/src/alerts/alerts.controller.ts | 15 +++++++++++++++ web-portal/backend/src/alerts/alerts.module.ts | 9 +++++++++ .../backend/src/alerts/alerts.service.spec.ts | 18 ++++++++++++++++++ .../backend/src/alerts/alerts.service.ts | 13 +++++++++++++ web-portal/backend/src/app.module.ts | 2 ++ web-portal/frontend/next.config.js | 12 +----------- web-portal/frontend/utils/Web3Provider.tsx | 16 ++++++++++------ 10 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 web-portal/backend/src/alerts/alerts.controller.spec.ts create mode 100644 web-portal/backend/src/alerts/alerts.controller.ts create mode 100644 web-portal/backend/src/alerts/alerts.module.ts create mode 100644 web-portal/backend/src/alerts/alerts.service.spec.ts create mode 100644 web-portal/backend/src/alerts/alerts.service.ts diff --git a/docs/fly.prod.toml b/docs/fly.prod.toml index e2f32ae..dd21b81 100644 --- a/docs/fly.prod.toml +++ b/docs/fly.prod.toml @@ -8,6 +8,7 @@ primary_region = 'sea' [http_service] internal_port = 3000 + force_https = true auto_stop_machines = true auto_start_machines = true min_machines_running = 0 diff --git a/docs/fly.toml b/docs/fly.toml index 556cb11..a5f565c 100644 --- a/docs/fly.toml +++ b/docs/fly.toml @@ -9,6 +9,7 @@ primary_region = 'sea' [http_service] internal_port = 3000 + force_https = true auto_stop_machines = true auto_start_machines = true min_machines_running = 0 diff --git a/web-portal/backend/src/alerts/alerts.controller.spec.ts b/web-portal/backend/src/alerts/alerts.controller.spec.ts new file mode 100644 index 0000000..3986c6d --- /dev/null +++ b/web-portal/backend/src/alerts/alerts.controller.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AlertsController } from './alerts.controller'; + +describe('AlertsController', () => { + let controller: AlertsController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AlertsController], + }).compile(); + + controller = module.get(AlertsController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/web-portal/backend/src/alerts/alerts.controller.ts b/web-portal/backend/src/alerts/alerts.controller.ts new file mode 100644 index 0000000..5e4d7b8 --- /dev/null +++ b/web-portal/backend/src/alerts/alerts.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { AlertsService } from './alerts.service'; + +@Controller('alerts') +export class AlertsController { + constructor(private readonly alertService: AlertsService) { } + @Get('app/:appId') + async getAppAlerts(@Param('appId') appId: string) { + return this.alertService.getAppAlerts(appId) + } + @Get('tenant/:tenantId') + async getTenantAlerts(@Param('appId') tenantId: string) { + return this.alertService.getTenantAlerts(tenantId) + } +} diff --git a/web-portal/backend/src/alerts/alerts.module.ts b/web-portal/backend/src/alerts/alerts.module.ts new file mode 100644 index 0000000..62ebc07 --- /dev/null +++ b/web-portal/backend/src/alerts/alerts.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { AlertsService } from './alerts.service'; +import { AlertsController } from './alerts.controller'; + +@Module({ + providers: [AlertsService], + controllers: [AlertsController] +}) +export class AlertsModule {} diff --git a/web-portal/backend/src/alerts/alerts.service.spec.ts b/web-portal/backend/src/alerts/alerts.service.spec.ts new file mode 100644 index 0000000..0294813 --- /dev/null +++ b/web-portal/backend/src/alerts/alerts.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AlertsService } from './alerts.service'; + +describe('AlertsService', () => { + let service: AlertsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AlertsService], + }).compile(); + + service = module.get(AlertsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/web-portal/backend/src/alerts/alerts.service.ts b/web-portal/backend/src/alerts/alerts.service.ts new file mode 100644 index 0000000..d71d1e7 --- /dev/null +++ b/web-portal/backend/src/alerts/alerts.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AlertsService { + async getAppAlerts(appId: string): Promise { + const rateLimited = Math.random() < 0.5 + return rateLimited + } + async getTenantAlerts(tenantId: string): Promise { + const rateLimited = Math.random() < 0.5 + return rateLimited + } +} diff --git a/web-portal/backend/src/app.module.ts b/web-portal/backend/src/app.module.ts index 65fe402..eabbd2b 100644 --- a/web-portal/backend/src/app.module.ts +++ b/web-portal/backend/src/app.module.ts @@ -14,6 +14,7 @@ import { UsageModule } from './usage/usage.module'; import { SiweService } from './siwe/siwe.service'; import { AuthGuard } from './guards/auth.guard'; import { AppsService } from './apps/apps.service'; +import { AlertsModule } from './alerts/alerts.module'; @Module({ imports: [ @@ -32,6 +33,7 @@ import { AppsService } from './apps/apps.service'; OrgModule, UtilsModule, UsageModule, + AlertsModule, ], providers: [ SiweService, diff --git a/web-portal/frontend/next.config.js b/web-portal/frontend/next.config.js index 819fc45..b210464 100644 --- a/web-portal/frontend/next.config.js +++ b/web-portal/frontend/next.config.js @@ -19,17 +19,7 @@ const nextConfig = { return config; }, images: { - remotePatterns: [ - { - protocol: "https", - hostname: "api.web3modal.com", - port: "", - }, - { - protocol: "https", - hostname: "*.1inch.io", - }, - ], + domains: ['api.web3modal.com','*.1inch.io'], }, async rewrites() { return [ diff --git a/web-portal/frontend/utils/Web3Provider.tsx b/web-portal/frontend/utils/Web3Provider.tsx index 3c19ea5..cf2306f 100644 --- a/web-portal/frontend/utils/Web3Provider.tsx +++ b/web-portal/frontend/utils/Web3Provider.tsx @@ -6,13 +6,17 @@ import { Provider as JotaiProvider } from "jotai"; import { State, WagmiProvider } from "wagmi"; import { ReactNode } from "react"; -export const projectId = String( - process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID, -); +export const projectId = process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!; +export const NEXT_PUBLIC_APP_URL = process.env.NEXT_PUBLIC_APP_URL!; + +const envVariables = { projectId, NEXT_PUBLIC_APP_URL }; + +Object.entries(envVariables).forEach(([key, value]) => { + if (!value) { + throw new Error(`${key} is not defined`); + } +}); -export const NODE_ENV = process.env.NODE_ENV; -export const NEXT_PUBLIC_APP_URL = process.env.NEXT_PUBLIC_APP_URL; -if (!projectId) throw new Error("Project ID is not defined"); const metadata = { name: "Porters RPC Gateway", From 3ae0eba267d00850d2837ca2a8a6731bc1f60c17 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 15:41:49 +0530 Subject: [PATCH 02/20] nano id update --- web-portal/backend/src/apps/apps.service.ts | 5 ++--- web-portal/backend/src/tenant/tenant.service.ts | 5 ++--- web-portal/backend/src/user/user.service.ts | 5 ++--- web-portal/backend/src/utils/const.ts | 3 +++ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/web-portal/backend/src/apps/apps.service.ts b/web-portal/backend/src/apps/apps.service.ts index e17a2ab..34a0361 100644 --- a/web-portal/backend/src/apps/apps.service.ts +++ b/web-portal/backend/src/apps/apps.service.ts @@ -4,8 +4,7 @@ import { AppRule, PrismaClient, Tenant, RuleType } from '@/.generated/client'; import { UserService } from '../user/user.service'; import { createHash, randomBytes } from 'crypto'; import { Request } from 'express'; -import { nanoid } from 'nanoid'; -import { NANO_ID_LENGTH } from '../utils/const'; +import { nanoid } from '@/src/utils/const'; @Injectable() export class AppsService { @@ -85,7 +84,7 @@ export class AppsService { if (!tenants) return; const newApp = await this.prisma.client.app.create({ data: { - id: nanoid(NANO_ID_LENGTH), + id: nanoid(), tenantId: tenants[0].id, name, description, diff --git a/web-portal/backend/src/tenant/tenant.service.ts b/web-portal/backend/src/tenant/tenant.service.ts index f8e4c21..8c9269e 100644 --- a/web-portal/backend/src/tenant/tenant.service.ts +++ b/web-portal/backend/src/tenant/tenant.service.ts @@ -2,8 +2,7 @@ import { Injectable, Inject, HttpException, HttpStatus } from '@nestjs/common'; import { CustomPrismaService } from 'nestjs-prisma'; import { PrismaClient } from '@/.generated/client'; import { createHash, randomBytes } from 'crypto'; -import { nanoid } from 'nanoid' -import { NANO_ID_LENGTH } from '../utils/const'; +import { nanoid } from '@/src/utils/const'; @Injectable() export class TenantService { @@ -28,7 +27,7 @@ export class TenantService { const tenant = await this.prisma.client.tenant.create({ data: { - id: nanoid(NANO_ID_LENGTH), + id: nanoid(), enterpriseId: enterprise.id, secretKey: hashedKey, }, diff --git a/web-portal/backend/src/user/user.service.ts b/web-portal/backend/src/user/user.service.ts index 7cb60f9..d01eafc 100644 --- a/web-portal/backend/src/user/user.service.ts +++ b/web-portal/backend/src/user/user.service.ts @@ -6,8 +6,7 @@ import { TenantService } from '../tenant/tenant.service'; import { unsealData } from 'iron-session'; import { Request } from 'express'; import { ISession, SESSION_OPTIONS } from '../siwe/siwe.service'; -import { nanoid } from 'nanoid'; -import { NANO_ID_LENGTH } from '../utils/const'; +import { nanoid } from '@/src/utils/const'; @Injectable() export class UserService { @@ -66,7 +65,7 @@ export class UserService { } const newUser = await this.prisma.client.user.create({ data: { - id: nanoid(NANO_ID_LENGTH), + id: nanoid(), ethAddress: createHash('sha256').update(ethAddress).digest('hex'), orgs: { create: { diff --git a/web-portal/backend/src/utils/const.ts b/web-portal/backend/src/utils/const.ts index 7525bae..a4322dc 100644 --- a/web-portal/backend/src/utils/const.ts +++ b/web-portal/backend/src/utils/const.ts @@ -1,2 +1,5 @@ +import { customAlphabet } from "nanoid"; export const NANO_ID_LENGTH = 10; // https://zelark.github.io/nano-id-cc/ export const PORTR_ADDRESS = '0x54d5f8a0e0f06991e63e46420bcee1af7d9fe944'; +export const NANO_ID_ALPHABETS = '123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz'; +export const nanoid = () => customAlphabet(NANO_ID_ALPHABETS, NANO_ID_LENGTH); From e533f7c4e79215c1de754c04c1f40617bab11712 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 16:00:52 +0530 Subject: [PATCH 03/20] Revert "nano id update" This reverts commit 3ae0eba267d00850d2837ca2a8a6731bc1f60c17. --- web-portal/backend/src/apps/apps.service.ts | 5 +++-- web-portal/backend/src/tenant/tenant.service.ts | 5 +++-- web-portal/backend/src/user/user.service.ts | 5 +++-- web-portal/backend/src/utils/const.ts | 3 --- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/web-portal/backend/src/apps/apps.service.ts b/web-portal/backend/src/apps/apps.service.ts index 34a0361..e17a2ab 100644 --- a/web-portal/backend/src/apps/apps.service.ts +++ b/web-portal/backend/src/apps/apps.service.ts @@ -4,7 +4,8 @@ import { AppRule, PrismaClient, Tenant, RuleType } from '@/.generated/client'; import { UserService } from '../user/user.service'; import { createHash, randomBytes } from 'crypto'; import { Request } from 'express'; -import { nanoid } from '@/src/utils/const'; +import { nanoid } from 'nanoid'; +import { NANO_ID_LENGTH } from '../utils/const'; @Injectable() export class AppsService { @@ -84,7 +85,7 @@ export class AppsService { if (!tenants) return; const newApp = await this.prisma.client.app.create({ data: { - id: nanoid(), + id: nanoid(NANO_ID_LENGTH), tenantId: tenants[0].id, name, description, diff --git a/web-portal/backend/src/tenant/tenant.service.ts b/web-portal/backend/src/tenant/tenant.service.ts index 8c9269e..f8e4c21 100644 --- a/web-portal/backend/src/tenant/tenant.service.ts +++ b/web-portal/backend/src/tenant/tenant.service.ts @@ -2,7 +2,8 @@ import { Injectable, Inject, HttpException, HttpStatus } from '@nestjs/common'; import { CustomPrismaService } from 'nestjs-prisma'; import { PrismaClient } from '@/.generated/client'; import { createHash, randomBytes } from 'crypto'; -import { nanoid } from '@/src/utils/const'; +import { nanoid } from 'nanoid' +import { NANO_ID_LENGTH } from '../utils/const'; @Injectable() export class TenantService { @@ -27,7 +28,7 @@ export class TenantService { const tenant = await this.prisma.client.tenant.create({ data: { - id: nanoid(), + id: nanoid(NANO_ID_LENGTH), enterpriseId: enterprise.id, secretKey: hashedKey, }, diff --git a/web-portal/backend/src/user/user.service.ts b/web-portal/backend/src/user/user.service.ts index d01eafc..7cb60f9 100644 --- a/web-portal/backend/src/user/user.service.ts +++ b/web-portal/backend/src/user/user.service.ts @@ -6,7 +6,8 @@ import { TenantService } from '../tenant/tenant.service'; import { unsealData } from 'iron-session'; import { Request } from 'express'; import { ISession, SESSION_OPTIONS } from '../siwe/siwe.service'; -import { nanoid } from '@/src/utils/const'; +import { nanoid } from 'nanoid'; +import { NANO_ID_LENGTH } from '../utils/const'; @Injectable() export class UserService { @@ -65,7 +66,7 @@ export class UserService { } const newUser = await this.prisma.client.user.create({ data: { - id: nanoid(), + id: nanoid(NANO_ID_LENGTH), ethAddress: createHash('sha256').update(ethAddress).digest('hex'), orgs: { create: { diff --git a/web-portal/backend/src/utils/const.ts b/web-portal/backend/src/utils/const.ts index a4322dc..7525bae 100644 --- a/web-portal/backend/src/utils/const.ts +++ b/web-portal/backend/src/utils/const.ts @@ -1,5 +1,2 @@ -import { customAlphabet } from "nanoid"; export const NANO_ID_LENGTH = 10; // https://zelark.github.io/nano-id-cc/ export const PORTR_ADDRESS = '0x54d5f8a0e0f06991e63e46420bcee1af7d9fe944'; -export const NANO_ID_ALPHABETS = '123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz'; -export const nanoid = () => customAlphabet(NANO_ID_ALPHABETS, NANO_ID_LENGTH); From 1a275063ae4ec63eb8fed6a8cf1d196a7aa27ab9 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 16:37:38 +0530 Subject: [PATCH 04/20] temp-save --- .../frontend/components/dashboard/layout.tsx | 24 +++++++++++-- web-portal/frontend/pages/apps/[app].tsx | 12 +++++-- web-portal/frontend/utils/hooks.ts | 36 +++++++++++++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index 75be259..3afa1fa 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -5,8 +5,8 @@ import { Container, Flex, Title, - Button, Stack, + Alert } from "@mantine/core"; import Link from "next/link"; @@ -21,6 +21,8 @@ import { IconReceipt, IconBrandDiscord, IconArrowUpRight, + IconAlertOctagon, + IconSettings } from "@tabler/icons-react"; import { useEffect } from "react"; import Image from "next/image"; @@ -30,6 +32,8 @@ import { useUserApps, useEndpoints, useRuleTypes, + useAppAlert, + useTenantAlert, } from "@frontend/utils/hooks"; import { useAtom, useSetAtom } from "jotai"; import { @@ -39,10 +43,12 @@ import { sessionAtom, } from "@frontend/utils/atoms"; import { useAccount, useAccountEffect, useEnsName } from "wagmi"; -import { IconSettings } from "@tabler/icons-react"; + import CreateAppModal from "./createAppModal"; import CreateAppButton from "./createApp"; +import { useParams } from "next/navigation"; +import _ from "lodash"; export default function DashboardLayout({ children, @@ -98,6 +104,12 @@ export default function DashboardLayout({ address: session?.address, }); + + const tenantId = _.get(session, 'tenantId') + + const {data: showTenantAlert} = useTenantAlert(tenantId!); + + const { width } = useViewportSize(); const isMobile = width < 600; @@ -183,7 +195,13 @@ export default function DashboardLayout({ - {children} + + + { showTenantAlert && } my={32} bg='#F9DCBF'> + Your relay request balance is running low, Please top-up you balance by redeeming some PORTR tokens. + + } + {children} ); diff --git a/web-portal/frontend/pages/apps/[app].tsx b/web-portal/frontend/pages/apps/[app].tsx index aa95dfb..ee87849 100644 --- a/web-portal/frontend/pages/apps/[app].tsx +++ b/web-portal/frontend/pages/apps/[app].tsx @@ -7,8 +7,10 @@ import { Title, Tooltip, CopyButton, - Input + Input, + Alert } from "@mantine/core"; +import { IconAlertOctagon } from "@tabler/icons-react"; import _ from "lodash"; import DashboardLayout from "@frontend/components/dashboard/layout"; import { usePathname, useRouter } from "next/navigation"; @@ -17,7 +19,7 @@ import { appsAtom } from "@frontend/utils/atoms"; import { IApp } from "@frontend/utils/types"; import StyledLink from "@frontend/components/dashboard/styledlink"; import AppTabs from "@frontend/components/apps/apptabs"; - +import { useAppAlert } from "@frontend/utils/hooks"; import UpdateAppModal from "@frontend/components/apps/updateAppModal"; @@ -35,7 +37,7 @@ export default function App({appId}: {appId:string}) { const path = usePathname(); const router = useRouter(); - + const { data:showAppAlert } = useAppAlert(appId); const breadCrumbItems = _.map( [ @@ -55,6 +57,10 @@ export default function App({appId}: {appId:string}) { return ( + { showAppAlert && } my={32} bg='#F9DCBF'> + You app maybe getting rate-limited! + + } {breadCrumbItems} diff --git a/web-portal/frontend/utils/hooks.ts b/web-portal/frontend/utils/hooks.ts index 3752ae1..a558a3c 100644 --- a/web-portal/frontend/utils/hooks.ts +++ b/web-portal/frontend/utils/hooks.ts @@ -432,3 +432,39 @@ export const useAppUsage = () => { return appUsage; }; + + +export const useAppAlert = (appId:string) => { + const fetchAppAlert = async () => { + const response = await fetch(`/api/alerts/app/${appId}`); + if (!response.ok) { + throw new Error("Failed to fetch app alerts"); + } + return response.json(); + }; + return useQuery({ + queryKey: ["alert", "app", appId], + queryFn: fetchAppAlert, + enabled: !!appId, + refetchInterval: 60 * 1000, + refetchOnMount: true, + }) +} + + +export const useTenantAlert = (tenantId:string) => { + const fetchAppAlert = async () => { + const response = await fetch(`/api/alerts/tenant/${tenantId}`); + if (!response.ok) { + throw new Error("Failed to fetch app alerts"); + } + return response.json(); + }; + return useQuery({ + queryKey: ["alert", "tenant", tenantId], + queryFn: fetchAppAlert, + enabled: !!tenantId, + refetchInterval: 60 * 1000, + refetchOnMount: true, + }) +} From b2c2c945dac63844428d36ce1f6d593a62266ae0 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 16:47:49 +0530 Subject: [PATCH 05/20] fix balance thing! convert to number first --- web-portal/backend/src/utils/utils.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-portal/backend/src/utils/utils.service.ts b/web-portal/backend/src/utils/utils.service.ts index 0922799..d0a1623 100644 --- a/web-portal/backend/src/utils/utils.service.ts +++ b/web-portal/backend/src/utils/utils.service.ts @@ -221,7 +221,7 @@ export class UtilsService { parseLogs(logs: any[], network: string): IParsedLog[] { return logs.map((log: any) => ({ tenantId: fromHex(log?.args?._identifier, 'string').replaceAll(`\x00`, ''), - amount: Number(log?.args?._amount * 10 ** -12), + amount: Number(log?.args?._amount) * 10 ** -12, // 10 ** -18 (to parse to human readable) * 10 ** 3 (for 1000 relay per token) * 10 ** 3 for chain weight = 10 ** -12 referenceId: network + `:` + log.transactionHash!, transactionType: TransactionType.CREDIT!, From 3ab029e7326bfe09916f6f83bfa0b5207dd7ee3d Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Thu, 23 May 2024 20:23:47 +0530 Subject: [PATCH 06/20] links-update --- .../frontend/components/dashboard/layout.tsx | 5 +- .../frontend/components/home/02-Partners.tsx | 17 ++-- .../frontend/components/home/07-Footer.tsx | 86 +++++++++++++++---- web-portal/frontend/utils/theme.ts | 3 +- 4 files changed, 83 insertions(+), 28 deletions(-) diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index 3afa1fa..bff5841 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -47,7 +47,6 @@ import { useAccount, useAccountEffect, useEnsName } from "wagmi"; import CreateAppModal from "./createAppModal"; import CreateAppButton from "./createApp"; -import { useParams } from "next/navigation"; import _ from "lodash"; export default function DashboardLayout({ @@ -179,7 +178,7 @@ export default function DashboardLayout({ } label="Docs" - link="/docs" + link="https://docs.porters.xyz" /> } @@ -187,7 +186,7 @@ export default function DashboardLayout({ } label="Discord" - link="/discord" + link="https://discord.gg/GZywNxPJgd" /> diff --git a/web-portal/frontend/components/home/02-Partners.tsx b/web-portal/frontend/components/home/02-Partners.tsx index d870abe..e1d4e24 100644 --- a/web-portal/frontend/components/home/02-Partners.tsx +++ b/web-portal/frontend/components/home/02-Partners.tsx @@ -5,16 +5,19 @@ import poktLogo from "@frontend/public/pokt-logo.png"; import taikoLogo from "@frontend/public/taiko.png"; import Image from "next/image"; import SectionTitle from "./common/SectionTitle"; +import { useRouter } from "next/navigation"; export default function Partners() { + const router = useRouter() return ( - + router.replace('https://raidguild.org')}> + borderRadius: 10, + cursor: "pointer" + }} onClick={() => router.replace('https://pokt.network')}> Pokt Network + borderRadius: 10, + cursor: "pointer" + }} onClick={() => router.replace('https://taiko.xyz')}> Taiko Network 920 ? 'row' : 'column' - + const { width } = useViewportSize(); + const dir = width > 920 ? "row" : "column"; + const router = useRouter(); return ( - - © - 2024 + © + 2024 - Privacy Policy - Terms of Service + router.push("privacy-policy")} + style={{ cursor: "pointer" }} + > + Privacy Policy + + router.push("terms-of-service")} + style={{ cursor: "pointer" }} + > + Terms of Service + - + + router.replace("https://pokt.network/")} + style={{ cursor: "pointer" }} + > Powered By svg - - - - svg - + router.replace("https://github.com/porters-xyz")} + style={{ cursor: "pointer" }} + /> - + router.replace("https://discord.gg/GZywNxPJgd")} + style={{ cursor: "pointer" }} + /> + + router.replace("https://twitter.com/PORTERSXYZ")} + style={{ cursor: "pointer" }} + /> + + svg router.replace("https://google.com")} + style={{ cursor: "pointer" }} + /> + + ); } diff --git a/web-portal/frontend/utils/theme.ts b/web-portal/frontend/utils/theme.ts index 5cfda28..a412cbf 100644 --- a/web-portal/frontend/utils/theme.ts +++ b/web-portal/frontend/utils/theme.ts @@ -1,5 +1,6 @@ -import { createTheme, rem, Button, Modal, TextInput, Select, NumberInput, Textarea, Stack, Pill } from "@mantine/core"; +import { createTheme, rem, Button, Modal, TextInput, Select, NumberInput, Textarea, Pill } from "@mantine/core"; import { Crimson_Text, Karla, Red_Rose } from "next/font/google"; +import Link from "next/link"; export const crimson = Crimson_Text({ subsets: ["latin"], display: "swap", From 9bb9b539eda3f74b62555eafa3f8e213e7acdd18 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 08:41:04 +0530 Subject: [PATCH 07/20] clean up unused! --- web-portal/frontend/components/settings/displayItem.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/web-portal/frontend/components/settings/displayItem.tsx b/web-portal/frontend/components/settings/displayItem.tsx index 0e62d01..8e891d3 100644 --- a/web-portal/frontend/components/settings/displayItem.tsx +++ b/web-portal/frontend/components/settings/displayItem.tsx @@ -1,7 +1,5 @@ -import DashboardLayout from "@frontend/components/dashboard/layout"; import { CopyButton, - Button, Divider, Text, Stack, From 83d9a531fdae867160be3ad7b1dcd359f7f0ce1b Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 15:55:35 +0530 Subject: [PATCH 08/20] save: alert progress --- .../backend/src/alerts/alerts.service.ts | 48 +- web-portal/frontend/utils/hooks.ts | 748 +++++++++--------- 2 files changed, 417 insertions(+), 379 deletions(-) diff --git a/web-portal/backend/src/alerts/alerts.service.ts b/web-portal/backend/src/alerts/alerts.service.ts index d71d1e7..c5010c2 100644 --- a/web-portal/backend/src/alerts/alerts.service.ts +++ b/web-portal/backend/src/alerts/alerts.service.ts @@ -1,13 +1,51 @@ -import { Injectable } from '@nestjs/common'; +import { HttpException, Injectable } from '@nestjs/common'; +import { createHash } from 'crypto'; + + +interface PromResponse { + data: { + result: { + value: any[]; + }; + }; +} @Injectable() export class AlertsService { + async getAppAlerts(appId: string): Promise { - const rateLimited = Math.random() < 0.5 - return rateLimited + const hashedAppId = createHash('sha256').update(appId).digest('hex'); + const result = await this.fetchRateLimitStatus({ appId: hashedAppId }) + return result.json() } + async getTenantAlerts(tenantId: string): Promise { - const rateLimited = Math.random() < 0.5 - return rateLimited + const result = await this.fetchRateLimitStatus({ tenantId }) + return result.json() + } + + private async fetchRateLimitStatus( + { tenantId, appId }: { tenantId?: string; appId?: string } + ): Promise { + + const query = tenantId + ? `query?query=gateway_rate_limit_hit{tenant="${tenantId}"}` + : `query?query=gateway_rate_limit_hit{appId="${appId}"}`; + + const url = process.env.PROM_URL + query; + + const res = await fetch(url, { + headers: { + Authorization: String(process.env.PROM_TOKEN), + }, + }); + + if (!res.ok) { + throw new HttpException('Failed to fetch data', res.status); + } + + + return res } + } diff --git a/web-portal/frontend/utils/hooks.ts b/web-portal/frontend/utils/hooks.ts index a558a3c..2363951 100644 --- a/web-portal/frontend/utils/hooks.ts +++ b/web-portal/frontend/utils/hooks.ts @@ -1,8 +1,8 @@ import { - useQuery, - useMutation, - useQueryClient, - useQueries, + useQuery, + useMutation, + useQueryClient, + useQueries, } from "@tanstack/react-query"; import { getSession } from "./siwe"; import { useAccount, useBalance, useReadContract } from "wagmi"; @@ -16,431 +16,431 @@ import { useAtomValue } from "jotai"; import { sessionAtom } from "./atoms"; export const useSession = () => { - const { address, isConnected } = useAccount(); - const { data, isLoading, isFetched } = useQuery({ - queryKey: ["session"], - queryFn: getSession, - enabled: address && isConnected, - refetchInterval: 60 * 60 * 1000, - refetchOnMount: false, - }); - - return { data, isLoading, isFetched }; + const { address, isConnected } = useAccount(); + const { data, isLoading, isFetched } = useQuery({ + queryKey: ["session"], + queryFn: getSession, + enabled: address && isConnected, + refetchInterval: 60 * 60 * 1000, + refetchOnMount: false, + }); + + return { data, isLoading, isFetched }; }; export const useEndpoints = () => { - const { address } = useAccount(); - const fetchEndpoints = async () => { - const response = await fetch(`/api/utils/endpoints`); - if (!response.ok) { - throw new Error("Failed to fetch endpoints"); - } - return response.json(); - }; - - return useQuery({ - queryKey: ["endpoints"], - queryFn: fetchEndpoints, - enabled: Boolean(address), - }); + const { address } = useAccount(); + const fetchEndpoints = async () => { + const response = await fetch(`/api/utils/endpoints`); + if (!response.ok) { + throw new Error("Failed to fetch endpoints"); + } + return response.json(); + }; + + return useQuery({ + queryKey: ["endpoints"], + queryFn: fetchEndpoints, + enabled: Boolean(address), + }); }; export const useRuleTypes = () => { - const { address } = useAccount(); - const fetchRuleTypes = async () => { - const response = await fetch(`/api/utils/ruletypes`); - if (!response.ok) { - throw new Error("Failed to fetch ruletypes"); - } - return response.json(); - }; - - return useQuery({ - queryKey: ["ruletypes"], - queryFn: fetchRuleTypes, - enabled: Boolean(address), - }); + const { address } = useAccount(); + const fetchRuleTypes = async () => { + const response = await fetch(`/api/utils/ruletypes`); + if (!response.ok) { + throw new Error("Failed to fetch ruletypes"); + } + return response.json(); + }; + + return useQuery({ + queryKey: ["ruletypes"], + queryFn: fetchRuleTypes, + enabled: Boolean(address), + }); }; export const useUserApps = (userAddress: string) => { - const fetchApps = async () => { - const response = await fetch(`/api/apps`); - if (!response.ok) { - throw new Error("Failed to validate tenant"); - } - return response.json(); - }; - - return useQuery({ - queryKey: ["user", userAddress, "apps"], - queryFn: fetchApps, - enabled: Boolean(userAddress), - }); + const fetchApps = async () => { + const response = await fetch(`/api/apps`); + if (!response.ok) { + throw new Error("Failed to validate tenant"); + } + return response.json(); + }; + + return useQuery({ + queryKey: ["user", userAddress, "apps"], + queryFn: fetchApps, + enabled: Boolean(userAddress), + }); }; export const useCreateAppMutation = (data: { - name: string; - description?: string; + name: string; + description?: string; }) => { - const { name, description } = data; - const router = useRouter(); - const queryClient = useQueryClient(); - - const createAppMutation = async () => { - const response = await fetch(`/api/apps`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ name, description }), - }); - if (!response.ok) { - throw new Error("Failed to create app"); - } - return response.json(); - }; - - return useMutation({ - mutationFn: createAppMutation, - onSuccess: () => { - router.push("/dashboard"); - queryClient.invalidateQueries(); // TODO <--- revisit this - console.log("New App Created"); - }, + const { name, description } = data; + const router = useRouter(); + const queryClient = useQueryClient(); + + const createAppMutation = async () => { + const response = await fetch(`/api/apps`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name, description }), }); + if (!response.ok) { + throw new Error("Failed to create app"); + } + return response.json(); + }; + + return useMutation({ + mutationFn: createAppMutation, + onSuccess: () => { + router.push("/dashboard"); + queryClient.invalidateQueries(); // TODO <--- revisit this + console.log("New App Created"); + }, + }); }; export const useUpdateAppMutation = (appId: string) => { - const queryClient = useQueryClient(); - const path = usePathname(); - const router = useRouter(); - const updateAppMutation = async ({ - action, - data, - }: { - action: "update" | "delete"; - data?: { name?: string; description?: string }; - }) => { - const method = action === "update" ? "PATCH" : "DELETE"; - const requestBody = - action === "update" ? JSON.stringify({ ...data }) : null; - - const response = await fetch(`/api/apps/${appId}`, { - method: method, - headers: { - "Content-Type": "application/json", - }, - body: requestBody, - }); - - if (!response.ok) { - throw new Error(`Failed to ${action} app`); - } - - return response.json(); - }; - - return useMutation({ - mutationFn: updateAppMutation, - onSuccess: () => { - router.replace(path); - queryClient.invalidateQueries(); // TODO <--- revisit this - console.log(`Updated App`); - }, + const queryClient = useQueryClient(); + const path = usePathname(); + const router = useRouter(); + const updateAppMutation = async ({ + action, + data, + }: { + action: "update" | "delete"; + data?: { name?: string; description?: string }; + }) => { + const method = action === "update" ? "PATCH" : "DELETE"; + const requestBody = + action === "update" ? JSON.stringify({ ...data }) : null; + + const response = await fetch(`/api/apps/${appId}`, { + method: method, + headers: { + "Content-Type": "application/json", + }, + body: requestBody, }); + + if (!response.ok) { + throw new Error(`Failed to ${action} app`); + } + + return response.json(); + }; + + return useMutation({ + mutationFn: updateAppMutation, + onSuccess: () => { + router.replace(path); + queryClient.invalidateQueries(); // TODO <--- revisit this + console.log(`Updated App`); + }, + }); }; export const useUpdateRuleMutation = (appId: string, ruleName: string) => { - const queryClient = useQueryClient(); - const router = useRouter(); - const updateRuleMutation = async (data?: Array) => { - const response = await fetch(`/api/apps/${appId}/rules`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ ruleName, data }), - }); - if (!response.ok) { - throw new Error("Failed to update app rule"); - } - return response.json(); - }; - - return useMutation({ - mutationFn: updateRuleMutation, - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["user"] }); - router.replace("/apps/" + appId + "?i=rules"); - console.log(ruleName + " Updated"); - }, + const queryClient = useQueryClient(); + const router = useRouter(); + const updateRuleMutation = async (data?: Array) => { + const response = await fetch(`/api/apps/${appId}/rules`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ ruleName, data }), }); + if (!response.ok) { + throw new Error("Failed to update app rule"); + } + return response.json(); + }; + + return useMutation({ + mutationFn: updateRuleMutation, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["user"] }); + router.replace("/apps/" + appId + "?i=rules"); + console.log(ruleName + " Updated"); + }, + }); }; export const useBillingHistory = (id: string) => { - const fetchBillingHistory = async () => { - const response = await fetch(`/api/tenant/${id}/billing`); - if (!response.ok) { - throw new Error("Failed to fetch billing history"); - } - return response.json(); - }; - - return useQuery({ - queryKey: ["billing", id], - queryFn: fetchBillingHistory, - enabled: Boolean(id), - }); + const fetchBillingHistory = async () => { + const response = await fetch(`/api/tenant/${id}/billing`); + if (!response.ok) { + throw new Error("Failed to fetch billing history"); + } + return response.json(); + }; + + return useQuery({ + queryKey: ["billing", id], + queryFn: fetchBillingHistory, + enabled: Boolean(id), + }); }; export const useSecretKeyMutation = (appId: string) => { - const queryClient = useQueryClient(); - const { address: userAddress } = useAccount(); - const router = useRouter(); - const createSecretKeyMutation = async (action: string) => { - const response = await fetch(`/api/apps/${appId}/secret`, { - method: action == "generate" ? "PUT" : "DELETE", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to update secret key"); - } - - return response.json(); - }; - - return useMutation({ - mutationFn: createSecretKeyMutation, - onSuccess: (data) => { - queryClient.invalidateQueries({ - queryKey: ["user", userAddress, "apps"], - }); - - const { key } = data; - if (key) { - router.replace( - "/apps/" + appId + "?i=rules&rule=secret-key&key=" + key, - ); - } - console.log("Secret Key Updated"); - }, + const queryClient = useQueryClient(); + const { address: userAddress } = useAccount(); + const router = useRouter(); + const createSecretKeyMutation = async (action: string) => { + const response = await fetch(`/api/apps/${appId}/secret`, { + method: action == "generate" ? "PUT" : "DELETE", + headers: { + "Content-Type": "application/json", + }, }); + + if (!response.ok) { + throw new Error("Failed to update secret key"); + } + + return response.json(); + }; + + return useMutation({ + mutationFn: createSecretKeyMutation, + onSuccess: (data) => { + queryClient.invalidateQueries({ + queryKey: ["user", userAddress, "apps"], + }); + + const { key } = data; + if (key) { + router.replace( + "/apps/" + appId + "?i=rules&rule=secret-key&key=" + key, + ); + } + console.log("Secret Key Updated"); + }, + }); }; export const useQuote = ({ - sellToken, - chainId, - sellAmount, + sellToken, + chainId, + sellAmount, }: { - sellToken: string; - chainId: number | string; - sellAmount: number; + sellToken: string; + chainId: number | string; + sellAmount: number; }) => { - const fetchQuote = async () => { - const chainName = _.get( - _.find(supportedChains, { id: String(chainId) }), - "name", - ); - - const response = await fetch( - `/api/utils/quote/${chainName}/${sellToken}/${sellAmount}`, - ); - if (!response.ok) { - throw new Error("Failed to fetch quote"); - } - return response.json(); - }; - return useQuery({ - queryKey: ["0xQuote", sellToken], - queryFn: fetchQuote, - enabled: sellAmount > 0 && Boolean(sellToken) && Boolean(chainId), - refetchInterval: 10000, - }); + const fetchQuote = async () => { + const chainName = _.get( + _.find(supportedChains, { id: String(chainId) }), + "name", + ); + + const response = await fetch( + `/api/utils/quote/${chainName}/${sellToken}/${sellAmount}`, + ); + if (!response.ok) { + throw new Error("Failed to fetch quote"); + } + return response.json(); + }; + return useQuery({ + queryKey: ["0xQuote", sellToken], + queryFn: fetchQuote, + enabled: sellAmount > 0 && Boolean(sellToken) && Boolean(chainId), + refetchInterval: 10000, + }); }; export const usePrice = ({ - sellToken, - chainId, - sellAmount, + sellToken, + chainId, + sellAmount, }: { - sellToken: string; - chainId: number | string; - sellAmount: number; + sellToken: string; + chainId: number | string; + sellAmount: number; }) => { - const fetchQuote = async () => { - const chainName = _.get( - _.find(supportedChains, { id: String(chainId) }), - "name", - ); - - const response = await fetch( - `/api/utils/price/${chainName}/${sellToken}/${sellAmount}`, - ); - if (!response.ok) { - throw new Error("Failed to fetch quote"); - } - return response.json(); - }; - return useQuery({ - queryKey: ["0xPrice", sellToken], - queryFn: fetchQuote, - enabled: sellAmount > 0 && Boolean(sellToken) && Boolean(chainId), - refetchInterval: 10000, - }); + const fetchQuote = async () => { + const chainName = _.get( + _.find(supportedChains, { id: String(chainId) }), + "name", + ); + + const response = await fetch( + `/api/utils/price/${chainName}/${sellToken}/${sellAmount}`, + ); + if (!response.ok) { + throw new Error("Failed to fetch quote"); + } + return response.json(); + }; + return useQuery({ + queryKey: ["0xPrice", sellToken], + queryFn: fetchQuote, + enabled: sellAmount > 0 && Boolean(sellToken) && Boolean(chainId), + refetchInterval: 10000, + }); }; export const useTokenBalance = ({ - token, - chainId, + token, + chainId, }: { - token?: Address; - chainId: number; + token?: Address; + chainId: number; }) => { - const { address } = useAccount(); - return useBalance({ - chainId, - token, - address, - }); + const { address } = useAccount(); + return useBalance({ + chainId, + token, + address, + }); }; export const useTokenPrice = ({ - token, - chainId, + token, + chainId, }: { - token: Address; - chainId: number; + token: Address; + chainId: number; }) => { - const fetchTokenPrice = async () => { - const response = await fetch(`/api/utils/price/${chainId}/${token}`); - if (!response.ok) { - throw new Error("Failed to fetch token price"); - } - return response.json(); - }; - - return useQuery({ - queryKey: ["price", token], - queryFn: fetchTokenPrice, - }); + const fetchTokenPrice = async () => { + const response = await fetch(`/api/utils/price/${chainId}/${token}`); + if (!response.ok) { + throw new Error("Failed to fetch token price"); + } + return response.json(); + }; + + return useQuery({ + queryKey: ["price", token], + queryFn: fetchTokenPrice, + }); }; export const useTokenList = ({ chainId }: { chainId: number | string }) => { - const fetchTokenList = async () => { - const response = await fetch(`/api/utils/tokens/${chainId}`); - if (!response.ok) { - throw new Error("Failed to fetch token list"); - } - const res = await response.json(); - return _.toArray(res) as IToken[]; - }; - - return useQuery({ - queryKey: ["tokens", chainId], - queryFn: fetchTokenList, - }); + const fetchTokenList = async () => { + const response = await fetch(`/api/utils/tokens/${chainId}`); + if (!response.ok) { + throw new Error("Failed to fetch token list"); + } + const res = await response.json(); + return _.toArray(res) as IToken[]; + }; + + return useQuery({ + queryKey: ["tokens", chainId], + queryFn: fetchTokenList, + }); }; export const useCheckAllowance = ({ - sellTokenAddress, - selectedChainId, - exchangeProxy, + sellTokenAddress, + selectedChainId, + exchangeProxy, }: { - selectedChainId: number; - sellTokenAddress: Address; - exchangeProxy: Address; + selectedChainId: number; + sellTokenAddress: Address; + exchangeProxy: Address; }) => { - const { address } = useAccount(); - - return useReadContract({ - chainId: selectedChainId, - address: sellTokenAddress, - abi: erc20Abi, - functionName: "allowance", - args: [address!, exchangeProxy!], - }); + const { address } = useAccount(); + + return useReadContract({ + chainId: selectedChainId, + address: sellTokenAddress, + abi: erc20Abi, + functionName: "allowance", + args: [address!, exchangeProxy!], + }); }; export const useTenantUsage = () => { - const session = useAtomValue(sessionAtom); - const tenantId = _.get(session, "tenantId"); - - const fetchTenantUsage = async (period: string) => { - const response = await fetch(`/api/usage/tenant/${tenantId}/${period}`); - if (!response.ok) { - throw new Error("Failed to fetch tenant usage"); - } - return response.json(); - }; - - const tenantUsageData = useQueries({ - queries: timeOptions.map(({ option }) => ({ - queryKey: ["usage", "tenant", tenantId, option], - queryFn: () => fetchTenantUsage(option), - enabled: !!tenantId, - })), - combine: (results) => { - return { - data: results.map((result, index) => { - return { - period: [timeOptions[index].option], - data: result?.data?.data?.result[0]?.values ?? [], - }; - }), - pending: results.some((result) => result.isPending), - isFetched: results.some((result) => result.isPending), - }; - }, - }); + const session = useAtomValue(sessionAtom); + const tenantId = _.get(session, "tenantId"); + + const fetchTenantUsage = async (period: string) => { + const response = await fetch(`/api/usage/tenant/${tenantId}/${period}`); + if (!response.ok) { + throw new Error("Failed to fetch tenant usage"); + } + return response.json(); + }; - return tenantUsageData; + const tenantUsageData = useQueries({ + queries: timeOptions.map(({ option }) => ({ + queryKey: ["usage", "tenant", tenantId, option], + queryFn: () => fetchTenantUsage(option), + enabled: !!tenantId, + })), + combine: (results) => { + return { + data: results.map((result, index) => { + return { + period: [timeOptions[index].option], + data: result?.data?.data?.result[0]?.values ?? [], + }; + }), + pending: results.some((result) => result.isPending), + isFetched: results.some((result) => result.isPending), + }; + }, + }); + + return tenantUsageData; }; export const useAppUsage = () => { - const appId = _.get(useParams(), "app", ""); - - const fetchAppUsage = async (period: string) => { - const response = await fetch(`/api/usage/app/${appId}/${period}`); - if (!response.ok) { - throw new Error("Failed to fetch app usage"); - } - return response.json(); - }; - - const appUsage = useQueries({ - queries: timeOptions.map(({ option }) => ({ - queryKey: ["usage", "app", appId, option], - queryFn: () => fetchAppUsage(option), - enabled: Boolean(appId), - })), - combine: (results) => { - return { - data: results.map((result, index) => { - return { - period: [timeOptions[index].option], - data: result?.data?.data?.result[0]?.values ?? [], - }; - }), - pending: results.some((result) => result.isPending), - isFetched: results.some((result) => result.isPending), - }; - }, - }); + const appId = _.get(useParams(), "app", ""); + + const fetchAppUsage = async (period: string) => { + const response = await fetch(`/api/usage/app/${appId}/${period}`); + if (!response.ok) { + throw new Error("Failed to fetch app usage"); + } + return response.json(); + }; - return appUsage; + const appUsage = useQueries({ + queries: timeOptions.map(({ option }) => ({ + queryKey: ["usage", "app", appId, option], + queryFn: () => fetchAppUsage(option), + enabled: Boolean(appId), + })), + combine: (results) => { + return { + data: results.map((result, index) => { + return { + period: [timeOptions[index].option], + data: result?.data?.data?.result[0]?.values ?? [], + }; + }), + pending: results.some((result) => result.isPending), + isFetched: results.some((result) => result.isPending), + }; + }, + }); + + return appUsage; }; - -export const useAppAlert = (appId:string) => { - const fetchAppAlert = async () => { - const response = await fetch(`/api/alerts/app/${appId}`); - if (!response.ok) { - throw new Error("Failed to fetch app alerts"); - } - return response.json(); +export const useAppAlert = (appId: string) => { + const fetchAppAlert = async () => { + const response = await fetch(`/api/alerts/app/${appId}`); + if (!response.ok) { + throw new Error("Failed to fetch app alerts"); + } + const x = response.json(); + return _.get(x, "data.result[0].value"); }; return useQuery({ queryKey: ["alert", "app", appId], @@ -448,17 +448,17 @@ export const useAppAlert = (appId:string) => { enabled: !!appId, refetchInterval: 60 * 1000, refetchOnMount: true, - }) -} - + }); +}; -export const useTenantAlert = (tenantId:string) => { - const fetchAppAlert = async () => { - const response = await fetch(`/api/alerts/tenant/${tenantId}`); - if (!response.ok) { - throw new Error("Failed to fetch app alerts"); - } - return response.json(); +export const useTenantAlert = (tenantId: string) => { + const fetchAppAlert = async () => { + const response = await fetch(`/api/alerts/tenant/${tenantId}`); + if (!response.ok) { + throw new Error("Failed to fetch app alerts"); + } + const x = response.json(); + return _.get(x, "data.result[0].value"); }; return useQuery({ queryKey: ["alert", "tenant", tenantId], @@ -466,5 +466,5 @@ export const useTenantAlert = (tenantId:string) => { enabled: !!tenantId, refetchInterval: 60 * 1000, refetchOnMount: true, - }) -} + }); +}; From fa56a8011e1d1a6a7e53baa3e5f3f070b53dba78 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 16:44:40 +0530 Subject: [PATCH 09/20] clean up! --- .../frontend/components/dashboard/layout.tsx | 47 +++++++++++-------- .../frontend/components/dashboard/logout.tsx | 6 ++- .../frontend/components/login/modal.tsx | 17 ------- web-portal/frontend/next.config.js | 2 +- web-portal/frontend/pages/login/index.tsx | 29 +++++------- 5 files changed, 45 insertions(+), 56 deletions(-) delete mode 100644 web-portal/frontend/components/login/modal.tsx diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index bff5841..e31ba0f 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -6,7 +6,7 @@ import { Flex, Title, Stack, - Alert + Alert, } from "@mantine/core"; import Link from "next/link"; @@ -22,7 +22,7 @@ import { IconBrandDiscord, IconArrowUpRight, IconAlertOctagon, - IconSettings + IconSettings, } from "@tabler/icons-react"; import { useEffect } from "react"; import Image from "next/image"; @@ -44,10 +44,11 @@ import { } from "@frontend/utils/atoms"; import { useAccount, useAccountEffect, useEnsName } from "wagmi"; - import CreateAppModal from "./createAppModal"; import CreateAppButton from "./createApp"; import _ from "lodash"; +import { Address } from "viem"; +import { useRouter } from "next/navigation"; export default function DashboardLayout({ children, @@ -59,14 +60,20 @@ export default function DashboardLayout({ const { data: endpoints } = useEndpoints(); const { data: ruletypes } = useRuleTypes(); + const router = useRouter(); + const [session, setSession] = useAtom(sessionAtom); const { address } = useAccount(); const setEndpointAtom = useSetAtom(endpointsAtom); const setApps = useSetAtom(appsAtom); const setRuleTypes = useSetAtom(ruleTypesAtom); - const { data: appsData } = useUserApps(sessionValue?.address); + const { data: appsData } = useUserApps(address as Address); useEffect(() => { + // if (!sessionValue) { + // router.replace("/login"); + // } + if (sessionValue?.address) { setSession(sessionValue); } @@ -92,22 +99,13 @@ export default function DashboardLayout({ address, ]); - useAccountEffect({ - onDisconnect() { - console.log("disconnecting"); - setSession(null); - }, - }); - const { data: ensName } = useEnsName({ address: session?.address, }); + const tenantId = _.get(session, "tenantId"); - const tenantId = _.get(session, 'tenantId') - - const {data: showTenantAlert} = useTenantAlert(tenantId!); - + const { data: showTenantAlert } = useTenantAlert(tenantId!); const { width } = useViewportSize(); const isMobile = width < 600; @@ -196,11 +194,20 @@ export default function DashboardLayout({ - { showTenantAlert && } my={32} bg='#F9DCBF'> - Your relay request balance is running low, Please top-up you balance by redeeming some PORTR tokens. - - } - {children} + {showTenantAlert && ( + } + my={32} + bg="#F9DCBF" + > + Your relay request balance is running low, Please top-up you + balance by redeeming some PORTR tokens. + + )} + {children} + ); diff --git a/web-portal/frontend/components/dashboard/logout.tsx b/web-portal/frontend/components/dashboard/logout.tsx index 080c835..8187d8d 100644 --- a/web-portal/frontend/components/dashboard/logout.tsx +++ b/web-portal/frontend/components/dashboard/logout.tsx @@ -4,12 +4,14 @@ import { useDisconnect } from "wagmi"; import { useViewportSize } from "@mantine/hooks"; export default function LogoutButton() { - const { disconnect } = useDisconnect(); + const { disconnectAsync } = useDisconnect(); + const { width } = useViewportSize(); const isMobile = width < 600; + return ( - - Powered By Pokt Network + + Powered By Pokt Network - ); From 57c1ae69e0b945e79aef9cb2c0ec70ba51ed3ec0 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 17:03:27 +0530 Subject: [PATCH 10/20] final fix alerts! --- .../frontend/components/dashboard/layout.tsx | 16 +- web-portal/frontend/pages/apps/[app].tsx | 232 +++++++++--------- web-portal/frontend/utils/hooks.ts | 6 +- 3 files changed, 125 insertions(+), 129 deletions(-) diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index e31ba0f..ac6d371 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -48,7 +48,6 @@ import CreateAppModal from "./createAppModal"; import CreateAppButton from "./createApp"; import _ from "lodash"; import { Address } from "viem"; -import { useRouter } from "next/navigation"; export default function DashboardLayout({ children, @@ -60,8 +59,6 @@ export default function DashboardLayout({ const { data: endpoints } = useEndpoints(); const { data: ruletypes } = useRuleTypes(); - const router = useRouter(); - const [session, setSession] = useAtom(sessionAtom); const { address } = useAccount(); const setEndpointAtom = useSetAtom(endpointsAtom); @@ -70,14 +67,9 @@ export default function DashboardLayout({ const { data: appsData } = useUserApps(address as Address); useEffect(() => { - // if (!sessionValue) { - // router.replace("/login"); - // } - if (sessionValue?.address) { setSession(sessionValue); } - if (appsData) { setApps(appsData); } @@ -105,7 +97,11 @@ export default function DashboardLayout({ const tenantId = _.get(session, "tenantId"); - const { data: showTenantAlert } = useTenantAlert(tenantId!); + const { data: tenantAlertCheck } = useTenantAlert(tenantId!); + + const showTenantAlert = Number( + _.last(_.get(_.first(_.get(tenantAlertCheck, "data.result")), "value")), + ); const { width } = useViewportSize(); const isMobile = width < 600; @@ -194,7 +190,7 @@ export default function DashboardLayout({ - {showTenantAlert && ( + {Boolean(showTenantAlert) && ( = useAtomValue(appsAtom); +export default function App({ appId }: { appId: string }) { + const apps: Array = useAtomValue(appsAtom); - const app = _.find(apps, { id: appId }) as IApp; + const app = _.find(apps, { id: appId }) as IApp; - const path = usePathname(); - const router = useRouter(); - const { data:showAppAlert } = useAppAlert(appId); + const path = usePathname(); + const router = useRouter(); + const { data: appAlertCheck } = useAppAlert(appId); - const breadCrumbItems = _.map( - [ - ...appsRootUrl, - { - title: _.get(app, "name", ""), - href: `/apps/${_.get(app, "id", "")}`, - }, - ], - (item, index) => ( - - {_.get(item, "title").toUpperCase()} - - ), - ); + const showAppAlert = Number( + _.last(_.get(_.first(_.get(appAlertCheck, "data.result")), "value")), + ); + const breadCrumbItems = _.map( + [ + ...appsRootUrl, + { + title: _.get(app, "name", ""), + href: `/apps/${_.get(app, "id", "")}`, + }, + ], + (item, index) => ( + + {_.get(item, "title").toUpperCase()} + + ), + ); - return ( - - { showAppAlert && } my={32} bg='#F9DCBF'> - You app maybe getting rate-limited! - - } - - - {breadCrumbItems} + return ( + + {Boolean(showAppAlert) && ( + } + my={32} + bg="#F9DCBF" + > + You app maybe getting rate-limited! + + )} + + + {breadCrumbItems} - - - - App Name - - - {_.get(app, "name")} - - - {({ copied, copy }) => ( - - - - )} - - - - - - - - - - Description {` `} - {_.truncate(_.get(app, "description"), { - length: 100, - })} - - - + + + )} + + - - ); + + + + + + Description {` `} + {_.truncate(_.get(app, "description"), { + length: 100, + })} + + + + + + ); } - -export const getServerSideProps = async ({ params }: {params: any}) => { - const appIdFromParams = _.get(params, 'app') +export const getServerSideProps = async ({ params }: { params: any }) => { + const appIdFromParams = _.get(params, "app"); return { props: { - appId: appIdFromParams + appId: appIdFromParams, }, }; }; diff --git a/web-portal/frontend/utils/hooks.ts b/web-portal/frontend/utils/hooks.ts index 2363951..8c3f135 100644 --- a/web-portal/frontend/utils/hooks.ts +++ b/web-portal/frontend/utils/hooks.ts @@ -439,8 +439,7 @@ export const useAppAlert = (appId: string) => { if (!response.ok) { throw new Error("Failed to fetch app alerts"); } - const x = response.json(); - return _.get(x, "data.result[0].value"); + return response.json(); }; return useQuery({ queryKey: ["alert", "app", appId], @@ -457,8 +456,7 @@ export const useTenantAlert = (tenantId: string) => { if (!response.ok) { throw new Error("Failed to fetch app alerts"); } - const x = response.json(); - return _.get(x, "data.result[0].value"); + return response.json(); }; return useQuery({ queryKey: ["alert", "tenant", tenantId], From 140201b2265c59999300de7eac52a714a800218c Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 17:06:33 +0530 Subject: [PATCH 11/20] save --- .../frontend/components/dashboard/applist.tsx | 49 +++++++++++-------- .../components/settings/displayItem.tsx | 1 - 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/web-portal/frontend/components/dashboard/applist.tsx b/web-portal/frontend/components/dashboard/applist.tsx index c0a56dd..1516b9f 100644 --- a/web-portal/frontend/components/dashboard/applist.tsx +++ b/web-portal/frontend/components/dashboard/applist.tsx @@ -1,5 +1,14 @@ import React from "react"; -import { Stack, Table, Flex, Title, Card, Button, CopyButton, Input, Tooltip } from "@mantine/core"; +import { + Stack, + Table, + Flex, + Title, + Button, + CopyButton, + Input, + Tooltip, +} from "@mantine/core"; import { IApp } from "@frontend/utils/types"; import { IconChevronRight, IconCopy } from "@tabler/icons-react"; import { usePathname, useRouter } from "next/navigation"; @@ -21,27 +30,27 @@ const AppList: React.FC = () => { > {app.name ?? "Un-named App"} - - {({ copied, copy }) => ( - - - } - /> - - )} - + + {({ copied, copy }) => ( + + } + /> + + )} + {app.active ? "Yes" : "No"} - {new Date(app?.createdAt as string).toLocaleDateString()} + + {new Date(app?.createdAt as string).toLocaleDateString()} + )); diff --git a/web-portal/frontend/components/settings/displayItem.tsx b/web-portal/frontend/components/settings/displayItem.tsx index 8e891d3..5a39484 100644 --- a/web-portal/frontend/components/settings/displayItem.tsx +++ b/web-portal/frontend/components/settings/displayItem.tsx @@ -5,7 +5,6 @@ import { Stack, Title, Flex, - Card, ActionIcon, Tooltip, rem, From f46be7412bf35de6e33bdf6f16e41159dd69c410 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Fri, 24 May 2024 17:11:17 +0530 Subject: [PATCH 12/20] fix copy! --- .../frontend/components/dashboard/layout.tsx | 16 +++++++++++++++- web-portal/frontend/pages/apps/[app].tsx | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index ac6d371..b957f08 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -66,6 +66,8 @@ export default function DashboardLayout({ const setRuleTypes = useSetAtom(ruleTypesAtom); const { data: appsData } = useUserApps(address as Address); + const balance = _.get(_.first(_.get(session, "netBalance")), "net", 0); + useEffect(() => { if (sessionValue?.address) { setSession(sessionValue); @@ -190,7 +192,7 @@ export default function DashboardLayout({ - {Boolean(showTenantAlert) && ( + {appsData.length && balance < 1000 && ( )} + + {showTenantAlert && ( + } + my={32} + bg="#F9DCBF" + > + Some of your apps maybe getting rate-limited + + )} {children} diff --git a/web-portal/frontend/pages/apps/[app].tsx b/web-portal/frontend/pages/apps/[app].tsx index 9f03126..ebd9392 100644 --- a/web-portal/frontend/pages/apps/[app].tsx +++ b/web-portal/frontend/pages/apps/[app].tsx @@ -62,12 +62,12 @@ export default function App({ appId }: { appId: string }) { {Boolean(showAppAlert) && ( } my={32} bg="#F9DCBF" > - You app maybe getting rate-limited! + This app is getting rate limited! )} From 686c5c7c38df7ab0fd0d238a5b9ac83d6cd8ff93 Mon Sep 17 00:00:00 2001 From: plor Date: Fri, 24 May 2024 16:20:54 -0500 Subject: [PATCH 13/20] Properly managing CORS headers * Updated app rule to include origin headers if set --- gateway/plugins/origin.go | 49 ++++++++++++++++++++++------------ gateway/plugins/origin_test.go | 27 +++++++++++++++++++ gateway/proxy/proxy.go | 7 +++++ 3 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 gateway/plugins/origin_test.go diff --git a/gateway/plugins/origin.go b/gateway/plugins/origin.go index 17a2404..d201f77 100644 --- a/gateway/plugins/origin.go +++ b/gateway/plugins/origin.go @@ -4,7 +4,7 @@ import ( "context" log "log/slog" "net/http" - "regexp" + "strings" "porters/db" "porters/proxy" @@ -43,14 +43,7 @@ func (a *AllowedOriginFilter) HandleRequest(req *http.Request) error { } rules := a.getRulesForScope(ctx, app) - allow := (len(rules) == 0) - - for _, rule := range rules { - if rule.MatchString(origin) { - allow = true - break - } - } + allow := a.matchesRules(origin, rules) if !allow { return proxy.NewHTTPError(http.StatusUnauthorized) @@ -59,8 +52,26 @@ func (a *AllowedOriginFilter) HandleRequest(req *http.Request) error { return nil } -func (a *AllowedOriginFilter) getRulesForScope(ctx context.Context, app *db.App) []regexp.Regexp { - origins := make([]regexp.Regexp, 0) +func (a *AllowedOriginFilter) HandleResponse(resp *http.Response) error { + ctx := resp.Request.Context() + app := &db.App{ + Id: proxy.PluckAppId(resp.Request), + } + err := app.Lookup(ctx) + if err != nil { + return nil // don't modify header + } + + rules := a.getRulesForScope(ctx, app) + if len(rules) > 0 { + allowedOrigins := strings.Join(rules, ",") + resp.Header.Set("Access-Control-Allow-Origin", allowedOrigins) + } + return nil +} + +func (a *AllowedOriginFilter) getRulesForScope(ctx context.Context, app *db.App) []string { + origins := make([]string, 0) rules, err := app.Rules(ctx) if err != nil { log.Error("couldn't get rules", "app", app.HashId(), "err", err) @@ -69,13 +80,17 @@ func (a *AllowedOriginFilter) getRulesForScope(ctx context.Context, app *db.App) if rule.RuleType != ALLOWED_ORIGIN || !rule.Active { continue } - matcher, err := regexp.Compile(rule.Value) - if err != nil { - log.Error("error compiling origin regex", "regex", rule.Value, "err", err) - continue - } - origins = append(origins, *matcher) + origins = append(origins, rule.Value) } } return origins } + +func (a *AllowedOriginFilter) matchesRules(origin string, rules []string) bool { + for _, rule := range rules { + if strings.EqualFold(rule, origin) { + return true + } + } + return false +} diff --git a/gateway/plugins/origin_test.go b/gateway/plugins/origin_test.go new file mode 100644 index 0000000..b21e1cb --- /dev/null +++ b/gateway/plugins/origin_test.go @@ -0,0 +1,27 @@ +package plugins + +import ( + "testing" +) + +func TestAllowedOriginMatches(t *testing.T) { + want := true + origin := "http://test.com" + allowed := []string{"http://test2.com", "http://test.com"} + filter := &AllowedOriginFilter{} + got := filter.matchesRules(origin, allowed) + if want != got { + t.Fatal("origin doesn't match") + } +} + +func TestAllowedOriginMismatch(t *testing.T) { + want := false + origin := "http://test3.com" + allowed := []string{"http://test2.com", "http://test.com"} + filter := &AllowedOriginFilter{} + got := filter.matchesRules(origin, allowed) + if want != got { + t.Fatal("origin doesn't match") + } +} diff --git a/gateway/proxy/proxy.go b/gateway/proxy/proxy.go index 82e68e7..0fb9758 100644 --- a/gateway/proxy/proxy.go +++ b/gateway/proxy/proxy.go @@ -132,6 +132,7 @@ func setupProxy(remote *url.URL) *httputil.ReverseProxy { revProxy.ModifyResponse = func(resp *http.Response) error { ctx := resp.Request.Context() + defaultHeaders(resp) if common.Enabled(common.INSTRUMENT_ENABLED) { instr, ok := common.FromContext(ctx, common.INSTRUMENT) @@ -191,6 +192,12 @@ func setupContext(req *http.Request) { *req = *req.WithContext(ctx) } +// Add or remove headers on response +// Dealing with CORS mostly +func defaultHeaders(resp *http.Response) { + resp.Header.Set("Access-Control-Allow-Origin", "*") +} + func lookupPoktId(req *http.Request) (string, bool) { ctx := req.Context() name := PluckProductName(req) From 510fb7f01cef21492b4af8f498f5738d5609f2a3 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Sat, 25 May 2024 19:25:06 +0530 Subject: [PATCH 14/20] fixed logout --- .../frontend/components/dashboard/layout.tsx | 4 ++-- .../frontend/components/dashboard/logout.tsx | 11 ++-------- web-portal/frontend/utils/Web3Provider.tsx | 3 +-- web-portal/frontend/utils/siwe.ts | 22 ++++++++++--------- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/web-portal/frontend/components/dashboard/layout.tsx b/web-portal/frontend/components/dashboard/layout.tsx index b957f08..1eddf8f 100644 --- a/web-portal/frontend/components/dashboard/layout.tsx +++ b/web-portal/frontend/components/dashboard/layout.tsx @@ -192,7 +192,7 @@ export default function DashboardLayout({ - {appsData.length && balance < 1000 && ( + {!!appsData?.length && balance < 1000 && ( )} - {showTenantAlert && ( + {!!showTenantAlert && ( disconnectAsync()} - variant="outline" - color="#856853" - w="max-content" - > + diff --git a/web-portal/frontend/utils/Web3Provider.tsx b/web-portal/frontend/utils/Web3Provider.tsx index cf2306f..f22889d 100644 --- a/web-portal/frontend/utils/Web3Provider.tsx +++ b/web-portal/frontend/utils/Web3Provider.tsx @@ -17,7 +17,6 @@ Object.entries(envVariables).forEach(([key, value]) => { } }); - const metadata = { name: "Porters RPC Gateway", description: "Porters RPC Gateway", @@ -38,7 +37,7 @@ export const config = defaultWagmiConfig({ }), }); -const queryClient = new QueryClient(); +export const queryClient = new QueryClient(); export default function Web3Provider({ children, diff --git a/web-portal/frontend/utils/siwe.ts b/web-portal/frontend/utils/siwe.ts index ae940ed..7680035 100644 --- a/web-portal/frontend/utils/siwe.ts +++ b/web-portal/frontend/utils/siwe.ts @@ -1,6 +1,8 @@ import { SiweMessage } from "siwe"; import Cookies from "js-cookie"; import { createSIWEConfig } from "@web3modal/siwe"; +import { queryClient, config } from "./Web3Provider"; +import { disconnect } from "@wagmi/core"; export const getNonce = async () => { const res = await fetch("/api/siwe", { method: "PUT" }); @@ -54,16 +56,16 @@ export const getSession = async () => { }; export const signOut = async () => { - Cookies.remove("session"); - const res = await fetch("/api/siwe", { - method: "DELETE", - }); - if (!Cookies.get("session")) { - window.location.href = "/login"; - } - if (res.ok) return true; - return false; + const result = await disconnect(config); + Cookies.set("session", ""); + queryClient.setQueryData(["session"], null); + console.log({ session: Cookies.get("session"), result }); + + setTimeout(() => (window.location.href = "/login"), 1500); + + return result; }; + // @ts-ignore export const siweConfig = createSIWEConfig({ createMessage, @@ -72,5 +74,5 @@ export const siweConfig = createSIWEConfig({ verifyMessage, signOut, signOutOnNetworkChange: false, - signOutOnDisconnect: true + signOutOnDisconnect: true, }); From bcb29d182112a0c1708e7655134796e6669b3706 Mon Sep 17 00:00:00 2001 From: memosys <82053242+memosys@users.noreply.github.com> Date: Sat, 25 May 2024 19:31:11 +0530 Subject: [PATCH 15/20] fix handling of network switch buttons when no balance --- web-portal/backend/src/siwe/siwe.service.ts | 1 - web-portal/frontend/components/swap/Redeem.tsx | 4 ++-- web-portal/frontend/components/swap/Swap.tsx | 8 +++----- web-portal/frontend/utils/hooks.ts | 6 ++++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/web-portal/backend/src/siwe/siwe.service.ts b/web-portal/backend/src/siwe/siwe.service.ts index 0d9bb55..45cb7b1 100644 --- a/web-portal/backend/src/siwe/siwe.service.ts +++ b/web-portal/backend/src/siwe/siwe.service.ts @@ -13,7 +13,6 @@ export interface ISession { } export const SESSION_OPTIONS = { - ttl: 60 * 60, // 1 hour password: process.env.SESSION_SECRET! ?? `NNb774sZ7bNnGkWTwkXE3T9QWCAC5DkY0HTLz`, // TODO: get via env vars only }; diff --git a/web-portal/frontend/components/swap/Redeem.tsx b/web-portal/frontend/components/swap/Redeem.tsx index 71ca4d4..32c9d32 100644 --- a/web-portal/frontend/components/swap/Redeem.tsx +++ b/web-portal/frontend/components/swap/Redeem.tsx @@ -249,8 +249,8 @@ export default function Redeem() { diff --git a/web-portal/frontend/utils/Web3Provider.tsx b/web-portal/frontend/utils/Web3Provider.tsx index f22889d..fa37881 100644 --- a/web-portal/frontend/utils/Web3Provider.tsx +++ b/web-portal/frontend/utils/Web3Provider.tsx @@ -1,10 +1,10 @@ -import { defaultWagmiConfig } from "@web3modal/wagmi/react/config"; -import { cookieStorage, createStorage } from "wagmi"; +import { ConnectKitProvider, SIWEProvider, getDefaultConfig } from "connectkit"; import { base, gnosis, mainnet, optimism } from "wagmi/chains"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Provider as JotaiProvider } from "jotai"; -import { State, WagmiProvider } from "wagmi"; +import { WagmiProvider, createConfig, http } from "wagmi"; import { ReactNode } from "react"; +import { siweConfig } from "./siwe"; export const projectId = process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!; export const NEXT_PUBLIC_APP_URL = process.env.NEXT_PUBLIC_APP_URL!; @@ -17,39 +17,44 @@ Object.entries(envVariables).forEach(([key, value]) => { } }); -const metadata = { - name: "Porters RPC Gateway", - description: "Porters RPC Gateway", - url: String(NEXT_PUBLIC_APP_URL), - icons: ["https://staging.porters.xyz/favicon.ico"], -}; - // Create wagmiConfig export const chains = [mainnet, optimism, base, gnosis] as const; -export const config = defaultWagmiConfig({ - chains, - projectId, - metadata, - ssr: true, - storage: createStorage({ - storage: cookieStorage, - }), -}); +export const config = createConfig( + getDefaultConfig({ + chains: [mainnet, base, gnosis, optimism], + transports: { + [mainnet.id]: http( + `https://eth-mainnet.rpc.grove.city/v1/1eec3963` + ), + [base.id]: http(`https://base-mainnet.rpc.grove.city/v1/1eec3963`), + [gnosis.id]: http(`https://gnosischain-mainnet.rpc.grove.city/v1/1eec3963`), + [optimism.id]: http(`https://optimism-mainnet.rpc.grove.city/v1/1eec3963`), + }, + walletConnectProjectId: projectId, + appName: "Porters RPC Gateway", + appDescription: "Porters RPC Gateway", + appUrl: String(NEXT_PUBLIC_APP_URL), + appIcon: 'https://porters.xyz/favicon.ico' + })); export const queryClient = new QueryClient(); export default function Web3Provider({ children, - initialState, }: { children: ReactNode; - initialState?: State; }) { return ( - + - {children} + + + + {children} + + + ); diff --git a/web-portal/frontend/utils/siwe.ts b/web-portal/frontend/utils/siwe.ts index a14f3f3..1ac89f5 100644 --- a/web-portal/frontend/utils/siwe.ts +++ b/web-portal/frontend/utils/siwe.ts @@ -1,8 +1,8 @@ -import { SiweMessage } from "siwe"; import Cookies from "js-cookie"; -import { createSIWEConfig } from "@web3modal/siwe"; import { queryClient, config } from "./Web3Provider"; +import { SiweMessage } from 'siwe'; import { Config, disconnect } from "@wagmi/core"; +import { SIWEConfig } from "connectkit"; export const getNonce = async () => { const res = await fetch("/api/siwe", { method: "PUT" }); @@ -66,8 +66,7 @@ export const signOut = async () => { return Boolean(result) }; -// @ts-ignore -export const siweConfig = createSIWEConfig({ +export const siweConfig:SIWEConfig = { createMessage, getNonce, getSession, @@ -75,4 +74,4 @@ export const siweConfig = createSIWEConfig({ signOut, signOutOnNetworkChange: false, signOutOnDisconnect: true, -}); +}