diff --git a/.env b/.env.local similarity index 65% rename from .env rename to .env.local index 1a2b47f98f..fb35ddc973 100644 --- a/.env +++ b/.env.local @@ -2,4 +2,4 @@ gist_token= account_passphrase= account_password= NODE_OPTIONS=--max-old-space-size=2048 -# WALLET_CONNECT_PROJECT_ID= +WALLET_CONNECT_PROJECT_ID= diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 31b05d0778..72252c06ba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,8 +25,8 @@ If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. Windows, Linux or MacOS] - - Browser [e.g. chrome, firefox] - - Version [e.g. 22] + - Browser: [e.g. chrome, firefox] + - Version: [e.g. 22] **Additional context** Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index 7955bf6455..ab74544426 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ soljson.js *_group*.ts stats.json release +.env # compiled output diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83722de3d0..0f5759403b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Everyone is welcome to contribute to Remix's codebase and please join our [Discord](https://discord.gg/mh9hFCKkEq). +Everyone is welcome to contribute to Remix's codebase and please join our [Discord](https://discord.com/invite/nfv6ZYjAeP). ## Development Remix libraries work closely with [Remix IDE](https://remix.ethereum.org). Each library has a README to explain its application. @@ -72,7 +72,7 @@ import panelJson from './panel.json'; import enJson from '../en'; // There may have some untranslated content. Always fill in the gaps with EN JSON. -// No need for a defaultMessage prop when render a FormattedMessage component. +// No need for a defaultMessage prop when rendering a FormattedMessage component. export default Object.assign({}, enJson, { ...panelJson, }) diff --git a/apps/circuit-compiler/src/app/services/circomPluginClient.ts b/apps/circuit-compiler/src/app/services/circomPluginClient.ts index f9421eb528..ff3170f26e 100644 --- a/apps/circuit-compiler/src/app/services/circomPluginClient.ts +++ b/apps/circuit-compiler/src/app/services/circomPluginClient.ts @@ -502,9 +502,9 @@ export class CircomPluginClient extends PluginClient { const exists = await this.call('fileManager', 'exists', path) if (exists) return path - else throw new Error(`Report path ${path} do no exist in the Remix FileSystem`) + else throw new Error(`Report path ${path} does not exist in the Remix FileSystem`) } else { - throw new Error(`Report path ${path} do no exist in the Remix FileSystem`) + throw new Error(`Report path ${path} does not exist in the Remix FileSystem`) } } } diff --git a/apps/circuit-compiler/webpack.config.js b/apps/circuit-compiler/webpack.config.js index fecff4fa70..a4aa984df9 100644 --- a/apps/circuit-compiler/webpack.config.js +++ b/apps/circuit-compiler/webpack.config.js @@ -55,7 +55,7 @@ module.exports = composePlugins(withNx(), (config) => { }) ) - // souce-map loader + // source-map loader config.module.rules.push({ test: /\.js$/, use: ["source-map-loader"], diff --git a/apps/contract-verification/README.md b/apps/contract-verification/README.md new file mode 100644 index 0000000000..6cbcd88173 --- /dev/null +++ b/apps/contract-verification/README.md @@ -0,0 +1,19 @@ +# Contract Verification Plugin + +With this plugin, contracts written and compiled in Remix can be verified at Sourcify, Etherscan, Blockscout and Routescan at the same time. Besides that, the source code of any address can be fetched from the verifiers and added to the file editor. + +## Adding a new verification service + +Currently, the plugin supports Sourcify, Etherscan, Blockscout and Routescan. To add a new verifier, you need to make the following changes: + +In `./src/app/types/VerificationTypes.ts`, add the new verifier to the `VerifierIdentifier` type and the`VERIFIERS` array. + +In order to interact with the API of the verification service, you need to create a new class that extends the `AbstractVerifier` class. If your API is based on the Etherscan API, you can simply extend the `EtherscanVerifier` class. In this case, see the `RoutescanVerifier` and the `BlockscoutVerifier` for reference. All related classes are located in the `./src/app/Verifiers` directory. + +In `./src/app/Verifiers/index.ts`, add your new verifier to the `getVerifier` function. Validate any settings properties that are required by your verifier. + +In `./src/app/utils/default-apis.json`, you need to add default settings for your new verifier. If you can, simply add your defaults in the form of `{ [VerifierIdentifier]: { [chainId]: { apiUrl: [value], explorerUrl: [value] } } }`. If you need more flexibility, you might also want to change the `src/app/utils/default-settings.ts` file. See Routescan there for reference. + +Your new verifier will automatically be shown in the `VerifyView` and the `LookupView` since we added it to the `VERIFIERS` array. You only need to make a change to the `SettingsView` because the required settings depend on the verifier. There, add a new div block in the same format as the other verifiers. Only add the `ConfigInput` elements for the settings that your verifier needs to the div block. + +That's it! Your verification service should be able to verify contracts through Remix now. diff --git a/apps/contract-verification/src/app/app.tsx b/apps/contract-verification/src/app/app.tsx index 0ea4332543..85ebbfb19b 100644 --- a/apps/contract-verification/src/app/app.tsx +++ b/apps/contract-verification/src/app/app.tsx @@ -13,6 +13,7 @@ import { CompilerAbstract } from '@remix-project/remix-solidity' import { useLocalStorage } from './hooks/useLocalStorage' import { getVerifier } from './Verifiers' import { ContractDropdownSelection } from './components/ContractDropdown' +import { IntlProvider } from 'react-intl' const plugin = new ContractVerificationPluginClient() @@ -32,11 +33,25 @@ const App = () => { const [proxyAddressError, setProxyAddressError] = useState('') const [abiEncodedConstructorArgs, setAbiEncodedConstructorArgs] = useState('') const [abiEncodingError, setAbiEncodingError] = useState('') + const [locale, setLocale] = useState<{ code: string; messages: any }>({ + code: 'en', + messages: {} + }) const timer = useRef(null) useEffect(() => { plugin.internalEvents.on('verification_activated', () => { + + // @ts-ignore + plugin.call('locale', 'currentLocale').then((locale: any) => { + setLocale(locale) + }) + + // @ts-ignore + plugin.on('locale', 'localeChanged', (locale: any) => { + setLocale(locale) + }) // Fetch compiler artefacts initially plugin.call('compilerArtefacts' as any, 'getAllCompilerAbstracts').then((obj: any) => { setCompilationOutput(obj) @@ -143,11 +158,13 @@ const App = () => { }, [submittedContracts]) return ( - - - - - + + + + + + + ) } diff --git a/apps/contract-verification/src/app/components/AccordionReceipt.tsx b/apps/contract-verification/src/app/components/AccordionReceipt.tsx index 68332d09bb..944cc37046 100644 --- a/apps/contract-verification/src/app/components/AccordionReceipt.tsx +++ b/apps/contract-verification/src/app/components/AccordionReceipt.tsx @@ -97,32 +97,32 @@ const ReceiptsBody = ({ receipts }: { receipts: VerificationReceipt[] }) => { className="list-group-item d-flex flex-row align-items-center" > - - {['verified', 'partially verified', 'already verified'].includes(receipt.status) ? - : - receipt.status === 'fully verified' ? - : - receipt.status === 'failed' ? - : - ['pending', 'awaiting implementation verification'].includes(receipt.status) ? - : - - } - - -
+ placement="top" + tooltipClasses=" text-break" + tooltipTextClasses="text-capitalize" + tooltipText={`Status: ${receipt.status}${receipt.message ? `, Message: ${receipt.message}` : ''}`} + > + + {['verified', 'partially verified', 'already verified'].includes(receipt.status) ? + : + receipt.status === 'fully verified' ? + : + receipt.status === 'failed' ? + : + ['pending', 'awaiting implementation verification'].includes(receipt.status) ? + : + + } + + +
{receipt.verifierInfo.name}
{!!receipt.lookupUrl && receipt.verifierInfo.name === 'Blockscout' ? : - !!receipt.lookupUrl && + !!receipt.lookupUrl && }
diff --git a/apps/contract-verification/src/app/components/ConfigInput.tsx b/apps/contract-verification/src/app/components/ConfigInput.tsx index 0737840115..9f08ab42c5 100644 --- a/apps/contract-verification/src/app/components/ConfigInput.tsx +++ b/apps/contract-verification/src/app/components/ConfigInput.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react' import { CustomTooltip } from '@remix-ui/helper' +import { FormattedMessage, useIntl } from 'react-intl' interface ConfigInputProps { label: string @@ -13,6 +14,7 @@ interface ConfigInputProps { export const ConfigInput: React.FC = ({ label, id, secret, initialValue, saveResult }) => { const [value, setValue] = useState(initialValue) const [enabled, setEnabled] = useState(false) + const intl = useIntl() // Reset state when initialValue changes useEffect(() => { @@ -42,7 +44,7 @@ export const ConfigInput: React.FC = ({ label, id, secret, ini type={secret ? 'password' : 'text'} className={`form-control small w-100 ${!enabled ? 'bg-transparent pl-0 border-0' : ''}`} id={id} - placeholder={`Add ${label}`} + placeholder={intl.formatMessage({ id: "contract-verification.configInputPlaceholder" }, { label })} value={value} onChange={(e) => setValue(e.target.value)} disabled={!enabled} @@ -51,10 +53,10 @@ export const ConfigInput: React.FC = ({ label, id, secret, ini { enabled ? ( <> ) : ( diff --git a/apps/contract-verification/src/app/components/ConstructorArguments.tsx b/apps/contract-verification/src/app/components/ConstructorArguments.tsx index e2a4239eaa..46fa9822a7 100644 --- a/apps/contract-verification/src/app/components/ConstructorArguments.tsx +++ b/apps/contract-verification/src/app/components/ConstructorArguments.tsx @@ -3,6 +3,7 @@ import { ethers } from 'ethers' import { AppContext } from '../AppContext' import { ContractDropdownSelection } from './ContractDropdown' +import { FormattedMessage } from 'react-intl' interface ConstructorArgumentsProps { abiEncodedConstructorArgs: string @@ -102,7 +103,9 @@ export const ConstructorArguments: React.FC = ({ abiE
setToggleRawInput(!toggleRawInput)} />
{toggleRawInput ? ( @@ -122,7 +125,10 @@ export const ConstructorArguments: React.FC = ({ abiE {abiEncodedConstructorArgs && (