plugin.ts 3.59 KB
Newer Older
1
import * as path from 'path'
2
import * as fs from 'fs'
3 4 5 6 7 8 9

import { extendEnvironment, extendConfig } from 'hardhat/config'
import {
  HardhatConfig,
  HardhatRuntimeEnvironment,
  HardhatUserConfig,
} from 'hardhat/types'
10
import { lazyObject, lazyFunction } from 'hardhat/plugins'
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import { ethers } from 'ethers'

// From: https://github.com/wighawag/hardhat-deploy/blob/master/src/index.ts#L63-L76
const normalizePath = (
  config: HardhatConfig,
  userPath: string | undefined,
  defaultPath: string
): string => {
  if (userPath === undefined) {
    userPath = path.join(config.paths.root, defaultPath)
  } else {
    if (!path.isAbsolute(userPath)) {
      userPath = path.normalize(path.join(config.paths.root, userPath))
    }
  }
  return userPath
}

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
const getDeployConfig = (
  dir: string,
  network: string
): { [key: string]: any } => {
  let config: any
  try {
    const base = `${dir}/${network}`
    if (fs.existsSync(`${base}.ts`)) {
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      config = require(`${base}.ts`).default
    } else if (fs.existsSync(`${base}.json`)) {
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      config = require(`${base}.json`)
    } else {
      throw new Error('not found')
44
    }
45 46 47 48
  } catch (err) {
    throw new Error(
      `error while loading deploy config for network: ${network}, ${err}`
    )
49
  }
50 51
  return config
}
52

53
export const loadDeployConfig = (hre: HardhatRuntimeEnvironment): any => {
54 55 56 57 58
  const paths = hre.config.paths.deployConfig
  const conf = getDeployConfig(paths, hre.network.name)
  const spec = parseDeployConfig(hre, conf)

  return new Proxy(spec, {
59 60 61 62 63
    get: (target, prop) => {
      if (target.hasOwnProperty(prop)) {
        return target[prop]
      }

64
      // Explicitly throw if the property is not found
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
      throw new Error(
        `property does not exist in deploy config: ${String(prop)}`
      )
    },
  })
}

export const parseDeployConfig = (
  hre: HardhatRuntimeEnvironment,
  config: any
): any => {
  // Create a clone of the config object. Shallow clone is fine because none of the input options
  // are expected to be objects or functions etc.
  const parsed = { ...config }

  // If the deployConfigSpec is not provided, do no validation
  if (!hre.config.deployConfigSpec) {
    return parsed
  }

  for (const [key, spec] of Object.entries(hre.config.deployConfigSpec)) {
    // Make sure the value is defined, or use a default.
    if (parsed[key] === undefined) {
      if ('default' in spec) {
        parsed[key] = spec.default
      } else {
        throw new Error(
          `deploy config is missing required field: ${key} (${spec.type})`
        )
      }
    } else {
      // Make sure the default has the correct type.
      if (spec.type === 'address') {
        if (!ethers.utils.isAddress(parsed[key])) {
          throw new Error(
            `deploy config field: ${key} is not of type ${spec.type}: ${parsed[key]}`
          )
        }
      } else if (typeof parsed[key] !== spec.type) {
        throw new Error(
          `deploy config field: ${key} is not of type ${spec.type}: ${parsed[key]}`
        )
      }
    }
  }

  return parsed
}

extendConfig(
  (config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
    config.paths.deployConfig = normalizePath(
      config,
118
      userConfig.paths?.deployConfig,
119 120 121 122 123 124
      'deploy-config'
    )
  }
)

extendEnvironment((hre) => {
125
  hre.deployConfig = lazyObject(() => loadDeployConfig(hre))
126 127 128 129
  hre.getDeployConfig = lazyFunction(() => {
    const paths = hre.config.paths.deployConfig
    return (network: string) => getDeployConfig(paths, network)
  })
130
})