Merge branch 'master' of https://github.com/ethereum/remix-project into editorcontext

pull/5370/head
filip mertens 3 years ago
commit d76e5a0eb7
  1. 6
      .github/workflows/publish-action.yml
  2. 8
      apps/remix-ide-e2e/src/tests/publishContract.test.ts
  3. 4
      apps/remix-ide/ci/publishIpfs
  4. 33
      apps/remix-ide/src/app/editor/editor.js
  5. 4
      apps/remix-ide/src/app/files/fileManager.ts
  6. 3
      apps/remix-ide/src/app/panels/layout.ts
  7. 7
      apps/remix-ide/src/app/panels/tab-proxy.js
  8. 13
      apps/solidity-compiler/src/app/compiler-api.ts
  9. 6
      libs/remix-ui/helper/src/lib/helper-components.tsx
  10. 12
      libs/remix-ui/publish-to-storage/src/lib/publish-to-storage.tsx
  11. 9
      libs/remix-ui/publish-to-storage/src/lib/publishOnSwarm.tsx
  12. 9
      libs/remix-ui/publish-to-storage/src/lib/publishToIPFS.tsx
  13. 9
      libs/remixd/src/bin/remixd.ts

@ -9,11 +9,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- run: yarn install
- run: yarn install --ignore-engines
- run: ls
- run: pwd
- run: yarn run downloadsolc_assets
- run: yarn run build:production
- run: yarn run downloadsolc_assets --ignore-engines
- run: yarn run build:production --ignore-engines
- run: echo "action_state=$('./apps/remix-ide/ci/publishIpfs')" >> $GITHUB_ENV
- uses: mshick/add-pr-comment@v1
with:

@ -25,11 +25,13 @@ module.exports = {
const value = <string>(result.value)
browser.perform((done) => {
if (value.indexOf('Metadata of "ballot" was published successfully.') === -1) browser.assert.fail('ipfs deploy failed')
if (value.indexOf('Metadata and sources of "ballot" were published successfully.') === -1) browser.assert.fail('ipfs deploy failed')
done()
})
})
.click('[data-id="publishToStorage-modal-footer-ok-react"]')
.openFile('ipfs/QmSUodhSvoorFL5m5CNqve8YvmuBpjCq17NbTf4GUX8ydw')
.openFile('ipfs/QmXYUS1ueS22EqNVRaKuZa31EgHLjKZ8uTM8vWhQLxa3pw')
},
/* Disableing the test untill refactoring and the new swarm usage
@ -41,7 +43,7 @@ module.exports = {
const value = <string>(result.value)
browser.perform((done) => {
if (value.indexOf('Metadata of "ballot" was published successfully.') === -1) browser.assert.fail('swarm deploy failed')
if (value.indexOf('Metadata and sources of "ballot" were published successfully.') === -1) browser.assert.fail('swarm deploy failed')
if (value.indexOf('bzz') === -1) browser.assert.fail('swarm deploy failed')
done()
})
@ -65,7 +67,7 @@ module.exports = {
.getText('[data-id="udappModalDialogModalBody-react"]', (result) => {
const value = typeof result.value === 'string' ? result.value : null
if (value.indexOf('Metadata of "storage" was published successfully.') === -1) browser.assert.fail('ipfs deploy failed')
if (value.indexOf('Metadata and sources of "storage" were published successfully.') === -1) browser.assert.fail('ipfs deploy failed')
})
.modalFooterOKClick('udapp')
},

@ -5,8 +5,8 @@ const { globSource } = IpfsHttpClient
const folder = process.cwd() + '/dist/apps/remix-ide';
(async () => {
const host = 'ipfs.remixproject.org'
const ipfs = IpfsHttpClient({ host, port: 443, protocol: 'https' })
const host = 'ipfs.infura.io'
const ipfs = IpfsHttpClient({ host, port: 5001, protocol: 'https' })
try {
let result = await ipfs.add(globSource(folder, { recursive: true}), { pin: false })
const hash = result.cid.toString()

@ -1,5 +1,6 @@
'use strict'
import React from 'react' // eslint-disable-line
import { resolve } from 'path'
import { EditorUI } from '@remix-ui/editor' // eslint-disable-line
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
@ -140,14 +141,38 @@ class Editor extends Plugin {
this.on('sidePanel', 'pluginDisabled', (name) => {
this.clearAllDecorationsFor(name)
})
this.on('fileManager', 'fileClosed', (name) => {
this.on('theme', 'themeLoaded', (theme) => {
this.currentThemeType = theme.quality
this.renderComponent()
})
this.on('fileManager', 'currentFileChanged', async (name) => {
if (name.endsWith('.ts')) {
// extract the import, resolve their content
// and add the imported files to Monaco through the `addModel`
// so Monaco can provide auto completion
let content = await this.call('fileManager', 'readFile', name)
const paths = name.split('/')
paths.pop()
const fromPath = paths.join('/') // get current execution context path
for (const match of content.matchAll(/import\s+.*\s+from\s+(?:"(.*?)"|'(.*?)')/g)) {
let path = match[2]
if (path.startsWith('./') || path.startsWith('../')) path = resolve(fromPath, path)
if (path.startsWith('/')) path = path.substring(1)
if (!path.endsWith('.ts')) path = path + '.ts'
if (await this.call('fileManager', 'exists', path)) {
content = await this.call('fileManager', 'readFile', path)
this.emit('addModel', content, 'typescript', path, false)
}
}
}
if (name === this.currentFile) {
this.currentFile = null
this.currentFile = name
this.renderComponent()
}
})
this.on('theme', 'themeLoaded', (theme) => {
this.currentThemeType = theme.quality
this.on('fileManager', 'noFileSelected', async () => {
this.currentFile = null
this.renderComponent()
})
try {

@ -4,7 +4,7 @@ import * as packageJson from '../../../../../package.json'
import Registry from '../state/registry'
import { EventEmitter } from 'events'
import { RemixAppManager } from '../../../../../libs/remix-ui/plugin-manager/src/types'
import { fileChangedToastMsg, storageFullMessage } from '@remix-ui/helper'
import { fileChangedToastMsg, recursivePasteToastMsg, storageFullMessage } from '@remix-ui/helper'
import helper from '../../lib/helper.js'
/*
@ -277,7 +277,7 @@ class FileManager extends Plugin {
const provider = this.fileProviderOf(src)
if (provider.isSubDirectory(src, dest)) {
this.call('notification', 'toast', 'File(s) to paste is an ancestor of the destination folder')
this.call('notification', 'toast', recursivePasteToastMsg())
} else {
await this.inDepthCopy(src, dest)
}

@ -57,9 +57,6 @@ export class Layout extends Plugin {
this.panels.main.active = false
this.event.emit('change', null)
})
this.on('tabs', 'tabCountChanged', async count => {
if (!count) await this.call('manager', 'activatePlugin', 'home')
})
this.on('manager', 'activate', (profile: Profile) => {
switch (profile.name) {
case 'filePanel':

@ -283,7 +283,12 @@ export class TabProxy extends Plugin {
delete this._handlers[name]
let previous = currentFileTab
this.loadedTabs = this.loadedTabs.filter((tab, index) => {
if (!previous && tab.name === name) previous = this.loadedTabs[index - 1]
if (!previous && tab.name === name) {
if(index - 1 >= 0 && this.loadedTabs[index - 1])
previous = this.loadedTabs[index - 1]
else if (index + 1 && this.loadedTabs[index + 1])
previous = this.loadedTabs[index + 1]
}
return tab.name !== name
})
this.renderComponent()

@ -309,14 +309,15 @@ export const CompilerApiMixin = (Base) => class extends Base {
if (data.errors) {
for (const error of data.errors) {
let pos = helper.getPositionDetails(error.formattedMessage)
if (pos.errFile) {
const file = pos.errFile
if (file) {
pos = {
row: pos.errLine,
column: pos.errCol,
text: error.formattedMessage,
type: error.severity
}
await this.call('editor', 'addAnnotation', pos, pos.errFile)
await this.call('editor', 'addAnnotation', pos, file)
}
}
}
@ -340,9 +341,11 @@ export const CompilerApiMixin = (Base) => class extends Base {
// ctrl+s or command+s
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.keyCode === 83 && this.currentFile !== '') {
e.preventDefault()
if(await this.getAppParameter('hardhat-compilation')) this.compileTabLogic.runCompiler('hardhat')
else if(await this.getAppParameter('truffle-compilation')) this.compileTabLogic.runCompiler('truffle')
else this.compileTabLogic.runCompiler(undefined)
if (this.currentFile && (this.currentFile.endsWith('.sol') || this.currentFile.endsWith('.yul'))) {
if(await this.getAppParameter('hardhat-compilation')) this.compileTabLogic.runCompiler('hardhat')
else if(await this.getAppParameter('truffle-compilation')) this.compileTabLogic.runCompiler('truffle')
else this.compileTabLogic.runCompiler(undefined)
}
}
}
window.document.addEventListener('keydown', this.data.eventHandlers.onKeyDown)

@ -78,3 +78,9 @@ export const storageFullMessage = () => (
</span>
</div>
)
export const recursivePasteToastMsg = () => (
<div>
File(s) to paste is an ancestor of the destination folder
</div>
)

@ -28,9 +28,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
try {
const result = await publishToSwarm(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
api.writeFile('swarm/' + result.item.hash, result.item.content)
modal(`Published ${contract.name}'s Metadata and Sources`, publishMessage(result.uploaded))
} catch (err) {
let parseError = err
try {
@ -43,9 +41,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
try {
const result = await publishToIPFS(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
api.writeFile('ipfs/' + result.item.hash, result.item.content)
modal(`Published ${contract.name}'s Metadata and Sources`, publishMessage(result.uploaded))
} catch (err) {
modal('IPFS Publish Failed', publishMessageFailed(storage, err))
}
@ -59,7 +55,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
}, [storage])
const publishMessage = (uploaded) => (
<span> Metadata of "{contract.name.toLowerCase()}" was published successfully. <br />
<span> Metadata and sources of "{contract.name.toLowerCase()}" were published successfully. <br />
<pre>
<div>
{ uploaded.map((value, index) => <div key={index}><b>{ value.filename }</b> : <pre>{ value.output.url }</pre></div>) }
@ -69,7 +65,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
)
const publishMessageFailed = (storage, err) => (
<span>Failed to publish metadata file to { storage }, please check the { storage } gateways is available. <br />
<span>Failed to publish metadata file and sources to { storage }, please check the { storage } gateways is available. <br />
{err}
</span>
)

@ -79,7 +79,7 @@ export const publishToSwarm = async (contract, api) => {
// publish the list of sources in order, fail if any failed
await Promise.all(sources.map(async (item) => {
try {
const result = await swarmVerifiedPublish(beeNodes, postageStampId, item.content, item.hash)
const result = await swarmVerifiedPublish(beeNodes, postageStampId, item.content, item.hash, api)
try {
item.hash = result.url.match('bzz-raw://(.+)')[1]
@ -96,9 +96,9 @@ export const publishToSwarm = async (contract, api) => {
}
}))
const metadataContent = JSON.stringify(metadata)
const metadataContent = JSON.stringify(metadata, null, '\t')
try {
const result = await swarmVerifiedPublish(beeNodes, postageStampId, metadataContent, '')
const result = await swarmVerifiedPublish(beeNodes, postageStampId, metadataContent, '', api)
try {
contract.metadataHash = result.url.match('bzz-raw://(.+)')[1]
@ -121,7 +121,7 @@ export const publishToSwarm = async (contract, api) => {
return { uploaded, item }
}
const swarmVerifiedPublish = async (beeNodes: Bee[], postageStampId: string, content, expectedHash): Promise<Record<string, any>> => {
const swarmVerifiedPublish = async (beeNodes: Bee[], postageStampId: string, content, expectedHash, api): Promise<Record<string, any>> => {
try {
const results = await uploadToBeeNodes(beeNodes, postageStampId, content)
const hash = hashFromResults(results)
@ -129,6 +129,7 @@ const swarmVerifiedPublish = async (beeNodes: Bee[], postageStampId: string, con
if (expectedHash && hash !== expectedHash) {
return { message: 'hash mismatch between solidity bytecode and uploaded content.', url: 'bzz-raw://' + hash, hash }
} else {
api.writeFile('swarm/' + hash, content)
return { message: 'ok', url: 'bzz-raw://' + hash, hash }
}
} catch (error) {

@ -63,7 +63,7 @@ export const publishToIPFS = async (contract, api) => {
// publish the list of sources in order, fail if any failed
await Promise.all(sources.map(async (item) => {
try {
const result = await ipfsVerifiedPublish(item.content, item.hash)
const result = await ipfsVerifiedPublish(item.content, item.hash, api)
try {
item.hash = result.url.match('dweb:/ipfs/(.+)')[1]
@ -76,10 +76,10 @@ export const publishToIPFS = async (contract, api) => {
throw new Error(error)
}
}))
const metadataContent = JSON.stringify(metadata)
const metadataContent = JSON.stringify(metadata, null, '\t')
try {
const result = await ipfsVerifiedPublish(metadataContent, '')
const result = await ipfsVerifiedPublish(metadataContent, '', api)
try {
contract.metadataHash = result.url.match('dweb:/ipfs/(.+)')[1]
@ -101,13 +101,14 @@ export const publishToIPFS = async (contract, api) => {
return { uploaded, item }
}
const ipfsVerifiedPublish = async (content, expectedHash) => {
const ipfsVerifiedPublish = async (content, expectedHash, api) => {
try {
const results = await severalGatewaysPush(content)
if (expectedHash && results !== expectedHash) {
return { message: 'hash mismatch between solidity bytecode and uploaded content.', url: 'dweb:/ipfs/' + results, hash: results }
} else {
api.writeFile('ipfs/' + results, content)
return { message: 'ok', url: 'dweb:/ipfs/' + results, hash: results }
}
} catch (error) {

@ -60,13 +60,12 @@ function errorHandler (error: any, service: string) {
program.version(version, '-v, --version')
program
.usage('-s <shared folder>')
.description('Provide a two-way connection between the local computer and Remix IDE')
.option('-u, --remix-ide <url>', 'URL of remix instance allowed to connect to this web sockect connection')
.option('-s, --shared-folder <path>', 'Folder to share with Remix IDE')
.description('Establish a two-way websocket connection between the local computer and Remix IDE for a folder')
.option('-u, --remix-ide <url>', 'URL of remix instance allowed to connect')
.option('-s, --shared-folder <path>', 'Folder to share with Remix IDE (Default: CWD)')
.option('-r, --read-only', 'Treat shared folder as read-only (experimental)')
.on('--help', function () {
console.log('\nExample:\n\n remixd -s ./ -u http://localhost:8080')
console.log('\nExample:\n\n remixd -s ./shared_project -u http://localhost:8080')
}).parse(process.argv)
// eslint-disable-next-line

Loading…
Cancel
Save