Skip to content

Commit 4f963f7

Browse files
authored
feat: add api key to GraphQL (#164)
1 parent 2bc3ba4 commit 4f963f7

File tree

10 files changed

+57
-13
lines changed

10 files changed

+57
-13
lines changed

packages/app-explorer/.env.example

+3
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
FUEL_PROVIDER=https://beta-5.fuel.network/graphql
2+
# Explorer API URL
3+
FUEL_EXPLORER_API=
4+
FUEL_EXPLORER_API_KEY=

packages/app-explorer/.env.production

-1
This file was deleted.

packages/app-explorer/src/app/api/graphql/route.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createExecutor, createSchema } from '@fuel-explorer/graphql';
22
import { ContextDomain } from '@fuel-explorer/graphql/src/domains/Context';
33
import { createYoga } from 'graphql-yoga';
4+
import { NextResponse } from 'next/server';
45
import { requireEnv } from '~/systems/utils/requireEnv';
56

67
const { FUEL_PROVIDER: url } = requireEnv(['FUEL_PROVIDER']);
@@ -29,8 +30,17 @@ const { handleRequest } = createYoga({
2930
},
3031
});
3132

33+
const authenticatiohMiddleware = async (request: Request, ctx: Object) => {
34+
if (process.env.FUEL_EXPLORER_API) {
35+
return new NextResponse('Unauthorized', {
36+
status: 401,
37+
});
38+
}
39+
return handleRequest(request, ctx);
40+
};
41+
3242
export {
33-
handleRequest as GET,
34-
handleRequest as POST,
35-
handleRequest as OPTIONS,
43+
authenticatiohMiddleware as GET,
44+
authenticatiohMiddleware as POST,
45+
authenticatiohMiddleware as OPTIONS,
3646
};
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
import { resolve } from 'url';
2-
import { getSdk } from '@fuel-explorer/graphql';
2+
import { getSdk } from '@fuel-explorer/graphql/src/sdk';
33
import { GraphQLClient } from 'graphql-request';
44

5+
const { FUEL_EXPLORER_API, FUEL_EXPLORER_API_KEY } = process.env;
56
const VERCEL_URL = process.env.VERCEL_URL || process.env.NEXT_PUBLIC_VERCEL_URL;
67
const VERCEL_ENV =
78
process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || 'development';
89

910
const getBaseUrl = () => {
10-
if (VERCEL_ENV !== 'development') return `https://${VERCEL_URL}`;
11-
return 'http://localhost:3000';
11+
if (FUEL_EXPLORER_API && FUEL_EXPLORER_API_KEY) return FUEL_EXPLORER_API;
12+
if (VERCEL_ENV !== 'development')
13+
return resolve(`https://${VERCEL_URL}`, '/api/graphql');
14+
return 'http://localhost:3000/api/graphql';
15+
};
16+
const getHeaders = () => {
17+
if (FUEL_EXPLORER_API_KEY) {
18+
return { Authorization: `Bearer ${FUEL_EXPLORER_API_KEY}` };
19+
}
20+
return undefined;
1221
};
1322

14-
const API_URL = resolve(getBaseUrl(), '/api/graphql');
15-
const client = new GraphQLClient(API_URL, { fetch });
23+
const client = new GraphQLClient(getBaseUrl(), {
24+
fetch,
25+
headers: getHeaders(),
26+
});
1627
export const sdk = getSdk(client);

packages/app-explorer/src/systems/Transaction/component/TxScripts/TxScripts.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { ReceiptType } from '@fuel-explorer/graphql';
1+
import { ReceiptType } from '@fuel-explorer/graphql/src/sdk';
22
import type {
33
Maybe,
44
OperationReceipt,
55
TransactionReceiptFragment,
6-
} from '@fuel-explorer/graphql';
6+
} from '@fuel-explorer/graphql/src/sdk';
77
import type { BaseProps } from '@fuels/ui';
88
import {
99
Address,

packages/app-explorer/src/systems/Transactions/components/TxCard/TxCard.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { IconGasStation } from '@tabler/icons-react';
1414
import Link from 'next/link';
1515
import { Routes } from '~/routes';
1616

17+
import { isValidAddress } from '~/systems/Core/utils/address';
1718
import { TX_INTENT_MAP } from '../../../Transaction/component/TxIcon/TxIcon';
1819
import type { TransactionNode } from '../../../Transaction/types';
1920

@@ -29,9 +30,10 @@ export function TxCard({
2930
...props
3031
}: TxCardProps) {
3132
const fee = bn(tx.fee);
33+
const isValidTxID = isValidAddress(tx.id);
3234

3335
return (
34-
<Link scroll={true} href={Routes.txSimple(tx.id)}>
36+
<Link scroll={true} href={Routes.txSimple(tx.id)} prefetch={isValidTxID}>
3537
<Card {...props} className={cx(className)}>
3638
<Card.Body className="flex flex-col gap-4 laptop:flex-row laptop:justify-between">
3739
<Box className="flex gap-3 h-[26px]">

packages/graphql/.dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_moduels
22
.turbo
33
dist
4+
.env

packages/graphql/codegen.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import type { CodegenConfig } from '@graphql-codegen/cli';
33
const config: CodegenConfig = {
44
overwrite: true,
55
documents: ['./src/queries/**.graphql'],
6-
schema: `http://localhost:${process.env.SERVER_PORT}/graphql`,
6+
schema: {
7+
[`http://localhost:${process.env.SERVER_PORT}/graphql`]: {
8+
headers: {
9+
Authorization: `Bearer ${process.env.FUEL_EXPLORER_API_KEY}`,
10+
},
11+
},
12+
},
713
generates: {
814
'src/generated/types.ts': {
915
plugins: [

packages/graphql/src/sdk.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './generated/types';

packages/graphql/src/server.ts

+11
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,24 @@ import { requireEnv } from './utils/requireEnv';
1111
const { FUEL_PROVIDER } = requireEnv([
1212
['FUEL_PROVIDER', 'https://beta-5.fuel.network/graphql'],
1313
]);
14+
const { FUEL_EXPLORER_API_KEY } = process.env;
1415

1516
// Create a server:
1617
const app = express();
1718

1819
app.use(cors<cors.CorsRequest>());
1920
app.use(express.json());
2021

22+
if (FUEL_EXPLORER_API_KEY) {
23+
app.use((req, res, next) => {
24+
if (req.headers.authorization !== `Bearer ${FUEL_EXPLORER_API_KEY}`) {
25+
res.status(401).send('Unauthorized');
26+
return;
27+
}
28+
next();
29+
});
30+
}
31+
2132
app.get(
2233
'/graphql',
2334
expressPlayground({

0 commit comments

Comments
 (0)