Commit 90630336 authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat(ctb): export ABI when building (#3067)

Updates the TypeScript build to also generate ABI objects that can be
imported on the client-side. Specifically necessary so that these ABIs
can be imported on the frontend where fs/glob is not available.
Co-authored-by: default avatarmergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
parent 7d68f82f
---
'@eth-optimism/contracts-bedrock': patch
---
Properly generates and exports ABI and artifact files that can be imported by client libraries
module.exports = { module.exports = {
extends: '../../.eslintrc.js', extends: '../../.eslintrc.js',
ignorePatterns: ['src/contract-artifacts.ts'],
} }
...@@ -7,3 +7,4 @@ coverage.out ...@@ -7,3 +7,4 @@ coverage.out
deployments deployments
broadcast broadcast
genesis.json genesis.json
src/contract-artifacts.ts
...@@ -9,15 +9,16 @@ ...@@ -9,15 +9,16 @@
"dist/**/*.js", "dist/**/*.js",
"dist/**/*.d.ts", "dist/**/*.d.ts",
"dist/types/*.ts", "dist/types/*.ts",
"artifacts/src/**/*.json", "artifacts/contracts/**/*.json",
"deployments/**/*.json", "deployments/**/*.json",
"contracts/**/*.sol" "contracts/**/*.sol"
], ],
"scripts": { "scripts": {
"build:forge": "forge build", "build:forge": "forge build",
"prebuild": "yarn ts-node scripts/verifyFoundryInstall.ts", "prebuild": "yarn ts-node scripts/verifyFoundryInstall.ts",
"build": "hardhat compile && yarn build:ts && yarn typechain", "build": "hardhat compile && yarn autogen:artifacts && yarn build:ts && yarn typechain",
"build:ts": "tsc -p tsconfig.json", "build:ts": "tsc -p tsconfig.json",
"autogen:artifacts": "ts-node scripts/generate-artifacts.ts",
"deploy": "hardhat deploy", "deploy": "hardhat deploy",
"test": "yarn build:ts && forge test", "test": "yarn build:ts && forge test",
"gas-snapshot": "forge snapshot", "gas-snapshot": "forge snapshot",
...@@ -64,6 +65,7 @@ ...@@ -64,6 +65,7 @@
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"ethereum-waffle": "^3.0.0", "ethereum-waffle": "^3.0.0",
"ethers": "^5.6.8", "ethers": "^5.6.8",
"glob": "^7.1.6",
"hardhat-deploy": "^0.11.4", "hardhat-deploy": "^0.11.4",
"solhint": "^3.3.6", "solhint": "^3.3.6",
"solhint-plugin-prettier": "^0.0.5", "solhint-plugin-prettier": "^0.0.5",
......
import path from 'path'
import fs from 'fs'
import glob from 'glob'
/**
* Script for automatically generating a file which has a series of `require` statements for
* importing JSON contract artifacts. We do this to preserve browser compatibility.
*/
const main = async () => {
const contractArtifactsFolder = path.resolve(
__dirname,
`../artifacts/contracts`
)
const artifactPaths = glob
.sync(`${contractArtifactsFolder}/**/*[!.t].sol/**.json`)
.filter((match) => {
// Filter out the debug outputs.
return !match.endsWith('.dbg.json')
})
const content = `
/* eslint-disable @typescript-eslint/no-var-requires, no-empty */
/*
THIS FILE IS AUTOMATICALLY GENERATED.
DO NOT EDIT.
*/
${artifactPaths
.map((artifactPath) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const artifact = require(artifactPath)
// handles the case - '\u' (\utils folder) is considered as an unicode encoded char
const pattern = /\\/g
const relPath = path
.relative(__dirname, artifactPath)
.replace(pattern, '/')
return `
let ${artifact.contractName}
try {
${artifact.contractName} = require('${relPath}')
} catch {}
`
})
.join('\n')}
export const getContractArtifact = (name: string): any => {
return {
${artifactPaths
.map((artifactPath) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const artifact = require(artifactPath)
return `${artifact.contractName}`
})
.join(',\n')}
}[name]
}
`
fs.writeFileSync(
path.resolve(__dirname, `../src/contract-artifacts.ts`),
content
)
}
main()
import { ethers } from 'ethers'
/**
* Gets the hardhat artifact for the given contract name.
* Will throw an error if the contract artifact is not found.
*
* @param name Contract name.
* @returns The artifact for the given contract name.
*/
export const getContractDefinition = (name: string): any => {
// We import this using `require` because hardhat tries to build this file when compiling
// the contracts, but we need the contracts to be compiled before the contract-artifacts.ts
// file can be generated.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { getContractArtifact } = require('./contract-artifacts')
const artifact = getContractArtifact(name)
if (artifact === undefined) {
throw new Error(`Unable to find artifact for contract: ${name}`)
}
return artifact
}
/**
* Gets an ethers Interface instance for the given contract name.
*
* @param name Contract name.
* @returns The interface for the given contract name.
*/
export const getContractInterface = (name: string): ethers.utils.Interface => {
const definition = getContractDefinition(name)
return new ethers.utils.Interface(definition.abi)
}
/**
* Gets an ethers ContractFactory instance for the given contract name.
*
* @param name Contract name.
* @param signer The signer for the ContractFactory to use.
* @returns The contract factory for the given contract name.
*/
export const getContractFactory = (
name: string,
signer?: ethers.Signer
): ethers.ContractFactory => {
const definition = getContractDefinition(name)
const contractInterface = getContractInterface(name)
return new ethers.ContractFactory(
contractInterface,
definition.bytecode,
signer
)
}
export * from './constants' export * from './constants'
export * from './contract-defs'
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
"outDir": "./dist" "outDir": "./dist"
}, },
"exclude": ["hardhat.config.ts", "deploy", "tasks", "test"], "exclude": ["hardhat.config.ts", "deploy", "tasks", "test"],
"include": ["src/**/*", "scripts/differential-testing.ts"] "include": ["src/**/*", "scripts/**/*"]
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment