Merge branch 'master' into explorer-layout-shift

pull/3671/head
Liana Husikyan 1 year ago committed by GitHub
commit 273d8f3f5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .env
  2. 6
      apps/etherscan/src/app/RemixPlugin.tsx
  3. 97
      apps/etherscan/src/app/app.tsx
  4. 157
      apps/etherscan/src/app/components/HeaderWithSettings.tsx
  5. 49
      apps/etherscan/src/app/components/SubmitButton.tsx
  6. 2
      apps/etherscan/src/app/routes.tsx
  7. 5
      apps/etherscan/src/app/types/Receipt.ts
  8. 36
      apps/etherscan/src/app/utils/networks.ts
  9. 16
      apps/etherscan/src/app/utils/scripts.ts
  10. 34
      apps/etherscan/src/app/utils/utilities.ts
  11. 53
      apps/etherscan/src/app/utils/verify.ts
  12. 2
      apps/etherscan/src/app/views/CaptureKeyView.tsx
  13. 100
      apps/etherscan/src/app/views/ReceiptsView.tsx
  14. 170
      apps/etherscan/src/app/views/VerifyView.tsx
  15. 3
      apps/etherscan/src/index.html
  16. 4
      apps/etherscan/src/profile.json
  17. 220
      apps/remix-ide-e2e/src/tests/contract_flattener.test.ts
  18. 3
      apps/remix-ide-e2e/src/tests/erc721.test.ts
  19. 2
      apps/remix-ide-e2e/src/tests/plugin_api.ts
  20. 2
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  21. 218
      apps/remix-ide-e2e/src/tests/sol2uml.test.ts
  22. 5
      apps/remix-ide-e2e/src/tests/solidityImport.test.ts
  23. 3
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  24. 11
      apps/remix-ide-e2e/src/tests/staticAnalysis.test.ts
  25. 7
      apps/remix-ide-e2e/src/tests/transactionExecution.test.ts
  26. 30
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  27. 6
      apps/remix-ide-e2e/src/tests/workspace_git.test.ts
  28. 2
      apps/remix-ide/project.json
  29. 9
      apps/remix-ide/src/app/panels/file-panel.js
  30. 2
      apps/remix-ide/src/app/tabs/compile-and-run.ts
  31. 3
      apps/remix-ide/src/app/tabs/compile-tab.js
  32. 6
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  33. 6
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  34. 11
      apps/remix-ide/src/app/tabs/locales/es/debugger.json
  35. 70
      apps/remix-ide/src/app/tabs/locales/es/filePanel.json
  36. 61
      apps/remix-ide/src/app/tabs/locales/es/home.json
  37. 6
      apps/remix-ide/src/app/tabs/locales/es/panel.json
  38. 13
      apps/remix-ide/src/app/tabs/locales/es/permissionHandler.json
  39. 31
      apps/remix-ide/src/app/tabs/locales/es/pluginManager.json
  40. 14
      apps/remix-ide/src/app/tabs/locales/es/search.json
  41. 26
      apps/remix-ide/src/app/tabs/locales/es/settings.json
  42. 4
      apps/remix-ide/src/app/tabs/locales/es/solUmlgen.json
  43. 41
      apps/remix-ide/src/app/tabs/locales/es/solidity.json
  44. 35
      apps/remix-ide/src/app/tabs/locales/es/solidityUnitTesting.json
  45. 17
      apps/remix-ide/src/app/tabs/locales/es/terminal.json
  46. 64
      apps/remix-ide/src/app/tabs/locales/es/udapp.json
  47. 11
      apps/remix-ide/src/app/tabs/locales/fr/debugger.json
  48. 70
      apps/remix-ide/src/app/tabs/locales/fr/filePanel.json
  49. 61
      apps/remix-ide/src/app/tabs/locales/fr/home.json
  50. 6
      apps/remix-ide/src/app/tabs/locales/fr/panel.json
  51. 13
      apps/remix-ide/src/app/tabs/locales/fr/permissionHandler.json
  52. 31
      apps/remix-ide/src/app/tabs/locales/fr/pluginManager.json
  53. 14
      apps/remix-ide/src/app/tabs/locales/fr/search.json
  54. 26
      apps/remix-ide/src/app/tabs/locales/fr/settings.json
  55. 4
      apps/remix-ide/src/app/tabs/locales/fr/solUmlgen.json
  56. 41
      apps/remix-ide/src/app/tabs/locales/fr/solidity.json
  57. 35
      apps/remix-ide/src/app/tabs/locales/fr/solidityUnitTesting.json
  58. 17
      apps/remix-ide/src/app/tabs/locales/fr/terminal.json
  59. 64
      apps/remix-ide/src/app/tabs/locales/fr/udapp.json
  60. 14
      apps/remix-ide/src/app/tabs/locales/zh/filePanel.json
  61. 12
      apps/remix-ide/src/app/tabs/locales/zh/home.json
  62. 2
      apps/remix-ide/src/app/tabs/locales/zh/settings.json
  63. 4
      apps/remix-ide/src/app/tabs/locales/zh/solUmlgen.json
  64. 8
      apps/remix-ide/src/app/tabs/locales/zh/solidity.json
  65. 3
      apps/remix-ide/src/app/tabs/locales/zh/udapp.json
  66. 2
      apps/remix-ide/src/app/udapp/run-tab.js
  67. 17
      apps/remix-ide/src/assets/js/loader.js
  68. 9
      apps/remix-ide/src/blockchain/blockchain.tsx
  69. 32
      apps/remix-ide/src/remixAppManager.js
  70. 16
      apps/solhint/package.json
  71. 70
      apps/solhint/project.json
  72. 8
      apps/solhint/src/app/App.tsx
  73. 145
      apps/solhint/src/app/SolhintPluginClient.ts
  74. BIN
      apps/solhint/src/favicon.ico
  75. 13
      apps/solhint/src/index.html
  76. 10
      apps/solhint/src/main.tsx
  77. 20
      apps/solhint/src/profile.json
  78. 23
      apps/solhint/tsconfig.app.json
  79. 16
      apps/solhint/tsconfig.json
  80. 60
      apps/solhint/webpack.config.js
  81. 517
      apps/solhint/yarn.lock
  82. 59
      apps/walletconnect/project.json
  83. 35
      apps/walletconnect/src/app/app.tsx
  84. 17
      apps/walletconnect/src/app/walletConnectUI.tsx
  85. 38
      apps/walletconnect/src/css/app.css
  86. 13
      apps/walletconnect/src/css/index.css
  87. 14
      apps/walletconnect/src/index.html
  88. 1
      apps/walletconnect/src/logo.svg
  89. 8
      apps/walletconnect/src/main.tsx
  90. 7
      apps/walletconnect/src/polyfills.ts
  91. 16
      apps/walletconnect/src/profile.json
  92. 107
      apps/walletconnect/src/services/RemixClient.ts
  93. 2
      apps/walletconnect/src/services/constant.ts
  94. 53
      apps/walletconnect/src/services/provider.ts
  95. 24
      apps/walletconnect/tsconfig.app.json
  96. 17
      apps/walletconnect/tsconfig.json
  97. 90
      apps/walletconnect/webpack.config.js
  98. 3
      crowdin.yml
  99. 8
      libs/ghaction-helper/package.json
  100. 8
      libs/remix-analyzer/package.json
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,4 +1,5 @@
gist_token=<token>
account_passphrase=<passphrase>
account_password=<password>
NODE_OPTIONS=--max-old-space-size=2048
NODE_OPTIONS=--max-old-space-size=2048
# WALLET_CONNECT_PROJECT_ID=<walletconnect cloud PROJECT_ID>

@ -9,18 +9,18 @@ export class RemixClient extends PluginClient {
}
async verify (apiKey: string, contractAddress: string, contractArguments: string, contractName: string, compilationResultParam: any) {
const result = await verify(apiKey, contractAddress, contractArguments, contractName, compilationResultParam, this,
const result = await verify(apiKey, contractAddress, contractArguments, contractName, compilationResultParam, null, false, null, this,
(value: EtherScanReturn) => {}, (value: string) => {})
return result
}
async receiptStatus (receiptGuid: string, apiKey: string) {
try {
const network = await getNetworkName(this)
const { network, networkId } = await getNetworkName(this)
if (network === "vm") {
throw new Error("Cannot check the receipt status in the selected network")
}
const etherscanApi = getEtherScanApi(network)
const etherscanApi = getEtherScanApi(networkId)
const receiptStatus = await getReceiptStatus(receiptGuid, apiKey, etherscanApi)
return {
message: receiptStatus.result,

@ -13,7 +13,7 @@ import { DisplayRoutes } from "./routes"
import { useLocalStorage } from "./hooks/useLocalStorage"
import { getReceiptStatus, getEtherScanApi, getNetworkName } from "./utils"
import { getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus } from "./utils"
import { Receipt, ThemeType } from "./types"
import "./App.css"
@ -36,6 +36,7 @@ const App = () => {
const [receipts, setReceipts] = useLocalStorage("receipts", [])
const [contracts, setContracts] = useState([] as string[])
const [themeType, setThemeType] = useState("dark" as ThemeType)
const timer = useRef(null)
const clientInstanceRef = useRef(clientInstance)
clientInstanceRef.current = clientInstance
@ -80,56 +81,70 @@ const App = () => {
}, [])
useEffect(() => {
if (!clientInstance) {
return
}
const receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => {
return item.status !== "Verified"
let receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => {
return item.status === "Pending in queue" || item.status === "Max rate limit reached"
})
if (receiptsNotVerified.length > 0) {
const timer1 = setInterval(() => {
for (const item in receiptsNotVerified) {
if (timer.current) {
clearInterval(timer.current)
timer.current = null
}
timer.current = setInterval(async () => {
const { network, networkId } = await getNetworkName(clientInstanceRef.current)
if (!clientInstanceRef.current) {
return
}
if (network === "vm") {
return
}
receiptsNotVerified.forEach(async (item) => {
if (!clientInstanceRef.current) {
return {}
}
const network = await getNetworkName(clientInstanceRef.current)
if (network === "vm") {
return {}
}
const status = await getReceiptStatus(
item.guid,
apiKey,
getEtherScanApi(network)
)
if (status.result === "Pass - Verified") {
const newReceipts = receipts.map((currentReceipt: Receipt) => {
let newReceipts = receipts
for (const item of receiptsNotVerified) {
await new Promise(r => setTimeout(r, 500)) // avoid api rate limit exceed.
let status
if (item.isProxyContract) {
status = await getProxyContractReceiptStatus(
item.guid,
apiKey,
getEtherScanApi(networkId)
)
if (status.status === '1') {
status.message = status.result
status.result = 'Successfully Updated'
}
} else
status = await getReceiptStatus(
item.guid,
apiKey,
getEtherScanApi(networkId)
)
if (status.result === "Pass - Verified" || status.result === "Already Verified" ||
status.result === "Successfully Updated") {
newReceipts = newReceipts.map((currentReceipt: Receipt) => {
if (currentReceipt.guid === item.guid) {
return {
let res = {
...currentReceipt,
status: "Verified",
status: status.result,
}
if (currentReceipt.isProxyContract) res.message = status.message
return res
}
return currentReceipt
})
clearInterval(timer1)
setReceipts(newReceipts)
return () => {
clearInterval(timer1)
}
}
return {}
})
}
}
receiptsNotVerified = newReceipts.filter((item: Receipt) => {
return item.status === "Pending in queue" || item.status === "Max rate limit reached"
})
}, 5000)
if (timer.current && receiptsNotVerified.length === 0) {
clearInterval(timer.current)
timer.current = null
}
setReceipts(newReceipts)
}, 10000)
}
}, [receipts, clientInstance, apiKey, setReceipts])
}, [receipts])
return (
<AppContext.Provider
@ -150,4 +165,4 @@ const App = () => {
)
}
export default App
export default App

@ -1,8 +1,8 @@
import React from "react"
import { NavLink } from "react-router-dom"
import { CustomTooltip } from '@remix-ui/helper'
import { AppContext } from "../AppContext"
import { ThemeType } from "../types"
interface Props {
title?: string
@ -12,130 +12,69 @@ interface Props {
interface IconProps {
from: string
themeType: ThemeType
}
const HomeIcon: React.FC<IconProps> = ({ from, themeType }: IconProps) => {
const HomeIcon: React.FC<IconProps> = ({ from }: IconProps) => {
return (
<NavLink
data-id="home"
data-toggle="tooltip"
data-placement="top"
title="Home"
to={{
pathname: "/"
}}
state={ from }
style={isActive => {
return {
...(isActive ? getStyleFilterIcon(themeType) : {}), ...{ marginRight: "0.4em" }
}
}}
>
<svg
style={{ filter: "invert(0.5)" }}
width="1em"
height="1em"
viewBox="0 0 16 16"
className="bi bi-house-door-fill"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
<NavLink
data-id="home"
to={{
pathname: "/"
}}
state={ from }
>
<path d="M6.5 10.995V14.5a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5h-4a.5.5 0 0 1-.5-.5V11c0-.25-.25-.5-.5-.5H7c-.25 0-.5.25-.5.495z" />
<path
fillRule="evenodd"
d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"
/>
</svg>
</NavLink>
<CustomTooltip
tooltipText='Home'
tooltipId='etherscan-nav-home'
placement='bottom'
>
<i className="fas fa-home"></i>
</CustomTooltip>
</NavLink>
)
}
const SettingsIcon: React.FC<IconProps> = ({ from, themeType }: IconProps) => {
const ReceiptsIcon: React.FC<IconProps> = ({ from }: IconProps) => {
return (
<NavLink
data-toggle="tooltip"
data-placement="top"
title="Settings"
to={{
pathname: "/settings",
}}
state= {from}
style={isActive => {
return {
...(isActive ? getStyleFilterIcon(themeType) : {}), ...{ marginRight: "0.4em" }
}
}}
>
<svg
style={{ filter: "invert(0.5)" }}
width="1em"
height="1em"
viewBox="0 0 16 16"
className="bi bi-gear-fill"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
<NavLink
data-id="receipts"
to={{
pathname: "/receipts"
}}
state={ from }
className="mx-2"
>
<path
fillRule="evenodd"
d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 0 0-5.86 2.929 2.929 0 0 0 0 5.858z"
/>
<path
fillRule="evenodd"
d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 0 0-5.86 2.929 2.929 0 0 0 0 5.858z"
/>
</svg>
</NavLink>
<CustomTooltip
tooltipText='Receipts'
tooltipId='etherscan-nav-receipts'
placement='bottom'
>
<i className="fas fa-receipt"></i>
</CustomTooltip>
</NavLink>
)
}
const getStyleFilterIcon = (themeType: ThemeType) => {
const invert = themeType === "dark" ? 1 : 0
const brightness = themeType === "dark" ? "150" : "0" // should be >100 for icons with color
return {
filter: `invert(${invert}) grayscale(1) brightness(${brightness}%)`,
}
}
const ReceiptsIcon: React.FC<IconProps> = ({ from, themeType }: IconProps) => {
const SettingsIcon: React.FC<IconProps> = ({ from }: IconProps) => {
return (
<NavLink
data-toggle="tooltip"
data-placement="top"
title="Receipts"
<NavLink
data-id="settings"
to={{
pathname: "/receipts",
}}
state= { from }
style={isActive => {
return {
...(isActive ? getStyleFilterIcon(themeType) : {}), ...{ marginRight: "0.4em" }
}
pathname: "/settings"
}}
state= {from}
>
<svg
style={{ filter: "invert(0.5)" }}
width="1em"
height="1em"
viewBox="0 0 16 16"
className="bi bi-receipt"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
<CustomTooltip
tooltipText='Settings'
tooltipId='etherscan-nav-settings'
placement='bottom'
>
<path
fillRule="evenodd"
d="M1.92.506a.5.5 0 0 1 .434.14L3 1.293l.646-.647a.5.5 0 0 1 .708 0L5 1.293l.646-.647a.5.5 0 0 1 .708 0L7 1.293l.646-.647a.5.5 0 0 1 .708 0L9 1.293l.646-.647a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .708 0l.646.647.646-.647a.5.5 0 0 1 .801.13l.5 1A.5.5 0 0 1 15 2v12a.5.5 0 0 1-.053.224l-.5 1a.5.5 0 0 1-.8.13L13 14.707l-.646.647a.5.5 0 0 1-.708 0L11 14.707l-.646.647a.5.5 0 0 1-.708 0L9 14.707l-.646.647a.5.5 0 0 1-.708 0L7 14.707l-.646.647a.5.5 0 0 1-.708 0L5 14.707l-.646.647a.5.5 0 0 1-.708 0L3 14.707l-.646.647a.5.5 0 0 1-.801-.13l-.5-1A.5.5 0 0 1 1 14V2a.5.5 0 0 1 .053-.224l.5-1a.5.5 0 0 1 .367-.27zm.217 1.338L2 2.118v11.764l.137.274.51-.51a.5.5 0 0 1 .707 0l.646.647.646-.646a.5.5 0 0 1 .708 0l.646.646.646-.646a.5.5 0 0 1 .708 0l.646.646.646-.646a.5.5 0 0 1 .708 0l.646.646.646-.646a.5.5 0 0 1 .708 0l.646.646.646-.646a.5.5 0 0 1 .708 0l.509.509.137-.274V2.118l-.137-.274-.51.51a.5.5 0 0 1-.707 0L12 1.707l-.646.647a.5.5 0 0 1-.708 0L10 1.707l-.646.647a.5.5 0 0 1-.708 0L8 1.707l-.646.647a.5.5 0 0 1-.708 0L6 1.707l-.646.647a.5.5 0 0 1-.708 0L4 1.707l-.646.647a.5.5 0 0 1-.708 0l-.509-.51z"
/>
<path
fillRule="evenodd"
d="M3 4.5a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 1 1 0 1h-6a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm8-6a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 0 1h-1a.5.5 0 0 1-.5-.5z"
/>
</svg>
<i className="fas fa-cog"></i>
</CustomTooltip>
</NavLink>
)
}
export const HeaderWithSettings: React.FC<Props> = ({
title = "",
showBackButton = false,
@ -143,13 +82,13 @@ export const HeaderWithSettings: React.FC<Props> = ({
}) => {
return (
<AppContext.Consumer>
{({ themeType }) => (
{() => (
<div>
<h6 className="d-inline">{title}</h6>
<div style={{ float: "right" }}>
<HomeIcon from={from} themeType={themeType} />
<ReceiptsIcon from={from} themeType={themeType} />
<SettingsIcon from={from} themeType={themeType} />
<HomeIcon from={from} />
<ReceiptsIcon from={from} />
<SettingsIcon from={from} />
</div>
</div>
)}

@ -1,4 +1,5 @@
import React from "react"
import { CustomTooltip } from '@remix-ui/helper'
interface Props {
text: string
@ -14,27 +15,33 @@ export const SubmitButton: React.FC<Props> = ({
disable = true
}) => {
return (
<button
data-id={dataId}
style={{ padding: "0.25rem 0.4rem", marginRight: "0.5em" }}
type="submit"
className="btn btn-primary"
disabled={disable}
title={disable ? "Fill all the fields with valid values" : "Click to proceed"}
<CustomTooltip
tooltipText={disable ? "Fill the fields with valid values" : "Click to proceed"}
tooltipId='etherscan-submit-button'
placement='bottom'
>
{!isSubmitting && text}
{isSubmitting && (
<div>
<span
className="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
style={{ marginRight: "0.3em" }}
/>
Verifying... Please wait
</div>
)}
</button>
<div>
<button
data-id={dataId}
style={{ padding: "0.25rem 0.4rem", marginRight: "0.5em" }}
type="submit"
className="btn btn-primary btn-block text-decoration-none"
disabled={disable}
>
{!isSubmitting && text}
{isSubmitting && (
<div>
<span
className="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
style={{ marginRight: "0.3em" }}
/>
Verifying... Please wait
</div>
)}
</button>
</div>
</CustomTooltip>
)
}

@ -43,7 +43,7 @@ export const DisplayRoutes = () => (
</DefaultLayout>} />
<Route
path="/settings"
element={<DefaultLayout from="/settings" title="Set Etherscan API Key">
element={<DefaultLayout from="/settings" title="Set Explorer API Key">
<CaptureKeyView />
</DefaultLayout>} />
</Routes>

@ -1,6 +1,9 @@
export type ReceiptStatus = "Verified" | "Queue"
export type ReceiptStatus = "Pending in queue" | "Pass - Verified" | "Already Verified" | "Max rate limit reached" | "Successfully Updated"
export interface Receipt {
guid: string
status: ReceiptStatus
isProxyContract: boolean
message?: string
succeed?: boolean
}

@ -0,0 +1,36 @@
export const scanAPIurls = {
// all mainnet
1: "https://api.etherscan.io/api",
56: "https://api.bscscan.com/api",
137: "https://api.polygonscan.com/api",
250: "https://api.ftmscan.com/api",
42161: "https://api.arbiscan.io/api",
43114: "https://api.snowtrace.io/api",
1285: "https://api-moonriver.moonscan.io/api",
1284: "https://api-moonbeam.moonscan.io/api",
25: "https://api.cronoscan.com/api",
199: "https://api.bttcscan.com/api",
10: "https://api-optimistic.etherscan.io/api",
42220: "https://api.celoscan.io/api",
288: "https://api.bobascan.com/api",
100: "https://api.gnosisscan.io/api",
1101: "https://api-zkevm.polygonscan.com/api",
// all testnet
5: "https://api-goerli.etherscan.io/api",
11155111: "https://api-sepolia.etherscan.io/api",
97: "https://api-testnet.bscscan.com/api",
80001: "https://api-testnet.polygonscan.com/api",
4002: "https://api-testnet.ftmscan.com/api",
421611: "https://api-testnet.arbiscan.io/api",
42170: "https://api-nova.arbiscan.io/api",
43113: "https://api-testnet.snowtrace.io/api",
1287: "https://api-moonbase.moonscan.io/api",
338: "https://api-testnet.cronoscan.com/api",
1028: "https://api-testnet.bttcscan.com/api",
420: "https://api-goerli-optimistic.etherscan.io/api",
44787: "https://api-alfajores.celoscan.io/api",
2888: "https://api-testnet.bobascan.com/api",
84531: "https://api-goerli.basescan.org/api",
1442: "https://api-testnet-zkevm.polygonscan.com/api"
}

@ -1,22 +1,24 @@
export const verifyScript = `
/**
* @param {string} apikey - etherscan api key.
* @param {string} contractAddress - Address of the contract to verify.
* @param {string} contractArguments - Parameters used in the contract constructor during the initial deployment. It should be the hex encoded value.
* @param {string} apikey - etherscan api key
* @param {string} contractAddress - Address of the contract to verify
* @param {string} contractArguments - Parameters used in the contract constructor during the initial deployment. It should be the hex encoded value
* @param {string} contractName - Name of the contract
* @param {string} contractFile - File where the contract is located
* @param {number | string} chainRef - Network chain id or API URL
* @returns {{ guid, status, message, succeed }} verification result
*/
export const verify = async (apikey: string, contractAddress: string, contractArguments: string, contractName: string, contractFile: string) => {
export const verify = async (apikey: string, contractAddress: string, contractArguments: string, contractName: string, contractFile: string, chainRef: number | string) => {
const compilationResultParam = await remix.call('compilerArtefacts' as any, 'getCompilerAbstract', contractFile)
console.log('verifying.. ' + contractName)
return await remix.call('etherscan' as any, 'verify', apikey, contractAddress, contractArguments, contractName, compilationResultParam)
// update apiKey and chainRef to verify contract on multiple networks
return await remix.call('etherscan' as any, 'verify', apikey, contractAddress, contractArguments, contractName, compilationResultParam, chainRef)
}`
export const receiptGuidScript = `
/**
* @param {string} apikey - etherscan api key.
* @param {string} guid - receipt id.
* @param {string} apikey - etherscan api key
* @param {string} guid - receipt id
* @returns {{ status, message, succeed }} receiptStatus
*/
export const receiptStatus = async (apikey: string, guid: string) => {

@ -1,5 +1,6 @@
import { PluginClient } from "@remixproject/plugin"
import axios from 'axios'
import { scanAPIurls } from "./networks"
type RemixClient = PluginClient
/*
@ -13,18 +14,20 @@ export type receiptStatus = {
status: string
}
export const getEtherScanApi = (network: string) => {
return network === "main"
? `https://api.etherscan.io/api`
: `https://api-${network}.etherscan.io/api`
export const getEtherScanApi = (networkId: any) => {
if (!(networkId in scanAPIurls)) {
throw new Error("no known network to verify against")
}
const apiUrl = (scanAPIurls as any)[networkId]
return apiUrl
}
export const getNetworkName = async (client: RemixClient) => {
const network = await client.call("network", "detectNetwork")
if (!network) {
throw new Error("no known network to verify against")
}
return network.name!.toLowerCase()
}
return { network: network.name!.toLowerCase(), networkId: network.id }
}
export const getReceiptStatus = async (
@ -45,3 +48,22 @@ export const getReceiptStatus = async (
console.error(error)
}
}
export const getProxyContractReceiptStatus = async (
receiptGuid: string,
apiKey: string,
etherscanApi: string
): Promise<receiptStatus> => {
const params = `guid=${receiptGuid}&module=contract&action=checkproxyverification&apiKey=${apiKey}`
try {
const response = await axios.get(`${etherscanApi}?${params}`)
const { result, message, status } = response.data
return {
result,
message,
status,
}
} catch (error) {
console.error(error)
}
}

@ -1,4 +1,4 @@
import { getNetworkName, getEtherScanApi, getReceiptStatus } from "../utils"
import { getNetworkName, getEtherScanApi, getReceiptStatus, getProxyContractReceiptStatus } from "../utils"
import { CompilationResult } from "@remixproject/plugin-api"
import { CompilerAbstract } from '@remix-project/remix-solidity'
import axios from 'axios'
@ -20,19 +20,34 @@ export const verify = async (
contractAddress: string,
contractArgumentsParam: string,
contractName: string,
compilationResultParam: CompilerAbstract,
compilationResultParam: CompilerAbstract,
chainRef: number | string,
isProxyContract: boolean,
expectedImplAddress: string,
client: PluginClient,
onVerifiedContract: (value: EtherScanReturn) => void,
setResults: (value: string) => void
) => {
const network = await getNetworkName(client)
if (network === "vm") {
let networkChainId
let etherscanApi
if (chainRef) {
if (typeof chainRef === 'number') {
networkChainId = chainRef
etherscanApi = getEtherScanApi(networkChainId)
} else if (typeof chainRef === 'string') etherscanApi = chainRef
} else {
const { network, networkId } = await getNetworkName(client)
if (network === "vm") {
return {
succeed: false,
message: "Cannot verify in the selected network"
}
} else {
networkChainId = networkId
etherscanApi = getEtherScanApi(networkChainId)
}
}
const etherscanApi = getEtherScanApi(network)
try {
const contractMetadata = getContractMetadata(
@ -72,13 +87,20 @@ export const verify = async (
module: "contract", // Do not change
action: "verifysourcecode", // Do not change
codeformat: "solidity-standard-json-input",
contractaddress: contractAddress, // Contract Address starts with 0x...
sourceCode: JSON.stringify(jsonInput),
contractname: fileName + ':' + contractName,
compilerversion: `v${contractMetadataParsed.compiler.version}`, // see http://etherscan.io/solcversions for list of support versions
constructorArguements: contractArgumentsParam ? contractArgumentsParam.replace('0x', '') : '', // if applicable
}
if (isProxyContract) {
data.action = "verifyproxycontract"
data.expectedimplementation = expectedImplAddress
data.address = contractAddress
} else {
data.contractaddress = contractAddress
}
const body = new FormData()
Object.keys(data).forEach((key) => body.append(key, data[key]))
@ -92,7 +114,18 @@ export const verify = async (
if (message === "OK" && status === "1") {
resetAfter10Seconds(client, setResults)
const receiptStatus = await getReceiptStatus(
let receiptStatus
if (isProxyContract) {
receiptStatus = await getProxyContractReceiptStatus(
result,
apiKeyParam,
etherscanApi
)
if (receiptStatus.status === '1') {
receiptStatus.message = receiptStatus.result
receiptStatus.result = 'Successfully Updated'
}
} else receiptStatus = await getReceiptStatus(
result,
apiKeyParam,
etherscanApi
@ -102,7 +135,8 @@ export const verify = async (
guid: result,
status: receiptStatus.result,
message: `Verification process started correctly. Receipt GUID ${result}`,
succeed: true
succeed: true,
isProxyContract
}
onVerifiedContract(returnValue)
return returnValue
@ -114,7 +148,8 @@ export const verify = async (
})
const returnValue = {
message: result,
succeed: false
succeed: false,
isProxyContract
}
resetAfter10Seconds(client, setResults)
return returnValue

@ -27,7 +27,7 @@ export const CaptureKeyView: React.FC = () => {
if (apiKey.length === 34) {
setAPIKey(values.apiKey)
clientInstance.call('notification' as any, 'toast', 'API key saved successfully!!!')
navigate((location.state as any).from)
navigate((location && location.state ? location.state : '/'))
} else clientInstance.call('notification' as any, 'toast', 'API key should be 34 characters long')
}}
>

@ -1,44 +1,69 @@
import React, { useState } from "react"
import { Formik, ErrorMessage, Field } from "formik"
import { getEtherScanApi, getNetworkName, getReceiptStatus } from "../utils"
import { getEtherScanApi, getNetworkName, getReceiptStatus, getProxyContractReceiptStatus } from "../utils"
import { Receipt } from "../types"
import { AppContext } from "../AppContext"
import { SubmitButton } from "../components"
import { Navigate } from "react-router-dom"
import { Button } from "react-bootstrap"
import { CustomTooltip } from '@remix-ui/helper'
interface FormValues {
receiptGuid: string
}
export const ReceiptsView: React.FC = () => {
const [results, setResults] = useState("")
const [results, setResults] = useState({succeed: false, message: ''})
const [isProxyContractReceipt, setIsProxyContractReceipt] = useState(false)
const onGetReceiptStatus = async (
values: FormValues,
clientInstance: any,
apiKey: string
) => {
try {
const network = await getNetworkName(clientInstance)
const { network, networkId } = await getNetworkName(clientInstance)
if (network === "vm") {
setResults("Cannot verify in the selected network")
setResults({
succeed: false,
message: "Cannot verify in the selected network"
})
return
}
const etherscanApi = getEtherScanApi(network)
const result = await getReceiptStatus(
values.receiptGuid,
apiKey,
etherscanApi
)
setResults(result.result)
const etherscanApi = getEtherScanApi(networkId)
let result
if (isProxyContractReceipt) {
result = await getProxyContractReceiptStatus(
values.receiptGuid,
apiKey,
etherscanApi
)
if (result.status === '1') {
result.message = result.result
result.result = 'Successfully Updated'
}
} else
result = await getReceiptStatus(
values.receiptGuid,
apiKey,
etherscanApi
)
setResults({
succeed: result.status === '1' ? true : false,
message: result.result || (result.status === '0' ? 'Verification failed' : result.message)
})
} catch (error: any) {
setResults(error.message)
setResults({
succeed: false,
message: error.message
})
}
}
return (
<AppContext.Consumer>
{({ apiKey, clientInstance, receipts }) => {
{({ apiKey, clientInstance, receipts, setReceipts }) => {
if (!apiKey && clientInstance && clientInstance.call) clientInstance.call('notification' as any, 'toast', 'Please add API key to continue')
return !apiKey ? (
<Navigate
@ -61,7 +86,7 @@ export const ReceiptsView: React.FC = () => {
onGetReceiptStatus(values, clientInstance, apiKey)
}
>
{({ errors, touched, handleSubmit }) => (
{({ errors, touched, handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<div
className="form-group"
@ -83,6 +108,21 @@ export const ReceiptsView: React.FC = () => {
component="div"
/>
</div>
<div className="d-flex mb-2 custom-control custom-checkbox">
<Field
className="custom-control-input"
type="checkbox"
name="isProxyReceipt"
id="isProxyReceipt"
onChange={async (e) => {
handleChange(e)
if (e.target.checked) setIsProxyContractReceipt(true)
else setIsProxyContractReceipt(false)
}}
/>
<label className="form-check-label custom-control-label" htmlFor="isProxyReceipt">It's a proxy contract GUID</label>
</div>
<SubmitButton text="Check" disable = {!touched.receiptGuid || (touched.receiptGuid && errors.receiptGuid) ? true : false} />
</form>
)}
@ -93,11 +133,19 @@ export const ReceiptsView: React.FC = () => {
marginTop: "2em",
fontSize: "0.8em",
textAlign: "center",
color: results['succeed'] ? "green" : "red"
}}
dangerouslySetInnerHTML={{ __html: results }}
dangerouslySetInnerHTML={{ __html: results.message ? results.message : '' }}
/>
<ReceiptsTable receipts={receipts} />
<ReceiptsTable receipts={receipts} /><br/>
<CustomTooltip
tooltipText="Clear the list of receipts"
tooltipId='etherscan-clear-receipts'
placement='bottom'
>
<Button onClick={() => { setReceipts([]) }} >Clear</Button>
</CustomTooltip>
</div>
)
}
@ -108,13 +156,13 @@ export const ReceiptsView: React.FC = () => {
const ReceiptsTable: React.FC<{ receipts: Receipt[] }> = ({ receipts }) => {
return (
<div className="table-responsive" style={{ fontSize: "0.7em" }}>
<div className="table-responsive" style={{ fontSize: "0.8em" }}>
<h6>Receipts</h6>
<table className="table table-sm">
<thead>
<tr>
<th scope="col">Guid</th>
<th scope="col">Status</th>
<th scope="col">GUID</th>
</tr>
</thead>
<tbody>
@ -123,8 +171,22 @@ const ReceiptsTable: React.FC<{ receipts: Receipt[] }> = ({ receipts }) => {
receipts.map((item: Receipt, index) => {
return (
<tr key={item.guid}>
<td className={(item.status === 'Pass - Verified' || item.status === 'Successfully Updated')
? 'text-success' : (item.status === 'Pending in queue'
? 'text-warning' : (item.status === 'Already Verified'
? 'text-info': 'text-secondary'))}>
{item.status}
{item.status === 'Successfully Updated' && <CustomTooltip
placement={'bottom'}
tooltipClasses="text-wrap"
tooltipId="etherscan-receipt-proxy-status"
tooltipText={item.message}
>
<i style={{ fontSize: 'small' }} className={'ml-1 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
</CustomTooltip>
}
</td>
<td>{item.guid}</td>
<td>{item.status}</td>
</tr>
)
})}

@ -1,8 +1,10 @@
import React, { useEffect, useRef, useState } from "react"
import Web3 from 'web3'
import {
PluginClient,
} from "@remixproject/plugin"
import { CustomTooltip } from '@remix-ui/helper'
import { Formik, ErrorMessage, Field } from "formik"
import { SubmitButton } from "../components"
@ -19,8 +21,8 @@ interface Props {
interface FormValues {
contractName: string
contractArguments: string
contractAddress: string
expectedImplAddress?: string
}
export const VerifyView: React.FC<Props> = ({
@ -32,12 +34,14 @@ export const VerifyView: React.FC<Props> = ({
const [results, setResults] = useState("")
const [networkName, setNetworkName] = useState("Loading...")
const [showConstructorArgs, setShowConstructorArgs] = useState(false)
const [isProxyContract, setIsProxyContract] = useState(false)
const [constructorInputs, setConstructorInputs] = useState([])
const verificationResult = useRef({})
useEffect(() => {
if (client && client.on) {
client.on("blockchain" as any, 'networkStatus', (result) => {
setNetworkName(result.network.name)
setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : ''}`)
})
}
return () => {
@ -56,13 +60,24 @@ export const VerifyView: React.FC<Props> = ({
throw new Error("no compilation result available")
}
const contractArguments = values.contractArguments.replace("0x", "")
const constructorValues = []
for (const key in values) {
if (key.startsWith('contractArgValue')) constructorValues.push(values[key])
}
const web3 = new Web3()
const constructorTypes = constructorInputs.map(e => e.type)
let contractArguments = web3.eth.abi.encodeParameters(constructorTypes, constructorValues)
contractArguments = contractArguments.replace("0x", "")
verificationResult.current = await verify(
apiKey,
values.contractAddress,
contractArguments,
values.contractName,
compilationResult,
null,
isProxyContract,
values.expectedImplAddress,
client,
onVerifiedContract,
setResults,
@ -75,8 +90,7 @@ export const VerifyView: React.FC<Props> = ({
<Formik
initialValues={{
contractName: "",
contractArguments: "",
contractAddress: "",
contractAddress: ""
}}
validate={(values) => {
const errors = {} as any
@ -120,8 +134,13 @@ export const VerifyView: React.FC<Props> = ({
onChange={async (e) => {
handleChange(e)
const {artefact} = await client.call("compilerArtefacts" as any, "getArtefactsByContractName", e.target.value)
if (artefact && artefact.abi && artefact.abi[0] && artefact.abi[0].type && artefact.abi[0].type === 'constructor') setShowConstructorArgs(true)
else setShowConstructorArgs(false)
if (artefact && artefact.abi && artefact.abi[0] && artefact.abi[0].type && artefact.abi[0].type === 'constructor' && artefact.abi[0].inputs.length > 0) {
setConstructorInputs(artefact.abi[0].inputs)
setShowConstructorArgs(true)
} else {
setConstructorInputs([])
setShowConstructorArgs(false)
}
}}
>
<option disabled={true} value="">
@ -141,22 +160,35 @@ export const VerifyView: React.FC<Props> = ({
</div>
<div className={ showConstructorArgs ? 'form-group d-block': 'form-group d-none' } >
<label htmlFor="contractArguments">Constructor Arguments</label>
<Field
className={
errors.contractArguments && touched.contractArguments
? "form-control is-invalid"
: "form-control"
}
type="text"
name="contractArguments"
placeholder="hex encoded args"
/>
<ErrorMessage
className="invalid-feedback"
name="contractArguments"
component="div"
/>
<label>Constructor Arguments</label>
{constructorInputs.map((item, index) => {
return (
<div className="d-flex">
<Field
className="form-control m-1"
type="text"
key={`contractArgName${index}`}
name={`contractArgName${index}`}
value={item.name}
disabled={true}
/>
<CustomTooltip
tooltipText={`value of ${item.name}`}
tooltipId={`etherscan-constructor-value${index}`}
placement='top'
>
<Field
className="form-control m-1"
type="text"
key={`contractArgValue${index}`}
name={`contractArgValue${index}`}
placeholder={item.type}
/>
</CustomTooltip>
</div>
)}
)}
</div>
<div className="form-group">
@ -178,6 +210,45 @@ export const VerifyView: React.FC<Props> = ({
/>
</div>
<div className="d-flex mb-2 custom-control custom-checkbox">
<Field
className="custom-control-input"
type="checkbox"
name="isProxy"
id="isProxy"
onChange={async (e) => {
handleChange(e)
if (e.target.checked) setIsProxyContract(true)
else setIsProxyContract(false)
}}
/>
<label className="form-check-label custom-control-label" htmlFor="isProxy">It's a proxy contract</label>
</div>
<div className={ isProxyContract ? 'form-group d-block': 'form-group d-none' }>
<label htmlFor="expectedImplAddress">Expected Implementation Address</label>
<CustomTooltip
placement={'top'}
tooltipClasses="text-wrap"
tooltipId="etherscan-impl-address-info"
tooltipText="Make sure implementation contract is already verified before proxy contract"
>
<i style={{ fontSize: 'small' }} className={'ml-1 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
</CustomTooltip>
<CustomTooltip
tooltipText='Providing expected implementation address enforces a check to ensure the returned implementation contract address is same as address picked up by the verifier'
tooltipId='etherscan-impl-address'
placement='bottom'
>
<Field
className="form-control"
type="text"
name="expectedImplAddress"
placeholder="e.g. 0x11b79afc03baf25c631dd70169bb6a3160b2706e"
/>
</CustomTooltip>
</div>
<SubmitButton dataId="verify-contract" text="Verify"
isSubmitting={isSubmitting}
disable={ !contracts.length ||
@ -188,30 +259,35 @@ export const VerifyView: React.FC<Props> = ({
? true
: false}
/>
<br/><br/>
<button
type="button"
style={{ padding: "0.25rem 0.4rem", marginRight: "0.5em", marginBottom: "0.5em"}}
className="btn btn-secondary"
title="Generate the required TS scripts to verify a contract on Etherscan"
onClick={async () => {
if (!await client.call('fileManager', 'exists' as any, 'scripts/etherscan/receiptStatus.ts')) {
await client.call('fileManager', 'writeFile', 'scripts/etherscan/receiptStatus.ts', receiptGuidScript)
await client.call('fileManager', 'open', 'scripts/etherscan/receiptStatus.ts')
} else {
client.call('notification' as any, 'toast', 'File receiptStatus.ts already exists')
}
if (!await client.call('fileManager', 'exists' as any, 'scripts/etherscan/verify.ts')) {
await client.call('fileManager', 'writeFile', 'scripts/etherscan/verify.ts', verifyScript)
await client.call('fileManager', 'open', 'scripts/etherscan/verify.ts')
} else {
client.call('notification' as any, 'toast', 'File verify.ts already exists')
}
}}
>
Generate Verification Scripts
</button>
<br/>
<CustomTooltip
tooltipText='Generate the required TS scripts to verify a contract on Etherscan'
tooltipId='etherscan-generate-scripts'
placement='bottom'
>
<button
type="button"
style={{ padding: "0.25rem 0.4rem", marginRight: "0.5em", marginBottom: "0.5em"}}
className="btn btn-secondary btn-block"
onClick={async () => {
if (!await client.call('fileManager', 'exists' as any, 'scripts/etherscan/receiptStatus.ts')) {
await client.call('fileManager', 'writeFile', 'scripts/etherscan/receiptStatus.ts', receiptGuidScript)
await client.call('fileManager', 'open', 'scripts/etherscan/receiptStatus.ts')
} else {
client.call('notification' as any, 'toast', 'File receiptStatus.ts already exists')
}
if (!await client.call('fileManager', 'exists' as any, 'scripts/etherscan/verify.ts')) {
await client.call('fileManager', 'writeFile', 'scripts/etherscan/verify.ts', verifyScript)
await client.call('fileManager', 'open', 'scripts/etherscan/verify.ts')
} else {
client.call('notification' as any, 'toast', 'File verify.ts already exists')
}
}}
>
Generate Verification Scripts
</button>
</CustomTooltip>
</form>
)
}

@ -7,8 +7,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="stylesheet" integrity="ha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
crossorigin="anonymous" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
</head>
<body>
<div id="root"></div>
<script src="https://kit.fontawesome.com/41dd021e94.js" crossorigin="anonymous"></script>
</body>
</html>

@ -1,7 +1,7 @@
{
"name": "etherscan",
"displayName": "Etherscan - Contract verification",
"description": "Verify Solidity contract code using Etherscan API",
"displayName": "Contract verification - Etherscan",
"description": "Verify Solidity contract code using Etherscan, BscScan, PolygonScan etc. APIs",
"version": "0.1.0",
"events": [],
"methods": ["verify", "receiptStatus"],

@ -0,0 +1,220 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'@sources': () => sources,
'Should flatten contract after creation': function (browser: NightwatchBrowser) {
browser.addFile('TestContract.sol', sources[0]['TestContract.sol'])
.pause(10000)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemTestContract.sol"]')
.pause(3000)
.click('*[data-id="treeViewLitreeViewItemTestContract.sol"]')
.rightClick('*[data-id="treeViewLitreeViewItemTestContract.sol"]')
.click('*[id="menuitemflattenacontract"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemTestContract_flattened.sol"]')
},
'Should not be able to flatten contract without imports': function (browser: NightwatchBrowser) {
browser.click('*[data-id="treeViewLitreeViewItemcontracts"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.pause(1000)
.click('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.rightClick('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot.sol"]')
.click('*[id="menuitemflattenacontract"]')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemcontracts/3_Ballot_flattened.sol"]')
},
'Should not flatten contract with errors in syntax': function (browser: NightwatchBrowser) {
browser.addFile('samplecontract.sol', { content })
.waitForElementVisible('*[data-id="treeViewLitreeViewItemsamplecontract.sol"]')
.click('*[data-id="treeViewLitreeViewItemsamplecontract.sol"]')
.pause(1000)
.rightClick('*[data-id="treeViewLitreeViewItemsamplecontract.sol"]')
.click('*[id="menuitemflattenacontract"]')
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemsamplecontract_flattened.sol"]')
}
}
const sources = [
{
'TestContract.sol': {
content: `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyToken is Initializable, ERC721Upgradeable, ERC721BurnableUpgradeable, OwnableUpgradeable, UUPSUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() initializer public {
__ERC721_init("MyToken", "MTK");
__ERC721Burnable_init();
__Ownable_init();
__UUPSUpgradeable_init();
}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
function _authorizeUpgrade(address newImplementation)
internal
onlyOwner
override
{}
}
`
},
}
]
const content = `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Ballot
* @dev Implements voting process along with vote delegation
*/
contract Voting {
struct Voter {
uint weight // weight is accumulated by delegation <-- missing semicolon
bool voted // if true, that person already voted <-- missing semicolon
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
struct Proposal {
// If you can limit the length to a certain number of bytes,
// always use one of bytes1 to bytes32 because they are much cheaper
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
/**
* @dev Create a new ballot to choose one of 'proposalNames'.
* @param proposalNames names of proposals
*/
constructor(bytes32[] memory proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
for (uint i = 0; i < proposalNames.length; i++) {
// 'Proposal({...})' creates a temporary
// Proposal object and 'proposals.push(...)'
// appends it to the end of 'proposals'.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
/**
* @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.
* @param voter address of voter
*/
function giveRightToVote(address voter) public {
require(
msg.sender == chairperson,
"Only chairperson can give right to vote."
);
require(
!voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/**
* @dev Delegate your vote to the voter 'to'.
* @param to address to which vote is delegated
*/
function delegate(address to) public {
Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
require(to != msg.sender, "Self-delegation is disallowed.");
while (voters[to].delegate != address(0)) {
to = voters[to].delegate;
// We found a loop in the delegation, not allowed.
require(to != msg.sender, "Found loop in delegation.");
}
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate_.vote].voteCount += sender.weight;
} else {
// If the delegate did not vote yet,
// add to her weight.
delegate_.weight += sender.weight;
}
}
/**
* @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.
* @param proposal index of proposal in the proposals array
*/
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// If 'proposal' is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/**
* @dev Computes the winning proposal taking all previous votes into account.
* @return winningProposal_ index of winning proposal in the proposals array
*/
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
/**
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
* @return winnerName_ the name of the winner
*/
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}
`

@ -14,7 +14,8 @@ module.exports = {
},
'Deploy SampleERC721 whose bytecode is very similar to ERC721': function (browser: NightwatchBrowser) {
browser.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
// create contract
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')

@ -217,7 +217,7 @@ module.exports = {
.rightClickCustom('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]').useXpath().waitForElementVisible('//*[@id="menuitemtestcommand"]').click('//*[@id="menuitemtestcommand"]', async () => {
// @ts-ignore
browser.click('//*[@data-id="verticalIconsKindlocalPlugin"]').frame(0, async () => {
await clickAndCheckLog(browser, null, { id: 'localPlugin', name: 'testCommand', label: 'testCommand', type: [], extension: ['.sol'], path: ['contracts/1_Storage.sol'], pattern: [] }, null, null)
await clickAndCheckLog(browser, null, { id: 'localPlugin', name: 'testCommand', label: 'testCommand', type: [], extension: ['.sol'], path: ['contracts/1_Storage.sol'], pattern: [], group: 99 }, null, null)
})
})
})

@ -104,7 +104,7 @@ module.exports = {
})
.addFile('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'])
.clickLaunchIcon('solidity')
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.0
.testContracts('test_import_node_modules_with_github_import.sol', sources[4]['test_import_node_modules_with_github_import.sol'], ['ERC20', 'test11'])
},
'Static Analysis run with remixd #group3': '' + function (browser) {

@ -0,0 +1,218 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'@sources': () => sources,
'Generate uml diagram from contract #group1': function (browser: NightwatchBrowser) {
browser.addFile('TestBallot.sol', sources[0]['TestBallot.sol'])
.waitForElementVisible('*[data-id="treeViewLitreeViewItemTestBallot.sol"')
.rightClick('*[data-id="treeViewLitreeViewItemTestBallot.sol"]')
.click('*[id="menuitemgeneratecustomaction"')
.waitForElementVisible('*[id="sol-uml-gen"]')
},
'Generate uml for contracts with imports #group1': function (browser: NightwatchBrowser) {
browser.addFile('secondContract.sol', sources[1]['secondContract.sol'])
.waitForElementVisible('*[data-id="treeViewLitreeViewItemsecondContract.sol"')
.pause(3000)
.rightClick('*[data-id="treeViewLitreeViewItemsecondContract.sol"]')
.click('*[id="menuitemgeneratecustomaction"')
.waitForElementVisible('*[id="sol-uml-gen"]')
.isVisible('*[data-id="treeViewLitreeViewItemsecondContract_flattened.sol"]')
},
'Zoom into uml diagram #group1': function (browser: NightwatchBrowser) {
browser.addFile('secondContract.sol', sources[1]['secondContract.sol'])
.waitForElementVisible('*[data-id="treeViewLitreeViewItemsecondContract.sol"')
.pause(3000)
.rightClick('*[data-id="treeViewLitreeViewItemsecondContract.sol"]')
.click('*[id="menuitemgeneratecustomaction"')
.waitForElementVisible('*[id="sol-uml-gen"]')
.click('*[data-id="umlZoominbtn"]')
}
}
const sources = [
{
'TestBallot.sol': {
content: `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Ballot
* @dev Implements voting process along with vote delegation
*/
contract Ballot {
struct Voter {
uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
struct Proposal {
// If you can limit the length to a certain number of bytes,
// always use one of bytes1 to bytes32 because they are much cheaper
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
/**
* @dev Create a new ballot to choose one of 'proposalNames'.
* @param proposalNames names of proposals
*/
constructor(bytes32[] memory proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
for (uint i = 0; i < proposalNames.length; i++) {
// 'Proposal({...})' creates a temporary
// Proposal object and 'proposals.push(...)'
// appends it to the end of 'proposals'.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
/**
* @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.
* @param voter address of voter
*/
function giveRightToVote(address voter) public {
require(
msg.sender == chairperson,
"Only chairperson can give right to vote."
);
require(
!voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/**
* @dev Delegate your vote to the voter 'to'.
* @param to address to which vote is delegated
*/
function delegate(address to) public {
Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
require(to != msg.sender, "Self-delegation is disallowed.");
while (voters[to].delegate != address(0)) {
to = voters[to].delegate;
// We found a loop in the delegation, not allowed.
require(to != msg.sender, "Found loop in delegation.");
}
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate_.vote].voteCount += sender.weight;
} else {
// If the delegate did not vote yet,
// add to her weight.
delegate_.weight += sender.weight;
}
}
/**
* @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.
* @param proposal index of proposal in the proposals array
*/
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// If 'proposal' is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/**
* @dev Computes the winning proposal taking all previous votes into account.
* @return winningProposal_ index of winning proposal in the proposals array
*/
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
/**
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
* @return winnerName_ the name of the winner
*/
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}
`}
},
{
'secondContract.sol': {
content: `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() initializer public {
__ERC721_init("MyToken", "MTK");
__Ownable_init();
__UUPSUpgradeable_init();
}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
1 + 1;
}
function _authorizeUpgrade(address newImplementation)
internal
onlyOwner
override
{}
}
`}
}
]

@ -38,7 +38,7 @@ module.exports = {
'Test GitHub Import - from master branch #group1': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.19 (master branch)
.addFile('Untitled4.sol', sources[3]['Untitled4.sol'])
.clickLaunchIcon('filePanel')
.verifyContracts(['test7', 'ERC20'], { wait: 10000 })
@ -54,7 +54,7 @@ module.exports = {
'Test GitHub Import - no branch specified #group2': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.0+commit.c7dfd78e.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.19 (master branch)
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled6.sol', sources[5]['Untitled6.sol'])
@ -64,6 +64,7 @@ module.exports = {
'Test GitHub Import - raw URL #group4': function (browser: NightwatchBrowser) {
browser
.setSolidityCompilerVersion('soljson-v0.8.19+commit.7dd6d404.js') // open-zeppelin moved to pragma ^0.8.0 (master branch)
.clickLaunchIcon('filePanel')
.click('li[data-id="treeViewLitreeViewItemREADME.txt"')
.addFile('Untitled7.sol', sources[6]['Untitled7.sol'])

@ -178,7 +178,8 @@ module.exports = {
.click('*[data-id="testTabGenerateTestFolder"]')
.clickLaunchIcon('filePanel')
// creating a new workspace
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_new')

@ -37,19 +37,24 @@ module.exports = {
.click('*[data-id="treeViewLitreeViewItemcontracts"]')
.click('*[data-id="treeViewLitreeViewItemcontracts/2_Owner.sol"]')
.clickLaunchIcon('solidity')
.click('*[id="compileBtn"]')
.pause(10000)
.clickLaunchIcon('solidityStaticAnalysis')
.click('*[id="staticAnalysisRunBtn"]')
.waitForElementPresent('#staticanalysisresult .warning', 5000)
.assert.containsText('#verticalIconsKindsolidityStaticAnalysis .remixui_status', '1') // Check warning count
// Check warning count
.click('*[data-rb-event-key="basic"]')
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '1')
.verify.elementPresent('input[name="showLibWarnings"]')
.verify.not.elementPresent('input[name="showLibWarnings"]:checked')
.verify.elementPresent('label[id="headingshowLibWarnings"]')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.assert.containsText('#verticalIconsKindsolidityStaticAnalysis .remixui_status', '382')
.click('*[data-rb-event-key="basic"]')
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '382')
.click('label[id="headingshowLibWarnings"]')
.pause(1000)
.assert.containsText('#verticalIconsKindsolidityStaticAnalysis .remixui_status', '1')
.assert.containsText('*[data-id="StaticAnalysisErrorCount"]', '1')
.end()
}
}

@ -144,6 +144,9 @@ module.exports = {
.waitForElementContainsText('*[data-id="terminalJournal"]', '-11300', 60000)
.clickFunction('inputValue2 - transact (not payable)', { types: 'uint256 _u', values: '2.345e10' })
.waitForElementContainsText('*[data-id="terminalJournal"]', '2340000000', 60000)
.clickFunction('inputValue3 - transact (not payable)', { types: 'uint256[] _u', values: '["2.445e10", "13e1"]' })
.waitForElementContainsText('*[data-id="terminalJournal"]', '24450000000', 60000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '130', 60000)
.click('*[data-id="deployAndRunClearInstances"]')
},
@ -501,6 +504,10 @@ contract C {
function inputValue2 (uint _u) public {
console.log(_u);
}
function inputValue3 (uint[] memory _u) public {
console.log(_u[0]);
console.log(_u[1]);
}
}
`
}

@ -36,7 +36,8 @@ module.exports = {
'Should create Remix default workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
@ -107,7 +108,8 @@ module.exports = {
'Should create blank workspace with no files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
@ -129,7 +131,8 @@ module.exports = {
'Should create ERC20 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
@ -189,7 +192,8 @@ module.exports = {
'Should create ERC721 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
@ -249,7 +253,8 @@ module.exports = {
'Should create ERC1155 workspace with files #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation
@ -309,7 +314,8 @@ module.exports = {
'Should create ERC1155 workspace with template customizations #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
@ -381,7 +387,8 @@ module.exports = {
'Should create two workspace and switch to the first one #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name')
@ -394,7 +401,8 @@ module.exports = {
selector: "//div[contains(@class, 'view-line') and contains(.//span, 'test')]",
locateStrategy: 'xpath'
})
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1')
@ -449,7 +457,8 @@ module.exports = {
'Should create workspace for test #group2': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
@ -475,7 +484,8 @@ module.exports = {
'Should create workspace for next test #group2': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation

@ -11,7 +11,8 @@ module.exports = {
'Should not be able to create GIT without credentials #group1': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.waitForElementVisible({
@ -43,7 +44,8 @@ module.exports = {
browser
.clickLaunchIcon('filePanel')
.waitForElementNotVisible('[data-id="workspaceGitPanel"]')
.click('*[data-id="workspaceCreate"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation

@ -3,7 +3,7 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/remix-ide/src",
"projectType": "application",
"implicitDependencies": ["doc-gen", "doc-viewer", "etherscan", "vyper"],
"implicitDependencies": ["doc-gen", "doc-viewer", "etherscan", "vyper", "solhint", "walletconnect"],
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",

@ -66,6 +66,15 @@ module.exports = class Filepanel extends ViewPlugin {
/**
* @param item { id: string, name: string, type?: string[], path?: string[], extension?: string[], pattern?: string[] }
* typically:
* group 0 for file manipulations
* group 1 for download operations
* group 2 for running operations (script for instance)
* group 3 for publishing operations (gist)
* group 4 for copying operations
* group 5 for solidity file operations (flatten for instance)
* group 6 for compiling operations
* group 7 for generating resource files (UML, documentation, ...)
* @param callback (...args) => void
*/
registerContextMenuItem (item) {

@ -73,8 +73,8 @@ export class CompileAndRun extends Plugin {
this.on('compilerMetadata', 'artefactsUpdated', async (fileName, contract) => {
if (this.targetFileName === contract.file) {
this.targetFileName = null
if (contract.object && contract.object.devdoc['custom:dev-run-script']) {
this.targetFileName = null
const file = contract.object.devdoc['custom:dev-run-script']
if (file) {
this.runScript(file, true)

@ -123,7 +123,8 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
type: [],
extension: ['.sol'],
path: [],
pattern: []
pattern: [],
group: 6
})
})
try {

@ -27,8 +27,14 @@
"filePanel.solghaction": "Solidity Test Workflow",
"filePanel.workspace.tssoltestghaction": "Adds a preset yml file to run mocha and chai tests for solidity on github actions CI",
"filePanel.tssoltestghaction": "Mocha Chai Test Workflow",
"filePanel.workspace.addscriptetherscan": "Adds a scripts which can be used to interact with the etherscan API.",
"filePanel.addscriptetherscan": "Add Etherscan script",
"filePanel.workspace.addscriptdeployer": "Adds a scripts which can be used to deploy contracts.",
"filePanel.addscriptdeployer": "Add Contract deployer script",
"filePanel.workspace.slitherghaction": "Adds a preset yml file to run slither analysis on github actions CI",
"filePanel.slitherghaction": "Slither Workflow",
"filePanel.workspace.helperscripts": "Adds convenient scripts to the 'scripts' directory",
"filePanel.helperscripts": "Web3 Scripts",
"filePanel.newFile": "New File",
"filePanel.newFolder": "New Folder",
"filePanel.rename": "Rename",

@ -4,7 +4,8 @@
"udapp.account": "Account",
"udapp.value": "Value",
"udapp.contract": "Contract",
"udapp.compiledBy": "Compiled by {compilerName}",
"udapp.compiledBy": "compiled by {compilerName}",
"udapp.warningEvmVersion": "Please make sure that the current network is compatible with this evm version: {evmVersion}. Otherwise any deployment will fail.",
"udapp.infoSyncCompiledContractTooltip": "Click here to import contracts compiled from an external framework.This action is enabled when Remix is connected to an external framework (hardhat, truffle, foundry) through remixd.",
"udapp.remixIpfsUdappTooltip": "Publishing the source code and metadata to IPFS facilitates source code verification using Sourcify and will greatly foster contract adoption (auditing, debugging, calling it, etc...)",
"udapp.signAMessage": "Sign a message",
@ -27,7 +28,8 @@
"udapp.contractOptionsTitle3": "Select and compile *.sol file to deploy or access a contract.",
"udapp.contractOptionsTitle4": "When there is a compiled .sol file, choose the contract to deploy or to use with AtAddress.'",
"udapp.checkSumWarning": "It seems you are not using a checksumed address.A checksummed address is an address that contains uppercase letters, as specified in {a}.Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.",
"udapp.isOverSizePrompt": "Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fails. More info: {a}",
"udapp.isOverSizePromptEip170": "Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fail if the current network has activated the eip 170. More info: {a}",
"udapp.isOverSizePromptEip3860": "Contract creation init code exceeds the allowed max code size of 49152 bytes. The deployment will likely fail if the current network has activated the eip 3860. More info: {a}",
"udapp.thisContractMayBeAbstract": "This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.",
"udapp.noCompiledContracts": "No compiled contracts",
"udapp.addressOfContract": "Address of contract",

@ -0,0 +1,11 @@
{
"debugger.displayName": "Debugger",
"debugger.debuggerConfiguration": "Debugger Configuration",
"debugger.stopDebugging": "Stop debugging",
"debugger.startDebugging": "Start debugging",
"debugger.placeholder": "Transaction hash, should start with 0x",
"debugger.debugLocaNodeLabel": "Force using local node",
"debugger.useGeneratedSources": "Use generated sources",
"debugger.debugWithGeneratedSources": "Debug with generated sources",
"debugger.introduction": "When Debugging with a transaction hash, if the contract is verified, Remix will try to fetch the source code from Sourcify or Etherscan. Put in your Etherscan API key in the Remix settings. For supported networks, please see"
}

@ -0,0 +1,70 @@
{
"filePanel.displayName": "File explorer",
"filePanel.workspace": "WORKSPACES",
"filePanel.create": "Create",
"filePanel.clone": "Clone",
"filePanel.download": "Download",
"filePanel.backup": "Backup",
"filePanel.restore": "Restore",
"filePanel.workspace.create": "Create Workspace",
"filePanel.workspace.rename": "Rename Workspace",
"filePanel.workspace.delete": "Delete Workspace",
"filePanel.workspace.deleteConfirm": "Are you sure to delete the current workspace?",
"filePanel.workspace.download": "Download Workspace",
"filePanel.workspace.downloadConfirm": "This will download current workspace in a zip file. Do you want to continue?",
"filePanel.workspace.deleteAll": "Delete All Workspaces",
"filePanel.workspace.deleteAllConfirm1": "Are you absolutely sure you want to delete all your workspaces?",
"filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.",
"filePanel.workspace.name": "Workspace name",
"filePanel.workspace.chooseTemplate": "Choose a template",
"filePanel.workspace.backup": "Backup All Workspaces",
"filePanel.workspace.restore": "Restore Workspaces from the Backup",
"filePanel.workspace.clone": "Clone Git Repository",
"filePanel.workspace.cloneMessage": "Please provide a valid git repository url.",
"filePanel.workspace.enterGitUrl": "Enter git repository url",
"filePanel.workspace.switch": "Switch To Workspace",
"filePanel.workspace.solghaction": "Adds a preset yml file to run solidity unit tests on github actions CI.",
"filePanel.solghaction": "Solidity Test Workflow",
"filePanel.workspace.tssoltestghaction": "Adds a preset yml file to run mocha and chai tests for solidity on github actions CI",
"filePanel.tssoltestghaction": "Mocha Chai Test Workflow",
"filePanel.workspace.addscriptetherscan": "Adds a scripts which can be used to interact with the etherscan API.",
"filePanel.addscriptetherscan": "Add Etherscan script",
"filePanel.workspace.addscriptdeployer": "Adds a scripts which can be used to deploy contracts.",
"filePanel.addscriptdeployer": "Add Contract deployer script",
"filePanel.workspace.slitherghaction": "Adds a preset yml file to run slither analysis on github actions CI",
"filePanel.slitherghaction": "Slither Workflow",
"filePanel.workspace.helperscripts": "Adds convenient scripts to the 'scripts' directory",
"filePanel.helperscripts": "Web3 Scripts",
"filePanel.newFile": "New File",
"filePanel.newFolder": "New Folder",
"filePanel.rename": "Rename",
"filePanel.delete": "Delete",
"filePanel.deleteAll": "Delete All",
"filePanel.run": "Run",
"filePanel.pushChangesToGist": "Push changes to gist",
"filePanel.publishFolderToGist": "Publish folder to gist",
"filePanel.publishFileToGist": "Publish file to gist",
"filePanel.copy": "Copy",
"filePanel.paste": "Paste",
"filePanel.compile": "Compile",
"filePanel.compileForNahmii": "Compile for Nahmii",
"filePanel.createNewFile": "Create new file",
"filePanel.createNewFolder": "Create new folder",
"filePanel.publishToGist": "Publish all files to GitHub gist",
"filePanel.uploadFile": "Upload files",
"filePanel.uploadFolder": "Upload folder",
"filePanel.updateGist": "Update the current [gist] explorer",
"filePanel.viewAllBranches": "View all branches",
"filePanel.createBranch": "Create branch",
"filePanel.switchBranches": "Switch branches",
"filePanel.checkoutGitBranch": "Checkout Git Branch",
"filePanel.findOrCreateABranch": "Find or create a branch.",
"filePanel.initGitRepositoryLabel": "Initialize workspace as a new git repository",
"filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Settings panel.",
"filePanel.workspaceName": "Workspace name",
"filePanel.customizeTemplate": "Customize template",
"filePanel.features": "Features",
"filePanel.upgradeability": "Upgradeability",
"filePanel.ok": "OK",
"filePanel.cancel": "Cancel"
}

@ -0,0 +1,61 @@
{
"home.scamAlert": "Scam Alert",
"home.scamAlertText": "The only URL Remix uses is remix.ethereum.org",
"home.scamAlertText2": "Beware of online videos promoting \"liquidity front runner bots\"",
"home.scamAlertText3": "Additional safety tips",
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
"home.remixYouTubeText2": "Remix has a growing library of videos containing lots of tips for using the tool. Check them out and subscribe to get our latest uploads.",
"home.betaTesting": "BETA TESTING",
"home.betaTestingText1": "Our community supports us.",
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test and analyse smart contract.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",
"home.solhintPluginDesc": "Solhint is an open source project for linting Solidity code.",
"home.sourcifyPluginDesc": "Solidity contract and metadata verification service.",
"home.unitTestPluginDesc": "Write and run unit tests for your contracts in Solidity.",
"home.dgitPluginDesc": "Add source control to your projects.",
"home.oneClickDappDesc": "Quickly generate smart contract interfaces",
"home.getStarted": "Get Started",
"home.projectTemplates": "Project Templates",
"home.blankTemplateDesc": "Create an empty workspace.",
"home.remixDefaultTemplateDesc": "Create a workspace with sample files.",
"home.ozerc20TemplateDesc": "Create an ERC20 token by importing OpenZeppelin library.",
"home.ozerc721TemplateDesc": "Create an NFT token by importing OpenZeppelin library.",
"home.ozerc1155TemplateDesc": "Create an ERC1155 token by importing OpenZeppelin library.",
"home.gnosisSafeMultisigTemplateDesc": "Create Multi-Signature wallets using this template.",
"home.zeroxErc20TemplateDesc": "Create an ERC20 token by importing 0xProject contract.",
"home.learn": "Learn",
"home.learnEth1": "Remix Basics",
"home.learnEth1Desc": "An introduction to Remix's interface and basic operations.",
"home.learnEth2": "Intro to Solidity",
"home.learnEth2Desc": "Interactively learn Solidity beginner concepts.",
"home.remixAdvanced": "Deploying with Libraries",
"home.remixAdvancedDesc": "Learn to deploy with libraries in Remix",
"home.remixYoutubePlaylist": "Remix Youtube Playlist",
"home.remixTwitterProfile": "Remix Twitter Profile",
"home.remixLinkedinProfile": "Remix Linkedin Profile",
"home.remixMediumPosts": "Remix Medium Posts",
"home.remixGitterChannel": "Join us on Discord",
"home.nativeIDE": "The Native IDE for Web3 Development.",
"home.website": "Website",
"home.documentation": "Documentation",
"home.remixPlugin": "Remix Plugin",
"home.remixDesktop": "Remix Desktop",
"home.searchDocumentation": "Search Documentation",
"home.files": "Files",
"home.newFile": "New File",
"home.openFile": "Open File",
"home.connectToLocalhost": "Access File System",
"home.loadFrom": "Load from",
"home.resources": "Resources"
}

@ -0,0 +1,6 @@
{
"panel.author": "Author",
"panel.maintainedBy": "Maintained By",
"panel.documentation": "Documentation",
"panel.description": "Description"
}

@ -0,0 +1,13 @@
{
"permissionHandler.allPermissionsReset": "All permisssions have been reset.",
"permissionHandler.rememberText": "has changed and",
"permissionHandler.permissionHandlerMessage": "\"{from}\" {rememberText} would like to access to \"{method}\" of \"{to}\"`",
"permissionHandler.description": "Description",
"permissionHandler.noDescriptionProvided": "No description Provided",
"permissionHandler.makeSureYouTrustThisPlugin": "Make sure you trust this plugin before processing this call. If you choose to remember the choice for this specific call, the value will be kept only for the current session.",
"permissionHandler.rememberThisChoice": "Remember this choice",
"permissionHandler.resetAllPermissions": "Reset all Permissions",
"permissionHandler.permissionNeededFor": "Permission needed for {to}",
"permissionHandler.accept": "Accept",
"permissionHandler.decline": "Decline"
}

@ -0,0 +1,31 @@
{
"pluginManager.displayName": "Plugin manager",
"pluginManager.activate": "Activate",
"pluginManager.deactivate": "Deactivate",
"pluginManager.activeModules": "Active Modules",
"pluginManager.inactiveModules": "Inactive Modules",
"pluginManager.connectLocal": "Connect to a Local Plugin",
"pluginManager.localForm.title": "Local Plugin",
"pluginManager.localForm.pluginName": "Plugin Name",
"pluginManager.localForm.shouldBeCamelCase": "Should be camelCase",
"pluginManager.localForm.displayName": "Display Name",
"pluginManager.localForm.nameInTheHeader": "Name in the header",
"pluginManager.localForm.required": "required",
"pluginManager.localForm.commaSeparatedMethod": "comma separated list of method names",
"pluginManager.localForm.commaSeparatedPlugin": "comma separated list of plugin names",
"pluginManager.localForm.pluginsItCanActivate": "Plugins it can activate",
"pluginManager.localForm.typeOfConnection": "Type of connection",
"pluginManager.localForm.locationInRemix": "Location in remix",
"pluginManager.localForm.sidePanel": "Side Panel",
"pluginManager.localForm.mainPanel": "Main Panel",
"pluginManager.localForm.none": "None",
"pluginManager.Permissions": "Permissions",
"pluginManager.permissions": "permissions",
"pluginManager.pluginManagerPermissions": "Plugin Manager Permissions",
"pluginManager.currentPermissionSettings": "Current Permission Settings",
"pluginManager.noPermissionRequestedYet": "No Permission requested yet.",
"pluginManager.allow": "Allow",
"pluginManager.toCall": "to call",
"pluginManager.ok": "OK",
"pluginManager.cancel": "Cancel"
}

@ -0,0 +1,14 @@
{
"search.displayName": "Search in files",
"search.replace": "Replace",
"search.replaceAll": "Replace All",
"search.placeholder1": "Search ( Enter to search )",
"search.placeholder2": "Include ie *.sol ( Enter to include )",
"search.placeholder3": "Exclude ie .git/**/* ( Enter to exclude )",
"search.matchCase": "Match Case",
"search.matchWholeWord": "Match Whole Word",
"search.useRegularExpression": "Use Regular Expression",
"search.replaceWithoutConfirmation": "replace without confirmation",
"search.filesToInclude": "Files to include",
"search.filesToExclude": "Files to exclude"
}

@ -0,0 +1,26 @@
{
"settings.displayName": "Settings",
"settings.reset": "Reset to Default settings",
"settings.general": "General settings",
"settings.generateContractMetadataText": "Generate contract metadata. Generate a JSON file in the contract folder. Allows to specify library addresses the contract depends on. If nothing is specified, Remix deploys libraries automatically.",
"settings.ethereunVMText": "Always use the Remix VM at load",
"settings.wordWrapText": "Word wrap in editor",
"settings.useAutoCompleteText": "Enable code completion in editor.",
"settings.useShowGasInEditorText": "Display gas estimates in editor.",
"settings.displayErrorsText": "Display errors in editor while typing.",
"settings.matomoAnalytics": "Enable Matomo Analytics. We do not collect personally identifiable information (PII). The info is used to improve the site’s UX & UI. See more about ",
"settings.enablePersonalModeText": " Enable Personal Mode for web3 provider. Transaction sent over Web3 will use the web3.personal API.\n",
"settings.warnText": "Be sure the endpoint is opened before enabling it. This mode allows a user to provide a passphrase in the Remix interface without having to unlock the account. Although this is very convenient, you should completely trust the backend you are connected to (Geth, Parity, ...). Remix never persists any passphrase",
"settings.gitAccessTokenTitle": "Github Credentials",
"settings.gitAccessTokenText": "The access token is used to publish a Gist and retrieve GitHub contents. You may need to input username/email.",
"settings.gitAccessTokenText2": "Go to github token page (link below) to create a new token and save it in Remix. Make sure this token has only 'create gist' permission",
"settings.etherscanTokenTitle": "EtherScan Access Token",
"settings.etherscanAccessTokenText": "Manage the api key used to interact with Etherscan.",
"settings.etherscanAccessTokenText2": "Go to Etherscan api key page (link below) to create a new api key and save it in Remix.",
"settings.save": "Save",
"settings.remove": "Remove",
"settings.themes": "Themes",
"settings.locales": "Language",
"settings.swarm": "Swarm Settings",
"settings.ipfs": "IPFS Settings"
}

@ -0,0 +1,4 @@
{
"solUml.pngDownload": "Download as PNG",
"solUml.pdfDownload": "Download as PDF"
}

@ -0,0 +1,41 @@
{
"solidity.displayName": "Solidity compiler",
"solidity.compiler": "Compiler",
"solidity.addACustomCompiler": "Add a custom compiler",
"solidity.addACustomCompilerWithURL": "Add a custom compiler with URL",
"solidity.includeNightlyBuilds": "Include nightly builds",
"solidity.autoCompile": "Auto compile",
"solidity.hideWarnings": "Hide warnings",
"solidity.enableHardhat": "Enable Hardhat Compilation",
"solidity.learnHardhat": "Learn how to use Hardhat Compilation",
"solidity.enableTruffle": "Enable Truffle Compilation",
"solidity.learnTruffle": "Learn how to use Truffle Compilation",
"solidity.advancedConfigurations": "Advanced Configurations",
"solidity.compilerConfiguration": "Compiler configuration",
"solidity.compilationDetails": "Compilation Details",
"solidity.language": "Language",
"solidity.evmVersion": "EVM Version",
"solidity.enableOptimization": "Enable optimization",
"solidity.useConfigurationFile": "Use configuration file",
"solidity.change": "Change",
"solidity.compile": "Compile",
"solidity.noFileSelected": "no file selected",
"solidity.compileAndRunScript": "Compile and Run script",
"solidity.publishOn": "Publish on",
"solidity.flatten": "Flatten contracts before UML generation.",
"solidity.generateUML": "Generate a UML diagram of your contract.",
"solidity.flattenLabel": "Flatten",
"solidity.generateUMLLabel": "Generate UML Diagram",
"solidity.Assembly": "Assembly opcodes describing the contract including corresponding solidity source code",
"solidity.Opcodes": "Assembly opcodes describing the contract",
"solidity.name": "Name of the compiled contract",
"solidity.metadata": "Contains all informations related to the compilation",
"solidity.bytecode": "Bytecode being executed during contract creation",
"solidity.abi": "ABI: describing all the functions (input/output params, scope, ...)",
"solidity.web3Deploy": "Copy/paste this code to any JavaScript/Web3 console to deploy this contract",
"solidity.metadataHash": "Hash representing all metadata information",
"solidity.functionHashes": "List of declared function and their corresponding hash",
"solidity.gasEstimates": "Gas estimation for each function call",
"solidity.Runtime Bytecode": "Bytecode storing the state and being executed during normal contract call",
"solidity.swarmLocation": "Swarm url where all metadata information can be found (contract needs to be published first)"
}

@ -0,0 +1,35 @@
{
"solidityUnitTesting.displayName": "Solidity unit testing",
"solidityUnitTesting.testDirectory": "Test directory",
"solidityUnitTesting.testYourSmartContract": "Test your smart contract in Solidity.",
"solidityUnitTesting.selectDirectory": "Select directory to load and generate test files.",
"solidityUnitTesting.uiPathInputTooltip": "Press 'Enter' to change the path for test files.",
"solidityUnitTesting.uiPathInputButtonTooltip": "Create a test folder",
"solidityUnitTesting.create": "Create",
"solidityUnitTesting.generateTestsButtonTooltip": "Generate a sample test file",
"solidityUnitTesting.generate": "Generate",
"solidityUnitTesting.generateTestsLinkTooltip": "Check out documentation.",
"solidityUnitTesting.howToUse": "How to use...",
"solidityUnitTesting.runButtonTitle1": "Run tests",
"solidityUnitTesting.runButtonTitle2": "Please select Solidity compiler version greater than 0.4.12.",
"solidityUnitTesting.runButtonTitle3": "No solidity file selected",
"solidityUnitTesting.runButtonTitle4": "The \"Solidity Plugin\" should be activated",
"solidityUnitTesting.runButtonTitle5": "No test file selected",
"solidityUnitTesting.stopButtonLabel1": "Stop",
"solidityUnitTesting.stopButtonLabel2": "Stopping",
"solidityUnitTesting.run": "Run",
"solidityUnitTesting.runTestsTabStopActionTooltip": "Stop running tests",
"solidityUnitTesting.selectAll": "Select all",
"solidityUnitTesting.testTabTestsExecutionStopped": "The test execution has been stopped",
"solidityUnitTesting.testTabTestsExecutionStoppedError": "The test execution has been stopped because of error(s) in your test file",
"solidityUnitTesting.progress": "Progress: {readyTestsNumber} finished (of {runningTestsNumber})",
"solidityUnitTesting.resultFor": "Result for",
"solidityUnitTesting.passed": "Passed",
"solidityUnitTesting.failed": "Failed",
"solidityUnitTesting.timeTaken": "Time Taken",
"solidityUnitTesting.errorMessage": "Error Message",
"solidityUnitTesting.assertion": "Assertion",
"solidityUnitTesting.expectedValueShouldBe": "Expected value should be",
"solidityUnitTesting.receivedValue": "Received value",
"solidityUnitTesting.skippingTheRemainingTests": "Skipping the remaining tests of the function."
}

@ -0,0 +1,17 @@
{
"terminal.listen": "listen on all transactions",
"terminal.listenTitle": "If checked Remix will listen on all transactions mined in the current environment and not only transactions created by you",
"terminal.search": "Search with transaction hash or address",
"terminal.used": "used",
"terminal.debug": "Debug",
"terminal.welcomeText1": "Welcome to",
"terminal.welcomeText2": "Your files are stored in",
"terminal.welcomeText3": "You can use this terminal to",
"terminal.welcomeText4": "Check transactions details and start debugging",
"terminal.welcomeText5": "Execute JavaScript scripts",
"terminal.welcomeText6": "Input a script directly in the command line interface",
"terminal.welcomeText7": "Select a Javascript file in the file explorer and then run `remix.execute()` or `remix.exeCurrent()` in the command line interface",
"terminal.welcomeText8": "Right click on a JavaScript file in the file explorer and then click `Run`",
"terminal.welcomeText9": "The following libraries are accessible",
"terminal.welcomeText10": "Type the library name to see available commands"
}

@ -0,0 +1,64 @@
{
"udapp.displayName": "Deploy & run transactions",
"udapp.gasLimit": "Gas limit",
"udapp.account": "Account",
"udapp.value": "Value",
"udapp.contract": "Contract",
"udapp.compiledBy": "compiled by {compilerName}",
"udapp.infoSyncCompiledContractTooltip": "Click here to import contracts compiled from an external framework.This action is enabled when Remix is connected to an external framework (hardhat, truffle, foundry) through remixd.",
"udapp.remixIpfsUdappTooltip": "Publishing the source code and metadata to IPFS facilitates source code verification using Sourcify and will greatly foster contract adoption (auditing, debugging, calling it, etc...)",
"udapp.signAMessage": "Sign a message",
"udapp.enterAMessageToSign": "Enter a message to sign",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.signedMessage": "Signed Message",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.deploy": "Deploy",
"udapp.publishTo": "Publish to",
"udapp.or": "or",
"udapp.atAddress": "At Address",
"udapp.atAddressOptionsTitle1": "address of contract",
"udapp.atAddressOptionsTitle2": "Interact with the deployed contract - requires the .abi file or compiled .sol file to be selected in the editor (with the same compiler configuration)",
"udapp.atAddressOptionsTitle3": "Compile a *.sol file or select a *.abi file.",
"udapp.atAddressOptionsTitle4": "To interact with a deployed contract, either enter its address and compile its source *.sol file (with the same compiler settings) or select its .abi file in the editor. ",
"udapp.contractOptionsTitle1": "Please compile *.sol file to deploy or access a contract",
"udapp.contractOptionsTitle2": "Select a compiled contract to deploy or to use with At Address.",
"udapp.contractOptionsTitle3": "Select and compile *.sol file to deploy or access a contract.",
"udapp.contractOptionsTitle4": "When there is a compiled .sol file, choose the contract to deploy or to use with AtAddress.'",
"udapp.checkSumWarning": "It seems you are not using a checksumed address.A checksummed address is an address that contains uppercase letters, as specified in {a}.Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.",
"udapp.isOverSizePromptEip170": "Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fail if the current network has activated the eip 170. More info: {a}",
"udapp.isOverSizePromptEip3860": "Contract creation init code exceeds the allowed max code size of 49152 bytes. The deployment will likely fail if the current network has activated the eip 3860. More info: {a}",
"udapp.thisContractMayBeAbstract": "This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.",
"udapp.noCompiledContracts": "No compiled contracts",
"udapp.addressOfContract": "Address of contract",
"udapp.loadContractFromAddress": "Load contract from Address",
"udapp.deployedContracts": "Deployed Contracts",
"udapp.deployAndRunClearInstances": "Clear instances list and reset recorder",
"udapp.deployAndRunNoInstanceText": "Currently you have no contract instances to interact with.",
"udapp.transactionsRecorded": "Transactions recorded",
"udapp.transactionsCountTooltip": "The number of recorded transactions",
"udapp.transactionSaveTooltip1": "No transactions to save",
"udapp.transactionSaveTooltip2": "Save {count} transaction as scenario file",
"udapp.transactionSaveTooltip3": "Save {count} transactions as scenario file",
"udapp.infoRecorderTooltip": "Save transactions (deployed contracts and function executions) and replay them in another environment e.g Transactions created in Remix VM can be replayed in the Injected Provider.",
"udapp.livemodeRecorderTooltip": "If contracts are updated after recording transactions, checking this box will run recorded transactions with the latest copy of the compiled contracts",
"udapp.livemodeRecorderLabel": "Run transactions using the latest compilation result",
"udapp.runRecorderTooltip": "Run transaction(s) from the current scenario file",
"udapp.save": "Save",
"udapp.run": "Run",
"udapp.ok": "OK",
"udapp.alert": "Alert",
"udapp.proceed": "Proceed",
"udapp.cancel": "Cancel",
"udapp.parameters": "Parameters",
"udapp.copyParameters": "Copy encoded input parameters to clipboard",
"udapp.copyCalldata": "Copy calldata to clipboard",
"udapp.deployWithProxy": "Deploy with Proxy",
"udapp.upgradeWithProxy": "Upgrade with Proxy",
"udapp.useLastDeployedERC1967Contract": "Use last deployed ERC1967 contract",
"udapp.proxyAddressLabel": "Proxy Address",
"udapp.proxyAddressPlaceholder": "proxy address",
"udapp.proxyAddressInputTooltip": "Enter previously deployed proxy address on the selected network",
"udapp.proxyAddressTooltip": "Select this option to use the last deployed ERC1967 contract on the current network."
}

@ -0,0 +1,11 @@
{
"debugger.displayName": "Debugger",
"debugger.debuggerConfiguration": "Debugger Configuration",
"debugger.stopDebugging": "Stop debugging",
"debugger.startDebugging": "Start debugging",
"debugger.placeholder": "Transaction hash, should start with 0x",
"debugger.debugLocaNodeLabel": "Forcer l'utilisation d'un noeud local",
"debugger.useGeneratedSources": "Use generated sources",
"debugger.debugWithGeneratedSources": "Debug with generated sources",
"debugger.introduction": "When Debugging with a transaction hash, if the contract is verified, Remix will try to fetch the source code from Sourcify or Etherscan. Put in your Etherscan API key in the Remix settings. For supported networks, please see"
}

@ -0,0 +1,70 @@
{
"filePanel.displayName": "File explorer",
"filePanel.workspace": "WORKSPACES",
"filePanel.create": "Create",
"filePanel.clone": "Clone",
"filePanel.download": "Download",
"filePanel.backup": "Backup",
"filePanel.restore": "Restore",
"filePanel.workspace.create": "Create Workspace",
"filePanel.workspace.rename": "Rename Workspace",
"filePanel.workspace.delete": "Delete Workspace",
"filePanel.workspace.deleteConfirm": "Are you sure to delete the current workspace?",
"filePanel.workspace.download": "Download Workspace",
"filePanel.workspace.downloadConfirm": "This will download current workspace in a zip file. Do you want to continue?",
"filePanel.workspace.deleteAll": "Delete All Workspaces",
"filePanel.workspace.deleteAllConfirm1": "Are you absolutely sure you want to delete all your workspaces?",
"filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.",
"filePanel.workspace.name": "Workspace name",
"filePanel.workspace.chooseTemplate": "Choose a template",
"filePanel.workspace.backup": "Backup All Workspaces",
"filePanel.workspace.restore": "Restore Workspaces from the Backup",
"filePanel.workspace.clone": "Clone Git Repository",
"filePanel.workspace.cloneMessage": "Please provide a valid git repository url.",
"filePanel.workspace.enterGitUrl": "Enter git repository url",
"filePanel.workspace.switch": "Switch To Workspace",
"filePanel.workspace.solghaction": "Adds a preset yml file to run solidity unit tests on github actions CI.",
"filePanel.solghaction": "Solidity Test Workflow",
"filePanel.workspace.tssoltestghaction": "Adds a preset yml file to run mocha and chai tests for solidity on github actions CI",
"filePanel.tssoltestghaction": "Mocha Chai Test Workflow",
"filePanel.workspace.addscriptetherscan": "Adds a scripts which can be used to interact with the etherscan API.",
"filePanel.addscriptetherscan": "Add Etherscan script",
"filePanel.workspace.addscriptdeployer": "Adds a scripts which can be used to deploy contracts.",
"filePanel.addscriptdeployer": "Add Contract deployer script",
"filePanel.workspace.slitherghaction": "Adds a preset yml file to run slither analysis on github actions CI",
"filePanel.slitherghaction": "Slither Workflow",
"filePanel.workspace.helperscripts": "Adds convenient scripts to the 'scripts' directory",
"filePanel.helperscripts": "Web3 Scripts",
"filePanel.newFile": "New File",
"filePanel.newFolder": "New Folder",
"filePanel.rename": "Rename",
"filePanel.delete": "Delete",
"filePanel.deleteAll": "Delete All",
"filePanel.run": "Run",
"filePanel.pushChangesToGist": "Push changes to gist",
"filePanel.publishFolderToGist": "Publish folder to gist",
"filePanel.publishFileToGist": "Publish file to gist",
"filePanel.copy": "Copy",
"filePanel.paste": "Paste",
"filePanel.compile": "Compile",
"filePanel.compileForNahmii": "Compile for Nahmii",
"filePanel.createNewFile": "Create new file",
"filePanel.createNewFolder": "Create new folder",
"filePanel.publishToGist": "Publish all files to GitHub gist",
"filePanel.uploadFile": "Upload files",
"filePanel.uploadFolder": "Upload folder",
"filePanel.updateGist": "Update the current [gist] explorer",
"filePanel.viewAllBranches": "View all branches",
"filePanel.createBranch": "Create branch",
"filePanel.switchBranches": "Switch branches",
"filePanel.checkoutGitBranch": "Checkout Git Branch",
"filePanel.findOrCreateABranch": "Find or create a branch.",
"filePanel.initGitRepositoryLabel": "Initialize workspace as a new git repository",
"filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Settings panel.",
"filePanel.workspaceName": "Workspace name",
"filePanel.customizeTemplate": "Customize template",
"filePanel.features": "Features",
"filePanel.upgradeability": "Upgradeability",
"filePanel.ok": "OK",
"filePanel.cancel": "Cancel"
}

@ -0,0 +1,61 @@
{
"home.scamAlert": "Scam Alert",
"home.scamAlertText": "The only URL Remix uses is remix.ethereum.org",
"home.scamAlertText2": "Beware of online videos promoting \"liquidity front runner bots\"",
"home.scamAlertText3": "Additional safety tips",
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
"home.remixYouTubeText2": "Remix has a growing library of videos containing lots of tips for using the tool. Check them out and subscribe to get our latest uploads.",
"home.betaTesting": "BETA TESTING",
"home.betaTestingText1": "Our community supports us.",
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test and analyse smart contract.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",
"home.solhintPluginDesc": "Solhint is an open source project for linting Solidity code.",
"home.sourcifyPluginDesc": "Solidity contract and metadata verification service.",
"home.unitTestPluginDesc": "Write and run unit tests for your contracts in Solidity.",
"home.dgitPluginDesc": "Add source control to your projects.",
"home.oneClickDappDesc": "Quickly generate smart contract interfaces",
"home.getStarted": "Get Started",
"home.projectTemplates": "Project Templates",
"home.blankTemplateDesc": "Create an empty workspace.",
"home.remixDefaultTemplateDesc": "Create a workspace with sample files.",
"home.ozerc20TemplateDesc": "Create an ERC20 token by importing OpenZeppelin library.",
"home.ozerc721TemplateDesc": "Create an NFT token by importing OpenZeppelin library.",
"home.ozerc1155TemplateDesc": "Create an ERC1155 token by importing OpenZeppelin library.",
"home.gnosisSafeMultisigTemplateDesc": "Create Multi-Signature wallets using this template.",
"home.zeroxErc20TemplateDesc": "Create an ERC20 token by importing 0xProject contract.",
"home.learn": "Learn",
"home.learnEth1": "Remix Basics",
"home.learnEth1Desc": "An introduction to Remix's interface and basic operations.",
"home.learnEth2": "Intro to Solidity",
"home.learnEth2Desc": "Interactively learn Solidity beginner concepts.",
"home.remixAdvanced": "Deploying with Libraries",
"home.remixAdvancedDesc": "Learn to deploy with libraries in Remix",
"home.remixYoutubePlaylist": "Remix Youtube Playlist",
"home.remixTwitterProfile": "Remix Twitter Profile",
"home.remixLinkedinProfile": "Remix Linkedin Profile",
"home.remixMediumPosts": "Remix Medium Posts",
"home.remixGitterChannel": "Join us on Discord",
"home.nativeIDE": "The Native IDE for Web3 Development.",
"home.website": "Website",
"home.documentation": "Documentation",
"home.remixPlugin": "Remix Plugin",
"home.remixDesktop": "Remix Desktop",
"home.searchDocumentation": "Search Documentation",
"home.files": "Files",
"home.newFile": "New File",
"home.openFile": "Open File",
"home.connectToLocalhost": "Access File System",
"home.loadFrom": "Load from",
"home.resources": "Resources"
}

@ -0,0 +1,6 @@
{
"panel.author": "Author",
"panel.maintainedBy": "Maintained By",
"panel.documentation": "Documentation",
"panel.description": "Description"
}

@ -0,0 +1,13 @@
{
"permissionHandler.allPermissionsReset": "All permisssions have been reset.",
"permissionHandler.rememberText": "has changed and",
"permissionHandler.permissionHandlerMessage": "\"{from}\" {rememberText} would like to access to \"{method}\" of \"{to}\"`",
"permissionHandler.description": "Description",
"permissionHandler.noDescriptionProvided": "No description Provided",
"permissionHandler.makeSureYouTrustThisPlugin": "Make sure you trust this plugin before processing this call. If you choose to remember the choice for this specific call, the value will be kept only for the current session.",
"permissionHandler.rememberThisChoice": "Remember this choice",
"permissionHandler.resetAllPermissions": "Reset all Permissions",
"permissionHandler.permissionNeededFor": "Permission needed for {to}",
"permissionHandler.accept": "Accept",
"permissionHandler.decline": "Decline"
}

@ -0,0 +1,31 @@
{
"pluginManager.displayName": "Plugin manager",
"pluginManager.activate": "Activate",
"pluginManager.deactivate": "Deactivate",
"pluginManager.activeModules": "Active Modules",
"pluginManager.inactiveModules": "Inactive Modules",
"pluginManager.connectLocal": "Connect to a Local Plugin",
"pluginManager.localForm.title": "Local Plugin",
"pluginManager.localForm.pluginName": "Plugin Name",
"pluginManager.localForm.shouldBeCamelCase": "Should be camelCase",
"pluginManager.localForm.displayName": "Display Name",
"pluginManager.localForm.nameInTheHeader": "Name in the header",
"pluginManager.localForm.required": "required",
"pluginManager.localForm.commaSeparatedMethod": "comma separated list of method names",
"pluginManager.localForm.commaSeparatedPlugin": "comma separated list of plugin names",
"pluginManager.localForm.pluginsItCanActivate": "Plugins it can activate",
"pluginManager.localForm.typeOfConnection": "Type of connection",
"pluginManager.localForm.locationInRemix": "Location in remix",
"pluginManager.localForm.sidePanel": "Side Panel",
"pluginManager.localForm.mainPanel": "Main Panel",
"pluginManager.localForm.none": "None",
"pluginManager.Permissions": "Permissions",
"pluginManager.permissions": "permissions",
"pluginManager.pluginManagerPermissions": "Plugin Manager Permissions",
"pluginManager.currentPermissionSettings": "Current Permission Settings",
"pluginManager.noPermissionRequestedYet": "No Permission requested yet.",
"pluginManager.allow": "Allow",
"pluginManager.toCall": "to call",
"pluginManager.ok": "OK",
"pluginManager.cancel": "Cancel"
}

@ -0,0 +1,14 @@
{
"search.displayName": "Search in files",
"search.replace": "Replace",
"search.replaceAll": "Replace All",
"search.placeholder1": "Search ( Enter to search )",
"search.placeholder2": "Include ie *.sol ( Enter to include )",
"search.placeholder3": "Exclude ie .git/**/* ( Enter to exclude )",
"search.matchCase": "Match Case",
"search.matchWholeWord": "Match Whole Word",
"search.useRegularExpression": "Use Regular Expression",
"search.replaceWithoutConfirmation": "replace without confirmation",
"search.filesToInclude": "Files to include",
"search.filesToExclude": "Files to exclude"
}

@ -0,0 +1,26 @@
{
"settings.displayName": "Settings",
"settings.reset": "Reset to Default settings",
"settings.general": "General settings",
"settings.generateContractMetadataText": "Generate contract metadata. Generate a JSON file in the contract folder. Allows to specify library addresses the contract depends on. If nothing is specified, Remix deploys libraries automatically.",
"settings.ethereunVMText": "Always use the Remix VM at load",
"settings.wordWrapText": "Word wrap in editor",
"settings.useAutoCompleteText": "Enable code completion in editor.",
"settings.useShowGasInEditorText": "Display gas estimates in editor.",
"settings.displayErrorsText": "Display errors in editor while typing.",
"settings.matomoAnalytics": "Enable Matomo Analytics. We do not collect personally identifiable information (PII). The info is used to improve the site’s UX & UI. See more about ",
"settings.enablePersonalModeText": " Enable Personal Mode for web3 provider. Transaction sent over Web3 will use the web3.personal API.\n",
"settings.warnText": "Be sure the endpoint is opened before enabling it. This mode allows a user to provide a passphrase in the Remix interface without having to unlock the account. Although this is very convenient, you should completely trust the backend you are connected to (Geth, Parity, ...). Remix never persists any passphrase",
"settings.gitAccessTokenTitle": "Github Credentials",
"settings.gitAccessTokenText": "The access token is used to publish a Gist and retrieve GitHub contents. You may need to input username/email.",
"settings.gitAccessTokenText2": "Go to github token page (link below) to create a new token and save it in Remix. Make sure this token has only 'create gist' permission",
"settings.etherscanTokenTitle": "EtherScan Access Token",
"settings.etherscanAccessTokenText": "Manage the api key used to interact with Etherscan.",
"settings.etherscanAccessTokenText2": "Go to Etherscan api key page (link below) to create a new api key and save it in Remix.",
"settings.save": "Save",
"settings.remove": "Remove",
"settings.themes": "Themes",
"settings.locales": "Language",
"settings.swarm": "Swarm Settings",
"settings.ipfs": "IPFS Settings"
}

@ -0,0 +1,4 @@
{
"solUml.pngDownload": "Download as PNG",
"solUml.pdfDownload": "Download as PDF"
}

@ -0,0 +1,41 @@
{
"solidity.displayName": "Solidity compiler",
"solidity.compiler": "Compiler",
"solidity.addACustomCompiler": "Add a custom compiler",
"solidity.addACustomCompilerWithURL": "Add a custom compiler with URL",
"solidity.includeNightlyBuilds": "Include nightly builds",
"solidity.autoCompile": "Auto compile",
"solidity.hideWarnings": "Hide warnings",
"solidity.enableHardhat": "Enable Hardhat Compilation",
"solidity.learnHardhat": "Learn how to use Hardhat Compilation",
"solidity.enableTruffle": "Enable Truffle Compilation",
"solidity.learnTruffle": "Learn how to use Truffle Compilation",
"solidity.advancedConfigurations": "Advanced Configurations",
"solidity.compilerConfiguration": "Compiler configuration",
"solidity.compilationDetails": "Compilation Details",
"solidity.language": "Language",
"solidity.evmVersion": "EVM Version",
"solidity.enableOptimization": "Enable optimization",
"solidity.useConfigurationFile": "Use configuration file",
"solidity.change": "Change",
"solidity.compile": "Compile",
"solidity.noFileSelected": "no file selected",
"solidity.compileAndRunScript": "Compile and Run script",
"solidity.publishOn": "Publish on",
"solidity.flatten": "Flatten contracts before UML generation.",
"solidity.generateUML": "Generate a UML diagram of your contract.",
"solidity.flattenLabel": "Flatten",
"solidity.generateUMLLabel": "Generate UML Diagram",
"solidity.Assembly": "Assembly opcodes describing the contract including corresponding solidity source code",
"solidity.Opcodes": "Assembly opcodes describing the contract",
"solidity.name": "Name of the compiled contract",
"solidity.metadata": "Contains all informations related to the compilation",
"solidity.bytecode": "Bytecode being executed during contract creation",
"solidity.abi": "ABI: describing all the functions (input/output params, scope, ...)",
"solidity.web3Deploy": "Copy/paste this code to any JavaScript/Web3 console to deploy this contract",
"solidity.metadataHash": "Hash representing all metadata information",
"solidity.functionHashes": "List of declared function and their corresponding hash",
"solidity.gasEstimates": "Gas estimation for each function call",
"solidity.Runtime Bytecode": "Bytecode storing the state and being executed during normal contract call",
"solidity.swarmLocation": "Swarm url where all metadata information can be found (contract needs to be published first)"
}

@ -0,0 +1,35 @@
{
"solidityUnitTesting.displayName": "Solidity unit testing",
"solidityUnitTesting.testDirectory": "Test directory",
"solidityUnitTesting.testYourSmartContract": "Test your smart contract in Solidity.",
"solidityUnitTesting.selectDirectory": "Select directory to load and generate test files.",
"solidityUnitTesting.uiPathInputTooltip": "Press 'Enter' to change the path for test files.",
"solidityUnitTesting.uiPathInputButtonTooltip": "Create a test folder",
"solidityUnitTesting.create": "Create",
"solidityUnitTesting.generateTestsButtonTooltip": "Generate a sample test file",
"solidityUnitTesting.generate": "Generate",
"solidityUnitTesting.generateTestsLinkTooltip": "Check out documentation.",
"solidityUnitTesting.howToUse": "How to use...",
"solidityUnitTesting.runButtonTitle1": "Run tests",
"solidityUnitTesting.runButtonTitle2": "Please select Solidity compiler version greater than 0.4.12.",
"solidityUnitTesting.runButtonTitle3": "No solidity file selected",
"solidityUnitTesting.runButtonTitle4": "The \"Solidity Plugin\" should be activated",
"solidityUnitTesting.runButtonTitle5": "No test file selected",
"solidityUnitTesting.stopButtonLabel1": "Stop",
"solidityUnitTesting.stopButtonLabel2": "Stopping",
"solidityUnitTesting.run": "Run",
"solidityUnitTesting.runTestsTabStopActionTooltip": "Stop running tests",
"solidityUnitTesting.selectAll": "Select all",
"solidityUnitTesting.testTabTestsExecutionStopped": "The test execution has been stopped",
"solidityUnitTesting.testTabTestsExecutionStoppedError": "The test execution has been stopped because of error(s) in your test file",
"solidityUnitTesting.progress": "Progress: {readyTestsNumber} finished (of {runningTestsNumber})",
"solidityUnitTesting.resultFor": "Result for",
"solidityUnitTesting.passed": "Passed",
"solidityUnitTesting.failed": "Failed",
"solidityUnitTesting.timeTaken": "Time Taken",
"solidityUnitTesting.errorMessage": "Error Message",
"solidityUnitTesting.assertion": "Assertion",
"solidityUnitTesting.expectedValueShouldBe": "Expected value should be",
"solidityUnitTesting.receivedValue": "Received value",
"solidityUnitTesting.skippingTheRemainingTests": "Skipping the remaining tests of the function."
}

@ -0,0 +1,17 @@
{
"terminal.listen": "listen on all transactions",
"terminal.listenTitle": "If checked Remix will listen on all transactions mined in the current environment and not only transactions created by you",
"terminal.search": "Search with transaction hash or address",
"terminal.used": "used",
"terminal.debug": "Debug",
"terminal.welcomeText1": "Welcome to",
"terminal.welcomeText2": "Your files are stored in",
"terminal.welcomeText3": "You can use this terminal to",
"terminal.welcomeText4": "Check transactions details and start debugging",
"terminal.welcomeText5": "Execute JavaScript scripts",
"terminal.welcomeText6": "Input a script directly in the command line interface",
"terminal.welcomeText7": "Select a Javascript file in the file explorer and then run `remix.execute()` or `remix.exeCurrent()` in the command line interface",
"terminal.welcomeText8": "Right click on a JavaScript file in the file explorer and then click `Run`",
"terminal.welcomeText9": "The following libraries are accessible",
"terminal.welcomeText10": "Type the library name to see available commands"
}

@ -0,0 +1,64 @@
{
"udapp.displayName": "Deploy & run transactions",
"udapp.gasLimit": "Gas limit",
"udapp.account": "Account",
"udapp.value": "Value",
"udapp.contract": "Contract",
"udapp.compiledBy": "compiled by {compilerName}",
"udapp.infoSyncCompiledContractTooltip": "Click here to import contracts compiled from an external framework.This action is enabled when Remix is connected to an external framework (hardhat, truffle, foundry) through remixd.",
"udapp.remixIpfsUdappTooltip": "Publishing the source code and metadata to IPFS facilitates source code verification using Sourcify and will greatly foster contract adoption (auditing, debugging, calling it, etc...)",
"udapp.signAMessage": "Sign a message",
"udapp.enterAMessageToSign": "Enter a message to sign",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.signedMessage": "Signed Message",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.deploy": "Deploy",
"udapp.publishTo": "Publish to",
"udapp.or": "or",
"udapp.atAddress": "At Address",
"udapp.atAddressOptionsTitle1": "address of contract",
"udapp.atAddressOptionsTitle2": "Interact with the deployed contract - requires the .abi file or compiled .sol file to be selected in the editor (with the same compiler configuration)",
"udapp.atAddressOptionsTitle3": "Compile a *.sol file or select a *.abi file.",
"udapp.atAddressOptionsTitle4": "To interact with a deployed contract, either enter its address and compile its source *.sol file (with the same compiler settings) or select its .abi file in the editor. ",
"udapp.contractOptionsTitle1": "Please compile *.sol file to deploy or access a contract",
"udapp.contractOptionsTitle2": "Select a compiled contract to deploy or to use with At Address.",
"udapp.contractOptionsTitle3": "Select and compile *.sol file to deploy or access a contract.",
"udapp.contractOptionsTitle4": "When there is a compiled .sol file, choose the contract to deploy or to use with AtAddress.'",
"udapp.checkSumWarning": "It seems you are not using a checksumed address.A checksummed address is an address that contains uppercase letters, as specified in {a}.Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.",
"udapp.isOverSizePromptEip170": "Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fail if the current network has activated the eip 170. More info: {a}",
"udapp.isOverSizePromptEip3860": "Contract creation init code exceeds the allowed max code size of 49152 bytes. The deployment will likely fail if the current network has activated the eip 3860. More info: {a}",
"udapp.thisContractMayBeAbstract": "This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.",
"udapp.noCompiledContracts": "No compiled contracts",
"udapp.addressOfContract": "Address of contract",
"udapp.loadContractFromAddress": "Load contract from Address",
"udapp.deployedContracts": "Deployed Contracts",
"udapp.deployAndRunClearInstances": "Clear instances list and reset recorder",
"udapp.deployAndRunNoInstanceText": "Currently you have no contract instances to interact with.",
"udapp.transactionsRecorded": "Transactions recorded",
"udapp.transactionsCountTooltip": "The number of recorded transactions",
"udapp.transactionSaveTooltip1": "No transactions to save",
"udapp.transactionSaveTooltip2": "Save {count} transaction as scenario file",
"udapp.transactionSaveTooltip3": "Save {count} transactions as scenario file",
"udapp.infoRecorderTooltip": "Save transactions (deployed contracts and function executions) and replay them in another environment e.g Transactions created in Remix VM can be replayed in the Injected Provider.",
"udapp.livemodeRecorderTooltip": "If contracts are updated after recording transactions, checking this box will run recorded transactions with the latest copy of the compiled contracts",
"udapp.livemodeRecorderLabel": "Run transactions using the latest compilation result",
"udapp.runRecorderTooltip": "Run transaction(s) from the current scenario file",
"udapp.save": "Save",
"udapp.run": "Run",
"udapp.ok": "OK",
"udapp.alert": "Alert",
"udapp.proceed": "Proceed",
"udapp.cancel": "Cancel",
"udapp.parameters": "Parameters",
"udapp.copyParameters": "Copy encoded input parameters to clipboard",
"udapp.copyCalldata": "Copy calldata to clipboard",
"udapp.deployWithProxy": "Deploy with Proxy",
"udapp.upgradeWithProxy": "Upgrade with Proxy",
"udapp.useLastDeployedERC1967Contract": "Use last deployed ERC1967 contract",
"udapp.proxyAddressLabel": "Proxy Address",
"udapp.proxyAddressPlaceholder": "proxy address",
"udapp.proxyAddressInputTooltip": "Enter previously deployed proxy address on the selected network",
"udapp.proxyAddressTooltip": "Select this option to use the last deployed ERC1967 contract on the current network."
}

@ -10,11 +10,14 @@
"filePanel.workspace.rename": "重命名工作空间",
"filePanel.workspace.delete": "删除工作空间",
"filePanel.workspace.deleteConfirm": "确定要删除当前工作空间?",
"filePanel.workspace.download": "下载工作空间",
"filePanel.workspace.downloadConfirm": "This will download current workspace in a zip file. Do you want to continue?",
"filePanel.workspace.deleteAll": "Delete All Workspaces",
"filePanel.workspace.deleteAllConfirm1": "Are you absolutely sure you want to delete all your workspaces?",
"filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.", "filePanel.workspace.name": "工作空间名称",
"filePanel.workspace.deleteAllConfirm2": "Deleted workspaces can not be restored in any manner.",
"filePanel.workspace.name": "工作空间名称",
"filePanel.workspace.chooseTemplate": "选择一个工作空间模板",
"filePanel.workspace.download": "下载工作空间",
"filePanel.workspace.backup": "Backup All Workspaces",
"filePanel.workspace.restore": "恢复工作空间",
"filePanel.workspace.clone": "克隆 Git 仓库",
"filePanel.workspace.cloneMessage": "请提供有效的 git 仓库 url。",
@ -24,8 +27,14 @@
"filePanel.solghaction": "Solidity 测试工作流",
"filePanel.workspace.tssoltestghaction": "添加一个预设的 yml 文件,这样就可以在 github actions CI 上为 solidity 运行 mocha 和 chai 测试",
"filePanel.tssoltestghaction": "Mocha Chai 测试工作流",
"filePanel.workspace.addscriptetherscan": "Adds a scripts which can be used to interact with the etherscan API.",
"filePanel.addscriptetherscan": "Add Etherscan script",
"filePanel.workspace.addscriptdeployer": "Adds a scripts which can be used to deploy contracts.",
"filePanel.addscriptdeployer": "Add Contract deployer script",
"filePanel.workspace.slitherghaction": "添加一个预设的 yml 文件,这样就可以在 github actions CI 上运行 slither 分析",
"filePanel.slitherghaction": "Slither 工作流",
"filePanel.workspace.helperscripts": "Adds convenient scripts to the 'scripts' directory",
"filePanel.helperscripts": "Web3 Scripts",
"filePanel.newFile": "新建文件",
"filePanel.newFolder": "新建文件夹",
"filePanel.rename": "重命名",
@ -43,6 +52,7 @@
"filePanel.createNewFolder": "新建文件夹",
"filePanel.publishToGist": "将当前工作空间下所有文件发布到github gist",
"filePanel.uploadFile": "加载本地文件到当前工作空间",
"filePanel.uploadFolder": "Upload folder",
"filePanel.updateGist": "更新当前 [gist] 浏览",
"filePanel.viewAllBranches": "查看所有分支",
"filePanel.createBranch": "创建分支",

@ -5,9 +5,9 @@
"home.scamAlertText3": "其他安全提示",
"home.learnMore": "了解更多",
"home.here": "这里",
"home.more": "更多",
"home.featured": "精选",
"home.jumpIntoWeb3": "迎接 WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix 项目是一个丰富的工具集,任何知识水平的用户都可以在这上面进行全周期的合约开发,并且可作为以太坊教学和实验的学习实验室。",
"home.remixYouTube": "观看学习",
"home.remixYouTubeText1": "来自 Remix 团队的视频小贴士",
@ -16,6 +16,7 @@
"home.betaTesting": "BETA 测试",
"home.betaTestingText1": "我们的社区支持我们",
"home.betaTestingText2": "每次 Remix IDE 发布版本之前,你都可以参与 Beta 测试。现在就来帮我们测试并且尝鲜新功能吧!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "精选插件",
"home.solidityPluginDesc": "编译、测试和分析智能合约。",
"home.starkNetPluginDesc": "用 Cairo 来编译且部署合约,这是 StarkNet 的原生语言",
@ -23,6 +24,7 @@
"home.sourcifyPluginDesc": "Solidity 合约和元数据验证服务。",
"home.unitTestPluginDesc": "在 Solidity 中为你的合约编写和运行单元测试。",
"home.dgitPluginDesc": "为你的项目添加源码控制。",
"home.oneClickDappDesc": "Quickly generate smart contract interfaces",
"home.getStarted": "开始使用",
"home.projectTemplates": "项目模板",
"home.blankTemplateDesc": "创建一个空的工作空间。",
@ -33,10 +35,10 @@
"home.gnosisSafeMultisigTemplateDesc": "使用此模板创建多重签名钱包。",
"home.zeroxErc20TemplateDesc": "通过引入 0xProject 合约来创建一个 ERC20 代币。",
"home.learn": "学习",
"home.remixBasics": "Remix 基础",
"home.remixBasicsDesc": "介绍 Remix 的界面和在以太坊中使用的概念,以及 Solidity 的基础知识。",
"home.remixIntermediate": "Remix 中级",
"home.remixIntermediateDesc": "使用 web3.js 与合约交互。使用记录器工具。",
"home.learnEth1": "Remix Basics",
"home.learnEth1Desc": "An introduction to Remix's interface and basic operations.",
"home.learnEth2": "Intro to Solidity",
"home.learnEth2Desc": "Interactively learn Solidity beginner concepts.",
"home.remixAdvanced": "Remix 高级",
"home.remixAdvancedDesc": "学习代理模式并使用 Remix 中的库。学习使用调试器。",
"home.remixYoutubePlaylist": "Remix Youtube 播放列表",

@ -13,7 +13,7 @@
"settings.warnText": "在启用之前请确认访问端结点已经开放. 此模式允许在Remix界面中提供密码而无需解锁账号. 虽然这很方便,但你应当完全信任所连接的后端节点 (Geth, Parity, ...). Remix不会持久化保存任何密码.",
"settings.gitAccessTokenTitle": "Github 访问令牌",
"settings.gitAccessTokenText": "管理用于发布到 Gist 以及读取 Github 内容的 GitHub 访问令牌.",
"settings.gitAccessTokenText2":"前往 github (参见下方链接) 创建一个新的token,然后保存到Remix中. 确保这个token只有 'create gist' 权限.",
"settings.gitAccessTokenText2": "前往 github (参见下方链接) 创建一个新的token,然后保存到Remix中. 确保这个token只有 'create gist' 权限.",
"settings.etherscanTokenTitle": "EtherScan 访问 Token",
"settings.etherscanAccessTokenText": "管理用于与Etherscan交互的api密钥.",
"settings.etherscanAccessTokenText2": "前往 Etherscan api 密钥页面 (参见下方链接),创建一个新的api密钥并保存到Remix中.",

@ -1,4 +1,4 @@
{
"solUml.PngDownload": "sfg",
"solUml.PdfDownload": "sdf"
"solUml.pngDownload": "Download as PNG",
"solUml.pdfDownload": "Download as PDF"
}

@ -22,10 +22,10 @@
"solidity.noFileSelected": "未选中文件",
"solidity.compileAndRunScript": "编译且执行脚本",
"solidity.publishOn": "发布到",
"solidity.flatten": "",
"solidity.generateUML": "",
"solidity.flattenLabel": "",
"solidity.generateUMLLabel": "",
"solidity.flatten": "Flatten contracts before UML generation.",
"solidity.generateUML": "Generate a UML diagram of your contract.",
"solidity.flattenLabel": "Flatten",
"solidity.generateUMLLabel": "Generate UML Diagram",
"solidity.Assembly": "合约的汇编操作码,包含对应的solidity源程序",
"solidity.Opcodes": "合约的汇编操作码",
"solidity.name": "已编译合约的名称",

@ -27,7 +27,8 @@
"udapp.contractOptionsTitle3": "选择并编译 *.sol 文件以部署或访问合约。",
"udapp.contractOptionsTitle4": "当有编译的 .sol 文件时,选择 {br} 合约进行部署或与 AtAddress 一起使用。",
"udapp.checkSumWarning": "您似乎没有使用 checksumed address 。{br} checksumed address 是包含大写字母的地址,如 {a} 中所指定。{br} checksumed address 旨在帮助防止用户将交易发送到错误地址。",
"udapp.isOverSizePrompt": "合约创建初始化返回长度超过24576字节的数据。部署可能会失败。 {br}更多信息:{a}",
"udapp.isOverSizePromptEip170": "合约创建初始化返回长度超过24576字节的数据。部署可能会失败。 {br}更多信息:{a}",
"udapp.isOverSizePromptEip3860": "Contract creation init code exceeds the allowed max code size of 49152 bytes. The deployment will likely fail if the current network has activated the eip 3860. More info: {a}",
"udapp.thisContractMayBeAbstract": "这个合约可能是抽象的,它可能没有完全实现抽象父类的方法,或者它可能没有正确调用继承合约的构造函数。",
"udapp.noCompiledContracts": "没有已编译的合约",
"udapp.addressOfContract": "合约地址",

@ -170,7 +170,7 @@ export class RunTab extends ViewPlugin {
await addProvider('injected-optimism-provider', 'L2 - Optimism Provider', true, false)
await addProvider('injected-arbitrum-one-provider', 'L2 - Arbitrum One Provider', true, false)
await addProvider('walletconnect', 'Wallet Connect', false, false)
await addProvider('walletconnect', 'WalletConnect', false, false)
}

@ -5,6 +5,13 @@ const domains = {
'6fd22d6fe5549ad4c4d8fd3ca0b7816b.mod': 35 // remix desktop
}
const domainsSecondaryTracker = {
'remix-alpha.ethereum.org': 27,
'remix-beta.ethereum.org': 25,
'remix.ethereum.org': 23,
'6fd22d6fe5549ad4c4d8fd3ca0b7816b.mod': 35 // remix desktop
}
if (domains[window.location.hostname]) {
var _paq = window._paq = window._paq || []
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
@ -21,12 +28,10 @@ if (domains[window.location.hostname]) {
var u = "https://matomo.ethereum.org/";
_paq.push(['setTrackerUrl', u + 'matomo.php'])
_paq.push(['setSiteId', domains[window.location.hostname]])
// Send all of the Remix live tracking data to the secondary Matomo server
if (window.location.hostname === 'remix.ethereum.org') {
var secondaryTracker = 'https://remix-ethereum.matomo.cloud/matomo.php';
var secondaryWebsiteId = 1;
_paq.push(['addTracker', secondaryTracker, secondaryWebsiteId]);
}
// Send all of the Remix tracking data to the secondary Matomo server
var secondaryTracker = 'https://ethereumfoundation.matomo.cloud/matomo.php';
var secondaryWebsiteId = domainsSecondaryTracker[window.location.hostname];
_paq.push(['addTracker', secondaryTracker, secondaryWebsiteId]);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0]
g.type = 'text/javascript'; g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s)
})()

@ -111,12 +111,21 @@ export class Blockchain extends Plugin {
this._triggerEvent('networkStatus', [this.networkStatus])
})
})
this.on('walletconnect', 'chainChanged', () => {
this.detectNetwork((error, network) => {
this.networkStatus = { network, error }
this._triggerEvent('networkStatus', [this.networkStatus])
})
})
}
onDeactivation () {
this.active = false
this.off('injected', 'chainChanged')
this.off('injected-trustwallet', 'chainChanged')
this.off('walletconnect', 'chainChanged')
this.off('walletconnect', 'accountsChanged')
}
setupEvents () {

@ -17,7 +17,7 @@ const requiredModules = [ // services + layout views + system views
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)
const dependentModules = ['foundry', 'hardhat', 'truffle', 'slither']
const loadLocalPlugins = ["doc-gen", "doc-viewer", "etherscan", "vyper"]
const loadLocalPlugins = ["doc-gen", "doc-viewer", "etherscan", "vyper", 'solhint', 'walletconnect']
const sensitiveCalls = {
'fileManager': ['writeFile', 'copyFile', 'rename', 'copyDir'],
@ -71,11 +71,19 @@ export class RemixAppManager extends PluginManager {
}
async deactivatePlugin(name) {
const profile = await this.getProfile(name)
const [to, from] = [
await this.getProfile(name),
profile,
await this.getProfile(this.requestFrom)
]
if (this.canDeactivatePlugin(from, to)) {
if (profile.methods.includes('deactivate')) {
try {
await this.call(name, 'deactivate')
} catch (e) {
console.log(e)
}
}
await this.toggleActive(name)
}
}
@ -184,7 +192,8 @@ export class RemixAppManager extends PluginManager {
extension: ['.sol'],
path: [],
pattern: [],
sticky: true
sticky: true,
group: 5
})
await this.call('filePanel', 'registerContextMenuItem', {
id: 'nahmii-compiler',
@ -194,7 +203,8 @@ export class RemixAppManager extends PluginManager {
extension: ['.sol'],
path: [],
pattern: [],
sticky: true
sticky: true,
group: 6
})
await this.call('filePanel', 'registerContextMenuItem', {
id: 'solidityumlgen',
@ -204,7 +214,8 @@ export class RemixAppManager extends PluginManager {
extension: ['.sol'],
path: [],
pattern: [],
sticky: true
sticky: true,
group: 7
})
await this.call('filePanel', 'registerContextMenuItem', {
id: 'doc-gen',
@ -214,6 +225,17 @@ export class RemixAppManager extends PluginManager {
extension: ['.sol'],
path: [],
pattern: [],
sticky: true,
group: 7
})
await this.call('filePanel', 'registerContextMenuItem', {
id: 'solhint',
name: 'lintContractCustomAction',
label: 'Lint Contract',
type: [],
extension: ['.sol'],
path: [],
pattern: [],
sticky: true
})
}

@ -0,0 +1,16 @@
{
"name": "solhint",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"resolutions": {
"antlr4": "4.11"
},
"dependencies": {
"solhint": "^3.4.1"
},
"devDependencies": {
"@remixproject/plugin": "^0.3.31",
"@remixproject/plugin-webview": "^0.3.31"
}
}

@ -0,0 +1,70 @@
{
"name": "solhint",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/solhint/src",
"projectType": "application",
"implicitDependencies": [],
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": [
"{options.outputPath}"
],
"dependsOn": ["install"],
"defaultConfiguration": "development",
"options": {
"compiler": "babel",
"outputPath": "dist/apps/solhint",
"index": "apps/solhint/src/index.html",
"baseHref": "./",
"main": "apps/solhint/src/main.tsx",
"tsConfig": "apps/solhint/tsconfig.app.json",
"assets": [
"apps/solhint/src/favicon.ico",
"apps/solhint/src/profile.json"
],
"styles": [],
"webpackConfig": "apps/solhint/webpack.config.js"
},
"configurations": {
"development": {},
"production": {
"fileReplacements": [
{
"replace": "apps/solhint/src/environments/environment.ts",
"with": "apps/solhint/src/environments/environment.prod.ts"
}
]
}
}
},
"install": {
"executor": "nx:run-commands",
"options": {
"commands": [
"cd apps/solhint && yarn"
],
"parallel": false
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "solhint:build",
"hmr": true,
"baseHref": "/"
},
"configurations": {
"development": {
"buildTarget": "solhint:build:development",
"port": 7003
},
"production": {
"buildTarget": "solhint:build:production"
}
}
}
},
"tags": []
}

@ -0,0 +1,8 @@
import React, { useEffect, useState } from "react";
import { SolHint } from "./SolhintPluginClient";
const client = new SolHint();
export default function App() {
return <></>;
}

@ -0,0 +1,145 @@
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import EventEmitter from 'events'
import { processStr } from 'solhint'
import { applyExtends } from 'solhint/lib/config/config-file'
import bestPractises from 'solhint/lib/rules/best-practises'
import naming from 'solhint/lib/rules/naming'
import order from 'solhint/lib/rules/order'
import security from 'solhint/lib/rules/security'
import deprecations from 'solhint/lib/rules/deprecations'
import miscellaneous from 'solhint/lib/rules/miscellaneous'
import { customAction } from '@remixproject/plugin-api'
type Report = {
line: number,
column: number,
severity: string,
message: string,
ruleId: string,
fix: string
}
const Config = `{
"extends": "solhint:recommended",
"plugins": [],
"rules": {
"avoid-suicide": "error",
"avoid-sha3": "warn"
}
}`
export class SolHint extends PluginClient {
triggerLinter: boolean
constructor() {
super()
this.methods = ['lintContract', 'lintOnCompilation', 'lintContractCustomAction', 'lint']
createClient(this)
this.onload().then(async () => {
await this.lintOnCompilation()
})
}
async createConfigFile () {
await this.call('fileManager', 'writeFile', '.solhint.json', Config)
}
async lintOnCompilation() {
if(!this.triggerLinter) return
this.on('solidity', 'compilationFinished', async (fileName, source, languageVersion, data) => {
const hints = await this.lint(fileName)
console.log('after compile', { hints })
this.emit('lintOnCompilationFinished', hints)
})
this.triggerLinter = false
}
/**
* method to handle context menu action in file explorer for
* solhint plugin
* @param action interface CustomAction
*/
async lintContractCustomAction(action: customAction) {
this.triggerLinter = true
await this.call('solidity', 'compile', action.path[0])
await this.lintContract(action.path[0])
}
async lintContract(file: string) {
const hints = await this.lint(file)
console.log({ hints })
this.emit('lintingFinished', hints)
}
public async lint(fileName: string) {
const content = await this.call('fileManager', 'readFile', fileName)
let configContent = Config
if (await this.call('fileManager' as any, 'exists', '.solhint.json')) {
configContent = await this.call('fileManager', 'readFile', '.solhint.json')
}
const configContentObj = JSON.parse(configContent)
// apply the extend property
const rulesObj = applyExtends(configContentObj, (path) => this.rules[path]())
configContentObj.rules = { ...rulesObj, ...configContentObj.rules }
configContentObj.extends = []
const reporters = processStr(content, configContentObj)
const reports: Array<Report> = reporters.reports
const hints = reports.map((report: Report) => {
return {
formattedMessage: `${report.message}\n${report.fix ? report.fix : ''}`,
type: this.severity[report.severity] || 'error',
column: report.column,
line: report.line - 1
}
})
return hints
}
severity = {
2: 'error',
3: 'warning'
}
rules = {
'solhint:recommended': () => {
const enabledRules = {}
this.coreRules().forEach(rule => {
if (!rule.meta.deprecated && rule.meta.recommended) {
enabledRules[rule.ruleId] = rule.meta.defaultSetup
}
})
return enabledRules
},
'solhint:all': () => {
const enabledRules = {}
this.coreRules().forEach(rule => {
if (!rule.meta.deprecated) {
enabledRules[rule.ruleId] = rule.meta.defaultSetup
}
})
return enabledRules
},
'solhint:default': () => {
const enabledRules = {}
this.coreRules().forEach(rule => {
if (!rule.meta.deprecated && rule.meta.isDefault) {
enabledRules[rule.ruleId] = rule.meta.defaultSetup
}
})
return enabledRules
}
}
coreRules() {
return [
...bestPractises(),
...deprecations(),
...miscellaneous(),
...naming(),
...order(),
...security()
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Solhint</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app/App'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)

@ -0,0 +1,20 @@
{
"name": "solhint",
"displayName": "Solhint Linter",
"description": "Linter for Solidity",
"version": "0.1.0",
"events": ["lintOnCompilationFinished", "lintingFinished"],
"methods": [
"lintWithoutCompilationCustomAction",
"lintOnCompilation",
"lintContractCustomAction"
],
"kind": "none",
"icon": "https://raw.githubusercontent.com/protofire/solhint/master/solhint-icon.png",
"location": "hiddenPanel",
"url": "",
"documentation": "https://remix-plugins.readthedocs.io/en/latest/",
"repo": "https://github.com/ethereum/remix-project",
"maintainedBy": "Remix",
"authorContact": "remix@ethereum.org"
}

@ -0,0 +1,23 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"jest.config.ts",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

@ -0,0 +1,60 @@
const { composePlugins, withNx } = require('@nrwl/webpack')
const { withReact } = require('@nrwl/react')
const webpack = require('webpack')
const TerserPlugin = require("terser-webpack-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), withReact(), (config) => {
// Update the webpack config as needed here.
config.resolve.fallback = {
...config.resolve.fallback,
"path": false,
"os": false,
"fs": false,
"module": false,
}
// add public path
config.output.publicPath = '/'
// add copy & provide plugin
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
url: ['url', 'URL'],
process: 'process/browser',
}),
new webpack.DefinePlugin({
"BROWSER": true,
}),
)
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 2015,
compress: false,
mangle: false,
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin(),
];
return config;
})

@ -0,0 +1,517 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/code-frame@^7.0.0":
version "7.21.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39"
integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
dependencies:
"@babel/highlight" "^7.18.6"
"@babel/helper-validator-identifier@^7.18.6":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
"@babel/highlight@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
dependencies:
"@babel/helper-validator-identifier" "^7.18.6"
chalk "^2.0.0"
js-tokens "^4.0.0"
"@remixproject/plugin-api@0.3.31":
version "0.3.31"
resolved "https://registry.yarnpkg.com/@remixproject/plugin-api/-/plugin-api-0.3.31.tgz#86e7c458c58ff200bd927fd3d642877f4b5a0013"
integrity sha512-LOJRHxORNp7zW8k7//DQz5aZ7eqB7TwhYXrvzqvaryDTvtvJGWrlTHg81hzALynaxZKEWneohxjUxKvGp/eA4g==
dependencies:
"@remixproject/plugin-utils" "0.3.31"
"@remixproject/plugin-utils@0.3.31":
version "0.3.31"
resolved "https://registry.yarnpkg.com/@remixproject/plugin-utils/-/plugin-utils-0.3.31.tgz#80771e00c1a1b776432abb17b1f4b2e25600d4f6"
integrity sha512-OOAjoSd+ErBMrcNQEh80NU3BjJ9fHXuftRfy5Ul9aGXN3b1LJSNVvfrG+FxX6lpyaAK5JBj+aB9pgFozgb2wlw==
dependencies:
tslib "2.0.1"
"@remixproject/plugin-webview@^0.3.31":
version "0.3.31"
resolved "https://registry.yarnpkg.com/@remixproject/plugin-webview/-/plugin-webview-0.3.31.tgz#e5cce7d0089439b35aee4ab2a724add1e5d36b40"
integrity sha512-8yoKwIkRi9S+rqvFShNt01FfXX0H/Fijn7UkWFWJ/V6ULcw2cw9ViCz8cYZLhNUpxqezyu/LKDQL9g1TbJJoYw==
dependencies:
"@remixproject/plugin" "0.3.31"
"@remixproject/plugin-api" "0.3.31"
"@remixproject/plugin-utils" "0.3.31"
axios "^0.21.1"
"@remixproject/plugin@0.3.31", "@remixproject/plugin@^0.3.31":
version "0.3.31"
resolved "https://registry.yarnpkg.com/@remixproject/plugin/-/plugin-0.3.31.tgz#b6c6b58d2c7964e37024eeca4819c70ece1f3953"
integrity sha512-9ntMU9CzStloahm/wXt4V8n64ERgJzY5nG0bzQfjnI12knrdTmUo+LC42M2xaTBDDP9CzMPdqClg7XhhRLzohA==
dependencies:
"@remixproject/plugin-api" "0.3.31"
"@remixproject/plugin-utils" "0.3.31"
events "3.2.0"
"@solidity-parser/parser@^0.16.0":
version "0.16.0"
resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.0.tgz#1fb418c816ca1fc3a1e94b08bcfe623ec4e1add4"
integrity sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q==
dependencies:
antlr4ts "^0.5.0-alpha.4"
ajv@^6.12.6:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^8.0.1:
version "8.12.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
uri-js "^4.2.2"
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
antlr4@4.11, antlr4@^4.11.0:
version "4.11.0"
resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.11.0.tgz#d7466f5044fa6e333c0ec821b30c6157f6b004ae"
integrity sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==
antlr4ts@^0.5.0-alpha.4:
version "0.5.0-alpha.4"
resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a"
integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
ast-parents@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3"
integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
axios@^0.21.1:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
chalk@^2.0.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
color-name "1.1.3"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
commander@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
cosmiconfig@^8.0.0:
version "8.1.3"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689"
integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==
dependencies:
import-fresh "^3.2.1"
js-yaml "^4.1.0"
parse-json "^5.0.0"
path-type "^4.0.0"
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
events@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-diff@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
follow-redirects@^1.14.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
glob@^8.0.3:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
ignore@^5.2.4:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema-traverse@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
lodash.truncate@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
dependencies:
brace-expansion "^2.0.1"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
dependencies:
callsites "^3.0.0"
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pluralize@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
prettier@^2.8.3:
version "2.8.7"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"
integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==
punycode@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
slice-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
dependencies:
ansi-styles "^4.0.0"
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
solhint@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46"
integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg==
dependencies:
"@solidity-parser/parser" "^0.16.0"
ajv "^6.12.6"
antlr4 "^4.11.0"
ast-parents "^0.0.1"
chalk "^4.1.2"
commander "^10.0.0"
cosmiconfig "^8.0.0"
fast-diff "^1.2.0"
glob "^8.0.3"
ignore "^5.2.4"
js-yaml "^4.1.0"
lodash "^4.17.21"
pluralize "^8.0.0"
semver "^6.3.0"
strip-ansi "^6.0.1"
table "^6.8.1"
text-table "^0.2.0"
optionalDependencies:
prettier "^2.8.3"
string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
table@^6.8.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==
dependencies:
ajv "^8.0.1"
lodash.truncate "^4.4.2"
slice-ansi "^4.0.0"
string-width "^4.2.3"
strip-ansi "^6.0.1"
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
tslib@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==

@ -0,0 +1,59 @@
{
"name": "walletconnect",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/walletconnect/src",
"projectType": "application",
"implicitDependencies": [],
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "development",
"options": {
"compiler": "babel",
"outputPath": "dist/apps/walletconnect",
"index": "apps/walletconnect/src/index.html",
"baseHref": "./",
"main": "apps/walletconnect/src/main.tsx",
"polyfills": "apps/walletconnect/src/polyfills.ts",
"tsConfig": "apps/walletconnect/tsconfig.app.json",
"assets": ["apps/walletconnect/src/profile.json"],
"styles": ["apps/walletconnect/src/css/app.css", "apps/walletconnect/src/css/index.css"],
"scripts": [],
"webpackConfig": "apps/walletconnect/webpack.config.js"
},
"configurations": {
"development": {
},
"production": {
"fileReplacements": [
{
"replace": "apps/walletconnect/src/environments/environment.ts",
"with": "apps/walletconnect/src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "walletconnect:build",
"hmr": true,
"baseHref": "/"
},
"configurations": {
"development": {
"buildTarget": "walletconnect:build:development",
"port": 2023
},
"production": {
"buildTarget": "walletconnect:build:production"
}
}
}
},
"tags": []
}

@ -0,0 +1,35 @@
import React, { useEffect, useState } from 'react'
import '../css/app.css'
import '@fortawesome/fontawesome-free/css/all.css'
import type { EthereumClient } from '@web3modal/ethereum'
import { RemixClient } from '../services/RemixClient'
import { WalletConnectUI } from './walletConnectUI'
const remix = new RemixClient()
function App() {
const [ethereumClient, setEthereumClient] = useState<EthereumClient>(null)
const [wagmiClient, setWagmiClient] = useState(null)
const [theme, setTheme] = useState<string>('dark')
useEffect(() => {
(async () => {
await remix.initClient()
remix.internalEvents.on('themeChanged', (theme: string) => {
setTheme(theme)
})
setWagmiClient(remix.wagmiClient)
setEthereumClient(remix.ethereumClient)
})()
}, [])
return (
<div className="App">
<h4 className='mt-1'>WalletConnect</h4>
{ ethereumClient && wagmiClient && <WalletConnectUI wagmiClient={wagmiClient} ethereumClient={ethereumClient} theme={theme} /> }
</div>
)
}
export default App

@ -0,0 +1,17 @@
import { Web3Button, Web3Modal } from "@web3modal/react"
import { WagmiConfig } from "wagmi"
import { PROJECT_ID } from "../services/constant"
export function WalletConnectUI ({ ethereumClient, wagmiClient, theme }) {
return (
<div>
<div style={{ display: 'inline-block' }}>
<WagmiConfig client={wagmiClient}>
<Web3Button label='Connect to a wallet' />
</WagmiConfig>
</div>
<Web3Modal projectId={PROJECT_ID} ethereumClient={ethereumClient} themeMode={theme} />
</div>
)
}

@ -0,0 +1,38 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Wallet Connect</title>
<base href="./" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"/>
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1 @@
<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100"><title>remix_logo1</title><path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z"/><path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z"/><path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1,8 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app/app'
ReactDOM.render(
<App />,
document.getElementById('root')
)

@ -0,0 +1,7 @@
/**
* Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
*
* See: https://github.com/zloirock/core-js#babel
*/
import 'core-js/stable';
import 'regenerator-runtime/runtime';

@ -0,0 +1,16 @@
{
"name": "walletconnect",
"kind": "provider",
"displayName": "Wallet Connect",
"events": [],
"version": "2.0.0",
"methods": ["sendAsync", "init"],
"url": "",
"description": "Use an external wallet for transacting",
"icon": "data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyYWRpYWxHcmFkaWVudCBpZD0iYSIgY3g9IjAlIiBjeT0iNTAlIiByPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1ZDlkZjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDZmZmYiLz48L3JhZGlhbEdyYWRpZW50PjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTI1NiAwYzE0MS4zODQ4OTYgMCAyNTYgMTE0LjYxNTEwNCAyNTYgMjU2cy0xMTQuNjE1MTA0IDI1Ni0yNTYgMjU2LTI1Ni0xMTQuNjE1MTA0LTI1Ni0yNTYgMTE0LjYxNTEwNC0yNTYgMjU2LTI1NnoiIGZpbGw9InVybCgjYSkiLz48cGF0aCBkPSJtNjQuNjkxNzU1OCAzNy43MDg4Mjk4YzUxLjUzMjgwNzItNTAuMjc4NDM5NyAxMzUuMDgzOTk0Mi01MC4yNzg0Mzk3IDE4Ni42MTY3OTkyIDBsNi4yMDIwNTcgNi4wNTEwOTA2YzIuNTc2NjQgMi41MTM5MjE4IDIuNTc2NjQgNi41ODk3OTQ4IDAgOS4xMDM3MTc3bC0yMS4yMTU5OTggMjAuNjk5NTc1OWMtMS4yODgzMjEgMS4yNTY5NjE5LTMuMzc3MSAxLjI1Njk2MTktNC42NjU0MjEgMGwtOC41MzQ3NjYtOC4zMjcwMjA1Yy0zNS45NTA1NzMtMzUuMDc1NDk2Mi05NC4yMzc5NjktMzUuMDc1NDk2Mi0xMzAuMTg4NTQ0IDBsLTkuMTQwMDI4MiA4LjkxNzU1MTljLTEuMjg4MzIxNyAxLjI1Njk2MDktMy4zNzcxMDE2IDEuMjU2OTYwOS00LjY2NTQyMDggMGwtMjEuMjE1OTk3My0yMC42OTk1NzU5Yy0yLjU3NjY0MDMtMi41MTM5MjI5LTIuNTc2NjQwMy02LjU4OTc5NTggMC05LjEwMzcxNzd6bTIzMC40OTM0ODUyIDQyLjgwODkxMTcgMTguODgyMjc5IDE4LjQyMjcyNjJjMi41NzY2MjcgMi41MTM5MTAzIDIuNTc2NjQyIDYuNTg5NzU5My4wMDAwMzIgOS4xMDM2ODYzbC04NS4xNDE0OTggODMuMDcwMzU4Yy0yLjU3NjYyMyAyLjUxMzk0MS02Ljc1NDE4MiAyLjUxMzk2OS05LjMzMDg0LjAwMDA2Ni0uMDAwMDEtLjAwMDAxLS4wMDAwMjMtLjAwMDAyMy0uMDAwMDMzLS4wMDAwMzRsLTYwLjQyODI1Ni01OC45NTc0NTFjLS42NDQxNi0uNjI4NDgxLTEuNjg4NTUtLjYyODQ4MS0yLjMzMjcxIDAtLjAwMDAwNC4wMDAwMDQtLjAwMDAwOC4wMDAwMDctLjAwMDAxMi4wMDAwMTFsLTYwLjQyNjk2ODMgNTguOTU3NDA4Yy0yLjU3NjYxNDEgMi41MTM5NDctNi43NTQxNzQ2IDIuNTEzOTktOS4zMzA4NDA4LjAwMDA5Mi0uMDAwMDE1MS0uMDAwMDE0LS4wMDAwMzA5LS4wMDAwMjktLjAwMDA0NjctLjAwMDA0NmwtODUuMTQzODY3NzQtODMuMDcxNDYzYy0yLjU3NjYzOTI4LTIuNTEzOTIxLTIuNTc2NjM5MjgtNi41ODk3OTUgMC05LjEwMzcxNjNsMTguODgyMzEyNjQtMTguNDIyNjk1NWMyLjU3NjYzOTMtMi41MTM5MjIyIDYuNzU0MTk5My0yLjUxMzkyMjIgOS4zMzA4Mzk3IDBsNjAuNDI5MTM0NyA1OC45NTgyNzU4Yy42NDQxNjA4LjYyODQ4IDEuNjg4NTQ5NS42Mjg0OCAyLjMzMjcxMDMgMCAuMDAwMDA5NS0uMDAwMDA5LjAwMDAxODItLjAwMDAxOC4wMDAwMjc3LS4wMDAwMjVsNjAuNDI2MTA2NS01OC45NTgyNTA4YzIuNTc2NTgxLTIuNTEzOTggNi43NTQxNDItMi41MTQwNzQzIDkuMzMwODQtLjAwMDIxMDMuMDAwMDM3LjAwMDAzNTQuMDAwMDcyLjAwMDA3MDkuMDAwMTA3LjAwMDEwNjNsNjAuNDI5MDU2IDU4Ljk1ODM1NDhjLjY0NDE1OS42Mjg0NzkgMS42ODg1NDkuNjI4NDc5IDIuMzMyNzA5IDBsNjAuNDI4MDc5LTU4Ljk1NzE5MjVjMi41NzY2NC0yLjUxMzkyMzEgNi43NTQxOTktMi41MTM5MjMxIDkuMzMwODM5IDB6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDk4IDE2MCkiLz48L2c+PC9zdmc+",
"location": "mainPanel",
"documentation": "",
"repo": "https://github.com/yann300/remix-walletconnect/issues",
"maintainedBy": "Remix",
"authorContact": ""
}

@ -0,0 +1,107 @@
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import { w3mConnectors, w3mProvider } from '@web3modal/ethereum'
import { configureChains, createClient as wagmiCreateClient } from 'wagmi'
import { arbitrum, arbitrumGoerli, mainnet, polygon, polygonMumbai, optimism, optimismGoerli, Chain, goerli, sepolia } from 'wagmi/chains'
import { EthereumClient } from '@web3modal/ethereum'
import EventManager from "events"
import { PROJECT_ID } from './constant'
export class RemixClient extends PluginClient {
wagmiClient
ethereumClient: EthereumClient
chains: Chain[]
currentChain: number
internalEvents: EventManager
constructor() {
super()
createClient(this)
this.internalEvents = new EventManager()
this.methods = ["sendAsync", "init", "deactivate"]
this.onload()
}
onActivation () {
this.subscribeToEvents()
this.call('theme', 'currentTheme').then((theme: any) => {
this.internalEvents.emit('themeChanged', theme.quality.toLowerCase())
})
}
init () {
console.log('initializing walletconnect plugin...')
}
async initClient () {
try {
this.chains = [arbitrum, arbitrumGoerli, mainnet, polygon, polygonMumbai, optimism, optimismGoerli, goerli, sepolia]
const { provider } = configureChains(this.chains, [w3mProvider({ projectId: PROJECT_ID })])
this.wagmiClient = wagmiCreateClient({
autoConnect: false,
connectors: w3mConnectors({ projectId: PROJECT_ID, version: 1, chains: this.chains }),
provider
})
this.ethereumClient = new EthereumClient(this.wagmiClient, this.chains)
} catch (e) {
return console.error("Could not get a wallet connection", e)
}
}
subscribeToEvents () {
this.wagmiClient.subscribe((event) => {
if (event.status === 'connected') {
this.emit('accountsChanged', [event.data.account])
if (this.currentChain !== event.data.chain.id) {
this.currentChain = event.data.chain.id
this.emit('chainChanged', event.data.chain.id)
}
} else if (event.status === 'disconnected') {
this.emit('accountsChanged', [])
this.emit('chainChanged', 0)
this.currentChain = 0
}
})
this.on('theme', 'themeChanged', (theme: any) => {
this.internalEvents.emit('themeChanged', theme.quality)
})
}
sendAsync (data: { method: string, params: string, id: string }) {
return new Promise((resolve, reject) => {
if (this.wagmiClient) {
if (this.wagmiClient.data && this.wagmiClient.data.provider && this.wagmiClient.data.provider.sendAsync) {
this.wagmiClient.data.provider.sendAsync(data, (error, message) => {
if (error) return reject(error)
resolve(message)
})
} else if (this.wagmiClient.data && this.wagmiClient.data.provider && this.wagmiClient.data.provider.jsonRpcFetchFunc) {
if (data.method === 'net_version' || data.method === 'eth_chainId') {
resolve({"jsonrpc": "2.0", "result": this.currentChain, "id": data.id})
} else {
this.wagmiClient.data.provider.jsonRpcFetchFunc(data.method, data.params).then((message) => {
resolve({"jsonrpc": "2.0", "result": message, "id": data.id})
}).catch((error) => {
reject(error)
})
}
} else {
this.wagmiClient.provider.send(data.method, data.params).then((message) => {
resolve({"jsonrpc": "2.0", "result": message, "id": data.id})
}).catch((error) => {
reject(error)
})
}
} else {
console.error(`Cannot make ${data.method} request. Remix client is not connect to walletconnect client`)
resolve({"jsonrpc": "2.0", "result": [], "id": data.id})
}
})
}
async deactivate(){
console.log('deactivating walletconnect plugin...')
await this.ethereumClient.disconnect()
}
}

@ -0,0 +1,2 @@
// @ts-ignore
export const PROJECT_ID = WALLET_CONNECT_PROJECT_ID

@ -0,0 +1,53 @@
import { providers } from 'ethers'
import type { Chain } from 'wagmi/chains'
import type { ChainProviderFn } from 'wagmi/'
interface FallbackProviderConfig {
// The Provider
provider: any;
// The priority to favour this Provider; lower values are used first (higher priority)
priority?: number;
// Timeout before also triggering the next provider; this does not stop
// this provider and if its result comes back before a quorum is reached
// it will be incorporated into the vote
// - lower values will cause more network traffic but may result in a
// faster result.
stallTimeout?: number;
// How much this provider contributes to the quorum; sometimes a specific
// provider may be more reliable or trustworthy than others, but usually
// this should be left as the default
weight?: number;
}
export function customProvider<TChain extends Chain = Chain>({
priority,
stallTimeout,
weight,
}: FallbackProviderConfig): ChainProviderFn<
TChain,
providers.Web3Provider,
providers.WebSocketProvider
> {
return function (chain) {
return {
chain: {
...chain,
} as TChain,
provider: () => {
const provider = new providers.Web3Provider(
window.ethereum,
{
chainId: chain.id,
name: chain.network,
ensAddress: chain.contracts?.ensRegistry?.address,
}
)
return Object.assign(provider, { priority, stallTimeout, weight })
}
}
}
}

@ -0,0 +1,24 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"jest.config.ts",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

@ -0,0 +1,90 @@
const { composePlugins, withNx } = require('@nrwl/webpack')
const webpack = require('webpack')
const TerserPlugin = require("terser-webpack-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
// Update the webpack config as needed here.
// e.g. `config.plugins.push(new MyPlugin())`
// add fallback for node modules
config.resolve.fallback = {
...config.resolve.fallback,
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"path": require.resolve("path-browserify"),
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"constants": require.resolve("constants-browserify"),
"os": false, //require.resolve("os-browserify/browser"),
"timers": false, // require.resolve("timers-browserify"),
"zlib": require.resolve("browserify-zlib"),
"fs": false,
"module": false,
"tls": false,
"net": false,
"readline": false,
"child_process": false,
"buffer": require.resolve("buffer/"),
"vm": require.resolve('vm-browserify'),
}
// add externals
config.externals = {
...config.externals,
solc: 'solc',
}
// add public path
config.output.publicPath = './'
// add copy & provide plugin
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
url: ['url', 'URL'],
process: 'process/browser',
})
)
// set the define plugin to load the WALLET_CONNECT_PROJECT_ID
config.plugins.push(
new webpack.DefinePlugin({
WALLET_CONNECT_PROJECT_ID: JSON.stringify(process.env.WALLET_CONNECT_PROJECT_ID),
})
)
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 2015,
compress: false,
mangle: false,
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin(),
];
config.watchOptions = {
ignored: /node_modules/
}
return config;
});

@ -0,0 +1,3 @@
files:
- source: /apps/remix-ide/src/app/tabs/locales/en/*.json
translation: /apps/remix-ide/src/app/tabs/locales/%two_letters_code%/%original_file_name%

@ -1,6 +1,6 @@
{
"name": "@remix-project/ghaction-helper",
"version": "0.1.8-alpha.0",
"version": "0.1.8",
"description": "Solidity Tests GitHub Action Helper",
"main": "src/index.js",
"scripts": {
@ -19,17 +19,17 @@
},
"homepage": "https://github.com/ethereum/remix-project#readme",
"devDependencies": {
"@remix-project/remix-solidity": "^0.5.11",
"@remix-project/remix-solidity": "^0.5.12",
"@types/chai": "^4.3.4",
"typescript": "^4.9.3"
},
"dependencies": {
"@ethereum-waffle/chai": "^3.4.4",
"@remix-project/remix-simulator": "^0.2.25",
"@remix-project/remix-simulator": "^0.2.26",
"chai": "^4.3.7",
"ethers": "^5.7.2",
"web3": "^1.5.3"
},
"types": "./src/index.d.ts",
"gitHead": "79fcaa673265865732f1b996ac48b2e20aba1995"
"gitHead": "18a9b1f4e6ec1fc94d2a81d0157d72b742daf620"
}

@ -1,6 +1,6 @@
{
"name": "@remix-project/remix-analyzer",
"version": "0.5.34",
"version": "0.5.35",
"description": "Tool to perform static analysis on Solidity smart contracts",
"scripts": {
"test": "./../../node_modules/.bin/ts-node --project ../../tsconfig.base.json --require tsconfig-paths/register ./../../node_modules/.bin/tape ./test/tests.ts"
@ -25,8 +25,8 @@
"@ethereumjs/tx": "^4.1.1",
"@ethereumjs/util": "^8.0.5",
"@ethereumjs/vm": "^6.4.1",
"@remix-project/remix-astwalker": "^0.0.55",
"@remix-project/remix-lib": "^0.5.25",
"@remix-project/remix-astwalker": "^0.0.56",
"@remix-project/remix-lib": "^0.5.32",
"async": "^2.6.2",
"ethers": "^5.4.2",
"ethjs-util": "^0.1.6",
@ -50,6 +50,6 @@
"typescript": "^3.7.5"
},
"typings": "src/index.d.ts",
"gitHead": "79fcaa673265865732f1b996ac48b2e20aba1995",
"gitHead": "18a9b1f4e6ec1fc94d2a81d0157d72b742daf620",
"main": "./src/index.js"
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save