Skip to content

Commit

Permalink
Merge pull request #1071 from graphprotocol/horizon-gre
Browse files Browse the repository at this point in the history
  • Loading branch information
tmigone authored Dec 17, 2024
2 parents 170572f + 58c518c commit 468ed2c
Show file tree
Hide file tree
Showing 56 changed files with 2,511 additions and 30 deletions.
18 changes: 17 additions & 1 deletion .github/workflows/ci-horizon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,26 @@ jobs:
submodules: recursive
- name: Set up environment
uses: ./.github/actions/setup
- name: Build
- name: Build contracts
run: |
pushd packages/contracts
yarn build
popd
- name: Build horizon
run: |
pushd packages/horizon
yarn build
popd
- name: Build subgraph service
run: |
pushd packages/subgraph-service
yarn build
popd
- name: Build hardhat-graph-protocol
run: |
pushd packages/hardhat-graph-protocol
yarn build
popd
- name: Run tests
run: |
pushd packages/horizon
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"packages/contracts",
"packages/data-edge",
"packages/eslint-graph-config",
"packages/hardhat-graph-protocol",
"packages/horizon",
"packages/sdk",
"packages/solhint-graph-config",
Expand All @@ -21,7 +22,7 @@
"postinstall": "husky install",
"clean": "yarn workspaces foreach --all --parallel --verbose run clean",
"clean:all": "yarn clean && rm -rf node_modules packages/*/node_modules",
"build": "yarn workspaces foreach --all --verbose run build",
"build": "chmod +x ./scripts/build && ./scripts/build",
"lint": "yarn workspaces foreach --all --parallel --verbose run lint",
"test": "yarn workspaces foreach --all --parallel --verbose --interlaced run test"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-graph-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ This repository contains shared linting and formatting rules for TypeScript proj
## Installation

```bash
yarn add --dev eslint eslint-graph-config
yarn add --dev eslint@^8.56.0 eslint-graph-config
```

For projects on this monorepo, you can use the following command to install the package:

```bash
yarn add --dev eslint eslint-graph-config@workspace:^x.y.z
yarn add --dev eslint@^8.56.0 eslint-graph-config@workspace:^x.y.z
```

To enable the rules, you need to create an `eslint.config.js` file in the root of your project with the following content:
Expand Down
5 changes: 5 additions & 0 deletions packages/hardhat-graph-protocol/.mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": "ts-node/register/files",
"ignore": ["test/fixtures/**/*"],
"timeout": 6000
}
32 changes: 32 additions & 0 deletions packages/hardhat-graph-protocol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# hardhat-graph-protocol


## Usage

Install with yarn

```bash
yarn add --dev hardhat-graph-protocol

# From the monorepo
yarn add --dev hardhat-graph-protocol@workspace:^x.y.z
```

And add it to your `hardhat.config.ts`:

```ts
import "hardhat-graph-protocol";

export default {
...
graph: {
deployments: {
horizon: require.resolve('@graphprotocol/horizon/addresses.json'),
subgraphService: require.resolve('@graphprotocol/subgraph-service/addresses.json'),
}
},
...
};
```

_Note_: When using the plugin from within this monorepo TypeScript fails to properly apply the type extension typings. This is a known issue and can be worked around by adding a `types/hardhat-graph-protocol.d.ts` file with the same content as the `type-extensions.ts` file in this repository.
14 changes: 14 additions & 0 deletions packages/hardhat-graph-protocol/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const config = require('eslint-graph-config')

module.exports = [
...config.default,
{
rules: {
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
},
},
]
55 changes: 55 additions & 0 deletions packages/hardhat-graph-protocol/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "hardhat-graph-protocol",
"version": "0.0.1",
"description": "A hardhat plugin that extends the runtime environment to inject additional functionality related to the usage of the Graph Protocol.",
"keywords": [
"ethereum",
"smart-contracts",
"hardhat",
"hardhat-plugin",
"graph",
"graph-protocol",
"horizon"
],
"author": "Tomás Migone <[email protected]>",
"license": "MIT",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"lint": "eslint '**/*.{js,ts}' --fix",
"test": "mocha --exit --recursive 'test/**/*.test.ts'",
"prepublishOnly": "npm run build"
},
"files": [
"dist/",
"src/",
"LICENSE",
"README.md"
],
"dependencies": {
"@graphprotocol/contracts": "workspace:^7.0.0",
"@graphprotocol/horizon": "workspace:^0.0.1",
"@graphprotocol/subgraph-service": "workspace:^0.0.1",
"@nomicfoundation/hardhat-ethers": "^3.0.8",
"debug": "^4.3.7"
},
"devDependencies": {
"@types/chai": "^4.0.0",
"@types/debug": "^4.1.12",
"@types/mocha": "^10.0.9",
"chai": "^4.0.0",
"eslint": "^8.56.0",
"eslint-graph-config": "workspace:^0.0.1",
"ethers": "^6.13.4",
"hardhat": "^2.22.16",
"mocha": "^10.8.2",
"ts-node": "^8.0.0",
"typescript": "^5.6.3"
},
"peerDependencies": {
"ethers": "^6.13.4",
"hardhat": "^2.22.16"
}
}
48 changes: 48 additions & 0 deletions packages/hardhat-graph-protocol/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import fs from 'fs'

import { GraphPluginError } from './sdk/utils/error'
import { logDebug } from './logger'
import { normalizePath } from './sdk/utils/path'

import type { GraphDeployment, GraphRuntimeEnvironmentOptions } from './types'
import type { HardhatRuntimeEnvironment } from 'hardhat/types'

export function getAddressBookPath(
deployment: GraphDeployment,
hre: HardhatRuntimeEnvironment,
opts: GraphRuntimeEnvironmentOptions,
): string {
const optsPath = getPath(opts.deployments?.[deployment])
const networkPath = getPath(hre.network.config.deployments?.[deployment])
const globalPath = getPath(hre.config.graph?.deployments?.[deployment])

logDebug(`Getting address book path...`)
logDebug(`Graph base dir: ${hre.config.paths.graph}`)
logDebug(`1) opts: ${optsPath}`)
logDebug(`2) network: ${networkPath}`)
logDebug(`3) global: ${globalPath}`)

const addressBookPath = optsPath ?? networkPath ?? globalPath
if (addressBookPath === undefined) {
throw new GraphPluginError('Must set a an addressBook path!')
}

const normalizedAddressBookPath = normalizePath(addressBookPath, hre.config.paths.graph)
if (!fs.existsSync(normalizedAddressBookPath)) {
throw new GraphPluginError(`Address book not found: ${normalizedAddressBookPath}`)
}

logDebug(`Address book path found: ${normalizedAddressBookPath}`)
return normalizedAddressBookPath
}

function getPath(value: string | {
addressBook: string
} | undefined): string | undefined {
if (typeof value === 'string') {
return value
} else if (value && typeof value == 'object') {
return value.addressBook
}
return
}
19 changes: 19 additions & 0 deletions packages/hardhat-graph-protocol/src/deployment-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { GraphHorizonAddressBook, GraphHorizonContracts } from './sdk/deployments/horizon'
import type { SubgraphServiceAddressBook, SubgraphServiceContracts } from './sdk/deployments/subgraph-service'

// List of supported Graph deployments
export const GraphDeploymentsList = [
'horizon',
'subgraphService',
] as const

export type GraphDeploymentRuntimeEnvironmentMap = {
horizon: {
contracts: GraphHorizonContracts
addressBook: GraphHorizonAddressBook
}
subgraphService: {
contracts: SubgraphServiceContracts
addressBook: SubgraphServiceAddressBook
}
}
84 changes: 84 additions & 0 deletions packages/hardhat-graph-protocol/src/gre.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import path from 'path'

import { getAddressBookPath } from './config'
import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider'
import { logDebug } from './logger'

import { GraphHorizonAddressBook } from './sdk/deployments/horizon'
import { SubgraphServiceAddressBook } from './sdk/deployments/subgraph-service'

import { assertGraphRuntimeEnvironment, type GraphRuntimeEnvironmentOptions, isGraphDeployment } from './types'
import type { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig } from 'hardhat/types'

export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
const userPath = userConfig.paths?.graph

let newPath: string
if (userPath === undefined) {
newPath = config.paths.root
} else {
if (path.isAbsolute(userPath)) {
newPath = userPath
} else {
newPath = path.normalize(path.join(config.paths.root, userPath))
}
}

config.paths.graph = newPath
}

export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => {
hre.graph = (opts: GraphRuntimeEnvironmentOptions = { deployments: {} }) => {
logDebug('*** Initializing Graph Runtime Environment (GRE) ***')
logDebug(`Main network: ${hre.network.name}`)
const chainId = hre.network.config.chainId
if (chainId === undefined) {
throw new Error('Please define chainId in your Hardhat network configuration')
}
logDebug(`Chain Id: ${chainId}`)

const deployments = [
...Object.keys(opts.deployments ?? {}),
...Object.keys(hre.network.config.deployments ?? {}),
...Object.keys(hre.config.graph?.deployments ?? {}),
].filter(v => isGraphDeployment(v))
logDebug(`Detected deployments: ${deployments.join(', ')}`)

// Build the Graph Runtime Environment (GRE) for each deployment
const provider = new HardhatEthersProvider(hre.network.provider, hre.network.name)
const greDeployments: Record<string, unknown> = {}
for (const deployment of deployments) {
logDebug(`== Initializing deployment: ${deployment} ==`)
const addressBookPath = getAddressBookPath(deployment, hre, opts)
let addressBook

switch (deployment) {
case 'horizon':
addressBook = new GraphHorizonAddressBook(addressBookPath, chainId)
greDeployments.horizon = {
addressBook: addressBook,
contracts: addressBook.loadContracts(provider),
}
break
case 'subgraphService':
addressBook = new SubgraphServiceAddressBook(addressBookPath, chainId)
greDeployments.subgraphService = {
addressBook: addressBook,
contracts: addressBook.loadContracts(provider),
}
break
default:
break
}
}

const gre = {
...greDeployments,
provider,
chainId,
}
assertGraphRuntimeEnvironment(gre)
logDebug('GRE initialized successfully!')
return gre
}
}
10 changes: 10 additions & 0 deletions packages/hardhat-graph-protocol/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { extendConfig, extendEnvironment } from 'hardhat/config'
import { greExtendConfig, greExtendEnvironment } from './gre'

// This import is needed to let the TypeScript compiler know that it should include your type
// extensions in your npm package's types file.
import './type-extensions'

// ** Graph Runtime Environment (GRE) extensions for the HRE **
extendConfig(greExtendConfig)
extendEnvironment(greExtendEnvironment)
7 changes: 7 additions & 0 deletions packages/hardhat-graph-protocol/src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import debug from 'debug'

const LOG_BASE = 'hardhat:graph'

export const logDebug = debug(`${LOG_BASE}:debug`)
export const logWarn = debug(`${LOG_BASE}:warn`)
export const logError = debug(`${LOG_BASE}:error`)
Loading

0 comments on commit 468ed2c

Please sign in to comment.