Files
explore/lib/api/useApiFetch.tsx
T
tom goriunovandGitHub ca4c8d6633 OP Superchain Explorer: MVP (#2786)
* context for storing subchain config and tx view for subchain

* address page and block page for subchain

* address aggregated page: local txs tab

* connect MultichainSelect to context

* home page placeholder

* refactor subchain select state

* envs for demo

* fix ts

* clear value for l2 review

* subchain widgets on home page

* csp policies

* sockets, duck and goose

* fix socket on subchain address page

* link builder for subchain views

* update home widget

* fix time increment

* enable tx interpretator and metadata service

* generate multichain config based on every chain app config

* Fix the multichain config to work in Docker

* multichain socket test

* rename subchain-id to subchain-slug path param

* refactoring

* update chain icons on entities

* home page: latest local txs

* latest cross-chain txs

* minor improvements

* renaming, pt. 1

* rename chain routes

* enable blockchain interaction

* add loading state to icon shield

* fix build

* fix tests

* update types package
2025-07-03 15:07:00 +02:00

69 lines
2.7 KiB
TypeScript

import { useQueryClient } from '@tanstack/react-query';
import { omit, pickBy } from 'es-toolkit';
import React from 'react';
import type { CsrfData } from 'types/client/account';
import type { ChainConfig } from 'types/multichain';
import config from 'configs/app';
import isBodyAllowed from 'lib/api/isBodyAllowed';
import isNeedProxy from 'lib/api/isNeedProxy';
import { getResourceKey } from 'lib/api/useApiQuery';
import * as cookies from 'lib/cookies';
import type { Params as FetchParams } from 'lib/hooks/useFetch';
import useFetch from 'lib/hooks/useFetch';
import buildUrl from './buildUrl';
import getResourceParams from './getResourceParams';
import type { ResourceName, ResourcePathParams } from './resources';
export interface Params<R extends ResourceName> {
pathParams?: ResourcePathParams<R>;
queryParams?: Record<string, string | Array<string> | number | boolean | undefined | null>;
fetchParams?: Pick<FetchParams, 'body' | 'method' | 'signal' | 'headers'>;
logError?: boolean;
chain?: ChainConfig;
}
export default function useApiFetch() {
const fetch = useFetch();
const queryClient = useQueryClient();
const { token: csrfToken } = queryClient.getQueryData<CsrfData>(getResourceKey('general:csrf')) || {};
return React.useCallback(<R extends ResourceName, SuccessType = unknown, ErrorType = unknown>(
resourceName: R,
{ pathParams, queryParams, fetchParams, logError, chain }: Params<R> = {},
) => {
const apiToken = cookies.get(cookies.NAMES.API_TOKEN);
const { api, apiName, resource } = getResourceParams(resourceName, chain);
const url = buildUrl(resourceName, pathParams, queryParams, undefined, chain);
const withBody = isBodyAllowed(fetchParams?.method);
const headers = pickBy({
'x-endpoint': api.endpoint && apiName !== 'general' && isNeedProxy() ? api.endpoint : undefined,
Authorization: [ 'admin', 'contractInfo' ].includes(apiName) ? apiToken : undefined,
'x-csrf-token': withBody && csrfToken ? csrfToken : undefined,
...resource.headers,
...fetchParams?.headers,
}, Boolean) as HeadersInit;
return fetch<SuccessType, ErrorType>(
url,
{
// as of today, we use cookies only
// for user authentication in My account
// for API rate-limits (cannot use in the condition though, but we agreed with devops team that should not be an issue)
// change condition here if something is changed
credentials: config.features.account.isEnabled ? 'include' : 'same-origin',
headers,
...(fetchParams ? omit(fetchParams, [ 'headers' ]) : {}),
},
{
resource: resource.path,
logError,
},
);
}, [ fetch, csrfToken ]);
}