Skip to content

Commit

Permalink
FOIL-209
Browse files Browse the repository at this point in the history
  • Loading branch information
noahlitvin authored Feb 12, 2025
2 parents 650db96 + 86bd1dd commit a4a7d51
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 399 deletions.
3 changes: 2 additions & 1 deletion packages/api/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ DISCORD_TOKEN=
DISCORD_PRIVATE_CHANNEL_ID=
DISCORD_PUBLIC_CHANNEL_ID=
SENTRY_AUTH_TOKEN=
IPINFO_TOKEN=
IPINFO_TOKEN=
API_ACCESS_TOKEN=
36 changes: 31 additions & 5 deletions packages/api/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
import express from 'express';
import express, { Request } from 'express';
import cors from 'cors';
import { router } from './routes';

const corsOptions: cors.CorsOptions = {
origin: (
origin: string | undefined,
callback: (error: Error | null, allow?: boolean) => void
callback: (error: Error | null, allow?: boolean) => void,
request?: Request
) => {
if (process.env.NODE_ENV !== 'production') {
// Allow all requests unless in production or staging
if (
process.env.NODE_ENV !== 'production' &&
process.env.NODE_ENV !== 'staging'
) {
callback(null, true);
return;
}

// Check for API token in production/staging
const authHeader = request?.headers?.authorization;
const apiToken = process.env.API_ACCESS_TOKEN;

// If API token is provided and matches, allow the request regardless of origin
if (
apiToken &&
authHeader?.startsWith('Bearer ') &&
authHeader.slice(7) === apiToken
) {
callback(null, true);
} else if (
return;
}

// Otherwise, only allow specific domains
if (
!origin || // Allow same-origin requests
/^https?:\/\/([a-zA-Z0-9-]+\.)*foil\.xyz$/.test(origin) ||
/^https?:\/\/localhost(:\d+)?$/.test(origin) || // local testing
/^https?:\/\/([a-zA-Z0-9-]+\.)*vercel\.app$/.test(origin) //staging sites
) {
callback(null, true);
Expand All @@ -21,6 +43,10 @@ const corsOptions: cors.CorsOptions = {
}
},
optionsSuccessStatus: 200,
// Allow the Authorization header to be exposed to the client
exposedHeaders: ['Authorization'],
// Allow the Authorization header to be sent
allowedHeaders: ['Authorization', 'Content-Type'],
};

const app = express();
Expand Down
1 change: 1 addition & 0 deletions packages/app/.env.sample
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
NEXT_PUBLIC_FOIL_API_URL=http://localhost:3001
NEXT_PUBLIC_FOIL_API_TOKEN=
IPINFO_TOKEN=
1 change: 0 additions & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
"@uniswap/sdk-core": "^5.3.1",
"@uniswap/v3-core": "^1.0.1",
"@uniswap/v3-sdk": "^3.13.1",
"axios": "^1.7.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^3.6.0",
Expand Down
11 changes: 5 additions & 6 deletions packages/app/src/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

'use client';

import axios from 'axios';
import { useState } from 'react';

import { Button } from '@/components/ui/button';
Expand All @@ -14,8 +13,8 @@ import {
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import AdminTable from '~/components/admin/AdminTable';
import { API_BASE_URL } from '~/lib/constants/constants';
import type { RenderJob } from '~/lib/interfaces/interfaces';
import { foilApi } from '~/lib/utils/util';

const Admin = () => {
const [job, setJob] = useState<RenderJob | undefined>();
Expand All @@ -33,12 +32,12 @@ const Admin = () => {
if (!serviceId || !jobId) return;

setLoadingAction((prev) => ({ ...prev, getStatus: true }));
const response = await axios.get(
`${API_BASE_URL}/reindexStatus?jobId=${jobId}&serviceId=${serviceId}`
const response = await foilApi.get(
`/reindexStatus?jobId=${jobId}&serviceId=${serviceId}`
);

if (response.data.success && response.data.job) {
setJob(response.data.job);
if (response.success && response.job) {
setJob(response.job);
}
setLoadingAction((prev) => ({ ...prev, getStatus: false }));
};
Expand Down
11 changes: 2 additions & 9 deletions packages/app/src/app/positions/[id]/[position]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import { Loader2, ExternalLink } from 'lucide-react';
import EpochTiming from '~/components/EpochTiming';
import NumberDisplay from '~/components/numberDisplay';
import { badgeVariants } from '~/components/ui/badge';
import { API_BASE_URL } from '~/lib/constants/constants';
import { PeriodProvider } from '~/lib/context/PeriodProvider';
import { useResources } from '~/lib/hooks/useResources';
import { cn } from '~/lib/utils';
import { tickToPrice } from '~/lib/utils/util';
import { tickToPrice, foilApi } from '~/lib/utils/util';

const POLLING_INTERVAL = 10000; // Refetch every 10 seconds

Expand All @@ -29,13 +28,7 @@ const usePosition = (contractId: string, positionId: string) => {
return useQuery({
queryKey: ['position', contractId, positionId],
queryFn: async () => {
const response = await fetch(
`${API_BASE_URL}/positions/${positionId}?contractId=${contractId}`
);
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
return foilApi.get(`/positions/${positionId}?contractId=${contractId}`);
},
refetchInterval: POLLING_INTERVAL,
});
Expand Down
29 changes: 9 additions & 20 deletions packages/app/src/app/subscribe/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
import { useFoil } from '~/lib/context/FoilProvider';
import { PeriodContext, PeriodProvider } from '~/lib/context/PeriodProvider';
import { useResources } from '~/lib/hooks/useResources';
import { convertWstEthToGwei } from '~/lib/utils/util';
import { convertWstEthToGwei, foilApi } from '~/lib/utils/util';

const SUBSCRIPTIONS_QUERY = gql`
query GetSubscriptions($owner: String!) {
Expand Down Expand Up @@ -139,23 +139,13 @@ const useSubscriptions = (address?: string) => {
}

// First fetch positions
const positionsResponse = await fetch(
`${process.env.NEXT_PUBLIC_FOIL_API_URL}/graphql`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: print(SUBSCRIPTIONS_QUERY),
variables: {
owner: address,
},
}),
}
);
const { data: positionsData, errors } = await foilApi.post('/graphql', {
query: print(SUBSCRIPTIONS_QUERY),
variables: {
owner: address,
},
});

const { data: positionsData, errors } = await positionsResponse.json();
if (errors) {
throw new Error(errors[0].message);
}
Expand All @@ -172,10 +162,9 @@ const useSubscriptions = (address?: string) => {
return Promise.all(
activePositions.map(async (position: any) => {
const contractId = `${position.epoch.market.chainId}:${position.epoch.market.address}`;
const transactionsResponse = await fetch(
`${process.env.NEXT_PUBLIC_FOIL_API_URL}/transactions?contractId=${contractId}&positionId=${position.positionId}`
const transactions = await foilApi.get(
`/transactions?contractId=${contractId}&positionId=${position.positionId}`
);
const transactions = await transactionsResponse.json();

return {
...position,
Expand Down
6 changes: 3 additions & 3 deletions packages/app/src/components/ConnectWalletModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { API_BASE_URL } from '~/lib/constants/constants';
import { cn } from '~/lib/utils';
import { foilApi } from '~/lib/utils/util';

interface ConnectWalletModalProps {
open: boolean;
Expand Down Expand Up @@ -62,8 +62,8 @@ export default function ConnectWalletModal({
return;
}

fetch(`${API_BASE_URL}/permit`)
.then((res) => res.json())
foilApi
.get('/permit')
.then((data) => setPermittedByApi(data.permitted))
.catch((err) => console.error('Error fetching permit status:', err));
}
Expand Down
12 changes: 3 additions & 9 deletions packages/app/src/components/VolumeChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ import {
} from 'recharts';

import NumberDisplay from '~/components/numberDisplay';
import { API_BASE_URL } from '~/lib/constants/constants';
import type { VolumeChartData, TimeWindow } from '~/lib/interfaces/interfaces';
import { formatXAxisTick, getXTicksToShow } from '~/lib/utils/chartUtil';
import { getDisplayTextForVolumeWindow } from '~/lib/utils/util';
import { getDisplayTextForVolumeWindow, foilApi } from '~/lib/utils/util';

const barColor = '#58585A';
const NETWORK_ERROR_STRING = 'Network response was not ok';

dayjs.extend(utc);

Expand Down Expand Up @@ -117,13 +115,9 @@ const VolumeChart = ({
} = useQuery({
queryKey: ['volume', contractId, epochId, activeWindow],
queryFn: async () => {
const response = await fetch(
`${API_BASE_URL}/volume?contractId=${contractId}&epochId=${epochId}&timeWindow=${activeWindow}`
return foilApi.get(
`/volume?contractId=${contractId}&epochId=${epochId}&timeWindow=${activeWindow}`
);
if (!response.ok) {
throw new Error(NETWORK_ERROR_STRING);
}
return response.json();
},
enabled: !!contractId && !!epochId && !!activeWindow,
retry: 3,
Expand Down
42 changes: 18 additions & 24 deletions packages/app/src/components/admin/AdminTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
getSortedRowModel,
type SortingState,
} from '@tanstack/react-table';
import axios from 'axios';
import { Loader2, ChevronDown, ChevronUp, ArrowUpDown } from 'lucide-react';
import React, { useState, useMemo } from 'react';
import { useSignMessage } from 'wagmi';
Expand All @@ -19,12 +18,10 @@ import {
TableCell,
} from '@/components/ui/table';
import { useToast } from '~/hooks/use-toast';
import {
ADMIN_AUTHENTICATE_MSG,
API_BASE_URL,
} from '~/lib/constants/constants';
import { ADMIN_AUTHENTICATE_MSG } from '~/lib/constants/constants';
import { useFoil } from '~/lib/context/FoilProvider';
import type { Market } from '~/lib/context/FoilProvider';
import { foilApi } from '~/lib/utils/util';

import getColumns from './columns';
import type { MissingBlocks } from './types';
Expand Down Expand Up @@ -66,14 +63,14 @@ const AdminTable: React.FC = () => {

const fetchMissingBlocks = async (market: Market, epochId: number) => {
try {
const response = await axios.get(
`${API_BASE_URL}/missing-blocks?chainId=${market.chainId}&address=${market.address}&epochId=${epochId}`
const data = await foilApi.get(
`/missing-blocks?chainId=${market.chainId}&address=${market.address}&epochId=${epochId}`
);

setMissingBlocks((prev) => ({
...prev,
[`${market.address}-${epochId}`]: {
resourcePrice: response.data.missingBlockNumbers,
resourcePrice: data.missingBlockNumbers,
},
}));
} catch (error) {
Expand Down Expand Up @@ -108,22 +105,19 @@ const AdminTable: React.FC = () => {
message: ADMIN_AUTHENTICATE_MSG,
});

const response = await axios.post(
`${API_BASE_URL}/reindexMissingBlocks`,
{
chainId,
address: marketAddress,
epochId,
model: reindexType === 'price' ? 'ResourcePrice' : 'Event',
signature,
timestamp,
}
);
const response = await foilApi.post('/reindexMissingBlocks', {
chainId,
address: marketAddress,
epochId,
model: reindexType === 'price' ? 'ResourcePrice' : 'Event',
signature,
timestamp,
});

if (response.data.success) {
if (response.success) {
toast({
title: 'Reindexing started',
description: response.data.message,
description: response.message,
variant: 'default',
});
const market = markets.find((m) => m.address === marketAddress);
Expand All @@ -133,7 +127,7 @@ const AdminTable: React.FC = () => {
} else {
toast({
title: 'Reindexing failed',
description: response.data.error,
description: response.error,
variant: 'destructive',
});
}
Expand All @@ -160,13 +154,13 @@ const AdminTable: React.FC = () => {
const signature = await signMessageAsync({
message: ADMIN_AUTHENTICATE_MSG,
});
const response = await axios.post(`${API_BASE_URL}/updateMarketPrivacy`, {
const response = await foilApi.post('/updateMarketPrivacy', {
address: market.address,
chainId: market.chainId,
signature,
timestamp,
});
if (response.data.success) {
if (response.success) {
await refetchMarkets();
}
setLoadingAction((prev) => ({ ...prev, [market.address]: false }));
Expand Down
12 changes: 3 additions & 9 deletions packages/app/src/components/leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { API_BASE_URL } from '~/lib/constants/constants';
import { foilApi } from '~/lib/utils/util';

import NumberDisplay from './numberDisplay';

Expand Down Expand Up @@ -67,15 +67,9 @@ const useLeaderboard = (marketId: string, epochId: string) => {
queryKey: ['epochLeaderboard', marketId, epochId],
queryFn: async () => {
// Get leaderboard and positions
const leaderboardResponse = await fetch(
`${API_BASE_URL}/leaderboard?contractId=${marketId}`
const leaderboard = await foilApi.get(
`/leaderboard?contractId=${marketId}`
);
if (!leaderboardResponse.ok) {
throw new Error('Failed to fetch leaderboard positions');
}

const [leaderboard] = await Promise.all([leaderboardResponse.json()]);

return [...leaderboard];
},
});
Expand Down
Loading

0 comments on commit a4a7d51

Please sign in to comment.