parent
1ff990f541
commit
7bab2e0d76
@ -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