diff --git a/packages/nextra-theme/src/components/DocSearch.tsx b/packages/nextra-theme/src/components/DocSearch.tsx index 8237ea14b56a..f06cc52dafc8 100644 --- a/packages/nextra-theme/src/components/DocSearch.tsx +++ b/packages/nextra-theme/src/components/DocSearch.tsx @@ -65,7 +65,7 @@ export function DocSearch(props: DocSearchProps) { innerFocusRing sx={{ borderRadius: [BorderRadius.FULL, null, null, BorderRadius.S], - '&:focus-visible': { outline: ['none', null, null, `${BorderWidth['4px']} solid ${theme.colors!.Purple16}`] }, + '&:focus-visible': { outline: ['none', null, null, `${BorderWidth['4px']} solid ${theme.colors.Purple16}`] }, }} > <Responsive.Multiple as="span" cases={['mobile', null, null, 'desktop']}> @@ -158,17 +158,17 @@ export function DocSearch(props: DocSearchProps) { styles={{ html: { '--docsearch-spacing': '0 !important', - '--docsearch-container-background': `${theme.colors!.Midnight88} !important`, + '--docsearch-container-background': `${theme.colors.Midnight88} !important`, '--docsearch-modal-width': 'min(calc(100vw - 32px), 840px) !important', - '--docsearch-modal-background': `${theme.colors!.Tooltip} !important`, + '--docsearch-modal-background': `${theme.colors.Tooltip} !important`, '--docsearch-modal-shadow': 'none !important', '--docsearch-searchbox-height': ['64px !important', null, '96px !important'], '--docsearch-searchbox-focus-background': 'transparent !important', '--docsearch-searchbox-shadow': 'none !important', '--docsearch-hit-background': 'transparent !important', - '--docsearch-hit-color': `${theme.colors!.White88} !important`, - '--docsearch-hit-active-color': `${theme.colors!.White} !important`, - '--docsearch-highlight-color': `${theme.colors!.Purple} !important`, + '--docsearch-hit-color': `${theme.colors.White88} !important`, + '--docsearch-hit-active-color': `${theme.colors.White} !important`, + '--docsearch-highlight-color': `${theme.colors.Purple} !important`, }, '.DocSearch-Container': { animation: `${animationFadeIn} 150ms ease-in-out`, diff --git a/website/pages/en/cookbook/_meta.js b/website/pages/en/cookbook/_meta.js index f8b5035ddb55..d1e9e050cef0 100644 --- a/website/pages/en/cookbook/_meta.js +++ b/website/pages/en/cookbook/_meta.js @@ -1,4 +1,5 @@ export default { + 'subgraph-composition': '', 'subgraph-debug-forking': '', near: '', cosmos: '', diff --git a/website/pages/en/cookbook/subgraph-composition.mdx b/website/pages/en/cookbook/subgraph-composition.mdx new file mode 100644 index 000000000000..14e8609fb7a7 --- /dev/null +++ b/website/pages/en/cookbook/subgraph-composition.mdx @@ -0,0 +1,127 @@ +--- +title: Subgraph Composition with Sushiswap v3 on Base +--- + +Leverage subgraph composition to create a base subgraph containing core data and build additional subgraphs on top. + +> - Subgraph composition is built into the CLI, and you can deploy with [Subgraph Studio](https://thegraph.com/studio/). +> - You can use existing subgraphs, but they must be redeployed with a new spec version, which doesn't require you to write new code. However, you may want to restructure your subgraph to split out the logic as you move to a composable subgraph world. + +## Overview + +### Benefits of Composition + +Subgraph composition is a powerful feature for scaling, allowing you to: + +- Reuse existing data +- Speed up your subgraph's syncing speed +- Handle errors and optimize the resync +- Enhance your subgraph development to effortlessly scale + +## Setup + +This guide uses the Sushiswap v3 subgraph on Base chain. + +### Tools Needed + +The setup involves two subgraphs: + +1. **Source Subgraph**: Tracks event data as entities. +2. **Dependent Subgraph**: Uses the source subgraph as a data source. + +You can find these in the `source` and `dependent` directories. + +- The **source subgraph** is a basic event-tracking subgraph that records events emitted by relevant contracts. +- The **dependent subgraph** references the source subgraph as a data source, using the entities from the source as triggers. + +While the source subgraph is a standard subgraph, the dependent subgraph utilizes the subgraph composition feature. + +### Source Subgraph + +The source subgraph tracks events from the Sushiswap v3 subgraph on the Base chain. This subgraph's configuration file is in the `source/subgraph.yaml`. + +### Dependent Subgraph + +The dependent subgraph is in the `dependent/subgraph.yaml` directory, which specifies the source subgraph as a data source. This subgraph uses entities from the source to trigger specific actions based on changes to those entities. + +## Get Started + +The following is a how-to-guide on using one subgraph as a data source for another. + +### Step 1. Set Up Your Source Subgraph + +To set the source subgraph as a data source in the dependent subgraph, include the following in `subgraph.yaml`: + +```yaml +specVersion: 1.3.0 +schema: + file: ./schema.graphql +dataSources: + - kind: subgraph + name: Factory + network: base + source: + address: 'QmdXu8byAFCGSDWsB5gMQjWr6GUvEVB7S1hemfxNuomerz' + startBlock: 82522 +``` + +Here, `source.address` refers to the Deployment ID of the source subgraph, and `startBlock` specifies the block from which indexing should begin. + +### Step 2. Define Handlers in Dependent Subgraph + +Below is an example of defining handlers in the dependent subgraph: + +```typescript +export function handleInitialize(trigger: EntityTrigger<Initialize>): void { + if (trigger.operation === EntityOp.Create) { + let entity = trigger.data + let poolAddressParam = Address.fromBytes(entity.poolAddress) + + // Update pool sqrt price and tick + let pool = Pool.load(poolAddressParam.toHexString()) as Pool + pool.sqrtPrice = entity.sqrtPriceX96 + pool.tick = BigInt.fromI32(entity.tick) + pool.save() + + // Update token prices + let token0 = Token.load(pool.token0) as Token + let token1 = Token.load(pool.token1) as Token + + // Update ETH price in USD + let bundle = Bundle.load('1') as Bundle + bundle.ethPriceUSD = getEthPriceInUSD() + bundle.save() + + updatePoolDayData(entity) + updatePoolHourData(entity) + + // Update derived ETH price for tokens + token0.derivedETH = findEthPerToken(token0) + token1.derivedETH = findEthPerToken(token1) + token0.save() + token1.save() + } +} +``` + +In this example, the `handleInitialize` function is triggered when a new `Initialize` entity is created in the source subgraph, passed as `EntityTrigger<Initialize>`. The handler updates the pool and token entities based on data from the new `Initialize` entity. + +`EntityTrigger` has three fields: + +1. `operation`: Specifies the operation type, which can be `Create`, `Modify`, or `Remove`. +2. `type`: Indicates the entity type. +3. `data`: Contains the entity data. + +Developers can then determine specific actions for the entity data based on the operation type. + +## Key Takeaways + +- Use this powerful tool to scale your subgraph development and reuse existing data. +- The setup includes creating a base source subgraph and referencing it in a dependent subgraph. +- You define handlers in the dependent subgraph to perform actions based on changes in the source subgraph's entities. + +This approach unlocks modularity and scalability, simplifying both development and maintenance efficiency. + +## Additional Resources + +To use other advance features in your subgraph check out [subgraph advance features](/developing/creating/advanced/) and the [subgraph composition repo](https://github.com/incrypto32/subgraph-composition-sample-subgraph).