Skip to content

Commit

Permalink
feat(gre): working version for horizon with legacy contracts
Browse files Browse the repository at this point in the history
Signed-off-by: Tomás Migone <[email protected]>
  • Loading branch information
tmigone committed Nov 21, 2024
1 parent 13ea6ca commit 4111600
Show file tree
Hide file tree
Showing 20 changed files with 258 additions and 209 deletions.
42 changes: 28 additions & 14 deletions packages/hardhat-graph-protocol/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,49 @@
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 { GraphDeployment } from './deployments'
import type { GraphRuntimeEnvironmentOptions } from './type-extensions'
import type { HardhatRuntimeEnvironment } from 'hardhat/types'
import { normalizePath } from './sdk/utils/path'

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(`== ${deployment} - Getting address book path`)
logDebug(`Graph base dir: ${hre.config.paths.graph}`)
logDebug(`1) opts.addressBooks.[deployment]: ${opts.addressBooks?.[deployment]}`)
logDebug(`2) hre.network.config.addressBooks.[deployment]: ${hre.network.config?.addressBooks?.[deployment]}`)
logDebug(`3) hre.config.graph.addressBooks.[deployment]: ${hre.config.graph?.addressBooks?.[deployment]}`)

let addressBookPath
= opts.addressBooks?.[deployment] ?? hre.network.config?.addressBooks?.[deployment] ?? hre.config.graph?.addressBooks?.[deployment]
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!')
}

addressBookPath = normalizePath(addressBookPath, hre.config.paths.graph)

if (!fs.existsSync(addressBookPath)) {
throw new GraphPluginError(`Address book not found: ${addressBookPath}`)
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: ${addressBookPath}`)
return addressBookPath
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
}
22 changes: 22 additions & 0 deletions packages/hardhat-graph-protocol/src/deployments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { GraphHorizonAddressBook, GraphHorizonContracts } from './sdk/deployments/horizon'

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

export type GraphDeployment = (typeof GraphDeploymentsList)[number]

export type GraphDeploymentRuntimeEnvironmentMap = {
horizon: {
contracts: GraphHorizonContracts
addressBook: GraphHorizonAddressBook
}
}

export function isGraphDeployment(deployment: unknown): deployment is GraphDeployment {
return (
typeof deployment === 'string'
&& GraphDeploymentsList.includes(deployment as GraphDeployment)
)
}
104 changes: 19 additions & 85 deletions packages/hardhat-graph-protocol/src/gre.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import path from 'path'

import { GraphDeploymentsList, GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions, isGraphDeployment } from './types'
import { logDebug, logWarn } from './logger'
import { assertGraphRuntimeEnvironment } from './type-extensions'
import { getAddressBookPath } from './config'
import { GraphHorizonAddressBook } from './sdk/deployments/horizon'
import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider'
import { isGraphDeployment } from './deployments'
import { logDebug } from './logger'

import type { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig } from 'hardhat/types'
import type { GraphRuntimeEnvironmentOptions } from './type-extensions'

export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
const userPath = userConfig.paths?.graph
Expand All @@ -26,113 +28,45 @@ export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly<Hard
}

export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => {
hre.graph = (opts: GraphRuntimeEnvironmentOptions = {}) => {
hre.graph = (opts: GraphRuntimeEnvironmentOptions = { deployments: {} }) => {
logDebug('*** Initializing Graph Runtime Environment (GRE) ***')
logDebug(`Main network: ${hre.network.name}`)

const provider = new HardhatEthersProvider(hre.network.provider, hre.network.name)
const deployments = [
...Object.keys(opts.addressBooks ?? {}),
...Object.keys(hre.network.config.addressBooks ?? {}),
...Object.keys(hre.config.graph?.addressBooks ?? {}),
]
...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 gre = {} as GraphRuntimeEnvironment
const provider = new HardhatEthersProvider(hre.network.provider, hre.network.name)
const greDeployments: Record<string, unknown> = {}
for (const deployment of deployments) {
if (!isGraphDeployment(deployment)) {
logWarn(`Invalid deployment: ${deployment}. Skipping...`)
continue
}

logDebug(`Initializing ${deployment} deployment...`)
const addressBookPath = getAddressBookPath(deployment, hre, opts)
let addressBook

switch (deployment) {
case 'horizon':
addressBook = new GraphHorizonAddressBook(addressBookPath, hre.network.config.chainId!)
gre.horizon = {
greDeployments.horizon = {
addressBook: addressBook,
contracts: addressBook.loadContracts(hre.network.config.chainId!, provider),
}
break

default:
break
}
}

const gre = {
...greDeployments,
provider,
chainId: async () => (await provider.getNetwork()).chainId,
}
assertGraphRuntimeEnvironment(gre)
logDebug('GRE initialized successfully!')
return gre
}
}

// function buildGraphNetworkEnvironment(
// chainId: number,
// provider: EthersProviderWrapper | undefined,
// graphConfigPath: string | undefined,
// addressBookPath: string,
// isHHL1: boolean,
// enableTxLogging: boolean,
// secureAccounts: boolean,
// fork: boolean,
// getWallets: () => Promise<Wallet[]>,
// getWallet: (address: string) => Promise<Wallet>,
// unlockProvider: (caller: string) => Promise<EthersProviderWrapper>,
// ): GraphNetworkEnvironment | null {
// if (graphConfigPath === undefined) {
// logWarn(
// `No graph config file provided for chain: ${chainId}. ${
// isHHL1 ? 'L2' : 'L1'
// } will not be initialized.`,
// )
// return null
// }

// if (provider === undefined) {
// logWarn(
// `No provider URL found for: ${chainId}. ${isHHL1 ? 'L2' : 'L1'} will not be initialized.`,
// )
// return null
// }

// // Upgrade provider to secure accounts if feature is enabled
// const getUpdatedProvider = async (caller: string) =>
// secureAccounts ? await unlockProvider(caller) : provider

// return {
// chainId: chainId,
// provider: provider,
// addressBook: lazyObject(() => new GraphNetworkAddressBook(addressBookPath, chainId)),
// graphConfig: lazyObject(() => {
// const config = readConfig(graphConfigPath, true)
// config.defaults = getDefaults(config, isHHL1)
// return config
// }),
// contracts: lazyObject(() =>
// loadGraphNetworkContracts(addressBookPath, chainId, provider, undefined, {
// enableTxLogging,
// }),
// ),
// getWallets: lazyFunction(() => () => getWallets()),
// getWallet: lazyFunction(() => (address: string) => getWallet(address)),
// getDeployer: lazyFunction(
// () => async () => getDeployer(await getUpdatedProvider('getDeployer')),
// ),
// getNamedAccounts: lazyFunction(
// () => async () =>
// getNamedAccounts(
// fork ? provider : await getUpdatedProvider('getNamedAccounts'),
// graphConfigPath,
// ),
// ),
// getTestAccounts: lazyFunction(
// () => async () =>
// getTestAccounts(await getUpdatedProvider('getTestAccounts'), graphConfigPath),
// ),
// getAllAccounts: lazyFunction(
// () => async () => getAllAccounts(await getUpdatedProvider('getAllAccounts')),
// ),
// }
// }
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class GraphHorizonAddressBook extends AddressBook<number, GraphHorizonCon
chainId: number,
signerOrProvider?: Signer | Provider,
): GraphHorizonContracts {
logDebug('Loading Graph Network contracts...')
logDebug('Loading Graph Horizon contracts...')
const artifactsPath = path.resolve('node_modules', '@graphprotocol/contracts/build/contracts')

const contracts = this._loadContracts(
Expand All @@ -26,6 +26,10 @@ export class GraphHorizonAddressBook extends AddressBook<number, GraphHorizonCon
)
assertGraphHorizonContracts(contracts, chainId)

// Aliases
contracts.GraphToken = contracts.L2GraphToken
contracts.GraphTokenGateway = contracts.L2GraphTokenGateway

// Iterator
contracts[Symbol.iterator] = function* () {
for (const key of Object.keys(this)) {
Expand Down Expand Up @@ -61,7 +65,7 @@ function assertGraphHorizonContracts(
)
}

// Assert that all GraphNetworkContracts were loaded
// Assert that all GraphHorizonContracts were loaded
for (const contractName of GraphHorizonContractNameList) {
if (!contracts[contractName]) {
const errMessage = `Missing GraphHorizon contract: ${contractName} for chainId ${chainId}`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GraphHorizonAddressBook } from './address-book'

import type { GraphHorizonContractName, GraphHorizonContracts, GraphHorizonRuntimeEnvironment } from './types'
import type { GraphHorizonContractName, GraphHorizonContracts } from './types'

export {
GraphHorizonAddressBook,
}

export type { GraphHorizonContractName, GraphHorizonContracts, GraphHorizonRuntimeEnvironment }
export type { GraphHorizonContractName, GraphHorizonContracts }
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
} from '@graphprotocol/contracts'
import type { Contract } from 'ethers'
import type { ContractList } from '../lib/contract'
import type { GraphHorizonAddressBook } from './address-book'

export const GraphHorizonContractNameList = [
'GraphProxyAdmin',
Expand All @@ -28,8 +27,8 @@ export interface GraphHorizonContracts extends ContractList<GraphHorizonContract
RewardsManager: RewardsManager & Contract
GraphProxyAdmin: GraphProxyAdmin & Contract
Controller: Controller & Contract
L2GraphToken?: L2GraphToken & Contract
L2GraphTokenGateway?: L2GraphTokenGateway & Contract
L2GraphToken: L2GraphToken & Contract
L2GraphTokenGateway: L2GraphTokenGateway & Contract

// Aliases
GraphToken: L2GraphToken
Expand All @@ -38,8 +37,3 @@ export interface GraphHorizonContracts extends ContractList<GraphHorizonContract
// Iterator
[Symbol.iterator]: () => Generator<Contract, void, void>
}

export interface GraphHorizonRuntimeEnvironment {
contracts: GraphHorizonContracts
addressBook: GraphHorizonAddressBook
}
67 changes: 58 additions & 9 deletions packages/hardhat-graph-protocol/src/type-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,48 @@
import 'hardhat/types/config'
import 'hardhat/types/runtime'

import type { GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions } from './types'
import type { GraphDeployment, GraphDeploymentRuntimeEnvironmentMap } from './deployments'
import type { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider'

export type GraphRuntimeEnvironmentOptions = {
deployments?: {
[deployment in GraphDeployment]?: string | {
addressBook: string
}
}
}

export type GraphRuntimeEnvironment = {
[deployment in keyof GraphDeploymentRuntimeEnvironmentMap]?: GraphDeploymentRuntimeEnvironmentMap[deployment]
} & {
provider: HardhatEthersProvider
chainId: () => Promise<bigint>
}

export function assertGraphRuntimeEnvironment(
obj: unknown,
): obj is GraphRuntimeEnvironment {
if (typeof obj !== 'object' || obj === null) return false

const deployments = obj as Partial<GraphDeploymentRuntimeEnvironmentMap>

for (const deployment in deployments) {
const environment = deployments[deployment as keyof GraphDeploymentRuntimeEnvironmentMap]
if (!environment || typeof environment !== 'object') {
return false
}
}

if (typeof (obj as GraphRuntimeEnvironment).provider !== 'object') {
return false
}

if (typeof (obj as GraphRuntimeEnvironment).chainId !== 'function') {
return false
}

return true
}

declare module 'hardhat/types/runtime' {
export interface HardhatRuntimeEnvironment {
Expand All @@ -20,26 +61,34 @@ declare module 'hardhat/types/config' {
}

export interface HardhatNetworkConfig {
addressBooks?: {
[deployment: string]: string
deployments?: {
[deployment in GraphDeployment]?: string | {
addressBook: string
}
}
}

export interface HardhatNetworkUserConfig {
addressBooks?: {
[deployment: string]: string
deployments?: {
[deployment in GraphDeployment]?: string | {
addressBook: string
}
}
}

export interface HttpNetworkConfig {
addressBooks?: {
[deployment: string]: string
deployments?: {
[deployment in GraphDeployment]?: string | {
addressBook: string
}
}
}

export interface HttpNetworkUserConfig {
addressBooks?: {
[deployment: string]: string
deployments?: {
[deployment in GraphDeployment]?: string | {
addressBook: string
}
}
}

Expand Down
Loading

0 comments on commit 4111600

Please sign in to comment.