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

desktopautoupdate
bunsenstraat 10 months ago
commit eb010b7774
  1. 2
      apps/circuit-compiler/src/app/services/circomPluginClient.ts
  2. 21
      apps/remix-ide-e2e/src/tests/gist.test.ts
  3. 2
      apps/remix-ide/ci/makeMockCompiler.js
  4. 2
      apps/solidity-compiler/src/app/compiler.ts
  5. 2
      libs/remix-solidity/src/compiler/types.ts
  6. 2
      libs/remix-ui/editor/src/lib/remix-plugin-types.ts
  7. 2
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  8. 2
      libs/remix-ui/solidity-compiler/src/lib/logic/compileTabLogic.ts
  9. 2
      libs/remix-ui/solidity-compiler/src/lib/solidity-compiler.tsx
  10. 40
      libs/remix-ui/workspace/src/lib/actions/index.ts
  11. 42
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  12. 9
      libs/remix-ui/workspace/src/lib/components/file-explorer-context-menu.tsx
  13. 1
      libs/remix-ui/workspace/src/lib/contexts/index.ts
  14. 6
      libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx
  15. 8
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  16. 2
      libs/remix-ui/workspace/src/lib/types/index.ts
  17. 7
      libs/remix-ui/workspace/src/lib/utils/index.ts

@ -21,7 +21,7 @@ export class CircomPluginClient extends PluginClient {
constructor() {
super()
this.methods = ['init', 'parse', 'compile', 'generateR1cs']
this.methods = ['init', 'parse', 'compile', 'generateR1cs', 'resolveDependencies']
createClient(this)
this.internalEvents = new EventManager()
this.onload()

@ -145,6 +145,23 @@ module.exports = {
.openFile(`gist-${testData.validGistId}/README.txt`)
.waitForElementVisible(`div[data-path='default_workspace/gist-${testData.validGistId}/README.txt']`)
.assert.containsText(`div[data-path='default_workspace/gist-${testData.validGistId}/README.txt'] > span`, 'README.txt')
.end()
}
},
'Load Gist from URL and verify truncated files are loaded #group3': function (browser: NightwatchBrowser) {
const gistId = '1b179bf1b92c8b0664b4cbe61774e15d'
browser
.url('http://127.0.0.1:8080/#gist=' + gistId) // loading the gist
.refreshPage()
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 15000)
.waitForElementVisible(`#fileExplorerView li[data-path='gist-${gistId}/README.txt']`, 30000)
.openFile(`gist-${gistId}/scripts/deploy_with_ethers.ts`)
.getEditorValue((content) => {
browser.assert.ok(content !== '')
})
.rightClickCustom(`li[data-path='gist-${gistId}'] div`) // saving the gist
.click('[data-id="contextMenuItempublishFolderToGist"]')
.modalFooterOKClick('fileSystem')
.waitForElementVisible('*[data-shared="tooltipPopup"]', 5000)
.assert.containsText('*[data-shared="tooltipPopup"]', 'Saving gist (' + gistId + ') ...')
}
}

@ -3,7 +3,7 @@
var fs = require('fs')
var compiler = require('solc')
var compilerInput = require('@remix-project/remix-solidity').CompilerInput
var defaultVersion = 'soljson-v0.8.22+commit.4fc1097e.js'
var defaultVersion = 'soljson-v0.8.24+commit.e11b9ed9.js'
const path = require('path')
compiler.loadRemoteVersion(defaultVersion, (error, solcSnapshot) => {

@ -9,7 +9,7 @@ import { CompileTabLogic } from '@remix-ui/solidity-compiler'
const defaultCompilerParameters = {
runs: '200',
optimize: false,
version: 'soljson-v0.8.22+commit.4fc1097e',
version: 'soljson-v0.8.24+commit.e11b9ed9',
evmVersion: null, // compiler default
language: 'Solidity',
useFileConfiguration: false,

@ -151,7 +151,7 @@ export interface CompilerInputOptions {
remappings?: string[]
}
export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'berlin' | 'london' | 'paris' | null
export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'berlin' | 'london' | 'paris' | 'shanghai' | 'cancun' | null
export type Language = 'Solidity' | 'Yul'

@ -226,7 +226,7 @@ declare interface CondensedCompilationInput {
optimize: boolean
/** e.g: 0.6.8+commit.0bbfe453 */
version: string
evmVersion?: 'paris' | 'berlin' | 'istanbul' | 'petersburg' | 'constantinople' | 'byzantium' | 'spuriousDragon' | 'tangerineWhistle' | 'homestead'
evmVersion?: 'cancun' | 'shanghai' | 'paris' | 'berlin' | 'istanbul' | 'petersburg' | 'constantinople' | 'byzantium' | 'spuriousDragon' | 'tangerineWhistle' | 'homestead'
}
declare interface ContentImport {

@ -61,7 +61,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
downloaded: [],
compilerLicense: null,
selectedVersion: null,
defaultVersion: 'soljson-v0.8.22+commit.4fc1097e.js', // this default version is defined: in makeMockCompiler (for browser test)
defaultVersion: 'soljson-v0.8.24+commit.e11b9ed9.js', // this default version is defined: in makeMockCompiler (for browser test)
runs: '',
compiledFileName: '',
includeNightlies: false,

@ -28,7 +28,7 @@ export class CompileTabLogic {
this.contentImport = contentImport
this.event = new EventEmitter()
this.compiler = new Compiler((url, cb) => api.resolveContentAndSave(url).then((result) => cb(null, result)).catch((error) => cb(error.message)))
this.evmVersions = ['default', 'shanghai', 'paris', 'london', 'berlin', 'istanbul', 'petersburg', 'constantinople', 'byzantium', 'spuriousDragon', 'tangerineWhistle', 'homestead']
this.evmVersions = ['default', 'cancun', 'shanghai', 'paris', 'london', 'berlin', 'istanbul', 'petersburg', 'constantinople', 'byzantium', 'spuriousDragon', 'tangerineWhistle', 'homestead']
}
init () {

@ -39,7 +39,7 @@ export const SolidityCompiler = (props: SolidityCompilerProps) => {
handleHide: null
},
solJsonBinData: null,
defaultVersion: 'soljson-v0.8.22+commit.4fc1097e.js', // this default version is defined: in makeMockCompiler (for browser test)
defaultVersion: 'soljson-v0.8.24+commit.e11b9ed9.js', // this default version is defined: in makeMockCompiler (for browser test)
})
const [currentVersion, setCurrentVersion] = useState('')
const [hideWarnings, setHideWarnings] = useState<boolean>(false)

@ -5,11 +5,11 @@ import { customAction } from '@remixproject/plugin-api'
import { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentLocalFilePath, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload'
import { listenOnPluginEvents, listenOnProviderEvents } from './events'
import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin, workspaceExists } from './workspace'
import { QueryParams } from '@remix-project/remix-lib'
import { QueryParams, Registry } from '@remix-project/remix-lib'
import { fetchContractFromEtherscan } from '@remix-project/core-plugin' // eslint-disable-line
import JSZip from 'jszip'
import { Actions, FileTree } from '../types'
import {Registry} from '@remix-project/remix-lib'
import IpfsHttpClient from 'ipfs-http-client'
export * from './events'
export * from './workspace'
@ -22,6 +22,7 @@ let plugin, dispatch: React.Dispatch<Actions>
export type UrlParametersType = {
gist: string,
code: string,
shareCode: string,
url: string,
address: string
opendir: string,
@ -75,7 +76,7 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
plugin.setWorkspace({ name: 'code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace({ name: 'code-sample', isGitRepo: false }))
await loadWorkspacePreset('gist-template')
} else if (params.code || params.url) {
} else if (params.code || params.url || params.shareCode) {
await createWorkspaceTemplate('code-sample', 'code-template')
plugin.setWorkspace({ name: 'code-sample', isLocalhost: false })
dispatch(setCurrentWorkspace({ name: 'code-sample', isGitRepo: false }))
@ -226,8 +227,11 @@ export type SolidityConfiguration = {
export const publishToGist = async (path?: string, type?: string) => {
// If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer.
const folder = path || '/'
const id = type === 'gist' ? extractNameFromKey(path).split('-')[1] : null
try {
const name = extractNameFromKey(path)
const id = name && name.startsWith('gist-') ? name.split('-')[1] : null
const packaged = await packageGistFiles(folder)
// check for token
const config = plugin.registry.get('config').api
@ -373,6 +377,33 @@ export const copyFile = async (src: string, dest: string) => {
}
}
export const copyShareURL = async (path: string) => {
const fileManager = plugin.fileManager
try {
const host = '127.0.0.1'
const port = 5001
const protocol = 'http'
// const projectId = ''
// const projectSecret = ''
// const auth = 'Basic ' + Buffer.from(projectId + ':' + projectSecret).toString('base64')
const ipfs = IpfsHttpClient({ port, host, protocol
, headers: {
// authorization: auth
}
})
const fileContent = await fileManager.readFile(path)
const result = await ipfs.add(fileContent)
const hash = result.cid.string
const shareUrl = `${window.location.origin}/#shareCode=${hash}`
navigator.clipboard.writeText(shareUrl)
} catch (error) {
dispatch(displayPopUp('Oops! An error ocurred while performing copyShareURL operation.' + error))
}
}
export const copyFolder = async (src: string, dest: string) => {
const fileManager = plugin.fileManager
@ -402,6 +433,7 @@ export const handleClickFile = async (path: string, type: 'file' | 'folder' | 'g
if (type === 'file' && path.endsWith('.md')) {
// just opening the preview
await plugin.call('doc-viewer' as any, 'viewDocs', [path])
plugin.call('tabs' as any, 'focus', 'doc-viewer')
} else {
await plugin.fileManager.open(path)
dispatch(focusElement([{ key: path, type }]))

@ -3,6 +3,7 @@ import { bufferToHex } from '@ethereumjs/util'
import { hash } from '@remix-project/remix-lib'
import { TEMPLATE_METADATA, TEMPLATE_NAMES } from '../utils/constants'
import { TemplateType } from '../utils/types'
import IpfsHttpClient from 'ipfs-http-client'
import axios, { AxiosResponse } from 'axios'
import {
addInputFieldSuccess,
@ -234,6 +235,7 @@ export const createWorkspaceTemplate = async (workspaceName: string, template: W
export type UrlParametersType = {
gist: string
code: string
shareCode: string
url: string
language: string
}
@ -257,6 +259,30 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe
content = atob(decodeURIComponent(params.code))
await workspaceProvider.set(path, content)
}
if (params.shareCode) {
const host = '127.0.0.1'
const port = 5001
const protocol = 'http'
// const projectId = ''
// const projectSecret = ''
// const auth = 'Basic ' + Buffer.from(projectId + ':' + projectSecret).toString('base64')
const ipfs = IpfsHttpClient({ port, host, protocol
, headers: {
// authorization: auth
}
})
const hashed = bufferToHex(hash.keccakFromString(params.shareCode))
path = 'contract-' + hashed.replace('0x', '').substring(0, 10) + (params.language && params.language.toLowerCase() === 'yul' ? '.yul' : '.sol')
const fileData = ipfs.get(params.shareCode)
for await (const file of fileData) {
const fileContent = []
for await (const chunk of file.content) fileContent.push(chunk)
content = Buffer.concat(fileContent).toString()
}
await workspaceProvider.set(path, content)
}
if (params.url) {
const data = await plugin.call('contentImport', 'resolve', params.url)
@ -308,11 +334,21 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe
}
const obj = {}
Object.keys(data.files).forEach((element) => {
for (const [element] of Object.entries(data.files)) {
const path = element.replace(/\.\.\./g, '/')
let value
if (data.files[element].truncated) {
const response: AxiosResponse = await axios.get(data.files[element].raw_url)
value = { content: response.data }
} else {
value = { content: data.files[element].content }
}
obj['/' + 'gist-' + gistId + '/' + path] = data.files[element]
})
if (data.files[element].type === 'application/json') {
obj['/' + 'gist-' + gistId + '/' + path] = { content: JSON.stringify(value.content, null, '\t') }
} else
obj['/' + 'gist-' + gistId + '/' + path] = value
}
plugin.fileManager.setBatchFiles(obj, 'workspace', true, (errorLoadingFile) => {
if (errorLoadingFile) {
dispatch(displayNotification('', errorLoadingFile.message || errorLoadingFile, 'OK', null, () => {}, null))

@ -28,6 +28,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) =>
publishFolderToGist,
copy,
copyFileName,
copyShareURL,
copyPath,
paste,
runScript,
@ -206,11 +207,15 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) =>
break
case 'Copy name':
copyFileName(path, type)
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'copy'])
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'copyName'])
break
case 'Copy path':
copyPath(path, type)
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'copy'])
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'copyPath'])
break
case 'Copy share URL':
copyShareURL(path, type)
_paq.push(['trackEvent', 'fileExplorer', 'contextMenu', 'copyShareURL'])
break
case 'Paste':
paste(path, type)

@ -27,6 +27,7 @@ export const FileSystemContext = createContext<{
dispatchRenamePath: (oldPath: string, newPath: string) => Promise<void>,
dispatchDownloadPath: (path:string) => Promise<void>,
dispatchCopyFile: (src: string, dest: string) => Promise<void>,
dispatchCopyShareURL: (path: string) => Promise<void>,
dispatchCopyFolder: (src: string, dest: string) => Promise<void>,
dispatchRunScript: (path: string) => Promise<void>,
dispatchEmitContextMenuEvent: (cmd: customAction) => Promise<void>,

@ -20,6 +20,7 @@ import {
renamePath,
downloadPath,
copyFile,
copyShareURL,
copyFolder,
runScript,
emitContextMenuEvent,
@ -156,6 +157,10 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await copyFile(src, dest)
}
const dispatchCopyShareURL = async (path: string) => {
await copyShareURL(path)
}
const dispatchCopyFolder = async (src: string, dest: string) => {
await copyFolder(src, dest)
}
@ -352,6 +357,7 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchRenamePath,
dispatchDownloadPath,
dispatchCopyFile,
dispatchCopyShareURL,
dispatchCopyFolder,
dispatchRunScript,
dispatchEmitContextMenuEvent,

@ -534,6 +534,11 @@ export function Workspace() {
navigator.clipboard.writeText(fileName)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleCopyShareURLClick = (path: string, _type: string) => {
global.dispatchCopyShareURL(path)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleCopyFilePathClick = (path: string, _type: string) => {
navigator.clipboard.writeText(path)
@ -1098,6 +1103,7 @@ export function Workspace() {
dispatchUploadFile={global.dispatchUploadFile}
dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFile={global.dispatchCopyFile}
dispatchCopyShareURL={global.dispatchCopyShareURL}
dispatchCopyFolder={global.dispatchCopyFolder}
dispatchPublishToGist={global.dispatchPublishToGist}
dispatchRunScript={global.dispatchRunScript}
@ -1157,6 +1163,7 @@ export function Workspace() {
dispatchUploadFile={global.dispatchUploadFile}
dispatchUploadFolder={global.dispatchUploadFolder}
dispatchCopyFile={global.dispatchCopyFile}
dispatchCopyShareURL={global.dispatchCopyShareURL}
dispatchCopyFolder={global.dispatchCopyFolder}
dispatchPublishToGist={global.dispatchPublishToGist}
dispatchRunScript={global.dispatchRunScript}
@ -1300,6 +1307,7 @@ export function Workspace() {
paste={handlePasteClick}
copyFileName={handleCopyFileNameClick}
copyPath={handleCopyFilePathClick}
copyShareURL={handleCopyShareURLClick}
emit={emitContextMenuEvent}
pageX={state.focusContext.x}
pageY={state.focusContext.y}

@ -105,6 +105,7 @@ export interface FileExplorerProps {
dispatchUploadFile: (target?: React.SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchUploadFolder: (target?: React.SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchCopyFile: (src: string, dest: string) => Promise<void>,
dispatchCopyShareURL: (path:string) => Promise<void>,
dispatchCopyFolder: (src: string, dest: string) => Promise<void>,
dispatchRunScript: (path: string) => Promise<void>,
dispatchPublishToGist: (path?: string, type?: string) => Promise<void>,
@ -165,6 +166,7 @@ export interface FileExplorerContextMenuProps {
copy?: (path: string, type: string) => void
paste?: (destination: string, type: string) => void
copyFileName?: (path: string, type: string) => void
copyShareURL?: (path: string, type: string) => void
copyPath?: (path: string, type: string) => void
generateUml?: (path: string) => Promise<void>
uploadFile?: (target: EventTarget & HTMLInputElement) => void

@ -59,6 +59,13 @@ export const contextMenuActions: MenuItems = [{
label: '',
group: 1
}, {
// id: 'copyShareURL',
// name: 'Copy share URL',
// type: ['file'],
// multiselect: false,
// label: '',
// group: 1
// }, {
id: 'download',
name: 'Download',
type: ['file', 'folder', 'workspace'],

Loading…
Cancel
Save