Commit c02fe2cd authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #659 from blockscout/graphql-1

Graphql
parents 1bd8a059 2e4b7b31
......@@ -40,7 +40,8 @@ NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_PLATE
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER__
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=__PLACEHOLDER_FOR_NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME__
NEXT_PUBLIC_AD_DOMAIN_WITH_AD=__PLACEHOLDER_FOR_NEXT_PUBLIC_DOMAIN_WITH_AD__
NEXT_PUBLIC_AD_ADBUTLER_ON=__PLACEHOLDER_FORNEXT_PUBLIC_AD_ADBUTLER_ON__
NEXT_PUBLIC_AD_ADBUTLER_ON=__PLACEHOLDER_FOR_NEXT_PUBLIC_AD_ADBUTLER_ON__
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=__PLACEHOLDER_FOR_NEXT_PUBLIC_GRAPHIQL_TRANSACTION__
# api config
NEXT_PUBLIC_API_HOST=__PLACEHOLDER_FOR_NEXT_PUBLIC_API_HOST__
......
......@@ -81,6 +81,8 @@ The app instance could be customized by passing following variables to NodeJS en
| NEXT_PUBLIC_DOMAIN_WITH_AD | `string` *(optional)* | The domain on which we display ads | `blockscout.com` |
| NEXT_PUBLIC_AD_ADBUTLER_ON | `boolean` *(optional)* | Set to true to show Adbutler banner instead of Coinzilla banner | `false` |
| NEXT_PUBLIC_API_SPEC_URL | `string` *(optional)* | Spec to be displayed on api-docs page | `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml` |
| NEXT_PUBLIC_GRAPHIQL_TRANSACTION | `string` *(optional)* | Txn hash for default query at GraphQl playground page | `0x69e3923eef50eada197c3336d546936d0c994211492c9f947a24c02827568f9f` |
### App configuration
| Variable | Type | Description | Default value
......
......@@ -136,6 +136,9 @@ const config = Object.freeze({
googleAnalytics: {
propertyId: getEnvValue(process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID),
},
graphQL: {
defaultTxnHash: getEnvValue(process.env.NEXT_PUBLIC_GRAPHIQL_TRANSACTION) || '',
},
});
export default config;
# ui config
NEXT_PUBLIC_FEATURED_NETWORKS=[{'title':'Ethereum','url':'https://blockscout.com/eth/mainnet','group':'mainnets','type':'eth_mainnet'},{'title':'Ethereum Classic','url':'https://blockscout.com/etx/mainnet','group':'mainnets','type':'etc_mainnet'},{'title':'Gnosis Chain','url':'https://blockscout.com/xdai/mainnet','group':'mainnets','type':'xdai_mainnet'},{'title':'Astar (EVM)','url':'https://blockscout.com/astar','group':'mainnets','type':'astar'},{'title':'Shiden (EVM)','url':'https://blockscout.com/shiden','group':'mainnets','type':'astar'},{'title':'Klaytn Mainnet (Cypress)','url':'https://klaytn-mainnet.aws-k8s.blockscout.com/','group':'mainnets','type':'klaytn'},{'title':'Goerli','url':'https://blockscout.com/eth/goerli/','group':'testnets','type':'goerli'},{'title':'Optimism Goerli','url':'https://blockscout.com/optimism/goerli/','group':'testnets','type':'optimism_goerli'},{'title':'Optimism Bedrock Alpha','url':'https://blockscout.com/optimism/bedrock-alpha','group':'testnets','type':'optimism_bedrock_alpha'},{'title':'Gnosis Chiado','url':'https://blockscout.com/gnosis/chiado/','group':'testnets','type':'gnosis_chiado'},{'title':'Shibuya (EVM)','url':'https://blockscout.com/shibuya','group':'testnets','type':'shibuya'},{'title':'Optimism Opcraft','url':'https://blockscout.com/optimism/opcraft','group':'other','type':'optimism_opcraft'},{'title':'Optimism on Gnosis Chain','url':'https://blockscout.com/xdai/optimism','group':'other','type':'optimism_gnosis'},{'title':'ARTIS-Σ1','url':'https://blockscout.com/artis/sigma1','group':'other','type':'artis_sigma1'},{'title':'LUKSO L14','url':'https://blockscout.com/lukso/l14','group':'other','type':'lukso_l14'},{'title':'POA','url':'https://blockscout.com/poa/core','group':'other','type':'poa_core'},{'title':'POA Sokol','url':'https://blockscout.com/poa/sokol','group':'other','type':'poa_sokol'}]
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/ethereum/goerli/transaction','address':'/ethereum/ethereum/goerli/address'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address'}}]
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
# network config
NEXT_PUBLIC_NETWORK_NAME=Goerli
......
......@@ -2,6 +2,7 @@
NEXT_PUBLIC_FEATURED_NETWORKS=[{'title':'Göerli','url':'https://eth-goerli.blockscout.com/','group':'testnets','type':'goerli'},{'title':'Base Göerli','url':'https://l2-goerli.blockscout.com/','group':'testnets','type':'base_goerli'}]
NEXT_PUBLIC_NETWORK_EXPLORERS=
NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT=linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
# network config
NEXT_PUBLIC_NETWORK_NAME=Base Göerli
......
......@@ -316,6 +316,7 @@ frontend:
- "/api-docs"
- "/csv-export"
- "/verified-contracts"
- "/graphiql"
resources:
limits:
......@@ -399,6 +400,8 @@ frontend:
_default: https://blockscout-main.test.aws-k8s.blockscout.com
NEXT_PUBLIC_L2_WITHDRAWAL_URL:
_default: https://app.optimism.io/bridge/withdraw
NEXT_PUBLIC_GRAPHIQL_TRANSACTION:
_default: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
# enable blockscout-allowance
allowance:
enabled: false
......
......@@ -364,6 +364,7 @@ frontend:
- "/api-docs"
- "/csv-export"
- "/verified-contracts"
- "/graphiql"
resources:
limits:
......@@ -442,3 +443,5 @@ frontend:
_default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_IS_TESTNET:
_default: true
NEXT_PUBLIC_GRAPHIQL_TRANSACTION:
_default: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
......@@ -39,6 +39,7 @@ frontend:
- "/api-docs"
- "/csv-export"
- "/verified-contracts"
- "/graphiql"
resources:
limits:
......@@ -124,3 +125,5 @@ frontend:
_default: https://blockscout-main.test.aws-k8s.blockscout.com
NEXT_PUBLIC_L2_WITHDRAWAL_URL:
_default: https://app.optimism.io/bridge/withdraw
NEXT_PUBLIC_GRAPHIQL_TRANSACTION:
_default: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
......@@ -39,6 +39,7 @@ frontend:
- "/api-docs"
- "/csv-export"
- "/verified-contracts"
- "/graphiql"
resources:
limits:
......@@ -120,3 +121,5 @@ frontend:
_default: https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_IS_TESTNET:
_default: true
NEXT_PUBLIC_GRAPHIQL_TRANSACTION:
_default: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
......@@ -354,6 +354,11 @@ export const RESOURCES = {
path: '/api/v2/search/check-redirect',
},
// GraphQL
graphql: {
path: '/graphql',
},
// DEPRECATED
old_api: {
path: '/api',
......
......@@ -140,7 +140,7 @@ export default function useNavItems(): ReturnType {
nextRoute: { pathname: '/graphiql' as const },
icon: graphQLIcon,
isActive: pathname === '/graphiql',
isNewUi: false,
isNewUi: true,
},
{
text: 'RPC API',
......
......@@ -10,7 +10,7 @@ import SwaggerUI from 'ui/apiDocs/SwaggerUI';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const AppsPage: NextPage = () => {
const APIDocsPage: NextPage = () => {
const networkTitle = getNetworkTitle();
return (
......@@ -22,7 +22,7 @@ const AppsPage: NextPage = () => {
);
};
export default AppsPage;
export default APIDocsPage;
export const getServerSideProps: GetServerSideProps<Props> = async(args) => {
if (!appConfig.apiDoc.specUrl) {
......
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
const GraphQL = dynamic(() => import('ui/graphQL/GraphQL'), {
loading: () => <ContentLoader/>,
ssr: false,
});
import Head from 'next/head';
import React from 'react';
const GraphQLPage: NextPage = () => {
return null;
import ContentLoader from 'ui/shared/ContentLoader';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
const GraphiqlPage: NextPage = () => {
return (
<Page>
<Head><title>Graph Page</title></Head>
<PageTitle text="GraphQL playground"/>
<GraphQL/>
</Page>
);
};
export default GraphQLPage;
export default GraphiqlPage;
export async function getServerSideProps() {
return {
notFound: true,
};
}
export { getServerSideProps } from 'lib/next/getServerSideProps';
/* eslint-disable @typescript-eslint/naming-convention */
const SwaggerUIReact = dynamic(() => import('swagger-ui-react'), {
loading: () => <Spinner/>,
loading: () => <ContentLoader/>,
ssr: false,
});
import { Box, Spinner, useColorModeValue } from '@chakra-ui/react';
import { Box, useColorModeValue } from '@chakra-ui/react';
import dynamic from 'next/dynamic';
import React from 'react';
import appConfig from 'configs/app/config';
import ContentLoader from 'ui/shared/ContentLoader';
import 'swagger-ui-react/swagger-ui.css';
......
import { Box, useColorMode } from '@chakra-ui/react';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { GraphiQL } from 'graphiql';
import React from 'react';
import appConfig from 'configs/app/config';
import buildUrl from 'lib/api/buildUrl';
import 'graphiql/graphiql.css';
import isBrowser from 'lib/isBrowser';
const graphQLStyle = {
'.graphiql-container': {
backgroundColor: 'unset',
},
};
const GraphQL = () => {
const { colorMode } = useColorMode();
// colorModeState used as a key to re-render GraphiQL conponent after color mode change
const [ colorModeState, setColorModeState ] = React.useState(colorMode);
React.useEffect(() => {
if (isBrowser()) {
const graphqlTheme = window.localStorage.getItem('graphiql:theme');
if (graphqlTheme !== colorMode) {
window.localStorage.setItem('graphiql:theme', colorMode);
setColorModeState(colorMode);
}
}
}, [ colorMode ]);
const initialQuery = `{
transaction(
hash: "${ appConfig.graphQL.defaultTxnHash }"
) {
hash
blockNumber
value
gasUsed
}
}`;
const graphqlUrl = buildUrl('graphql');
const fetcher = createGraphiQLFetcher({
url: graphqlUrl,
// graphql ws implementation with absinthe plugin is incompatible with graphiql-ws protocol
// or the older one subscriptions-transport-ws
// so we (isstuev & vbaranov) decided to configure playground without subscriptions
// in case of any complaint consider reconfigure the graphql ws server with absinthe_graphql_ws package
// subscriptionUrl: `wss://${appConfig.host}/socket/`,
});
return (
<Box h="100vh" overflowX="scroll" sx={ graphQLStyle }>
<Box h="100vh" minW="900px" sx={ graphQLStyle }>
<GraphiQL fetcher={ fetcher } defaultQuery={ initialQuery } key={ colorModeState }/>
</Box>
</Box>
);
};
export default GraphQL;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment