Merge branch 'master' into editorcontext

editorcontextDummy
bunsenstraat 3 years ago committed by GitHub
commit 6af0bfd370
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      apps/remix-ide-e2e/src/tests/publishContract.test.ts
  2. 4
      apps/remix-ide/ci/publishIpfs
  3. 33
      apps/remix-ide/src/app/editor/editor.js
  4. 4
      apps/remix-ide/src/app/files/fileManager.ts
  5. 3
      apps/remix-ide/src/app/panels/layout.ts
  6. 7
      apps/remix-ide/src/app/panels/tab-proxy.js
  7. 13
      apps/solidity-compiler/src/app/compiler-api.ts
  8. 6
      libs/remix-ui/helper/src/lib/helper-components.tsx
  9. 12
      libs/remix-ui/publish-to-storage/src/lib/publish-to-storage.tsx
  10. 9
      libs/remix-ui/publish-to-storage/src/lib/publishOnSwarm.tsx
  11. 9
      libs/remix-ui/publish-to-storage/src/lib/publishToIPFS.tsx
  12. 9
      libs/remixd/src/bin/remixd.ts

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

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

@ -1,5 +1,6 @@
'use strict' 'use strict'
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line
import { resolve } from 'path'
import { EditorUI } from '@remix-ui/editor' // eslint-disable-line import { EditorUI } from '@remix-ui/editor' // eslint-disable-line
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
@ -140,14 +141,38 @@ class Editor extends Plugin {
this.on('sidePanel', 'pluginDisabled', (name) => { this.on('sidePanel', 'pluginDisabled', (name) => {
this.clearAllDecorationsFor(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) { if (name === this.currentFile) {
this.currentFile = null this.currentFile = name
this.renderComponent() this.renderComponent()
} }
}) })
this.on('theme', 'themeLoaded', (theme) => {
this.currentThemeType = theme.quality this.on('fileManager', 'noFileSelected', async () => {
this.currentFile = null
this.renderComponent() this.renderComponent()
}) })
try { try {

@ -4,7 +4,7 @@ import * as packageJson from '../../../../../package.json'
import Registry from '../state/registry' import Registry from '../state/registry'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { RemixAppManager } from '../../../../../libs/remix-ui/plugin-manager/src/types' 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' import helper from '../../lib/helper.js'
/* /*
@ -277,7 +277,7 @@ class FileManager extends Plugin {
const provider = this.fileProviderOf(src) const provider = this.fileProviderOf(src)
if (provider.isSubDirectory(src, dest)) { 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 { } else {
await this.inDepthCopy(src, dest) await this.inDepthCopy(src, dest)
} }

@ -57,9 +57,6 @@ export class Layout extends Plugin {
this.panels.main.active = false this.panels.main.active = false
this.event.emit('change', null) 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) => { this.on('manager', 'activate', (profile: Profile) => {
switch (profile.name) { switch (profile.name) {
case 'filePanel': case 'filePanel':

@ -283,7 +283,12 @@ export class TabProxy extends Plugin {
delete this._handlers[name] delete this._handlers[name]
let previous = currentFileTab let previous = currentFileTab
this.loadedTabs = this.loadedTabs.filter((tab, index) => { 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 return tab.name !== name
}) })
this.renderComponent() this.renderComponent()

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

@ -78,3 +78,9 @@ export const storageFullMessage = () => (
</span> </span>
</div> </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 { try {
const result = await publishToSwarm(contract, api) const result = await publishToSwarm(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded)) modal(`Published ${contract.name}'s Metadata and Sources`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
api.writeFile('swarm/' + result.item.hash, result.item.content)
} catch (err) { } catch (err) {
let parseError = err let parseError = err
try { try {
@ -43,9 +41,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
try { try {
const result = await publishToIPFS(contract, api) const result = await publishToIPFS(contract, api)
modal(`Published ${contract.name}'s Metadata`, publishMessage(result.uploaded)) modal(`Published ${contract.name}'s Metadata and Sources`, publishMessage(result.uploaded))
// triggered each time there's a new verified publish (means hash correspond)
api.writeFile('ipfs/' + result.item.hash, result.item.content)
} catch (err) { } catch (err) {
modal('IPFS Publish Failed', publishMessageFailed(storage, err)) modal('IPFS Publish Failed', publishMessageFailed(storage, err))
} }
@ -59,7 +55,7 @@ export const PublishToStorage = (props: RemixUiPublishToStorageProps) => {
}, [storage]) }, [storage])
const publishMessage = (uploaded) => ( 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> <pre>
<div> <div>
{ uploaded.map((value, index) => <div key={index}><b>{ value.filename }</b> : <pre>{ value.output.url }</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) => ( 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} {err}
</span> </span>
) )

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

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

@ -60,13 +60,12 @@ function errorHandler (error: any, service: string) {
program.version(version, '-v, --version') program.version(version, '-v, --version')
program program
.usage('-s <shared folder>') .description('Establish a two-way websocket connection between the local computer and Remix IDE for a 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')
.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 (Default: CWD)')
.option('-s, --shared-folder <path>', 'Folder to share with Remix IDE')
.option('-r, --read-only', 'Treat shared folder as read-only (experimental)') .option('-r, --read-only', 'Treat shared folder as read-only (experimental)')
.on('--help', function () { .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) }).parse(process.argv)
// eslint-disable-next-line // eslint-disable-next-line

Loading…
Cancel
Save