commit
798c0bda69
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"extends": "../../.eslintrc", |
||||||
|
"rules": { |
||||||
|
"dot-notation": "off", |
||||||
|
"no-unused-vars": "off", |
||||||
|
"no-use-before-define": "off" |
||||||
|
}, |
||||||
|
"env": { |
||||||
|
"browser": true, |
||||||
|
"amd": true, |
||||||
|
"node": true, |
||||||
|
"es6": true |
||||||
|
}, |
||||||
|
"ignorePatterns": ["!**/*"] |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
src/ |
@ -0,0 +1,7 @@ |
|||||||
|
# ghaction |
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev). |
||||||
|
|
||||||
|
## Running unit tests |
||||||
|
|
||||||
|
Run `nx test ghaction` to execute the unit tests via [Jest](https://jestjs.io). |
@ -0,0 +1,32 @@ |
|||||||
|
{ |
||||||
|
"name": "@remix-project/ghaction-helper", |
||||||
|
"version": "0.1.3", |
||||||
|
"description": "Solidity Tests GitHub Action Helper", |
||||||
|
"main": "src/index.js", |
||||||
|
"scripts": { |
||||||
|
"test": "echo \"Error: no test specified\" && exit 1", |
||||||
|
"build": "tsc" |
||||||
|
}, |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git+https://github.com/ethereum/remix-project.git" |
||||||
|
}, |
||||||
|
"keywords": [], |
||||||
|
"author": "@ioedeveloper", |
||||||
|
"license": "ISC", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/ethereum/remix-project/issues" |
||||||
|
}, |
||||||
|
"homepage": "https://github.com/ethereum/remix-project#readme", |
||||||
|
"devDependencies": { |
||||||
|
"@remix-project/remix-solidity": "^0.5.6", |
||||||
|
"@types/chai": "^4.3.4", |
||||||
|
"typescript": "^4.9.3" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"@ethereum-waffle/chai": "^3.4.4", |
||||||
|
"chai": "^4.3.7", |
||||||
|
"ethers": "^5.7.2", |
||||||
|
"ganache": "^7.5.0" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
{ |
||||||
|
"name": "ghaction-helper", |
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json", |
||||||
|
"sourceRoot": "libs/ghaction-helper/src", |
||||||
|
"projectType": "library", |
||||||
|
"implicitDependencies": [ |
||||||
|
"remix-solidity" |
||||||
|
], |
||||||
|
"targets": { |
||||||
|
"build": { |
||||||
|
"executor": "@nrwl/js:tsc", |
||||||
|
"outputs": ["{options.outputPath}"], |
||||||
|
"options": { |
||||||
|
"outputPath": "dist/libs/ghaction-helper", |
||||||
|
"main": "libs/ghaction-helper/src/index.ts", |
||||||
|
"tsConfig": "libs/ghaction-helper/tsconfig.lib.json", |
||||||
|
"assets": [] |
||||||
|
} |
||||||
|
}, |
||||||
|
"lint": { |
||||||
|
"executor": "@nrwl/linter:eslint", |
||||||
|
"outputs": ["{options.outputFile}"], |
||||||
|
"options": { |
||||||
|
"lintFilePatterns": ["libs/ghaction-helper/**/*.ts"] |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
"tags": [] |
||||||
|
} |
||||||
|
|
@ -0,0 +1,21 @@ |
|||||||
|
import { CompilationResult } from '@remix-project/remix-solidity' |
||||||
|
//@ts-ignore
|
||||||
|
import * as fs from 'fs/promises' |
||||||
|
import * as path from 'path' |
||||||
|
|
||||||
|
export async function getArtifactsByContractName (contractIdentifier: string) { |
||||||
|
//@ts-ignore
|
||||||
|
const contractArtifacts = await fs.readdir(global.remixContractArtifactsPath) |
||||||
|
let contract |
||||||
|
|
||||||
|
for (const artifactFile of contractArtifacts) { |
||||||
|
//@ts-ignore
|
||||||
|
const artifact = await fs.readFile(path.join(global.remixContractArtifactsPath, artifactFile), 'utf-8') |
||||||
|
const artifactJSON: CompilationResult = JSON.parse(artifact) |
||||||
|
const contractFullPath = (Object.keys(artifactJSON.contracts!)).find((contractName) => artifactJSON.contracts![contractName] && artifactJSON.contracts![contractName][contractIdentifier]) |
||||||
|
|
||||||
|
contract = contractFullPath ? artifactJSON.contracts![contractFullPath!][contractIdentifier] : undefined |
||||||
|
if (contract) break |
||||||
|
} |
||||||
|
return contract |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
import * as chai from 'chai' |
||||||
|
// @ts-ignore
|
||||||
|
import { waffleChai } from '@ethereum-waffle/chai' |
||||||
|
|
||||||
|
chai.use(waffleChai) |
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
export * from 'chai' |
||||||
|
export { chai } |
@ -0,0 +1,8 @@ |
|||||||
|
// @ts-nocheck
|
||||||
|
import { ethers } from 'ethers' |
||||||
|
import * as hhEtherMethods from './methods' |
||||||
|
|
||||||
|
for(const method in hhEtherMethods) Object.defineProperty(ethers, method, { value: hhEtherMethods[method]})
|
||||||
|
|
||||||
|
export * from 'ethers' |
||||||
|
export { ethers } |
@ -0,0 +1,2 @@ |
|||||||
|
export * from './chai' |
||||||
|
export * from './ethers' |
@ -0,0 +1,265 @@ |
|||||||
|
// @ts-ignore
|
||||||
|
import { ethers } from "ethers" |
||||||
|
//@ts-ignore
|
||||||
|
import * as ganache from "ganache" |
||||||
|
import { getArtifactsByContractName } from './artifacts-helper' |
||||||
|
import { SignerWithAddress } from './signer' |
||||||
|
|
||||||
|
const initializeProvider = () => { |
||||||
|
//@ts-ignore
|
||||||
|
global.ganacheProvider = ganache.provider({ logging: { quiet: true } }) |
||||||
|
} |
||||||
|
|
||||||
|
const isFactoryOptions = (signerOrOptions: any) => { |
||||||
|
if (!signerOrOptions || signerOrOptions === undefined || signerOrOptions instanceof ethers.Signer) return false |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
const isArtifact = (artifact: any) => { |
||||||
|
const { |
||||||
|
contractName, |
||||||
|
sourceName, |
||||||
|
abi, |
||||||
|
bytecode, |
||||||
|
deployedBytecode, |
||||||
|
linkReferences, |
||||||
|
deployedLinkReferences, |
||||||
|
} = artifact |
||||||
|
|
||||||
|
return ( |
||||||
|
typeof contractName === "string" && |
||||||
|
typeof sourceName === "string" && |
||||||
|
Array.isArray(abi) && |
||||||
|
typeof bytecode === "string" && |
||||||
|
typeof deployedBytecode === "string" && |
||||||
|
linkReferences !== undefined && |
||||||
|
deployedLinkReferences !== undefined |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
function linkBytecode(artifact: any, libraries: any) { |
||||||
|
let bytecode = artifact.bytecode |
||||||
|
|
||||||
|
for (const { sourceName, libraryName, address } of libraries) { |
||||||
|
const linkReferences = artifact.linkReferences[sourceName][libraryName] |
||||||
|
|
||||||
|
for (const { start, length } of linkReferences) { |
||||||
|
bytecode = |
||||||
|
bytecode.substr(0, 2 + start * 2) + |
||||||
|
address.substr(2) + |
||||||
|
bytecode.substr(2 + (start + length) * 2) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return bytecode |
||||||
|
} |
||||||
|
|
||||||
|
const collectLibrariesAndLink = async (artifact: any, libraries: any) => { |
||||||
|
const neededLibraries = [] |
||||||
|
for (const [sourceName, sourceLibraries] of Object.entries(artifact.linkReferences)) { |
||||||
|
// @ts-ignore
|
||||||
|
for (const libName of Object.keys(sourceLibraries)) { |
||||||
|
neededLibraries.push({ sourceName, libName }) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const linksToApply = new Map() |
||||||
|
for (const [linkedLibraryName, linkedLibraryAddress] of Object.entries(libraries)) { |
||||||
|
// @ts-ignore
|
||||||
|
if (!ethers.utils.isAddress(linkedLibraryAddress)) { |
||||||
|
throw new Error( |
||||||
|
`You tried to link the contract ${artifact.contractName} with the library ${linkedLibraryName}, but provided this invalid address: ${linkedLibraryAddress}` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const matchingNeededLibraries = neededLibraries.filter((lib) => { |
||||||
|
return ( |
||||||
|
lib.libName === linkedLibraryName || |
||||||
|
`${lib.sourceName}:${lib.libName}` === linkedLibraryName |
||||||
|
) |
||||||
|
}) |
||||||
|
|
||||||
|
if (matchingNeededLibraries.length === 0) { |
||||||
|
let detailedMessage |
||||||
|
if (neededLibraries.length > 0) { |
||||||
|
const libraryFQNames = neededLibraries |
||||||
|
.map((lib) => `${lib.sourceName}:${lib.libName}`) |
||||||
|
.map((x) => `* ${x}`) |
||||||
|
.join("\n") |
||||||
|
detailedMessage = `The libraries needed are:
|
||||||
|
${libraryFQNames}` |
||||||
|
} else { |
||||||
|
detailedMessage = "This contract doesn't need linking any libraries." |
||||||
|
} |
||||||
|
throw new Error( |
||||||
|
`You tried to link the contract ${artifact.contractName} with ${linkedLibraryName}, which is not one of its libraries.
|
||||||
|
${detailedMessage}` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
if (matchingNeededLibraries.length > 1) { |
||||||
|
const matchingNeededLibrariesFQNs = matchingNeededLibraries |
||||||
|
.map(({ sourceName, libName }) => `${sourceName}:${libName}`) |
||||||
|
.map((x) => `* ${x}`) |
||||||
|
.join("\n") |
||||||
|
throw new Error( |
||||||
|
`The library name ${linkedLibraryName} is ambiguous for the contract ${artifact.contractName}.
|
||||||
|
It may resolve to one of the following libraries: |
||||||
|
${matchingNeededLibrariesFQNs} |
||||||
|
To fix this, choose one of these fully qualified library names and replace where appropriate.` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const [neededLibrary] = matchingNeededLibraries |
||||||
|
|
||||||
|
const neededLibraryFQN = `${neededLibrary.sourceName}:${neededLibrary.libName}` |
||||||
|
|
||||||
|
// The only way for this library to be already mapped is
|
||||||
|
// for it to be given twice in the libraries user input:
|
||||||
|
// once as a library name and another as a fully qualified library name.
|
||||||
|
if (linksToApply.has(neededLibraryFQN)) { |
||||||
|
throw new Error( |
||||||
|
`The library names ${neededLibrary.libName} and ${neededLibraryFQN} refer to the same library and were given as two separate library links.
|
||||||
|
Remove one of them and review your library links before proceeding.` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
linksToApply.set(neededLibraryFQN, { |
||||||
|
sourceName: neededLibrary.sourceName, |
||||||
|
libraryName: neededLibrary.libName, |
||||||
|
address: linkedLibraryAddress, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
if (linksToApply.size < neededLibraries.length) { |
||||||
|
const missingLibraries = neededLibraries |
||||||
|
.map((lib) => `${lib.sourceName}:${lib.libName}`) |
||||||
|
.filter((libFQName) => !linksToApply.has(libFQName)) |
||||||
|
.map((x) => `* ${x}`) |
||||||
|
.join("\n") |
||||||
|
|
||||||
|
throw new Error( |
||||||
|
`The contract ${artifact.contractName} is missing links for the following libraries:
|
||||||
|
${missingLibraries}` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return linkBytecode(artifact, [...linksToApply.values()]) |
||||||
|
} |
||||||
|
|
||||||
|
// Convert output.contracts.<filename>.<contractName> in Artifact object compatible form
|
||||||
|
const resultToArtifact = (result: any) => { |
||||||
|
const { fullyQualifiedName, artefact } = result |
||||||
|
return { |
||||||
|
contractName: fullyQualifiedName.split(':')[1], |
||||||
|
sourceName: fullyQualifiedName.split(':')[0], |
||||||
|
abi: artefact.abi, |
||||||
|
bytecode: artefact.evm.bytecode.object, |
||||||
|
deployedBytecode: artefact.evm.deployedBytecode.object, |
||||||
|
linkReferences: artefact.evm.bytecode.linkReferences, |
||||||
|
deployedLinkReferences: artefact.evm.deployedBytecode.linkReferences |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const getContractFactory = async (contractNameOrABI: ethers.ContractInterface, bytecode?: string, signerOrOptions = null) => { |
||||||
|
//@ts-ignore
|
||||||
|
if (!global.ganacheProvider) initializeProvider() |
||||||
|
if (bytecode && contractNameOrABI) { |
||||||
|
//@ts-ignore
|
||||||
|
return new ethers.ContractFactory(contractNameOrABI, bytecode, signerOrOptions || (new ethers.providers.Web3Provider(ganacheProvider)).getSigner()) |
||||||
|
} else if (typeof contractNameOrABI === 'string') { |
||||||
|
const contract = await getArtifactsByContractName(contractNameOrABI) |
||||||
|
|
||||||
|
if (contract) { |
||||||
|
//@ts-ignore
|
||||||
|
return new ethers.ContractFactory(contract.abi, contract.evm.bytecode.object, signerOrOptions || (new ethers.providers.Web3Provider(ganacheProvider)).getSigner()) |
||||||
|
} else { |
||||||
|
throw new Error('Contract artifacts not found') |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new Error('Invalid contract name or ABI provided') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const getContractAt = async (contractNameOrABI: ethers.ContractInterface, address: string, signer = null) => { |
||||||
|
//@ts-ignore
|
||||||
|
if (!global.ganacheProvider) initializeProvider() |
||||||
|
//@ts-ignore
|
||||||
|
const provider = new ethers.providers.Web3Provider(ganacheProvider) |
||||||
|
|
||||||
|
if(typeof contractNameOrABI === 'string') { |
||||||
|
const result = await getArtifactsByContractName(contractNameOrABI) |
||||||
|
|
||||||
|
if (result) { |
||||||
|
return new ethers.Contract(address, result.abi, signer || provider.getSigner()) |
||||||
|
} else { |
||||||
|
throw new Error('Contract artifacts not found') |
||||||
|
} |
||||||
|
} else { |
||||||
|
return new ethers.Contract(address, contractNameOrABI, signer || provider.getSigner()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const getSigner = async (address: string) => { |
||||||
|
//@ts-ignore
|
||||||
|
if (!global.ganacheProvider) initializeProvider() |
||||||
|
//@ts-ignore
|
||||||
|
const provider = new ethers.providers.Web3Provider(ganacheProvider) |
||||||
|
const signer = provider.getSigner(address) |
||||||
|
|
||||||
|
return SignerWithAddress.create(signer) |
||||||
|
} |
||||||
|
|
||||||
|
const getSigners = async () => { |
||||||
|
//@ts-ignore
|
||||||
|
if (!global.ganacheProvider) initializeProvider() |
||||||
|
//@ts-ignore
|
||||||
|
const provider = new ethers.providers.Web3Provider(ganacheProvider) |
||||||
|
const accounts = await provider.listAccounts() |
||||||
|
|
||||||
|
return await Promise.all( accounts.map((account: any) => getSigner(account))) |
||||||
|
} |
||||||
|
|
||||||
|
const getContractFactoryFromArtifact = async (artifact: any, signerOrOptions: { signer: any, libraries: any }) => { |
||||||
|
//@ts-ignore
|
||||||
|
if (!global.ganacheProvider) initializeProvider() |
||||||
|
let libraries = {} |
||||||
|
let signer |
||||||
|
|
||||||
|
if (!isArtifact(artifact)) { |
||||||
|
throw new Error( |
||||||
|
`You are trying to create a contract factory from an artifact, but you have not passed a valid artifact parameter.` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
if (isFactoryOptions(signerOrOptions)) { |
||||||
|
signer = signerOrOptions.signer; |
||||||
|
libraries = signerOrOptions.libraries ?? {}; |
||||||
|
} else { |
||||||
|
signer = signerOrOptions; |
||||||
|
} |
||||||
|
|
||||||
|
if (artifact.bytecode === "0x") { |
||||||
|
throw new Error( |
||||||
|
`You are trying to create a contract factory for the contract ${artifact.contractName}, which is abstract and can't be deployed.
|
||||||
|
If you want to call a contract using ${artifact.contractName} as its interface use the "getContractAt" function instead.` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const linkedBytecode = await collectLibrariesAndLink(artifact, libraries) |
||||||
|
//@ts-ignore
|
||||||
|
return new ethers.ContractFactory(artifact.abi, linkedBytecode || artifact.bytecode, signer || (new ethers.providers.Web3Provider(ganacheProvider)).getSigner()) |
||||||
|
} |
||||||
|
|
||||||
|
const getContractAtFromArtifact = async (artifact: any, address: string, signerOrOptions = null) => { |
||||||
|
if (!isArtifact(artifact)) { |
||||||
|
throw new Error( |
||||||
|
`You are trying to create a contract factory from an artifact, but you have not passed a valid artifact parameter.` |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
return await getContractAt(artifact.abi, address, signerOrOptions) |
||||||
|
} |
||||||
|
|
||||||
|
export { getContractAtFromArtifact, getContractFactoryFromArtifact, getSigners, getSigner, getContractAt, getContractFactory } |
@ -0,0 +1,53 @@ |
|||||||
|
// @ts-ignore
|
||||||
|
import { ethers } from "ethers" |
||||||
|
|
||||||
|
export class SignerWithAddress extends ethers.Signer { |
||||||
|
address: string |
||||||
|
_signer: { |
||||||
|
provider: any |
||||||
|
signTransaction: (transaction: any) => any, |
||||||
|
signMessage: (message: string) => any, |
||||||
|
sendTransaction: (transaction: any) => any, |
||||||
|
connect: (provider: any) => any, |
||||||
|
_signTypedData: (...params: any) => any |
||||||
|
} |
||||||
|
provider: any |
||||||
|
static async create(signer: any) { |
||||||
|
return new SignerWithAddress(await signer.getAddress(), signer) |
||||||
|
} |
||||||
|
|
||||||
|
constructor(address: string, _signer: any) { |
||||||
|
super() |
||||||
|
this.address = address |
||||||
|
this._signer = _signer |
||||||
|
this.provider = _signer.provider |
||||||
|
} |
||||||
|
|
||||||
|
async getAddress() { |
||||||
|
return this.address |
||||||
|
} |
||||||
|
|
||||||
|
signMessage(message: string){ |
||||||
|
return this._signer.signMessage(message) |
||||||
|
} |
||||||
|
|
||||||
|
signTransaction(transaction: any) { |
||||||
|
return this._signer.signTransaction(transaction) |
||||||
|
} |
||||||
|
|
||||||
|
sendTransaction(transaction: any) { |
||||||
|
return this._signer.sendTransaction(transaction) |
||||||
|
} |
||||||
|
|
||||||
|
connect(provider: any) { |
||||||
|
return new SignerWithAddress(this.address, this._signer.connect(provider)) |
||||||
|
} |
||||||
|
|
||||||
|
_signTypedData(...params: any) { |
||||||
|
return this._signer._signTypedData(...params) |
||||||
|
} |
||||||
|
|
||||||
|
toJSON() { |
||||||
|
return `<SignerWithAddress ${this.address}>` |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"extends": "../../tsconfig.base.json", |
||||||
|
"compilerOptions": { |
||||||
|
"types": ["jest", "node"] |
||||||
|
}, |
||||||
|
"include": ["**/*.ts"] |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"extends": "./tsconfig.json", |
||||||
|
"compilerOptions": { |
||||||
|
"module": "commonjs", |
||||||
|
"outDir": "../../dist/out-tsc", |
||||||
|
"declaration": true, |
||||||
|
"rootDir": "./src", |
||||||
|
"types": ["node"] |
||||||
|
}, |
||||||
|
"exclude": [ |
||||||
|
"**/*.spec.ts" |
||||||
|
], |
||||||
|
"include": ["**/*.ts"] |
||||||
|
} |
||||||
|
|
@ -0,0 +1,322 @@ |
|||||||
|
import React from 'react' |
||||||
|
import { CustomTooltip } from '@remix-ui/helper' |
||||||
|
import { Dropdown } from 'react-bootstrap' |
||||||
|
import { FormattedMessage } from 'react-intl' |
||||||
|
|
||||||
|
const _paq = window._paq = window._paq || [] |
||||||
|
|
||||||
|
export interface HamburgerMenuProps { |
||||||
|
createWorkspace: () => void, |
||||||
|
deleteCurrentWorkspace: () => void, |
||||||
|
renameCurrentWorkspace: () => void, |
||||||
|
cloneGitRepository: () => void, |
||||||
|
downloadWorkspaces: () => void, |
||||||
|
restoreBackup: () => void, |
||||||
|
hideIconsMenu: (showMenu: boolean) => void, |
||||||
|
addGithubAction: () => void, |
||||||
|
addTsSolTestGithubAction: () => void, |
||||||
|
addSlitherGithubAction: () => void, |
||||||
|
showIconsMenu: boolean, |
||||||
|
hideWorkspaceOptions: boolean, |
||||||
|
hideLocalhostOptions: boolean |
||||||
|
} |
||||||
|
|
||||||
|
export function HamburgerMenu (props: HamburgerMenuProps) { |
||||||
|
const { showIconsMenu, hideWorkspaceOptions, hideLocalhostOptions } = props |
||||||
|
return ( |
||||||
|
<> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right" |
||||||
|
tooltipId="createWorkspaceTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.create' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='workspaceCreate' |
||||||
|
onClick={() => { |
||||||
|
props.createWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceCreate']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
key={`workspacesCreate-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={hideWorkspaceOptions} |
||||||
|
id='workspaceCreate' |
||||||
|
data-id='workspaceCreate' |
||||||
|
onClick={() => { |
||||||
|
props.createWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceCreate']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-plus pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.create' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createWorkspaceTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.delete' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='workspaceDelete' |
||||||
|
onClick={() => { |
||||||
|
props.deleteCurrentWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceDelete']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
key={`workspacesDelete-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions || hideLocalhostOptions } |
||||||
|
id='workspaceDelete' |
||||||
|
data-id='workspaceDelete' |
||||||
|
onClick={() => { |
||||||
|
props.deleteCurrentWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceDelete']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-trash pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.delete' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement='right-start' |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipId="workspaceRenametooltip" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.rename' />} |
||||||
|
> |
||||||
|
<div onClick={() => { |
||||||
|
props.renameCurrentWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceRename']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
data-id='workspaceRename' |
||||||
|
key={`workspacesRename-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions || hideLocalhostOptions } |
||||||
|
id='workspaceRename' |
||||||
|
data-id='workspaceRename' |
||||||
|
onClick={() => { |
||||||
|
props.renameCurrentWorkspace() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspaceRename']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-edit pl-2'> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.rename' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item><Dropdown.Divider className="border mb-0 mt-0" /></Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="cloneWorkspaceTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.clone' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='cloneGitRepository' |
||||||
|
onClick={() => { |
||||||
|
props.cloneGitRepository() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'cloneGitRepository']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
key={`cloneGitRepository-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions } |
||||||
|
id='cloneGitRepository' |
||||||
|
data-id='cloneGitRepository' |
||||||
|
onClick={() => { |
||||||
|
props.cloneGitRepository() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'cloneGitRepository']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='fab fa-github pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.clone' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item><Dropdown.Divider className="border mt-0 mb-0 remixui_menuhr" style={{ pointerEvents: 'none' }}/></Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createWorkspaceTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.download' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='workspacesDownload' |
||||||
|
onClick={() => { |
||||||
|
props.downloadWorkspaces() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspacesDownload']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
key={`workspacesDownload-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions || hideLocalhostOptions } |
||||||
|
id='workspacesDownload' |
||||||
|
data-id='workspacesDownload' |
||||||
|
onClick={() => { |
||||||
|
props.downloadWorkspaces() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspacesDownload']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-download pl-2 ' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.download' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createWorkspaceTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.restore' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='workspacesRestore' |
||||||
|
onClick={() => { |
||||||
|
props.restoreBackup() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspacesRestore']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
key={`workspacesRestore-fe-ws`} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions } |
||||||
|
id='workspacesRestore' |
||||||
|
data-id='workspacesRestore' |
||||||
|
onClick={() => { |
||||||
|
props.restoreBackup() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'workspacesRestore']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-upload pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3"><FormattedMessage id='filePanel.restore' /></span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item><Dropdown.Divider className="border mt-0 mb-0 remixui_menuhr" style={{ pointerEvents: 'none' }}/></Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createSolGHActionTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.solghaction' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='soliditygithubaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addSolidityTesting']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions } |
||||||
|
id='soliditygithubaction' |
||||||
|
data-id='soliditygithubaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addSolidityTesting']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='fak fa-solidity-mono pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3">{<FormattedMessage id='filePanel.solghaction' />}</span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createTsSolTestGHActionTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.tssoltestghaction' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='typescriptsoliditygithubtestaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addTsSolTestGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addTsSolTestingAction']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions } |
||||||
|
id='tssoliditygithubaction' |
||||||
|
data-id='tssoliditygithubaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addTsSolTestGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addTsSolTestingAction']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='fab fa-js pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3">{<FormattedMessage id='filePanel.tssoltestghaction' />}</span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
<Dropdown.Item> |
||||||
|
<CustomTooltip |
||||||
|
placement="right-start" |
||||||
|
tooltipId="createSlitherGHActionTooltip" |
||||||
|
tooltipClasses="text-nowrap" |
||||||
|
tooltipText={<FormattedMessage id='filePanel.workspace.slitherghaction' />} |
||||||
|
> |
||||||
|
<div |
||||||
|
data-id='slithergithubtestaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addSlitherGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addSlitherAction']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
> |
||||||
|
<span |
||||||
|
hidden={ hideWorkspaceOptions } |
||||||
|
id='slithergithubaction' |
||||||
|
data-id='slithergithubaction' |
||||||
|
onClick={(e) => { |
||||||
|
e.stopPropagation() |
||||||
|
props.addSlitherGithubAction() |
||||||
|
_paq.push(['trackEvent', 'fileExplorer', 'workspaceMenu', 'addSlitherAction']) |
||||||
|
props.hideIconsMenu(!showIconsMenu) |
||||||
|
}} |
||||||
|
className='far fa-shield pl-2' |
||||||
|
> |
||||||
|
</span> |
||||||
|
<span className="pl-3">{<FormattedMessage id='filePanel.slitherghaction' />}</span> |
||||||
|
</div> |
||||||
|
</CustomTooltip> |
||||||
|
</Dropdown.Item> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
@ -1 +1,53 @@ |
|||||||
export const ROOT_PATH = '/' |
export const ROOT_PATH = '/' |
||||||
|
export const solTestYml = ` |
||||||
|
name: Running Solidity Unit Tests |
||||||
|
on: [push] |
||||||
|
|
||||||
|
jobs: |
||||||
|
run_sol_contracts_job: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
name: A job to run solidity unit tests on github actions CI |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@v2 |
||||||
|
- name: Run SUT Action |
||||||
|
uses: EthereumRemix/sol-test@v1 |
||||||
|
with: |
||||||
|
test-path: 'tests' |
||||||
|
compiler-version: '0.8.15' |
||||||
|
` |
||||||
|
export const tsSolTestYml = ` |
||||||
|
name: Running Mocha Chai Solidity Unit Tests |
||||||
|
on: [push] |
||||||
|
|
||||||
|
jobs: |
||||||
|
run_sample_test_job: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
name: A job to run mocha and chai tests for solidity on github actions CI |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@v2 |
||||||
|
- name: Run Mocha Chai Unit Test Action |
||||||
|
uses: EthereumRemix/ts-sol-test@v1.2 |
||||||
|
with: |
||||||
|
test-path: 'tests' |
||||||
|
contract-path: 'contracts' |
||||||
|
compiler-version: '0.8.7' |
||||||
|
` |
||||||
|
export const slitherYml = ` |
||||||
|
name: Slither Analysis |
||||||
|
on: [push] |
||||||
|
|
||||||
|
jobs: |
||||||
|
analyze: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v3 |
||||||
|
- run: npm install |
||||||
|
- uses: crytic/slither-action@v0.2.0 |
||||||
|
with: |
||||||
|
target: 'contracts' |
||||||
|
slither-args: '--solc-remaps "@openzeppelin/contracts=./node_modules/@openzeppelin/contracts hardhat=./node_modules/hardhat"' |
||||||
|
fail-on: 'low' |
||||||
|
solc-version: '0.8.2' |
||||||
|
` |
||||||
|
Loading…
Reference in new issue