Skip to content

Commit 13ea6ca

Browse files
committed
feat: add gre/sdk with support for horizon
Signed-off-by: Tomás Migone <[email protected]>
1 parent 9ae3410 commit 13ea6ca

39 files changed

+3066
-18
lines changed

package.json

Lines changed: 1 addition & 0 deletions
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",

packages/eslint-graph-config/README.md

Lines changed: 2 additions & 2 deletions
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:
Lines changed: 5 additions & 0 deletions
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+
}
Lines changed: 14 additions & 0 deletions
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+
]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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/index.js",
17+
"types": "dist/index.d.ts",
18+
"scripts": {
19+
"build": "tsc",
20+
"lint": "eslint '**/*.{js,ts}' --fix",
21+
"test": "mocha --exit --recursive 'test/**/*.test.ts'"
22+
},
23+
"files": [
24+
"dist/",
25+
"src/",
26+
"LICENSE",
27+
"README.md"
28+
],
29+
"dependencies": {
30+
"@graphprotocol/contracts": "workspace:^7.0.0",
31+
"@graphprotocol/horizon": "workspace:^0.0.1",
32+
"@nomicfoundation/hardhat-ethers": "^3.0.8",
33+
"debug": "^4.3.7"
34+
},
35+
"devDependencies": {
36+
"@types/chai": "^4.0.0",
37+
"@types/debug": "^4.1.12",
38+
"@types/mocha": "^10.0.9",
39+
"chai": "^4.0.0",
40+
"eslint": "^8.56.0",
41+
"eslint-graph-config": "workspace:^0.0.1",
42+
"ethers": "^6.13.4",
43+
"hardhat": "^2.22.16",
44+
"mocha": "^10.8.2",
45+
"ts-node": "^8.0.0",
46+
"typescript": "^5.6.3"
47+
},
48+
"peerDependencies": {
49+
"ethers": "^6.13.4",
50+
"hardhat": "^2.22.16"
51+
}
52+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import fs from 'fs'
2+
import { GraphPluginError } from './sdk/utils/error'
3+
import { logDebug } from './logger'
4+
5+
import type { GraphDeployment, GraphRuntimeEnvironmentOptions } from './types'
6+
import type { HardhatRuntimeEnvironment } from 'hardhat/types'
7+
import { normalizePath } from './sdk/utils/path'
8+
9+
export function getAddressBookPath(
10+
deployment: GraphDeployment,
11+
hre: HardhatRuntimeEnvironment,
12+
opts: GraphRuntimeEnvironmentOptions,
13+
): string {
14+
logDebug(`== ${deployment} - Getting address book path`)
15+
logDebug(`Graph base dir: ${hre.config.paths.graph}`)
16+
logDebug(`1) opts.addressBooks.[deployment]: ${opts.addressBooks?.[deployment]}`)
17+
logDebug(`2) hre.network.config.addressBooks.[deployment]: ${hre.network.config?.addressBooks?.[deployment]}`)
18+
logDebug(`3) hre.config.graph.addressBooks.[deployment]: ${hre.config.graph?.addressBooks?.[deployment]}`)
19+
20+
let addressBookPath
21+
= opts.addressBooks?.[deployment] ?? hre.network.config?.addressBooks?.[deployment] ?? hre.config.graph?.addressBooks?.[deployment]
22+
23+
if (addressBookPath === undefined) {
24+
throw new GraphPluginError('Must set a an addressBook path!')
25+
}
26+
27+
addressBookPath = normalizePath(addressBookPath, hre.config.paths.graph)
28+
29+
if (!fs.existsSync(addressBookPath)) {
30+
throw new GraphPluginError(`Address book not found: ${addressBookPath}`)
31+
}
32+
33+
logDebug(`Address book path found: ${addressBookPath}`)
34+
return addressBookPath
35+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import path from 'path'
2+
3+
import { GraphDeploymentsList, GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions, isGraphDeployment } from './types'
4+
import { logDebug, logWarn } from './logger'
5+
import { getAddressBookPath } from './config'
6+
import { GraphHorizonAddressBook } from './sdk/deployments/horizon'
7+
import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider'
8+
9+
import type { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig } from 'hardhat/types'
10+
11+
export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
12+
const userPath = userConfig.paths?.graph
13+
14+
let newPath: string
15+
if (userPath === undefined) {
16+
newPath = config.paths.root
17+
} else {
18+
if (path.isAbsolute(userPath)) {
19+
newPath = userPath
20+
} else {
21+
newPath = path.normalize(path.join(config.paths.root, userPath))
22+
}
23+
}
24+
25+
config.paths.graph = newPath
26+
}
27+
28+
export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => {
29+
hre.graph = (opts: GraphRuntimeEnvironmentOptions = {}) => {
30+
logDebug('*** Initializing Graph Runtime Environment (GRE) ***')
31+
logDebug(`Main network: ${hre.network.name}`)
32+
33+
const provider = new HardhatEthersProvider(hre.network.provider, hre.network.name)
34+
const deployments = [
35+
...Object.keys(opts.addressBooks ?? {}),
36+
...Object.keys(hre.network.config.addressBooks ?? {}),
37+
...Object.keys(hre.config.graph?.addressBooks ?? {}),
38+
]
39+
logDebug(`Detected deployments: ${deployments.join(', ')}`)
40+
41+
// Build the Graph Runtime Environment (GRE) for each deployment
42+
const gre = {} as GraphRuntimeEnvironment
43+
for (const deployment of deployments) {
44+
if (!isGraphDeployment(deployment)) {
45+
logWarn(`Invalid deployment: ${deployment}. Skipping...`)
46+
continue
47+
}
48+
49+
logDebug(`Initializing ${deployment} deployment...`)
50+
const addressBookPath = getAddressBookPath(deployment, hre, opts)
51+
let addressBook
52+
switch (deployment) {
53+
case 'horizon':
54+
addressBook = new GraphHorizonAddressBook(addressBookPath, hre.network.config.chainId!)
55+
gre.horizon = {
56+
addressBook: addressBook,
57+
contracts: addressBook.loadContracts(hre.network.config.chainId!, provider),
58+
}
59+
break
60+
61+
default:
62+
break
63+
}
64+
}
65+
66+
logDebug('GRE initialized successfully!')
67+
return gre
68+
}
69+
}
70+
71+
// function buildGraphNetworkEnvironment(
72+
// chainId: number,
73+
// provider: EthersProviderWrapper | undefined,
74+
// graphConfigPath: string | undefined,
75+
// addressBookPath: string,
76+
// isHHL1: boolean,
77+
// enableTxLogging: boolean,
78+
// secureAccounts: boolean,
79+
// fork: boolean,
80+
// getWallets: () => Promise<Wallet[]>,
81+
// getWallet: (address: string) => Promise<Wallet>,
82+
// unlockProvider: (caller: string) => Promise<EthersProviderWrapper>,
83+
// ): GraphNetworkEnvironment | null {
84+
// if (graphConfigPath === undefined) {
85+
// logWarn(
86+
// `No graph config file provided for chain: ${chainId}. ${
87+
// isHHL1 ? 'L2' : 'L1'
88+
// } will not be initialized.`,
89+
// )
90+
// return null
91+
// }
92+
93+
// if (provider === undefined) {
94+
// logWarn(
95+
// `No provider URL found for: ${chainId}. ${isHHL1 ? 'L2' : 'L1'} will not be initialized.`,
96+
// )
97+
// return null
98+
// }
99+
100+
// // Upgrade provider to secure accounts if feature is enabled
101+
// const getUpdatedProvider = async (caller: string) =>
102+
// secureAccounts ? await unlockProvider(caller) : provider
103+
104+
// return {
105+
// chainId: chainId,
106+
// provider: provider,
107+
// addressBook: lazyObject(() => new GraphNetworkAddressBook(addressBookPath, chainId)),
108+
// graphConfig: lazyObject(() => {
109+
// const config = readConfig(graphConfigPath, true)
110+
// config.defaults = getDefaults(config, isHHL1)
111+
// return config
112+
// }),
113+
// contracts: lazyObject(() =>
114+
// loadGraphNetworkContracts(addressBookPath, chainId, provider, undefined, {
115+
// enableTxLogging,
116+
// }),
117+
// ),
118+
// getWallets: lazyFunction(() => () => getWallets()),
119+
// getWallet: lazyFunction(() => (address: string) => getWallet(address)),
120+
// getDeployer: lazyFunction(
121+
// () => async () => getDeployer(await getUpdatedProvider('getDeployer')),
122+
// ),
123+
// getNamedAccounts: lazyFunction(
124+
// () => async () =>
125+
// getNamedAccounts(
126+
// fork ? provider : await getUpdatedProvider('getNamedAccounts'),
127+
// graphConfigPath,
128+
// ),
129+
// ),
130+
// getTestAccounts: lazyFunction(
131+
// () => async () =>
132+
// getTestAccounts(await getUpdatedProvider('getTestAccounts'), graphConfigPath),
133+
// ),
134+
// getAllAccounts: lazyFunction(
135+
// () => async () => getAllAccounts(await getUpdatedProvider('getAllAccounts')),
136+
// ),
137+
// }
138+
// }
Lines changed: 10 additions & 0 deletions
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)
Lines changed: 7 additions & 0 deletions
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)