Skip to content

Commit 468ed2c

Browse files
authored
Merge pull request #1071 from graphprotocol/horizon-gre
2 parents 170572f + 58c518c commit 468ed2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2511
-30
lines changed

.github/workflows/ci-horizon.yml

+17-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,26 @@ jobs:
2424
submodules: recursive
2525
- name: Set up environment
2626
uses: ./.github/actions/setup
27-
- name: Build
27+
- name: Build contracts
28+
run: |
29+
pushd packages/contracts
30+
yarn build
31+
popd
32+
- name: Build horizon
2833
run: |
2934
pushd packages/horizon
3035
yarn build
36+
popd
37+
- name: Build subgraph service
38+
run: |
39+
pushd packages/subgraph-service
40+
yarn build
41+
popd
42+
- name: Build hardhat-graph-protocol
43+
run: |
44+
pushd packages/hardhat-graph-protocol
45+
yarn build
46+
popd
3147
- name: Run tests
3248
run: |
3349
pushd packages/horizon

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"packages/contracts",
1111
"packages/data-edge",
1212
"packages/eslint-graph-config",
13+
"packages/hardhat-graph-protocol",
1314
"packages/horizon",
1415
"packages/sdk",
1516
"packages/solhint-graph-config",
@@ -21,7 +22,7 @@
2122
"postinstall": "husky install",
2223
"clean": "yarn workspaces foreach --all --parallel --verbose run clean",
2324
"clean:all": "yarn clean && rm -rf node_modules packages/*/node_modules",
24-
"build": "yarn workspaces foreach --all --verbose run build",
25+
"build": "chmod +x ./scripts/build && ./scripts/build",
2526
"lint": "yarn workspaces foreach --all --parallel --verbose run lint",
2627
"test": "yarn workspaces foreach --all --parallel --verbose --interlaced run test"
2728
},

packages/eslint-graph-config/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ This repository contains shared linting and formatting rules for TypeScript proj
55
## Installation
66

77
```bash
8-
yarn add --dev eslint eslint-graph-config
8+
yarn add --dev eslint@^8.56.0 eslint-graph-config
99
```
1010

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

1313
```bash
14-
yarn add --dev eslint eslint-graph-config@workspace:^x.y.z
14+
yarn add --dev eslint@^8.56.0 eslint-graph-config@workspace:^x.y.z
1515
```
1616

1717
To enable the rules, you need to create an `eslint.config.js` file in the root of your project with the following content:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"require": "ts-node/register/files",
3+
"ignore": ["test/fixtures/**/*"],
4+
"timeout": 6000
5+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# hardhat-graph-protocol
2+
3+
4+
## Usage
5+
6+
Install with yarn
7+
8+
```bash
9+
yarn add --dev hardhat-graph-protocol
10+
11+
# From the monorepo
12+
yarn add --dev hardhat-graph-protocol@workspace:^x.y.z
13+
```
14+
15+
And add it to your `hardhat.config.ts`:
16+
17+
```ts
18+
import "hardhat-graph-protocol";
19+
20+
export default {
21+
...
22+
graph: {
23+
deployments: {
24+
horizon: require.resolve('@graphprotocol/horizon/addresses.json'),
25+
subgraphService: require.resolve('@graphprotocol/subgraph-service/addresses.json'),
26+
}
27+
},
28+
...
29+
};
30+
```
31+
32+
_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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const config = require('eslint-graph-config')
2+
3+
module.exports = [
4+
...config.default,
5+
{
6+
rules: {
7+
'@typescript-eslint/no-unsafe-assignment': 'off',
8+
'@typescript-eslint/no-var-requires': 'off',
9+
'@typescript-eslint/no-unsafe-call': 'off',
10+
'@typescript-eslint/no-unsafe-member-access': 'off',
11+
'@typescript-eslint/no-unsafe-argument': 'off',
12+
},
13+
},
14+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"name": "hardhat-graph-protocol",
3+
"version": "0.0.1",
4+
"description": "A hardhat plugin that extends the runtime environment to inject additional functionality related to the usage of the Graph Protocol.",
5+
"keywords": [
6+
"ethereum",
7+
"smart-contracts",
8+
"hardhat",
9+
"hardhat-plugin",
10+
"graph",
11+
"graph-protocol",
12+
"horizon"
13+
],
14+
"author": "Tomás Migone <[email protected]>",
15+
"license": "MIT",
16+
"main": "dist/src/index.js",
17+
"types": "dist/src/index.d.ts",
18+
"scripts": {
19+
"build": "tsc",
20+
"clean": "rm -rf dist",
21+
"lint": "eslint '**/*.{js,ts}' --fix",
22+
"test": "mocha --exit --recursive 'test/**/*.test.ts'",
23+
"prepublishOnly": "npm run build"
24+
},
25+
"files": [
26+
"dist/",
27+
"src/",
28+
"LICENSE",
29+
"README.md"
30+
],
31+
"dependencies": {
32+
"@graphprotocol/contracts": "workspace:^7.0.0",
33+
"@graphprotocol/horizon": "workspace:^0.0.1",
34+
"@graphprotocol/subgraph-service": "workspace:^0.0.1",
35+
"@nomicfoundation/hardhat-ethers": "^3.0.8",
36+
"debug": "^4.3.7"
37+
},
38+
"devDependencies": {
39+
"@types/chai": "^4.0.0",
40+
"@types/debug": "^4.1.12",
41+
"@types/mocha": "^10.0.9",
42+
"chai": "^4.0.0",
43+
"eslint": "^8.56.0",
44+
"eslint-graph-config": "workspace:^0.0.1",
45+
"ethers": "^6.13.4",
46+
"hardhat": "^2.22.16",
47+
"mocha": "^10.8.2",
48+
"ts-node": "^8.0.0",
49+
"typescript": "^5.6.3"
50+
},
51+
"peerDependencies": {
52+
"ethers": "^6.13.4",
53+
"hardhat": "^2.22.16"
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import fs from 'fs'
2+
3+
import { GraphPluginError } from './sdk/utils/error'
4+
import { logDebug } from './logger'
5+
import { normalizePath } from './sdk/utils/path'
6+
7+
import type { GraphDeployment, GraphRuntimeEnvironmentOptions } from './types'
8+
import type { HardhatRuntimeEnvironment } from 'hardhat/types'
9+
10+
export function getAddressBookPath(
11+
deployment: GraphDeployment,
12+
hre: HardhatRuntimeEnvironment,
13+
opts: GraphRuntimeEnvironmentOptions,
14+
): string {
15+
const optsPath = getPath(opts.deployments?.[deployment])
16+
const networkPath = getPath(hre.network.config.deployments?.[deployment])
17+
const globalPath = getPath(hre.config.graph?.deployments?.[deployment])
18+
19+
logDebug(`Getting address book path...`)
20+
logDebug(`Graph base dir: ${hre.config.paths.graph}`)
21+
logDebug(`1) opts: ${optsPath}`)
22+
logDebug(`2) network: ${networkPath}`)
23+
logDebug(`3) global: ${globalPath}`)
24+
25+
const addressBookPath = optsPath ?? networkPath ?? globalPath
26+
if (addressBookPath === undefined) {
27+
throw new GraphPluginError('Must set a an addressBook path!')
28+
}
29+
30+
const normalizedAddressBookPath = normalizePath(addressBookPath, hre.config.paths.graph)
31+
if (!fs.existsSync(normalizedAddressBookPath)) {
32+
throw new GraphPluginError(`Address book not found: ${normalizedAddressBookPath}`)
33+
}
34+
35+
logDebug(`Address book path found: ${normalizedAddressBookPath}`)
36+
return normalizedAddressBookPath
37+
}
38+
39+
function getPath(value: string | {
40+
addressBook: string
41+
} | undefined): string | undefined {
42+
if (typeof value === 'string') {
43+
return value
44+
} else if (value && typeof value == 'object') {
45+
return value.addressBook
46+
}
47+
return
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { GraphHorizonAddressBook, GraphHorizonContracts } from './sdk/deployments/horizon'
2+
import type { SubgraphServiceAddressBook, SubgraphServiceContracts } from './sdk/deployments/subgraph-service'
3+
4+
// List of supported Graph deployments
5+
export const GraphDeploymentsList = [
6+
'horizon',
7+
'subgraphService',
8+
] as const
9+
10+
export type GraphDeploymentRuntimeEnvironmentMap = {
11+
horizon: {
12+
contracts: GraphHorizonContracts
13+
addressBook: GraphHorizonAddressBook
14+
}
15+
subgraphService: {
16+
contracts: SubgraphServiceContracts
17+
addressBook: SubgraphServiceAddressBook
18+
}
19+
}
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import path from 'path'
2+
3+
import { getAddressBookPath } from './config'
4+
import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider'
5+
import { logDebug } from './logger'
6+
7+
import { GraphHorizonAddressBook } from './sdk/deployments/horizon'
8+
import { SubgraphServiceAddressBook } from './sdk/deployments/subgraph-service'
9+
10+
import { assertGraphRuntimeEnvironment, type GraphRuntimeEnvironmentOptions, isGraphDeployment } from './types'
11+
import type { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig } from 'hardhat/types'
12+
13+
export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
14+
const userPath = userConfig.paths?.graph
15+
16+
let newPath: string
17+
if (userPath === undefined) {
18+
newPath = config.paths.root
19+
} else {
20+
if (path.isAbsolute(userPath)) {
21+
newPath = userPath
22+
} else {
23+
newPath = path.normalize(path.join(config.paths.root, userPath))
24+
}
25+
}
26+
27+
config.paths.graph = newPath
28+
}
29+
30+
export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => {
31+
hre.graph = (opts: GraphRuntimeEnvironmentOptions = { deployments: {} }) => {
32+
logDebug('*** Initializing Graph Runtime Environment (GRE) ***')
33+
logDebug(`Main network: ${hre.network.name}`)
34+
const chainId = hre.network.config.chainId
35+
if (chainId === undefined) {
36+
throw new Error('Please define chainId in your Hardhat network configuration')
37+
}
38+
logDebug(`Chain Id: ${chainId}`)
39+
40+
const deployments = [
41+
...Object.keys(opts.deployments ?? {}),
42+
...Object.keys(hre.network.config.deployments ?? {}),
43+
...Object.keys(hre.config.graph?.deployments ?? {}),
44+
].filter(v => isGraphDeployment(v))
45+
logDebug(`Detected deployments: ${deployments.join(', ')}`)
46+
47+
// Build the Graph Runtime Environment (GRE) for each deployment
48+
const provider = new HardhatEthersProvider(hre.network.provider, hre.network.name)
49+
const greDeployments: Record<string, unknown> = {}
50+
for (const deployment of deployments) {
51+
logDebug(`== Initializing deployment: ${deployment} ==`)
52+
const addressBookPath = getAddressBookPath(deployment, hre, opts)
53+
let addressBook
54+
55+
switch (deployment) {
56+
case 'horizon':
57+
addressBook = new GraphHorizonAddressBook(addressBookPath, chainId)
58+
greDeployments.horizon = {
59+
addressBook: addressBook,
60+
contracts: addressBook.loadContracts(provider),
61+
}
62+
break
63+
case 'subgraphService':
64+
addressBook = new SubgraphServiceAddressBook(addressBookPath, chainId)
65+
greDeployments.subgraphService = {
66+
addressBook: addressBook,
67+
contracts: addressBook.loadContracts(provider),
68+
}
69+
break
70+
default:
71+
break
72+
}
73+
}
74+
75+
const gre = {
76+
...greDeployments,
77+
provider,
78+
chainId,
79+
}
80+
assertGraphRuntimeEnvironment(gre)
81+
logDebug('GRE initialized successfully!')
82+
return gre
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { extendConfig, extendEnvironment } from 'hardhat/config'
2+
import { greExtendConfig, greExtendEnvironment } from './gre'
3+
4+
// This import is needed to let the TypeScript compiler know that it should include your type
5+
// extensions in your npm package's types file.
6+
import './type-extensions'
7+
8+
// ** Graph Runtime Environment (GRE) extensions for the HRE **
9+
extendConfig(greExtendConfig)
10+
extendEnvironment(greExtendEnvironment)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import debug from 'debug'
2+
3+
const LOG_BASE = 'hardhat:graph'
4+
5+
export const logDebug = debug(`${LOG_BASE}:debug`)
6+
export const logWarn = debug(`${LOG_BASE}:warn`)
7+
export const logError = debug(`${LOG_BASE}:error`)

0 commit comments

Comments
 (0)