parent
340d78000d
commit
d4c60aed81
@ -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 |
@ -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"] |
||||
} |
Loading…
Reference in new issue