commit
9f19ba5457
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 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