plugin compilerMetadata

pull/1324/head
filip mertens 3 years ago
parent 340d78000d
commit d4c60aed81
  1. 5
      apps/remix-ide/src/app.js
  2. 148
      apps/remix-ide/src/app/files/compiler-metadata.js
  3. 6
      apps/remix-ide/src/app/tabs/settings-tab.js
  4. 2
      libs/remix-core-plugin/compiler-content-imports/src/lib/compiler-content-imports.ts
  5. 1
      libs/remix-core-plugin/compiler-metadata/.eslintrc
  6. 3
      libs/remix-core-plugin/compiler-metadata/README.md
  7. 11
      libs/remix-core-plugin/compiler-metadata/package.json
  8. 1
      libs/remix-core-plugin/compiler-metadata/src/index.ts
  9. 146
      libs/remix-core-plugin/compiler-metadata/src/lib/compiler-metadata.ts
  10. 10
      libs/remix-core-plugin/compiler-metadata/tsconfig.json
  11. 12
      libs/remix-core-plugin/compiler-metadata/tsconfig.lib.json
  12. 3
      nx.json
  13. 3
      tsconfig.json
  14. 31
      workspace.json

@ -21,6 +21,7 @@ import { CompilerArtefacts } from '@remix-core-plugin/compiler-artefacts'
import { CompilerImports } from '@remix-core-plugin/compiler-content-imports'
import { FetchAndCompile } from '@remix-core-plugin/compiler-fetch-and-compile'
import { OffsetToLineColumnConverter } from '@remix-core-plugin/offset-line-to-column-converter'
import { CompilerMetadata } from '@remix-core-plugin/compiler-metadata'
import migrateFileSystem from './migrateFileSystem'
@ -42,7 +43,7 @@ const FileProvider = require('./app/files/fileProvider')
const DGitProvider = require('./app/files/dgitProvider')
const WorkspaceFileProvider = require('./app/files/workspaceFileProvider')
const toolTip = require('./app/ui/tooltip')
const CompilerMetadata = require('./app/files/compiler-metadata')
const Blockchain = require('./blockchain/blockchain.js')
@ -269,7 +270,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const blockchain = new Blockchain(registry.get('config').api)
// ----------------- compilation metadata generation service ---------
const compilerMetadataGenerator = new CompilerMetadata(blockchain, fileManager, registry.get('config').api)
const compilerMetadataGenerator = new CompilerMetadata()
// ----------------- compilation result service (can keep track of compilation results) ----------------------------
const compilersArtefacts = new CompilerArtefacts() // store all the compilation results (key represent a compiler name)
registry.put({ api: compilersArtefacts, name: 'compilersartefacts' })

@ -1,148 +0,0 @@
'use strict'
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
import { joinPath } from '../../lib/helper'
import { CompilerAbstract } from '@remix-project/remix-solidity'
const profile = {
name: 'compilerMetadata',
methods: ['deployMetadataOf'],
events: [],
version: packageJson.version
}
class CompilerMetadata extends Plugin {
constructor (blockchain, fileManager, config) {
super(profile)
this.blockchain = blockchain
this.fileManager = fileManager
this.config = config
this.networks = ['VM:-', 'main:1', 'ropsten:3', 'rinkeby:4', 'kovan:42', 'görli:5', 'Custom']
this.innerPath = 'artifacts'
}
_JSONFileName (path, contractName) {
return joinPath(path, this.innerPath, contractName + '.json')
}
_MetadataFileName (path, contractName) {
return joinPath(path, this.innerPath, contractName + '_metadata.json')
}
onActivation () {
var self = this
this.on('solidity', 'compilationFinished', (file, source, languageVersion, data) => {
if (!self.config.get('settings/generate-contract-metadata')) return
const compiler = new CompilerAbstract(languageVersion, data, source)
var provider = self.fileManager.fileProviderOf(source.target)
var path = self.fileManager.extractPathOf(source.target)
if (provider) {
compiler.visitContracts((contract) => {
if (contract.file !== source.target) return
var fileName = self._JSONFileName(path, contract.name)
var metadataFileName = self._MetadataFileName(path, contract.name)
provider.get(fileName, (error, content) => {
if (!error) {
content = content || '{}'
var metadata
try {
metadata = JSON.parse(content)
} catch (e) {
console.log(e)
}
var deploy = metadata.deploy || {}
self.networks.forEach((network) => {
deploy[network] = self._syncContext(contract, deploy[network] || {})
})
let parsedMetadata
try {
parsedMetadata = JSON.parse(contract.object.metadata)
} catch (e) {
console.log(e)
}
if (parsedMetadata) provider.set(metadataFileName, JSON.stringify(parsedMetadata, null, '\t'))
var data = {
deploy,
data: {
bytecode: contract.object.evm.bytecode,
deployedBytecode: contract.object.evm.deployedBytecode,
gasEstimates: contract.object.evm.gasEstimates,
methodIdentifiers: contract.object.evm.methodIdentifiers
},
abi: contract.object.abi
}
provider.set(fileName, JSON.stringify(data, null, '\t'))
}
})
})
}
})
}
_syncContext (contract, metadata) {
var linkReferences = metadata.linkReferences
var autoDeployLib = metadata.autoDeployLib
if (!linkReferences) linkReferences = {}
if (autoDeployLib === undefined) autoDeployLib = true
for (var libFile in contract.object.evm.bytecode.linkReferences) {
if (!linkReferences[libFile]) linkReferences[libFile] = {}
for (var lib in contract.object.evm.bytecode.linkReferences[libFile]) {
if (!linkReferences[libFile][lib]) {
linkReferences[libFile][lib] = '<address>'
}
}
}
metadata.linkReferences = linkReferences
metadata.autoDeployLib = autoDeployLib
return metadata
}
// TODO: is only called by dropdownLogic and can be moved there
deployMetadataOf (contractName, fileLocation) {
return new Promise((resolve, reject) => {
var provider
let path
if (fileLocation) {
provider = this.fileManager.fileProviderOf(fileLocation)
path = fileLocation.split('/')
path.pop()
path = path.join('/')
} else {
provider = this.fileManager.currentFileProvider()
path = this.fileManager.currentPath()
}
if (provider) {
this.blockchain.detectNetwork((err, { id, name } = {}) => {
if (err) {
console.log(err)
reject(err)
} else {
var fileName = this._JSONFileName(path, contractName)
provider.get(fileName, (error, content) => {
if (error) return reject(error)
if (!content) return resolve()
try {
var metadata = JSON.parse(content)
metadata = metadata.deploy || {}
return resolve(metadata[name + ':' + id] || metadata[name] || metadata[id] || metadata[name.toLowerCase() + ':' + id] || metadata[name.toLowerCase()])
} catch (e) {
reject(e.message)
}
})
}
})
} else {
reject(new Error(`Please select the folder in the file explorer where the metadata of ${contractName} can be found`))
}
})
}
}
module.exports = CompilerMetadata

@ -11,7 +11,7 @@ const _paq = window._paq = window._paq || []
const profile = {
name: 'settings',
displayName: 'Settings',
methods: ['getGithubAccessToken'],
methods: ['get'],
events: [],
icon: 'assets/img/settings.webp',
description: 'Remix-IDE settings',
@ -257,8 +257,8 @@ module.exports = class SettingsTab extends ViewPlugin {
return this._view.el
}
getGithubAccessToken () {
return this.config.get('settings/gist-access-token')
get (key) {
return this.config.get(key)
}
updateMatomoAnalyticsChoice (isChecked) {

@ -24,7 +24,7 @@ export class CompilerImports extends Plugin {
async setToken () {
const protocol = typeof window !== 'undefined' && window.location.protocol
const token = await this.call('settings', 'getGithubAccessToken')
const token = await this.call('settings', 'get', 'settings/gist-access-token')
this.urlResolver.setGistToken(token, protocol)
}

@ -0,0 +1 @@
{ "extends": "../../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] }

@ -0,0 +1,3 @@
# remix-core-plugin-compiler-metadata
This library was generated with [Nx](https://nx.dev).

@ -0,0 +1,11 @@
{
"name": "@remix-core-plugin/compiler-metadata",
"version": "0.0.1",
"description": "This library was generated with [Nx](https://nx.dev).",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Remix Team",
"license": "ISC"
}

@ -0,0 +1 @@
export * from './lib/compiler-metadata'

@ -0,0 +1,146 @@
'use strict'
import { Plugin } from '@remixproject/engine'
import { CompilerAbstract } from '@remix-project/remix-solidity'
const profile = {
name: 'compilerMetadata',
methods: ['deployMetadataOf'],
events: [],
version: '0.0.1'
}
export class CompilerMetadata extends Plugin {
networks: string[]
innerPath: string
constructor () {
super(profile)
this.networks = ['VM:-', 'main:1', 'ropsten:3', 'rinkeby:4', 'kovan:42', 'görli:5', 'Custom']
this.innerPath = 'artifacts'
}
_JSONFileName (path, contractName) {
return this.joinPath(path, this.innerPath, contractName + '.json')
}
_MetadataFileName (path, contractName) {
return this.joinPath(path, this.innerPath, contractName + '_metadata.json')
}
onActivation () {
var self = this
this.on('solidity', 'compilationFinished', async (file, source, languageVersion, data) => {
if (!await this.call('settings', 'get', 'settings/generate-contract-metadata')) return
const compiler = new CompilerAbstract(languageVersion, data, source)
var path = self._extractPathOf(source.target)
compiler.visitContracts((contract) => {
if (contract.file !== source.target) return
(async () => {
const fileName = self._JSONFileName(path, contract.name)
const content = await this.call('fileManager', 'exists', fileName) ? await this.call('fileManager', 'readFile', fileName) : null
await this._setArtefacts(content, contract, path)
})()
})
})
}
_extractPathOf (file) {
var reg = /(.*)(\/).*/
var path = reg.exec(file)
return path ? path[1] : '/'
}
async _setArtefacts (content, contract, path) {
content = content || '{}'
var metadata
try {
metadata = JSON.parse(content)
} catch (e) {
console.log(e)
}
var fileName = this._JSONFileName(path, contract.name)
var metadataFileName = this._MetadataFileName(path, contract.name)
var deploy = metadata.deploy || {}
this.networks.forEach((network) => {
deploy[network] = this._syncContext(contract, deploy[network] || {})
})
let parsedMetadata
try {
parsedMetadata = JSON.parse(contract.object.metadata)
} catch (e) {
console.log(e)
}
if (parsedMetadata) await this.call('fileManager', 'writeFile', metadataFileName, JSON.stringify(parsedMetadata, null, '\t'))
var data = {
deploy,
data: {
bytecode: contract.object.evm.bytecode,
deployedBytecode: contract.object.evm.deployedBytecode,
gasEstimates: contract.object.evm.gasEstimates,
methodIdentifiers: contract.object.evm.methodIdentifiers
},
abi: contract.object.abi
}
await this.call('fileManager', 'writeFile', fileName, JSON.stringify(data, null, '\t'))
}
_syncContext (contract, metadata) {
var linkReferences = metadata.linkReferences
var autoDeployLib = metadata.autoDeployLib
if (!linkReferences) linkReferences = {}
if (autoDeployLib === undefined) autoDeployLib = true
for (var libFile in contract.object.evm.bytecode.linkReferences) {
if (!linkReferences[libFile]) linkReferences[libFile] = {}
for (var lib in contract.object.evm.bytecode.linkReferences[libFile]) {
if (!linkReferences[libFile][lib]) {
linkReferences[libFile][lib] = '<address>'
}
}
}
metadata.linkReferences = linkReferences
metadata.autoDeployLib = autoDeployLib
return metadata
}
async deployMetadataOf (contractName, fileLocation) {
let path
if (fileLocation) {
path = fileLocation.split('/')
path.pop()
path = path.join('/')
} else {
try {
path = this._extractPathOf(await this.call('fileManager', 'getCurrentFile'))
} catch (err) {
console.log(err)
throw new Error(err)
}
}
try {
const { id, name } = await this.call('network', 'detectNetwork')
const fileName = this._JSONFileName(path, contractName)
try {
const content = await this.call('fileManager', 'readFile', fileName)
if (!content) return null
let metadata = JSON.parse(content)
metadata = metadata.deploy || {}
return metadata[name + ':' + id] || metadata[name] || metadata[id] || metadata[name.toLowerCase() + ':' + id] || metadata[name.toLowerCase()]
} catch (err) {
console.log(err)
throw new Error(err)
}
} catch (err) {
console.log(err)
throw new Error(err)
}
}
joinPath (...paths) {
paths = paths.filter((value) => value !== '').map((path) => path.replace(/^\/|\/$/g, '')) // remove first and last slash)
if (paths.length === 1) return paths[0]
return paths.join('/')
}
}

@ -0,0 +1,10 @@
{
"extends": "../../../tsconfig.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../dist/out-tsc",
"declaration": true,
"rootDir": "./src",
"types": ["node"]
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}

@ -114,6 +114,9 @@
},
"offset-line-to-column-converter": {
"tags": []
},
"compiler-metadata": {
"tags": []
}
}
}

@ -52,6 +52,9 @@
],
"@remix-core-plugin/offset-line-to-column-converter": [
"libs/remix-core-plugin/offset-line-to-column-converter/src/index.ts"
],
"@remix-core-plugin/compiler-metadata": [
"libs/remix-core-plugin/compiler-metadata/src/index.ts"
]
}
},

@ -840,7 +840,6 @@
]
}
},
"build": {
"builder": "@nrwl/node:package",
"options": {
@ -881,6 +880,36 @@
}
}
}
},
"compiler-metadata": {
"root": "libs/remix-core-plugin/compiler-metadata",
"sourceRoot": "libs/remix-core-plugin/compiler-metadata/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": [
"libs/remix-core-plugin/compiler-metadata/tsconfig.lib.json"
],
"exclude": [
"**/node_modules/**",
"!libs/remix-core-plugin/compiler-metadata/**/*"
]
}
},
"build": {
"builder": "@nrwl/node:package",
"options": {
"outputPath": "dist/libs/core-plugin/compiler-metadata",
"tsConfig": "libs/remix-core-plugin/compiler-metadata/tsconfig.lib.json",
"packageJson": "libs/remix-core-plugin/compiler-metadata/package.json",
"main": "libs/remix-core-plugin/compiler-metadata/src/index.ts"
}
}
}
}
},
"cli": {

Loading…
Cancel
Save