From f299559fe870734cf3eaee853cdb1065c3ab58f9 Mon Sep 17 00:00:00 2001 From: Jaden Date: Wed, 27 Dec 2023 15:09:33 -0500 Subject: [PATCH] feat: proxy changes --- components/collections/CollectionActions.tsx | 2 +- components/collections/TokenCard.tsx | 4 +- components/portfolio/PortfolioTokenCard.tsx | 4 +- components/portfolio/TokenTable.tsx | 4 +- pages/[chain]/asset/[assetId].tsx | 23 +-- pages/_app.tsx | 5 +- pages/api/reservoir/[...slug].ts | 151 ------------------- 7 files changed, 22 insertions(+), 171 deletions(-) delete mode 100644 pages/api/reservoir/[...slug].ts diff --git a/components/collections/CollectionActions.tsx b/components/collections/CollectionActions.tsx index 9688d0421..dd455067c 100644 --- a/components/collections/CollectionActions.tsx +++ b/components/collections/CollectionActions.tsx @@ -110,7 +110,7 @@ const CollectionActions: FC = ({ collection }) => { } setIsRefreshing(true) fetcher( - `${window.location.origin}/${marketplaceChain.proxyApi}/collections/refresh/v2`, + `${process.env.NEXT_PUBLIC_PROXY_URL}${marketplaceChain.proxyApi}/collections/refresh/v2`, undefined, { method: 'POST', diff --git a/components/collections/TokenCard.tsx b/components/collections/TokenCard.tsx index 9ccd5aafd..a7d9dcc4d 100644 --- a/components/collections/TokenCard.tsx +++ b/components/collections/TokenCard.tsx @@ -293,10 +293,10 @@ export default ({ onClick={(e) => { e.preventDefault() e.stopPropagation() - const url = `${proxyApi}/redirect/sources/${token?.market?.floorAsk?.source?.domain}/tokens/${token?.token?.contract}:${token?.token?.tokenId}/link/v2` + const url = `${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/redirect/sources/${token?.market?.floorAsk?.source?.domain}/tokens/${token?.token?.contract}:${token?.token?.tokenId}/link/v2` window.open(url, '_blank') }} - src={`${proxyApi}/redirect/sources/${token?.market?.floorAsk?.source?.domain}/logo/v2`} + src={`${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/redirect/sources/${token?.market?.floorAsk?.source?.domain}/logo/v2`} /> ) : null} diff --git a/components/portfolio/PortfolioTokenCard.tsx b/components/portfolio/PortfolioTokenCard.tsx index 2e4354420..aedecb447 100644 --- a/components/portfolio/PortfolioTokenCard.tsx +++ b/components/portfolio/PortfolioTokenCard.tsx @@ -339,7 +339,7 @@ export default ({ height: 20, borderRadius: '50%', }} - src={`${proxyApi}/redirect/sources/${token?.ownership?.floorAsk?.source?.domain}/logo/v2`} + src={`${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/redirect/sources/${token?.ownership?.floorAsk?.source?.domain}/logo/v2`} /> )} @@ -470,7 +470,7 @@ export default ({ } setIsRefreshing(true) fetcher( - `${window.location.origin}/${proxyApi}/tokens/refresh/v1`, + `${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/tokens/refresh/v1`, undefined, { method: 'POST', diff --git a/components/portfolio/TokenTable.tsx b/components/portfolio/TokenTable.tsx index 06a380693..21b9a8642 100644 --- a/components/portfolio/TokenTable.tsx +++ b/components/portfolio/TokenTable.tsx @@ -499,7 +499,7 @@ const TokenTableRow: FC = ({ } setIsRefreshing(true) fetcher( - `${window.location.origin}/${proxyApi}/tokens/refresh/v1`, + `${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/tokens/refresh/v1`, undefined, { method: 'POST', @@ -926,7 +926,7 @@ const TokenTableRow: FC = ({ } setIsRefreshing(true) fetcher( - `${window.location.origin}/${proxyApi}/tokens/refresh/v1`, + `${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/tokens/refresh/v1`, undefined, { method: 'POST', diff --git a/pages/[chain]/asset/[assetId].tsx b/pages/[chain]/asset/[assetId].tsx index 0ebc901e4..7ba4fa02f 100644 --- a/pages/[chain]/asset/[assetId].tsx +++ b/pages/[chain]/asset/[assetId].tsx @@ -387,7 +387,7 @@ const IndexPage: NextPage = ({ assetId, ssr }) => { } setIsRefreshing(true) fetcher( - `${window.location.origin}/${proxyApi}/tokens/refresh/v1`, + `${process.env.NEXT_PUBLIC_PROXY_URL}${proxyApi}/tokens/refresh/v1`, undefined, { method: 'POST', @@ -416,8 +416,8 @@ const IndexPage: NextPage = ({ assetId, ssr }) => { title: 'Refresh token failed', description: ratelimit ? `This token was recently refreshed. The next available refresh is ${timeTill( - ratelimit - )}.` + ratelimit + )}.` : `This token was recently refreshed. Please try again later.`, }) @@ -453,7 +453,10 @@ const IndexPage: NextPage = ({ assetId, ssr }) => { You own {countOwned} - + = ({ assetId, ssr }) => { type SSRProps = { collection?: - | paths['/collections/v7']['get']['responses']['200']['schema'] - | null + | paths['/collections/v7']['get']['responses']['200']['schema'] + | null tokens?: paths['/tokens/v6']['get']['responses']['200']['schema'] | null } @@ -648,10 +651,10 @@ export const getServerSideProps: GetServerSideProps<{ : {} let collectionQuery: paths['/collections/v7']['get']['parameters']['query'] = - { - id: tokens?.tokens?.[0]?.token?.collection?.id, - normalizeRoyalties: NORMALIZE_ROYALTIES, - } + { + id: tokens?.tokens?.[0]?.token?.collection?.id, + normalizeRoyalties: NORMALIZE_ROYALTIES, + } const collectionsPromise = fetcher( `${reservoirBaseUrl}/collections/v7`, diff --git a/pages/_app.tsx b/pages/_app.tsx index 0b260c6b0..4cae4d6c4 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -224,9 +224,8 @@ AppWrapper.getInitialProps = async (appContext: AppContext) => { const appProps = await NextApp.getInitialProps(appContext) let baseUrl = '' - if (appContext.ctx.req?.headers.host) { - const host = appContext.ctx.req?.headers.host - baseUrl = `${host.includes('localhost') ? 'http' : 'https'}://${host}` + if (process.env.NEXT_PUBLIC_PROXY_URL) { + baseUrl = process.env.NEXT_PUBLIC_PROXY_URL } else if (process.env.NEXT_PUBLIC_HOST_URL) { baseUrl = process.env.NEXT_PUBLIC_HOST_URL || '' } diff --git a/pages/api/reservoir/[...slug].ts b/pages/api/reservoir/[...slug].ts deleted file mode 100644 index e3f3159e3..000000000 --- a/pages/api/reservoir/[...slug].ts +++ /dev/null @@ -1,151 +0,0 @@ -import { setParams } from '@reservoir0x/reservoir-sdk' -import type { NextApiRequest, NextApiResponse } from 'next' -import supportedChains, { DefaultChain } from 'utils/chains' -import { arbitrum, goerli, mainnet, optimism, zora } from 'wagmi/chains' -import wrappedContracts from 'utils/wrappedContracts' -import { zeroAddress } from 'viem' - -// A proxy API endpoint to redirect all requests to `/api/reservoir/*` to -// MAINNET: https://api.reservoir.tools/{endpoint}/{query-string} -// and attach the `x-api-key` header to the request. This way the -// Reservoir API key is not exposed to the client. - -const allowedDomains = process.env.ALLOWED_API_DOMAINS - ? process.env.ALLOWED_API_DOMAINS.split(',') - : null - -// https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes -const proxy = async (req: NextApiRequest, res: NextApiResponse) => { - const { query, body, method, headers: reqHeaders } = req - if (allowedDomains && allowedDomains.length > 0) { - let origin = req.headers.origin || req.headers.referer || '' - try { - origin = new URL(origin).origin - } catch (e) {} - if (!origin.length || !allowedDomains.includes(origin)) { - res.status(403).json({ error: 'Access forbidden' }) - return - } - } - - const { slug } = query - // Isolate the query object - delete query.slug - - let endpoint: string = '' - - // convert the slug array into a path string: [a, b] -> 'a/b' - if (typeof slug === 'string') { - endpoint = slug - } else { - endpoint = (slug || ['']).join('/') - } - - const chainPrefix = endpoint.split('/')[0] - const chain = - supportedChains.find((chain) => chain.routePrefix === chainPrefix) || - DefaultChain - - const url = new URL(endpoint.replace(chainPrefix, ''), chain.reservoirBaseUrl) - setParams(url, query) - - if (endpoint.includes('redirect/')) { - // Redirect eth and weth currency icons to self-hosted - // versions without any padding - endpoint = endpoint.toLowerCase() - if ( - [ - mainnet.id as number, - goerli.id, - zora.id, - optimism.id, - arbitrum.id, - ].includes(chain.id) && - endpoint.includes('currency') - ) { - if (endpoint.includes(zeroAddress)) { - res.redirect('/icons/currency/no-padding-eth.png') - return - } else if ( - endpoint.includes(wrappedContracts['1'].toLowerCase()) || - endpoint.includes(wrappedContracts['5'].toLowerCase()) - ) { - res.redirect('/icons/currency/no-padding-weth.png') - return - } - } - res.redirect(url.href) - return - } else if (endpoint.match(/\/users\/(\w+)\/tokens\/v7/g)) { - if ( - url.searchParams.get('limit') && - Number(url.searchParams.get('limit')) > 195 - ) { - res.status(403).json({ error: 'Access forbidden' }) - } - } - - try { - const options: RequestInit | undefined = { - method, - } - - const headers = new Headers({ - Referrer: reqHeaders['referer'] || reqHeaders['origin'] || '', - Origin: 'https://explorer-proxy.reservoir.tools', - }) - - if (process.env.RESERVOIR_API_KEY) - headers.set('x-api-key', process.env.RESERVOIR_API_KEY) - - if (typeof body === 'object') { - headers.set('Content-Type', 'application/json') - options.body = JSON.stringify(body) - } - - if ( - reqHeaders['x-rkc-version'] && - typeof reqHeaders['x-rkc-version'] === 'string' - ) { - headers.set('x-rkc-version', reqHeaders['x-rkc-version']) - } - - if ( - reqHeaders['x-rkui-version'] && - typeof reqHeaders['x-rkui-version'] === 'string' - ) { - headers.set('x-rkui-version', reqHeaders['x-rkui-version']) - } - - options.headers = headers - - const response = await fetch(url.href, options) - let data: any - - const contentType = response.headers.get('content-type') - - const cacheControl = response.headers.get('cache-control') - if (cacheControl) { - headers.set('cache-control', cacheControl) - } - - if (contentType?.includes('application/json')) { - data = await response.json() - } else { - data = await response.text() - } - - if (!response.ok) throw data - - if (contentType?.includes('image/')) { - res.setHeader('Content-Type', 'text/html') - res.status(200).send(Buffer.from(data)) - } else { - res.status(200).json(data) - } - } catch (error) { - res.status(400).json(error) - } -} - -export default proxy