Merge remote-tracking branch 'upstream/master' into spacesailor24/web3js-v4-upgrade

pull/3951/head
Oleksii Kosynskyi 1 year ago
commit 41ce94fb9d
No known key found for this signature in database
GPG Key ID: B4A8D3CCE22EA65E
  1. 12
      .circleci/config.yml
  2. 18
      CONTRIBUTING.md
  3. 2
      apps/circuit-compiler/src/profile.json
  4. 6
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  5. 1
      apps/remix-ide/src/app/providers/abstract-provider.tsx
  6. 13
      apps/remix-ide/src/app/providers/custom-vm-fork-provider.tsx
  7. 48
      apps/remix-ide/src/app/providers/external-http-provider.tsx
  8. 17
      apps/remix-ide/src/app/providers/foundry-provider.tsx
  9. 17
      apps/remix-ide/src/app/providers/ganache-provider.tsx
  10. 17
      apps/remix-ide/src/app/providers/hardhat-provider.tsx
  11. 10
      apps/remix-ide/src/app/providers/injected-ephemery-testnet-provider.tsx
  12. 18
      apps/remix-ide/src/app/providers/injected-provider.tsx
  13. 16
      apps/remix-ide/src/app/tabs/locales/en/debugger.json
  14. 55
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  15. 9
      apps/remix-ide/src/app/tabs/locales/en/home.json
  16. 6
      apps/remix-ide/src/app/tabs/locales/en/index.js
  17. 6
      apps/remix-ide/src/app/tabs/locales/en/panel.json
  18. 14
      apps/remix-ide/src/app/tabs/locales/en/pluginManager.json
  19. 3
      apps/remix-ide/src/app/tabs/locales/en/remixApp.json
  20. 7
      apps/remix-ide/src/app/tabs/locales/en/remixUiTabs.json
  21. 12
      apps/remix-ide/src/app/tabs/locales/en/search.json
  22. 16
      apps/remix-ide/src/app/tabs/locales/en/settings.json
  23. 10
      apps/remix-ide/src/app/tabs/locales/en/solUmlGen.json
  24. 4
      apps/remix-ide/src/app/tabs/locales/en/solUmlgen.json
  25. 41
      apps/remix-ide/src/app/tabs/locales/en/solidity.json
  26. 8
      apps/remix-ide/src/app/tabs/locales/en/solidityUnitTesting.json
  27. 28
      apps/remix-ide/src/app/tabs/locales/en/terminal.json
  28. 122
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  29. 36
      apps/remix-ide/src/app/tabs/locales/es/index.js
  30. 3
      apps/remix-ide/src/app/tabs/locales/es/remixApp.json
  31. 7
      apps/remix-ide/src/app/tabs/locales/es/remixUiTabs.json
  32. 10
      apps/remix-ide/src/app/tabs/locales/es/solUmlGen.json
  33. 4
      apps/remix-ide/src/app/tabs/locales/es/solUmlgen.json
  34. 36
      apps/remix-ide/src/app/tabs/locales/fr/index.js
  35. 3
      apps/remix-ide/src/app/tabs/locales/fr/remixApp.json
  36. 7
      apps/remix-ide/src/app/tabs/locales/fr/remixUiTabs.json
  37. 10
      apps/remix-ide/src/app/tabs/locales/fr/solUmlGen.json
  38. 4
      apps/remix-ide/src/app/tabs/locales/fr/solUmlgen.json
  39. 6
      apps/remix-ide/src/app/tabs/locales/zh/index.js
  40. 3
      apps/remix-ide/src/app/tabs/locales/zh/remixApp.json
  41. 7
      apps/remix-ide/src/app/tabs/locales/zh/remixUiTabs.json
  42. 10
      apps/remix-ide/src/app/tabs/locales/zh/solUmlGen.json
  43. 4
      apps/remix-ide/src/app/tabs/locales/zh/solUmlgen.json
  44. 15
      apps/remix-ide/src/blockchain/blockchain.tsx
  45. 3
      apps/remix-ide/src/remixAppManager.js
  46. 10
      libs/remix-core-plugin/src/lib/helpers/fetch-etherscan.ts
  47. 17
      libs/remix-lib/src/execution/txExecution.ts
  48. 4
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  49. 16
      libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx
  50. 11
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  51. 7
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx
  52. 10
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  53. 8
      libs/remix-ui/editor/src/lib/providers/completion/completionGlobals.ts
  54. 8
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  55. 53
      libs/remix-ui/helper/src/lib/components/custom-dropdown.tsx
  56. 4
      libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx
  57. 2
      libs/remix-ui/home-tab/src/lib/components/homeTabLearn.tsx
  58. 2
      libs/remix-ui/home-tab/src/lib/components/homeTabTitle.tsx
  59. 3
      libs/remix-ui/home-tab/src/lib/components/pluginButton.tsx
  60. 8
      libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
  61. 31
      libs/remix-ui/plugin-manager/src/lib/components/ActivePluginCard.tsx
  62. 31
      libs/remix-ui/plugin-manager/src/lib/components/InactivePluginCard.tsx
  63. 8
      libs/remix-ui/plugin-manager/src/lib/components/LocalPluginForm.tsx
  64. 8
      libs/remix-ui/plugin-manager/src/lib/components/permissionsSettings.tsx
  65. 5
      libs/remix-ui/plugin-manager/src/lib/components/rootView.tsx
  66. 2
      libs/remix-ui/renderer/src/lib/renderer.css
  67. 11
      libs/remix-ui/renderer/src/lib/renderer.tsx
  68. 41
      libs/remix-ui/run-tab/src/lib/components/account.tsx
  69. 14
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  70. 18
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  71. 5
      libs/remix-ui/run-tab/src/lib/components/deployButton.tsx
  72. 14
      libs/remix-ui/run-tab/src/lib/components/environment.tsx
  73. 2
      libs/remix-ui/run-tab/src/lib/components/gasPrice.tsx
  74. 7
      libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx
  75. 63
      libs/remix-ui/run-tab/src/lib/components/mainnet.tsx
  76. 5
      libs/remix-ui/run-tab/src/lib/components/multiDeployInput.tsx
  77. 34
      libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx
  78. 2
      libs/remix-ui/run-tab/src/lib/components/value.tsx
  79. 3
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  80. 3
      libs/remix-ui/search/src/lib/components/FindContainer.tsx
  81. 6
      libs/remix-ui/search/src/lib/components/Replace.tsx
  82. 3
      libs/remix-ui/search/src/lib/components/StopSearch.tsx
  83. 3
      libs/remix-ui/search/src/lib/components/Undo.tsx
  84. 25
      libs/remix-ui/search/src/lib/components/results/ResultItem.tsx
  85. 19
      libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx
  86. 5
      libs/remix-ui/search/src/lib/components/results/Results.tsx
  87. 19
      libs/remix-ui/settings/src/lib/etherscan-settings.tsx
  88. 27
      libs/remix-ui/settings/src/lib/github-settings.tsx
  89. 30
      libs/remix-ui/settings/src/lib/remix-ui-settings.tsx
  90. 70
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  91. 24
      libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx
  92. 25
      libs/remix-ui/solidity-uml-gen/src/lib/components/UmlDownload.tsx
  93. 14
      libs/remix-ui/solidity-uml-gen/src/lib/solidity-uml-gen.tsx
  94. 25
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  95. 17
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
  96. 12
      libs/remix-ui/terminal/src/lib/components/RenderCall.tsx
  97. 11
      libs/remix-ui/terminal/src/lib/components/RenderKnownTransactions.tsx
  98. 11
      libs/remix-ui/terminal/src/lib/components/RenderUnknownTransactions.tsx
  99. 32
      libs/remix-ui/terminal/src/lib/components/Table.tsx
  100. 39
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -169,6 +169,11 @@ jobs:
- run: ls -la ./dist/apps/remix-ide/assets/js
- run: yarn run selenium-install || yarn run selenium-install
- when:
condition:
equal: [ "chrome", << parameters.browser >> ]
steps:
- run: cp ~/bin/chromedriver /home/circleci/remix-project/node_modules/selenium-standalone/.selenium/chromedriver/latest-x64/
- run:
name: Start Selenium
command: yarn run selenium
@ -215,6 +220,7 @@ jobs:
- run: unzip ./persist/plugin-<< parameters.plugin >>.zip
- run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules
- run: yarn run selenium-install || yarn run selenium-install
- run: cp ~/bin/chromedriver /home/circleci/remix-project/node_modules/selenium-standalone/.selenium/chromedriver/latest-x64/
- run:
name: Start Selenium
command: yarn run selenium
@ -376,7 +382,10 @@ commands:
- run:
name: install-chromedriver-custom-linux
command: |
CHROMEDRIVER_URL=$(curl -s 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json' | jq '.channels.Stable.downloads.chromedriver[] | select(.platform == "linux64") | .url' | tr -d '"')
google-chrome --version > version.txt
VERSION=$(grep -Eo '[0-9]+\.' < version.txt | head -1)
# CHROMEDRIVER_URL=$(curl -s 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json' | jq '.channels.Stable.downloads.chromedriver[] | select(.platform == "linux64") | .url' | tr -d '"')
CHROMEDRIVER_URL=$(curl -s 'https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json' | jq --arg v "$VERSION" '.versions[] | select(.version | startswith($v)) | .downloads.chromedriver[] | select(.platform == "linux64") | .url' | tail -n1 | tr -d '"')
echo $CHROMEDRIVER_URL
ZIPFILEPATH="/tmp/chromedriver.zip"
echo "Downloading from $CHROMEDRIVER_URL"
@ -394,6 +403,7 @@ commands:
echo Removing ZIP file
rm "$ZIPFILEPATH"
rm version.txt
echo Done
chromedriver -v

@ -93,3 +93,21 @@ But in some cases, the `id` prop may not be static. For example,
</h6>
```
You can't be sure there is a match key in locale file or not. So it will be better to provide a `defaultMessage` prop.
### Should I update the non-english locale json files?
You probably will have this question when you are updating the english locale json files.
Well, that depends.
If you update an old json file, then you don't need to update it in other languages, because crowdin will do it for you.
But if you add a new json file, then you have to add it in other languages, and import it in `index.js` of all languages. Because crowdin will not update `index.js`, you have to do it manually.
### How to contribute on translations?
Remix is using crowdin to manage translations. If you want to contribute on that, you can do it on crowdin. Check the link below.
https://crowdin.com/project/remix-translation
There are many languages, just get into your language, and you will see a folder named `Remix UI`, where you can do the translations.
Not only can you do the translations, you can also review it. If you agree or disagree with some translations, you can vote yes or no. If you vote no, you can comment to explain why you vote no, and give your translation.

@ -9,7 +9,7 @@
"url": "",
"description": "Enables circuit compilation and computing a witness for ZK proofs",
"icon": "https://docs.circom.io/assets/images/favicon.png",
"location": "sidePanel",
"location": "hiddenPanel",
"documentation": "",
"repo": "https://github.com/ethereum/remix-project/tree/master/apps/circuit-compiler",
"maintainedBy": "Remix",

@ -562,7 +562,7 @@ describe("Storage", function () {
contractName: 'StorageWithLib',
sourceName: 'contracts/StorageWithLib.sol',
abi: metadata.abi,
bytecode: '0x' + metadata.data.bytecode.object,
bytecode: metadata.data.bytecode.object,
deployedBytecode: '0x' + metadata.data.deployedBytecode.object,
linkReferences: metadata.data.bytecode.linkReferences,
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,
@ -700,7 +700,7 @@ const scriptAutoExec = {
contractName: 'Lib',
sourceName: 'contracts/1_Storage.sol',
abi: metadataLib.abi,
bytecode: '0x' + metadataLib.data.bytecode.object,
bytecode: metadataLib.data.bytecode.object,
deployedBytecode: '0x' + metadataLib.data.deployedBytecode.object,
linkReferences: metadataLib.data.bytecode.linkReferences,
deployedLinkReferences: metadataLib.data.deployedBytecode.linkReferences,
@ -720,7 +720,7 @@ const scriptAutoExec = {
contractName: 'Storage',
sourceName: 'contracts/1_Storage.sol',
abi: metadata.abi,
bytecode: '0x' + metadata.data.bytecode.object,
bytecode: metadata.data.bytecode.object,
deployedBytecode: '0x' + metadata.data.deployedBytecode.object,
linkReferences: metadata.data.bytecode.linkReferences,
deployedLinkReferences: metadata.data.deployedBytecode.linkReferences,

@ -15,6 +15,7 @@ export type JsonDataResult = {
jsonrpc: string // version
result?: any
error?: any
errorData?: any
}
export type RejectRequest = (error: Error) => void

@ -1,4 +1,5 @@
import React, {useRef} from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import * as packageJson from '../../../../../package.json'
import {AppModal, ModalTypes} from '@remix-ui/app'
import {BasicVMProvider} from './vm-provider'
@ -32,13 +33,19 @@ export class CustomForkVMProvider extends BasicVMProvider {
const body = () => {
return (
<div>
<span>Please provide information about the custom fork. If the node URL is not provided, the VM will start with an empty state.</span>
<span>
<FormattedMessage id="udapp.customVmForkProviderText" />
</span>
<div>
<label className="mt-3 mb-1">Node URL</label>
<label className="mt-3 mb-1">
<FormattedMessage id="udapp.nodeUrl" />
</label>
<input data-id="CustomForkNodeUrl" name="nodeUrl" type="text" className="border form-control border-right-0" />
</div>
<div>
<label className="mt-3 mb-1">Block number (or "latest")</label>
<label className="mt-3 mb-1">
<FormattedMessage id="udapp.blockNumber" />
</label>
<input
data-id="CustomForkBlockNumber"
name="blockNumber"

@ -1,5 +1,6 @@
import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {AbstractProvider} from './abstract-provider'
const profile = {
@ -21,29 +22,46 @@ export class ExternalHttpProvider extends AbstractProvider {
return (
<>
<div className="">
Note: To use Geth & https://remix.ethereum.org, configure it to allow requests from Remix:(see{' '}
<a href="https://geth.ethereum.org/docs/rpc/server" target="_blank" rel="noreferrer">
Geth Docs on rpc server
</a>
)<div className="border p-1">geth --http --http.corsdomain https://remix.ethereum.org</div>
<FormattedMessage
id="udapp.externalHttpProviderText1"
values={{
a: (chunks) => (
<a href="https://geth.ethereum.org/docs/rpc/server" target="_blank" rel="noreferrer">
{chunks}
</a>
)
}}
/>
<div className="border p-1">geth --http --http.corsdomain https://remix.ethereum.org</div>
<br />
To run Remix & a local Geth test node, use this command: (see{' '}
<a href="https://geth.ethereum.org/getting-started/dev-mode" target="_blank" rel="noreferrer">
Geth Docs on Dev mode
</a>
)
<FormattedMessage
id="udapp.externalHttpProviderText2"
values={{
a: (chunks) => (
<a href="https://geth.ethereum.org/getting-started/dev-mode" target="_blank" rel="noreferrer">
{chunks}
</a>
)
}}
/>
<div className="border p-1">
geth --http --http.corsdomain="{window.origin}" --http.api web3,eth,debug,personal,net --vmdebug --datadir {thePath} --dev console
</div>
<br />
<br />
<b>WARNING:</b> It is not safe to use the --http.corsdomain flag with a wildcard: <b>--http.corsdomain *</b>
<FormattedMessage id="udapp.externalHttpProviderText3" values={{b: (chunks) => <b>{chunks}</b>}} />
<br />
<br />
For more info:{' '}
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#more-about-web3-provider" target="_blank" rel="noreferrer">
Remix Docs on External HTTP Provider
</a>
<FormattedMessage
id="udapp.externalHttpProviderText4"
values={{
a: (chunks) => (
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#more-about-web3-provider" target="_blank" rel="noreferrer">
{chunks}
</a>
)
}}
/>
<br />
<br />
External HTTP Provider Endpoint

@ -1,5 +1,6 @@
import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {AbstractProvider} from './abstract-provider'
const profile = {
@ -20,7 +21,7 @@ export class FoundryProvider extends AbstractProvider {
return (
<div>
{' '}
Note: To run Anvil on your system, run:
<FormattedMessage id="udapp.foundryProviderText1" />
<div className="p-1 pl-3">
<b>curl -L https://foundry.paradigm.xyz | bash</b>
</div>
@ -28,10 +29,16 @@ export class FoundryProvider extends AbstractProvider {
<b>anvil</b>
</div>
<div className="pt-2 pb-4">
For more info, visit:{' '}
<a href="https://github.com/foundry-rs/foundry" target="_blank">
Foundry Documentation
</a>
<FormattedMessage
id="udapp.foundryProviderText2"
values={{
a: (chunks) => (
<a href="https://github.com/foundry-rs/foundry" target="_blank">
{chunks}
</a>
)
}}
/>
</div>
<div>Anvil JSON-RPC Endpoint:</div>
</div>

@ -1,5 +1,6 @@
import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {AbstractProvider} from './abstract-provider'
const profile = {
@ -20,7 +21,7 @@ export class GanacheProvider extends AbstractProvider {
return (
<div>
{' '}
Note: To run Ganache on your system, run:
<FormattedMessage id="udapp.ganacheProviderText1" />
<div className="p-1 pl-3">
<b>yarn global add ganache</b>
</div>
@ -28,10 +29,16 @@ export class GanacheProvider extends AbstractProvider {
<b>ganache</b>
</div>
<div className="pt-2 pb-4">
For more info, visit:{' '}
<a href="https://github.com/trufflesuite/ganache" target="_blank">
Ganache Documentation
</a>
<FormattedMessage
id="udapp.ganacheProviderText2"
values={{
a: (chunks) => (
<a href="https://github.com/trufflesuite/ganache" target="_blank">
{chunks}
</a>
)
}}
/>
</div>
<div>Ganache JSON-RPC Endpoint:</div>
</div>

@ -1,5 +1,6 @@
import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {AbstractProvider} from './abstract-provider'
const profile = {
@ -20,15 +21,21 @@ export class HardhatProvider extends AbstractProvider {
return (
<div>
{' '}
Note: To run Hardhat network node on your system, go to hardhat project folder and run command:
<FormattedMessage id="udapp.hardhatProviderText1" />
<div className="p-1 pl-3">
<b>npx hardhat node</b>
</div>
<div className="pt-2 pb-4">
For more info, visit:{' '}
<a href="https://hardhat.org/getting-started/#connecting-a-wallet-or-dapp-to-hardhat-network" target="_blank">
Hardhat Documentation
</a>
<FormattedMessage
id="udapp.hardhatProviderText2"
values={{
a: (chunks) => (
<a href="https://hardhat.org/getting-started/#connecting-a-wallet-or-dapp-to-hardhat-network" target="_blank">
{chunks}
</a>
)
}}
/>
</div>
<div>Hardhat JSON-RPC Endpoint:</div>
</div>

@ -1,5 +1,6 @@
import * as packageJson from '../../../../../package.json'
import {InjectedCustomProvider} from './injected-custom-provider'
import Web3 from 'web3'
const profile = {
name: 'injected-ephemery-testnet-provider',
@ -27,4 +28,13 @@ export class InjectedEphemeryTestnetProvider extends InjectedCustomProvider {
]
)
}
async init() {
const chainId = await new Web3(this.rpcUrls[0]).eth.getChainId()
this.chainId = `0x${chainId.toString(16)}`
this.chainName = `Ephemery Testnet ${chainId}`
await super.init()
return {}
}
}

@ -101,11 +101,19 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
resolve({jsonrpc: '2.0', error: 'no return data provided', id: data.id})
}
} catch (error) {
resolve({
jsonrpc: '2.0',
error: error.data && error.data.message ? error.data.message : error.message,
id: data.id
})
if (error.data && error.data.originalError && error.data.originalError.data) {
resolve({
jsonrpc: '2.0',
error: error.data.originalError.message,
errorData: error.data.originalError.data,
id: data.id
})
} else
resolve({
jsonrpc: '2.0',
error: error.data && error.data.message ? error.data.message : error.message,
id: data.id
})
}
}
}

@ -7,5 +7,19 @@
"debugger.debugLocaNodeLabel": "Force using local node",
"debugger.useGeneratedSources": "Use generated sources",
"debugger.debugWithGeneratedSources": "When checked, debugger will also step through the compiled .yul file if it exists.",
"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"
"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",
"debugger.forceToUseCurrentLocalNode": "Force the debugger to use the current local node",
"debugger.sourceLocationStatus1": "Locating breakpoint, this might take a while...",
"debugger.sourceLocationStatus2": "Source location not available, neither in Sourcify nor in Etherscan. Please make sure the Etherscan api key is provided in the settings.",
"debugger.sourcifyDocs": "Sourcify docs",
"debugger.noDataAvailable": "No data available",
"debugger.loadMore": "Load more",
"debugger.copy": "Copy",
"debugger.stepOverBack": "Step over back",
"debugger.stepBack": "Step back",
"debugger.stepInto": "Step into",
"debugger.stepOverForward": "Step over forward",
"debugger.jumpPreviousBreakpoint": "Jump to the previous breakpoint",
"debugger.jumpOut": "Jump out",
"debugger.jumpNextBreakpoint": "Jump to the next breakpoint"
}

@ -45,6 +45,13 @@
"filePanel.publishFolderToGist": "Publish folder to gist",
"filePanel.publishFileToGist": "Publish file to gist",
"filePanel.copy": "Copy",
"filePanel.copyFileName": "Copy name",
"filePanel.copyFilePath": "Copy path",
"filePanel.contractflattener": "Flatten",
"filePanel.nahmii-compiler": "Compile for Nahmii",
"filePanel.solidityumlgen": "Generate UML",
"filePanel.doc-gen": "Generate Docs",
"filePanel.solidity": "Compile",
"filePanel.paste": "Paste",
"filePanel.compile": "Compile",
"filePanel.compileForNahmii": "Compile for Nahmii",
@ -66,5 +73,51 @@
"filePanel.features": "Features",
"filePanel.upgradeability": "Upgradeability",
"filePanel.ok": "OK",
"filePanel.cancel": "Cancel"
"filePanel.cancel": "Cancel",
"filePanel.createNewWorkspace": "create a new workspace",
"filePanel.connectToLocalhost": "connect to localhost",
"filePanel.copiedToClipboard": "Copied to clipboard {path}",
"filePanel.downloadFailed": "Download Failed",
"filePanel.downloadFailedMsg": "Unexpected error while downloading: {error}",
"filePanel.close": "Close",
"filePanel.copyFileFailed": "Copy File Failed",
"filePanel.copyFileFailedMsg": "Unexpected error while copying file: {src}",
"filePanel.copyFolderFailed": "Copy Folder Failed",
"filePanel.copyFolderFailedMsg": "Unexpected error while copying folder: {src}",
"filePanel.runScriptFailed": "Run script failed",
"filePanel.createPublicGist": "Create a public gist",
"filePanel.createPublicGistMsg1": "Are you sure you want to push changes to remote gist file on github.com?",
"filePanel.createPublicGistMsg2": "Are you sure you want to anonymously publish all your files in the {path} folder as a public gist on github.com?",
"filePanel.createPublicGistMsg3": "Are you sure you want to anonymously publish {path} file as a public gist on github.com?",
"filePanel.createPublicGistMsg4": "Are you sure you want to anonymously publish all your files in the {name} workspace as a public gist on github.com?",
"filePanel.deleteMsg": "Are you sure you want to delete",
"filePanel.theseItems": "these items",
"filePanel.thisItem": "this item",
"filePanel.deleteItems": "Delete items",
"filePanel.deleteItem": "Delete item",
"filePanel.globalToast": "Cannot write/modify file system in read only mode.",
"filePanel.basic": "Basic",
"filePanel.blank": "Blank",
"filePanel.multiSigWallet": "MultiSig Wallet",
"filePanel.mintable": "Mintable",
"filePanel.burnable": "Burnable",
"filePanel.pausable": "Pausable",
"filePanel.transparent": "Transparent",
"filePanel.initGitRepoTitle": "Check option to initialize workspace as a new git repository",
"filePanel.switchToBranchTitle1": "Checkout new branch from remote branch",
"filePanel.switchToBranchTitle2": "Checkout to local branch",
"filePanel.readOnly": "read-only",
"filePanel.renameFileFailed": "Rename File Failed",
"filePanel.renameFileFailedMsg": "Unexpected error while renaming: {error}",
"filePanel.fileCreationFailed": "File Creation Failed",
"filePanel.folderCreationFailed": "Folder Creation Failed",
"filePanel.validationError": "Validation Error",
"filePanel.validationErrorMsg": "Special characters are not allowed",
"filePanel.reservedKeyword": "Reserved Keyword",
"filePanel.reservedKeywordMsg": "File name contains Remix reserved keywords. \"{content}\"",
"filePanel.movingFileFailed": "Moving File Failed",
"filePanel.movingFileFailedMsg": "Unexpected error while moving file: {src}",
"filePanel.movingFolderFailed": "Moving Folder Failed",
"filePanel.movingFolderFailedMsg": "Unexpected error while moving folder: {src}",
"filePanel.workspaceActions": "Workspace actions"
}

@ -47,7 +47,7 @@
"home.remixTwitterProfile": "Remix Twitter Profile",
"home.remixLinkedinProfile": "Remix Linkedin Profile",
"home.remixMediumPosts": "Remix Medium Posts",
"home.remixGitterChannel": "Join us on Discord",
"home.joinUsOnDiscord": "Join us on Discord",
"home.nativeIDE": "The Native IDE for Web3 Development.",
"home.website": "Website",
"home.documentation": "Documentation",
@ -57,7 +57,10 @@
"home.files": "Files",
"home.newFile": "New File",
"home.openFile": "Open File",
"home.connectToLocalhost": "Access File System",
"home.accessFileSystem": "Access File System",
"home.loadFrom": "Load from",
"home.resources": "Resources"
"home.resources": "Resources",
"home.connectToLocalhost": "Connect to Localhost",
"home.seeAllTutorials": "See all tutorials",
"home.maintainedByRemix": "Maintained by Remix"
}

@ -10,6 +10,9 @@ import terminalJson from './terminal.json';
import udappJson from './udapp.json';
import solidityUnitTestingJson from './solidityUnitTesting.json';
import permissionHandlerJson from './permissionHandler.json';
import solUmlGenJson from './solUmlGen.json'
import remixAppJson from './remixApp.json'
import remixUiTabsJson from './remixUiTabs.json'
export default {
...debuggerJson,
@ -24,4 +27,7 @@ export default {
...udappJson,
...solidityUnitTestingJson,
...permissionHandlerJson,
...solUmlGenJson,
...remixAppJson,
...remixUiTabsJson,
}

@ -2,5 +2,9 @@
"panel.author": "Author",
"panel.maintainedBy": "Maintained By",
"panel.documentation": "Documentation",
"panel.description": "Description"
"panel.description": "Description",
"panel.maintainedByRemix": "Maintained by Remix",
"panel.pluginInfo": "Plugin info",
"panel.linkToDoc": "Link to documentation",
"panel.makeAnissue": "Make an issue"
}

@ -19,6 +19,10 @@
"pluginManager.localForm.sidePanel": "Side Panel",
"pluginManager.localForm.mainPanel": "Main Panel",
"pluginManager.localForm.none": "None",
"pluginManager.localForm.methods": "Methods",
"pluginManager.localForm.pluginNames": "Plugin names",
"pluginManager.localForm.ok": "OK",
"pluginManager.localForm.cancel": "Cancel",
"pluginManager.Permissions": "Permissions",
"pluginManager.permissions": "permissions",
"pluginManager.pluginManagerPermissions": "Plugin Manager Permissions",
@ -27,5 +31,13 @@
"pluginManager.allow": "Allow",
"pluginManager.toCall": "to call",
"pluginManager.ok": "OK",
"pluginManager.cancel": "Cancel"
"pluginManager.cancel": "Cancel",
"pluginManager.maintainedByRemix": "Maintained by Remix",
"pluginManager.linkToDoc": "Link to documentation",
"pluginManager.versionAlpha": "Version Alpha",
"pluginManager.versionBeta": "Version Beta",
"pluginManager.deactivatePlugin": "Deactivate {pluginName}",
"pluginManager.activatePlugin": "Activate {pluginName}",
"pluginManager.search": "Search",
"pluginManager.managePluginsPermissions": "Manage plugins Permissions"
}

@ -0,0 +1,3 @@
{
"remixApp.scrollToSeeAllTabs": "Scroll to see all tabs"
}

@ -0,0 +1,7 @@
{
"remixUiTabs.tooltipText1": "Run script (CTRL + SHIFT + S)",
"remixUiTabs.tooltipText2": "Compile CTRL + S",
"remixUiTabs.tooltipText3": "Select .sol or .yul file to compile or a .ts or .js file and run it",
"remixUiTabs.zoomOut": "Zoom out",
"remixUiTabs.zoomIn": "Zoom in"
}

@ -10,5 +10,15 @@
"search.useRegularExpression": "Use Regular Expression",
"search.replaceWithoutConfirmation": "replace without confirmation",
"search.filesToInclude": "Files to include",
"search.filesToExclude": "Files to exclude"
"search.filesToExclude": "Files to exclude",
"search.toggleReplace": "Toggle Replace",
"search.replaceInFiles": "replace in files",
"search.stop": "stop",
"search.undoChanges": "Undo changes to {path}",
"search.confirmreplaceMsg": "Are you sure you want to replace \"{find}\" by \"{replace}\" in {filename}?",
"search.yes": "Yes",
"search.no": "No",
"search.loading": "Loading",
"search.text1": "showing {count} results in {fileCount} files",
"search.text2": "Too many resuls to display...{br}Please narrow down your search."
}

@ -22,5 +22,19 @@
"settings.themes": "Themes",
"settings.locales": "Language",
"settings.swarm": "Swarm Settings",
"settings.ipfs": "IPFS Settings"
"settings.ipfs": "IPFS Settings",
"settings.token": "TOKEN",
"settings.copy": "Copy",
"settings.deleteEtherscanToken": "Delete Etherscan token",
"settings.username": "USERNAME",
"settings.email": "EMAIL",
"settings.deleteGithubCredentials": "Delete Github Credentials",
"settings.privateBeeAddress": "PRIVATE BEE ADDRESS",
"settings.postageStampID": "POSTAGE STAMP ID",
"settings.host": "HOST",
"settings.protocol": "PROTOCOL",
"settings.port": "PORT",
"settings.projectID": "PROJECT ID",
"settings.projectSecret": "PROJECT SECRET",
"settings.analyticsInRemix": "Analytics in Remix IDE"
}

@ -0,0 +1,10 @@
{
"solUmlGen.pngDownload": "Download as PNG",
"solUmlGen.pdfDownload": "Download as PDF",
"solUmlGen.pngDownloadTooltip": "Download UML diagram as a PNG file",
"solUmlGen.pdfDownloadTooltip": "Download UML diagram as a PDF file",
"solUmlGen.text1": "To view your contract as a UML Diagram",
"solUmlGen.text2": "Right click on your contract file",
"solUmlGen.clickOn": "Click on",
"solUmlGen.generateUML": "Generate UML"
}

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

@ -1,5 +1,7 @@
{
"solidity.displayName": "Solidity compiler",
"solidity._comment_compiler-container.tsx": "libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx",
"solidity.compiler": "Compiler",
"solidity.addACustomCompiler": "Add a custom compiler",
"solidity.addACustomCompilerWithURL": "Add a custom compiler with URL",
@ -21,11 +23,46 @@
"solidity.compile": "Compile",
"solidity.noFileSelected": "no file selected",
"solidity.compileAndRunScript": "Compile and Run script",
"solidity.newConfigFileTitle": "New configuration file",
"solidity.newConfigFileMessage": "The file \"{configFilePathInput}\" you entered does not exist. Do you want to create a new one?",
"solidity.create": "Create",
"solidity.ok": "OK",
"solidity.cancel": "Cancel",
"solidity.noFileSelected1": "No file selected.",
"solidity.toCompile": "to compile",
"solidity.noConfigFileSelected": "No config file selected",
"solidity.copyNatSpecTag": "Click to copy the custom NatSpec tag",
"solidity.inputTitle1": "If the file you entered does not exist you will be able to create one in the next step.",
"solidity.inputTitle2": "Estimated number of times each opcode of the deployed code will be executed across the life-time of the contract.",
"solidity.tooltipText1": "Choose the script to execute right after compilation by adding the `dev-run-script` natspec tag, as in:",
"solidity.tooltipText2": "Click the \"i\" icon to learn more",
"solidity.tooltipText3": "for compiling and script execution",
"solidity.tooltipText4": "Click to open the config file",
"solidity.tooltipText5": "Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload. Error: ",
"solidity.tooltipText6": "Language specification available from Compiler >= v0.5.7",
"solidity.toastMessage": "Updating compiler version to match current contract file pragma i.e {version}",
"solidity.compileIconAttribute": "compiler is loading, please wait a few moments.",
"solidity.compilerLicense": "Compiler License",
"solidity.compilerLicenseMsg1": "Compiler is loading. License will be displayed once compiler is loaded",
"solidity.compilerLicenseMsg2": "Could not retreive license for selected compiler version",
"solidity.compilerLicenseMsg3": "License not available",
"solidity.seeCompilerLicense": "See compiler license",
"solidity._comment_contract-selection.tsx": "libs/remix-ui/solidity-compiler/src/lib/contract-selection.tsx",
"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.copy": "Copy",
"solidity.copyABI": "Copy ABI to clipboard",
"solidity.copyBytecode": "Copy Bytecode to clipboard",
"solidity.unableToDisplay": "Unable to display",
"solidity.download": "Download",
"solidity.close": "Close",
"solidity.contract": "Contract",
"solidity.displayContractDetails": "Display Contract Details",
"solidity.noContractCompiled": "No Contract Compiled Yet",
"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",
@ -37,5 +74,9 @@
"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.storageLayout": "See the Storage Layout documentation.",
"solidity.devdoc": "Developer documentation (natspec)",
"solidity.userdoc": "User documentation (natspec)",
"solidity.compilerInput": "Input to the Solidity compiler",
"solidity.swarmLocation": "Swarm url where all metadata information can be found (contract needs to be published first)"
}

@ -31,5 +31,11 @@
"solidityUnitTesting.assertion": "Assertion",
"solidityUnitTesting.expectedValueShouldBe": "Expected value should be",
"solidityUnitTesting.receivedValue": "Received value",
"solidityUnitTesting.skippingTheRemainingTests": "Skipping the remaining tests of the function."
"solidityUnitTesting.skippingTheRemainingTests": "Skipping the remaining tests of the function.",
"solidityUnitTesting.toasterMsg": "Folder created successfully",
"solidityUnitTesting.tooltipText1": "At least one contract test failed",
"solidityUnitTesting.tooltipText2": "All contract tests passed",
"solidityUnitTesting.tooltipText3": "Start debugging",
"solidityUnitTesting.fail": "FAIL",
"solidityUnitTesting.pass": "PASS"
}

@ -13,5 +13,31 @@
"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"
"terminal.welcomeText10": "Type the library name to see available commands",
"terminal.text1": "This type of command has been deprecated and is not functionning anymore. Please run remix.help() to list available commands.",
"terminal.hideTerminal": "Hide Terminal",
"terminal.showTerminal": "Show Terminal",
"terminal.clearConsole": "Clear console",
"terminal.pendingTransactions": "Pending Transactions",
"terminal.toasterMsg1": "no content to execute",
"terminal.toasterMsg2": "provider for path {fileName} not found",
"terminal.vmMode": "VM mode",
"terminal.vmModeMsg": "Cannot debug this call. Debugging calls is only possible in Remix VM mode.",
"terminal.ok": "Ok",
"terminal.cancel": "Cancel",
"terminal.callWarning": "(Cost only applies when called by a contract)",
"terminal.msg1": "Transaction mined but execution failed",
"terminal.msg2": "Transaction mined and execution succeed",
"terminal.msg3": "Status not available at the moment",
"terminal.status": "status",
"terminal.transactionHash": "transaction hash",
"terminal.blockHash": "block hash",
"terminal.blockNumber": "block number",
"terminal.contractAddress": "contract address",
"terminal.transactionCost": "transaction cost",
"terminal.executionCost": "execution cost",
"terminal.input": "input",
"terminal.decodedInput": "decoded input",
"terminal.decodedOutput": "decoded output",
"terminal.logs": "logs"
}

@ -1,23 +1,22 @@
{
"udapp.displayName": "Deploy & run transactions",
"udapp._comment_gasPrice.tsx": "libs/remix-ui/run-tab/src/lib/components/gasPrice.tsx",
"udapp.gasLimit": "Gas limit",
"udapp.account": "Account",
"udapp.tooltipText4": "The default gas limit is 3M. Adjust as needed.",
"udapp._comment_value.tsx": "libs/remix-ui/run-tab/src/lib/components/value.tsx",
"udapp.value": "Value",
"udapp.tooltipText5": "Enter an amount and choose its unit",
"udapp._comment_contractDropdownUI.tsx": "libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx",
"udapp.contract": "Contract",
"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",
"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)",
@ -34,9 +33,44 @@
"udapp.noCompiledContracts": "No compiled contracts",
"udapp.addressOfContract": "Address of contract",
"udapp.loadContractFromAddress": "Load contract from Address",
"udapp.ok": "OK",
"udapp.alert": "Alert",
"udapp.proceed": "Proceed",
"udapp.cancel": "Cancel",
"udapp.abiFileSelected": "ABI file selected",
"udapp.evmVersion": "evm version",
"udapp.addressNotValid": "The address is not valid",
"udapp._comment_account.tsx": "libs/remix-ui/run-tab/src/lib/components/account.tsx",
"udapp.account": "Account",
"udapp.signAMessage": "Sign a message",
"udapp.enterAMessageToSign": "Enter a message to sign",
"udapp.hash": "hash",
"udapp.signature": "signature",
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
"udapp.createNewAccount": "Create a new account",
"udapp.web3Title": "Creating an account is possible only in Personal mode. Please go to Settings to enable it.",
"udapp.defaultTitle": "Unfortunately it's not possible to create an account using an external wallet ({selectExEnv}).",
"udapp.text1": "Please provide a Passphrase for the account creation",
"udapp.tooltipText1": "Account list is empty, please make sure the current provider is properly connected to remix",
"udapp.modalTitle1": "Passphrase to sign a message",
"udapp.modalMessage1": "Enter your passphrase for this account to sign the message",
"udapp.copyAccount": "Copy account to clipboard",
"udapp.signMsgUsingAccount": "Sign a message using this account",
"udapp._comment_environment.tsx": "libs/remix-ui/run-tab/src/lib/components/environment.tsx",
"udapp.environment": "Environment",
"udapp.environmentDocs": "Click for docs about Environment",
"udapp.tooltipText2": "Open chainlist.org and get the connection specs of the chain you want to interact with.",
"udapp.tooltipText3": "Click to open a bridge for converting L1 mainnet ETH to the selected network currency.",
"udapp._comment_instanceContainerUI.tsx": "libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx",
"udapp.deployedContracts": "Deployed Contracts",
"udapp.deployAndRunClearInstances": "Clear instances list and reset recorder",
"udapp.deployAndRunNoInstanceText": "Currently you have no contract instances to interact with.",
"udapp.tooltipText6": "Autogenerated generic user interfaces for interaction with deployed contracts",
"udapp._comment_recorderCardUI.tsx": "libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx",
"udapp.transactionsRecorded": "Transactions recorded",
"udapp.transactionsCountTooltip": "The number of recorded transactions",
"udapp.transactionSaveTooltip1": "No transactions to save",
@ -48,18 +82,70 @@
"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._comment_contractGUI.tsx": "libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx",
"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."
"udapp.getEncodedCallError": "cannot encode empty arguments",
"udapp.proxyAddressError1": "proxy address cannot be empty",
"udapp.proxyAddressError2": "not a valid contract address",
"udapp.tooltipText11": "Proxy address cannot be empty",
"udapp.tooltipText12": "Input required",
"udapp.tooltipText13": "Deployed {date}",
"udapp._comment_universalDappUI.tsx": "libs/remix-ui/run-tab/src/lib/components/universalDappUI.tsx",
"udapp.tooltipText7": "Remove from the list",
"udapp.tooltipText8": "Click for docs about using 'receive'/'fallback'",
"udapp.tooltipText9": "The Calldata to send to fallback function of the contract.",
"udapp.tooltipText10": "Send data to contract.",
"udapp.balance": "Balance",
"udapp.lowLevelInteractions": "Low level interactions",
"udapp.llIError1": "Value to send should be a number",
"udapp.llIError2": "In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function",
"udapp.llIError3": "The calldata should be a valid hexadecimal value with size of at least one byte.",
"udapp.llIError4": "The calldata should be a valid hexadecimal value.",
"udapp.llIError5": "'Fallback' function is not defined",
"udapp.llIError6": "Both 'receive' and 'fallback' functions are not defined",
"udapp.llIError7": "Please define a 'Fallback' function to send calldata and a either 'Receive' or payable 'Fallback' to send ethers",
"udapp.copy": "Copy",
"udapp._comment_mainnet.tsx": "libs/remix-ui/run-tab/src/lib/components/mainnet.tsx",
"udapp.mainnetText1": "You are about to create a transaction on {name} Network. Confirm the details to send the info to your provider.",
"udapp.mainnetText2": "The provider for many users is MetaMask. The provider will ask you to sign the transaction before it is sent to {name} Network.",
"udapp.amount": "Amount",
"udapp.gasEstimation": "Gas estimation",
"udapp.maxPriorityFee": "Max Priority fee",
"udapp.maxFee": "Max fee (Not less than base fee {baseFeePerGas} Gwei)",
"udapp.contractCreation": "Contract Creation",
"udapp.transactionFee": "Transaction is invalid. Max fee should not be less than Base fee",
"udapp.title1": "Represents the part of the tx fee that goes to the miner.",
"udapp.title2": "Represents the maximum amount of fee that you will pay for this transaction. The minimun needs to be set to base fee.",
"udapp.gasPrice": "Gas price",
"udapp.gweiText": "visit {a} for current gas price info.",
"udapp.maxTransactionFee": "Max transaction fee",
"udapp.mainnetText3": "Do not show this warning again.",
"udapp._comment_run-tab.tsx": "libs/remix-ui/run-tab/src/lib/run-tab.tsx",
"udapp.gasEstimationPromptText": "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?",
"udapp._comment_custom-dropdown.tsx": "libs/remix-ui/helper/src/lib/components/custom-dropdown.tsx",
"udapp.enterProxyAddress": "Enter Proxy Address",
"udapp._comment_provider": "apps/remix-ide/src/app/providers",
"udapp.customVmForkProviderText": "Please provide information about the custom fork. If the node URL is not provided, the VM will start with an empty state.",
"udapp.nodeUrl": "Node URL",
"udapp.blockNumber": "Block number (or \"latest\")",
"udapp.externalHttpProviderText1": "Note: To use Geth & https://remix.ethereum.org, configure it to allow requests from Remix:(see <a>Geth Docs on rpc server</a>)",
"udapp.externalHttpProviderText2": "To run Remix & a local Geth test node, use this command: (see <a>Geth Docs on Dev mode</a>)",
"udapp.externalHttpProviderText3": "<b>WARNING:</b> It is not safe to use the --http.corsdomain flag with a wildcard: <b>--http.corsdomain *</b>",
"udapp.externalHttpProviderText4": "For more info: <a>Remix Docs on External HTTP Provider</a>",
"udapp.foundryProviderText1": "Note: To run Anvil on your system, run:",
"udapp.foundryProviderText2": "For more info, visit: <a>Foundry Documentation</a>",
"udapp.ganacheProviderText1": "Note: To run Ganache on your system, run:",
"udapp.ganacheProviderText2": "For more info, visit: <a>Ganache Documentation</a>",
"udapp.hardhatProviderText1": "Note: To run Hardhat network node on your system, go to hardhat project folder and run command:",
"udapp.hardhatProviderText2": "For more info, visit: <a>Hardhat Documentation</a>"
}

@ -0,0 +1,36 @@
import debuggerJson from './debugger.json';
import filePanelJson from './filePanel.json';
import homeJson from './home.json';
import panelJson from './panel.json';
import pluginManagerJson from './pluginManager.json';
import searchJson from './search.json';
import settingsJson from './settings.json';
import solidityJson from './solidity.json';
import terminalJson from './terminal.json';
import udappJson from './udapp.json';
import solidityUnitTestingJson from './solidityUnitTesting.json';
import permissionHandlerJson from './permissionHandler.json';
import solUmlGenJson from './solUmlGen.json'
import remixAppJson from './remixApp.json'
import remixUiTabsJson from './remixUiTabs.json'
import enJson from '../en';
// There may have some un-translated content. Always fill in the gaps with EN JSON.
// No need for a defaultMessage prop when render a FormattedMessage component.
export default Object.assign({}, enJson, {
...debuggerJson,
...filePanelJson,
...homeJson,
...panelJson,
...pluginManagerJson,
...searchJson,
...settingsJson,
...solidityJson,
...terminalJson,
...udappJson,
...solidityUnitTestingJson,
...permissionHandlerJson,
...solUmlGenJson,
...remixAppJson,
...remixUiTabsJson,
})

@ -0,0 +1,3 @@
{
"remixApp.scrollToSeeAllTabs": "Scroll to see all tabs"
}

@ -0,0 +1,7 @@
{
"remixUiTabs.tooltipText1": "Run script (CTRL + SHIFT + S)",
"remixUiTabs.tooltipText2": "Compile CTRL + S",
"remixUiTabs.tooltipText3": "Select .sol or .yul file to compile or a .ts or .js file and run it",
"remixUiTabs.zoomOut": "Zoom out",
"remixUiTabs.zoomIn": "Zoom in"
}

@ -0,0 +1,10 @@
{
"solUmlGen.pngDownload": "Download as PNG",
"solUmlGen.pdfDownload": "Download as PDF",
"solUmlGen.pngDownloadTooltip": "Download UML diagram as a PNG file",
"solUmlGen.pdfDownloadTooltip": "Download UML diagram as a PDF file",
"solUmlGen.text1": "To view your contract as a UML Diagram",
"solUmlGen.text2": "Right click on your contract file",
"solUmlGen.clickOn": "Click on",
"solUmlGen.generateUML": "Generate UML"
}

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

@ -0,0 +1,36 @@
import debuggerJson from './debugger.json';
import filePanelJson from './filePanel.json';
import homeJson from './home.json';
import panelJson from './panel.json';
import pluginManagerJson from './pluginManager.json';
import searchJson from './search.json';
import settingsJson from './settings.json';
import solidityJson from './solidity.json';
import terminalJson from './terminal.json';
import udappJson from './udapp.json';
import solidityUnitTestingJson from './solidityUnitTesting.json';
import permissionHandlerJson from './permissionHandler.json';
import solUmlGenJson from './solUmlGen.json'
import remixAppJson from './remixApp.json'
import remixUiTabsJson from './remixUiTabs.json'
import enJson from '../en';
// There may have some un-translated content. Always fill in the gaps with EN JSON.
// No need for a defaultMessage prop when render a FormattedMessage component.
export default Object.assign({}, enJson, {
...debuggerJson,
...filePanelJson,
...homeJson,
...panelJson,
...pluginManagerJson,
...searchJson,
...settingsJson,
...solidityJson,
...terminalJson,
...udappJson,
...solidityUnitTestingJson,
...permissionHandlerJson,
...solUmlGenJson,
...remixAppJson,
...remixUiTabsJson,
})

@ -0,0 +1,3 @@
{
"remixApp.scrollToSeeAllTabs": "Scroll to see all tabs"
}

@ -0,0 +1,7 @@
{
"remixUiTabs.tooltipText1": "Run script (CTRL + SHIFT + S)",
"remixUiTabs.tooltipText2": "Compile CTRL + S",
"remixUiTabs.tooltipText3": "Select .sol or .yul file to compile or a .ts or .js file and run it",
"remixUiTabs.zoomOut": "Zoom out",
"remixUiTabs.zoomIn": "Zoom in"
}

@ -0,0 +1,10 @@
{
"solUmlGen.pngDownload": "Download as PNG",
"solUmlGen.pdfDownload": "Download as PDF",
"solUmlGen.pngDownloadTooltip": "Download UML diagram as a PNG file",
"solUmlGen.pdfDownloadTooltip": "Download UML diagram as a PDF file",
"solUmlGen.text1": "To view your contract as a UML Diagram",
"solUmlGen.text2": "Right click on your contract file",
"solUmlGen.clickOn": "Click on",
"solUmlGen.generateUML": "Generate UML"
}

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

@ -10,6 +10,9 @@ import terminalJson from './terminal.json';
import udappJson from './udapp.json';
import solidityUnitTestingJson from './solidityUnitTesting.json';
import permissionHandlerJson from './permissionHandler.json';
import solUmlGenJson from './solUmlGen.json'
import remixAppJson from './remixApp.json'
import remixUiTabsJson from './remixUiTabs.json'
import enJson from '../en';
// There may have some un-translated content. Always fill in the gaps with EN JSON.
@ -27,4 +30,7 @@ export default Object.assign({}, enJson, {
...udappJson,
...solidityUnitTestingJson,
...permissionHandlerJson,
...solUmlGenJson,
...remixAppJson,
...remixUiTabsJson,
})

@ -0,0 +1,3 @@
{
"remixApp.scrollToSeeAllTabs": "滚动查看所有标签页"
}

@ -0,0 +1,7 @@
{
"remixUiTabs.tooltipText1": "执行脚本 (CTRL + SHIFT + S)",
"remixUiTabs.tooltipText2": "编译 CTRL + S",
"remixUiTabs.tooltipText3": "选择 .sol 或 .yul 文件进行编译,或选择 .ts 或 .js 文件并运行它",
"remixUiTabs.zoomOut": "缩小",
"remixUiTabs.zoomIn": "放大"
}

@ -0,0 +1,10 @@
{
"solUmlGen.pngDownload": "下载 PNG",
"solUmlGen.pdfDownload": "下载 PDF",
"solUmlGen.pngDownloadTooltip": "将 UML 图下载为 PNG 文件",
"solUmlGen.pdfDownloadTooltip": "将 UML 图下载为 PDF 文件",
"solUmlGen.text1": "以 UML 图查看您的合约",
"solUmlGen.text2": "右键单击您的合约文件",
"solUmlGen.clickOn": "点击",
"solUmlGen.generateUML": "生成 UML"
}

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

@ -945,13 +945,12 @@ export class Blockchain extends Plugin {
? toBuffer(execResult.returnValue)
: toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000')
const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas')
const vmError = txExecution.checkVMError(execResult, compiledContracts)
const vmError = txExecution.checkError({ errorMessage: execResult.exceptionError ? execResult.exceptionError.error : '', errorData: execResult.returnValue }, compiledContracts)
if (vmError.error) {
return cb(vmError.message)
}
}
}
if (!isVM && tx && tx.useCall) {
returnValue = toBuffer(addHexPrefix(txResult.result))
}
@ -963,7 +962,17 @@ export class Blockchain extends Plugin {
cb(null, txResult, address, returnValue)
} catch (error) {
cb(error)
if (this.isInjectedWeb3()) {
let errorObj = error.replace('Returned error: ', '')
errorObj = JSON.parse(errorObj)
if (errorObj.errorData) {
const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas')
const injectedError = txExecution.checkError({ errorMessage: errorObj.error, errorData: errorObj.errorData }, compiledContracts)
cb(injectedError.message)
} else
cb(error)
} else
cb(error)
}
}
}

@ -72,7 +72,8 @@ const requiredModules = [
'codeFormatter',
'solidityumlgen',
'contractflattener',
'solidity-script'
'solidity-script',
'openaigpt'
]
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)

@ -1,10 +1,8 @@
export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, shouldSetFile = true, key?) => {
export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, shouldSetFile = true, etherscanKey?) => {
let data
const compilationTargets = {}
let etherscanKey
if (!key) etherscanKey = await plugin.call('config', 'getAppParameter', 'etherscan-access-token')
else etherscanKey = key
if (!etherscanKey) etherscanKey = await plugin.call('config', 'getAppParameter', 'etherscan-access-token')
if (!etherscanKey) etherscanKey = '2HKUX5ZVASZIKWJM8MIQVCRUVZ6JAWT531'
if (etherscanKey) {
const endpoint = network.id == 1 ? 'api.etherscan.io' : 'api-' + network.name + '.etherscan.io'
@ -63,4 +61,4 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
settings,
compilationTargets
}
}
}

@ -54,10 +54,11 @@ export function callFunction (from, to, data, value, gasLimit, funAbi, txRunner,
/**
* check if the vm has errored
*
* @param {Object} execResult - execution result given by the VM
* @param {Object} execResult - execution result given by the VM, contain errorMessage and errorDate
* @param {Object} compiledContracts - Object containing contract compilation details
* @return {Object} - { error: true/false, message: DOMNode }
*/
export function checkVMError (execResult, compiledContracts) {
export function checkError (execResult, compiledContracts) {
const errorCode = {
OUT_OF_GAS: 'out of gas',
STACK_UNDERFLOW: 'stack underflow',
@ -75,11 +76,11 @@ export function checkVMError (execResult, compiledContracts) {
error: false,
message: ''
}
if (!execResult.exceptionError) {
if (!execResult.errorMessage) {
return ret
}
const exceptionError = execResult.exceptionError.error || ''
const error = `VM error: ${exceptionError}.\n`
const exceptionError = execResult.errorMessage || ''
const error = `Error occured: ${execResult.errorMessage}.\n`
let msg
if (exceptionError === errorCode.INVALID_OPCODE) {
msg = '\t\n\tThe execution might have thrown.\n'
@ -87,8 +88,8 @@ export function checkVMError (execResult, compiledContracts) {
} else if (exceptionError === errorCode.OUT_OF_GAS) {
msg = '\tThe transaction ran out of gas. Please increase the Gas Limit.\n'
ret.error = true
} else if (exceptionError === errorCode.REVERT) {
const returnData = execResult.returnValue
} else if (exceptionError === errorCode.REVERT || exceptionError === 'execution reverted') {
const returnData = execResult.errorData
const returnDataHex = returnData.slice(2, 10)
let customError
if (compiledContracts) {
@ -172,4 +173,4 @@ export function checkVMError (execResult, compiledContracts) {
}
ret.message = `${error}\n${exceptionError}\n${msg}\nDebug the transaction to get more information.`
return ret
}
}

@ -8,7 +8,7 @@ import {AppProvider} from './context/provider'
import AppDialogs from './components/modals/dialogs'
import DialogViewPlugin from './components/modals/dialogViewPlugin'
import {AppContext} from './context/context'
import {IntlProvider} from 'react-intl'
import {IntlProvider, FormattedMessage} from 'react-intl'
import {CustomTooltip} from '@remix-ui/helper'
interface IRemixAppUi {
@ -104,7 +104,7 @@ const RemixApp = (props: IRemixAppUi) => {
></DragBar>
<div id="main-panel" data-id="remixIdeMainPanel" className="mainpanel d-flex">
<RemixUIMainPanel Context={AppContext}></RemixUIMainPanel>
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-all-tabs" tooltipText="Scroll to see all tabs">
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-all-tabs" tooltipText={<FormattedMessage id="remixApp.scrollToSeeAllTabs" />}>
<div className="remix-ui-tabs_end remix-bg-opacity position-absolute position-fixed"></div>
</CustomTooltip>
</div>

@ -1,5 +1,6 @@
import {CustomTooltip} from '@remix-ui/helper'
import React, {useState, useEffect} from 'react' // eslint-disable-line
import {useIntl} from 'react-intl'
import './button-navigator.css'
export const ButtonNavigation = ({
@ -15,6 +16,7 @@ export const ButtonNavigation = ({
stepState,
jumpOutDisabled
}) => {
const intl = useIntl()
const [state, setState] = useState({
intoBackDisabled: true,
overBackDisabled: true,
@ -90,7 +92,7 @@ export const ButtonNavigation = ({
),
placement: 'top-start',
tagId: 'overbackTooltip',
tooltipMsg: 'Step over back'
tooltipMsg: intl.formatMessage({id: 'debugger.stepOverBack'})
},
stepBackJSX: {
markup: (
@ -118,7 +120,7 @@ export const ButtonNavigation = ({
),
placement: 'top-start',
tagId: 'intobackTooltip',
tooltipMsg: 'Step back'
tooltipMsg: intl.formatMessage({id: 'debugger.stepBack'})
},
stepIntoJSX: {
@ -147,7 +149,7 @@ export const ButtonNavigation = ({
),
placement: 'top-start',
tagId: 'intoforwardTooltip',
tooltipMsg: 'Step into'
tooltipMsg: intl.formatMessage({id: 'debugger.stepInto'})
},
stepOverForwardJSX: {
markup: (
@ -174,7 +176,7 @@ export const ButtonNavigation = ({
),
placement: 'top-end',
tagId: 'overbackTooltip',
tooltipMsg: 'Step over forward'
tooltipMsg: intl.formatMessage({id: 'debugger.stepOverForward'})
}
}
const jumpMarkupStructure = {
@ -208,7 +210,7 @@ export const ButtonNavigation = ({
),
placement: 'bottom-start',
tagId: 'jumppreviousbreakpointTooltip',
tooltipMsg: 'Jump to the previous breakpoint'
tooltipMsg: intl.formatMessage({id: 'debugger.jumpPreviousBreakpoint'})
},
jumpOutJSX: {
markup: (
@ -240,7 +242,7 @@ export const ButtonNavigation = ({
),
placement: 'bottom-end',
tagId: 'jumpoutTooltip',
tooltipMsg: 'Jump out'
tooltipMsg: intl.formatMessage({id: 'debugger.jumpOut'})
},
jumpNextBreakpointJSX: {
markup: (
@ -268,7 +270,7 @@ export const ButtonNavigation = ({
),
placement: 'bottom-end',
tagId: 'jumpnextbreakpointTooltip',
tooltipMsg: 'Jump to the next breakpoint'
tooltipMsg: intl.formatMessage({id: 'debugger.jumpNextBreakpoint'})
}
}

@ -1,5 +1,5 @@
import React, {useState, useEffect, useRef} from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import TxBrowser from './tx-browser/tx-browser' // eslint-disable-line
import StepManager from './step-manager/step-manager' // eslint-disable-line
import VmDebugger from './vm-debugger/vm-debugger' // eslint-disable-line
@ -13,6 +13,7 @@ import './debugger-ui.css'
const _paq = ((window as any)._paq = (window as any)._paq || [])
export const DebuggerUI = (props: DebuggerUIProps) => {
const intl = useIntl()
const debuggerModule = props.debuggerAPI
const [state, setState] = useState({
isActive: false,
@ -128,7 +129,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
setState((prevState) => {
return {
...prevState,
sourceLocationStatus: 'Locating breakpoint, this might take a while...'
sourceLocationStatus: intl.formatMessage({id: 'debugger.sourceLocationStatus1'})
}
})
})
@ -145,7 +146,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
setState((prevState) => {
return {
...prevState,
sourceLocationStatus: 'Source location not available, neither in Sourcify nor in Etherscan. Please make sure the Etherscan api key is provided in the settings.'
sourceLocationStatus: intl.formatMessage({id: 'debugger.sourceLocationStatus2'})
}
})
return
@ -408,7 +409,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
</div>
{state.isLocalNodeUsed && (
<div className="mb-2 debuggerConfig custom-control custom-checkbox">
<CustomTooltip tooltipId="debuggerGenSourceInput" tooltipText="Force the debugger to use the current local node" placement="right">
<CustomTooltip tooltipId="debuggerGenSourceInput" tooltipText={<FormattedMessage id="debugger.forceToUseCurrentLocalNode" />} placement="right">
<input
className="custom-control-input"
id="debugWithLocalNodeInput"
@ -448,7 +449,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<span>
<FormattedMessage id="debugger.introduction" />:{' '}
<a href="https://docs.sourcify.dev/docs/chains/" target="__blank">
Sourcify docs
<FormattedMessage id="debugger.sourcifyDocs" />
</a>{' '}
&{' '}
<a href="https://etherscan.io/contractsVerified" target="__blank">

@ -1,4 +1,5 @@
import React, {useState, useRef, useEffect, useReducer} from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {initialState, reducer} from '../../reducers/assembly-items'
import './styles/assembly-items.css'
@ -145,7 +146,11 @@ export const AssemblyItems = ({registerEvent}) => {
<div className="h-100 border rounded px-1 mt-1 bg-light">
<div className="dropdownpanel">
<div className="dropdowncontent pb-2">
{assemblyItems.display.length == 0 && <div>No data available</div>}
{assemblyItems.display.length == 0 && (
<div>
<FormattedMessage id="debugger.noDataAvailable" />
</div>
)}
<div className="pl-2 my-1 small instructions" data-id="asmitems" id="asmitems" ref={asmItemsRef}>
{assemblyItems.display.map((item, i) => {
return (

@ -1,4 +1,5 @@
import React, {useState, useEffect, useReducer} from 'react' // eslint-disable-line
import {useIntl} from 'react-intl'
import {TreeView, TreeViewItem} from '@remix-ui/tree-view' // eslint-disable-line
import {DropdownPanelProps, ExtractData, ExtractFunc} from '../../types' // eslint-disable-line
import {CopyToClipboard} from '@remix-ui/clipboard' // eslint-disable-line
@ -6,6 +7,7 @@ import {initialState, reducer} from '../../reducers/calldata'
import './styles/dropdown-panel.css'
export const DropdownPanel = (props: DropdownPanelProps) => {
const intl = useIntl()
const [calldataObj, dispatch] = useReducer(reducer, initialState)
const {
dropdownName,
@ -84,7 +86,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
header: '',
toggleDropdown: true,
message: {
innerText: 'No data available.',
innerText: intl.formatMessage({id: 'debugger.noDataAvailable'}),
display: 'block'
},
dropdownContent: {
@ -189,7 +191,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
// replace 0xNaN with 0x0
copiableContent: JSON.stringify(calldata, null, '\t').replace(/0xNaN/g, '0x0'),
message: {
innerText: isEmpty ? 'No data available' : '',
innerText: isEmpty ? intl.formatMessage({id: 'debugger.noDataAvailable'}) : '',
display: isEmpty ? 'block' : 'none'
},
updating: false,
@ -221,7 +223,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
id={'treeViewLoadMore'}
data-id={'treeViewLoadMore'}
className="cursor_pointer"
label="Load more"
label={intl.formatMessage({id: 'debugger.loadMore'})}
onClick={() => {
triggerEvent(loadMoreEvent, [data.cursor])
}}
@ -255,7 +257,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
<span className="nameDetail" onClick={handleToggle}>
{header}
</span>
<CopyToClipboard content={state.copiableContent} data-id={`dropdownPanelCopyToClipboard${uniquePanelName}`} />
<CopyToClipboard tip={intl.formatMessage({id: 'debugger.copy'})} content={state.copiableContent} data-id={`dropdownPanelCopyToClipboard${uniquePanelName}`} />
</div>
<div className="dropdownpanel" style={{display: state.toggleDropdown ? 'block' : 'none'}}>
<i className="refresh fas fa-sync" style={{display: state.updating ? 'inline-block' : 'none'}} aria-hidden="true"></i>

@ -293,6 +293,14 @@ export function getAbiCompletionItems(range: monacoTypes.IRange, monaco): monaco
label: 'encodeWithSignature',
range
},
{
label: 'decode',
kind: monaco.languages.CompletionItemKind.Method,
insertText: 'decode(${1:arg}, ${2:arg});',
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
detail: 'decode(bytes encodedData, (...)) returns (...): ABI-decodes the given arguments from the given encodedData',
range
}
];
}

@ -539,6 +539,14 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
props.editorAPI.getPositionAt = (offset: number) => {
if (!monacoRef.current) return
const model = editorModelsState[currentFileRef.current]?.model
if (model) {
return model.getPositionAt(offset)
}
}
props.editorAPI.getHoverPosition = (position: monacoTypes.Position) => {
if (!monacoRef.current) return
const model = editorModelsState[currentFileRef.current]?.model

@ -1,6 +1,7 @@
// The forwardRef is important!!
import React, {Ref} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {CustomTooltip} from '@remix-ui/helper'
// Dropdown needs access to the DOM node in order to position the Menu
@ -66,7 +67,12 @@ export const CustomIconsToggle = React.forwardRef(
data-id="workspaceMenuDropdown"
>
{icon && (
<CustomTooltip placement={'top'} tooltipClasses="text-nowrap text-left" tooltipId="remixHamburgerTooltip" tooltipText="Workspace actions">
<CustomTooltip
placement={'top'}
tooltipClasses="text-nowrap text-left"
tooltipId="remixHamburgerTooltip"
tooltipText={<FormattedMessage id="filePanel.workspaceActions" />}
>
<i style={{fontSize: 'large'}} className={`${icon}`} data-id="workspaceDropdownMenuIcon"></i>
</CustomTooltip>
)}
@ -118,29 +124,32 @@ export const ProxyAddressToggle = React.forwardRef(
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
},
ref: Ref<HTMLDivElement>
) => (
<div
ref={ref}
onClick={(e) => {
e.preventDefault()
onClick(e)
}}
className={'d-flex ' + className.replace('dropdown-toggle', '')}
data-id="toggleProxyAddressDropdown"
>
<input
onChange={(e) => {
) => {
const intl = useIntl()
return (
<div
ref={ref}
onClick={(e) => {
e.preventDefault()
onChange(e)
onClick(e)
}}
className="udapp_input form-control"
value={address}
placeholder="Enter Proxy Address"
style={{width: '100%'}}
data-id="ERC1967AddressInput"
/>
</div>
)
className={'d-flex ' + className.replace('dropdown-toggle', '')}
data-id="toggleProxyAddressDropdown"
>
<input
onChange={(e) => {
e.preventDefault()
onChange(e)
}}
className="udapp_input form-control"
value={address}
placeholder={intl.formatMessage({id: 'udapp.enterProxyAddress'})}
style={{width: '100%'}}
data-id="ERC1967AddressInput"
/>
</div>
)
}
)
export const ProxyDropdownMenu = React.forwardRef(

@ -203,11 +203,11 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
placement={'top'}
tooltipId="overlay-tooltip"
tooltipClasses="text-nowrap"
tooltipText={'Connect to Localhost'}
tooltipText={<FormattedMessage id="home.connectToLocalhost" />}
tooltipTextClasses="border bg-light text-dark p-1 pr-3"
>
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => connectToLocalhost()}>
<FormattedMessage id="home.connectToLocalhost" />
<FormattedMessage id="home.accessFileSystem" />
</button>
</CustomTooltip>
</div>

@ -56,7 +56,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
placement={'top'}
tooltipId="overlay-tooltip"
tooltipClasses="text-nowrap"
tooltipText={'See all tutorials'}
tooltipText={<FormattedMessage id="home.seeAllTutorials" />}
tooltipTextClasses="border bg-light text-dark p-1 pr-3"
>
<button

@ -129,7 +129,7 @@ function HomeTabTitle() {
placement={'top'}
tooltipId="overlay-tooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="home.remixGitterChannel" />}
tooltipText={<FormattedMessage id="home.joinUsOnDiscord" />}
tooltipTextClasses="border bg-light text-dark p-1 pr-3"
>
<button

@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {useContext} from 'react'
import {FormattedMessage} from 'react-intl'
import {ThemeContext} from '../themeContext'
import {CustomTooltip} from '@remix-ui/helper'
interface PluginButtonProps {
@ -30,7 +31,7 @@ function PluginButton({imgPath, envID, envText, callback, l2, description, remix
</button>
{l2 && <label className="bg-light mx-1 px-1 mb-0 mx-2 position-absolute remixui_home_l2Label">L2</label>}
{remixMaintained && (
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-by-remix" tooltipText={'Maintained by Remix'}>
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-by-remix" tooltipText={<FormattedMessage id="home.maintainedByRemix" />}>
<i className="bg-light text-success mx-1 px-1 mb-0 mx-2 position-absolute remixui_home_maintainedLabel fas fa-check"></i>
</CustomTooltip>
)}

@ -36,13 +36,13 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
<div className="d-flex flex-row">
<div className="d-flex flex-row">
{plugin?.profile?.maintainedBy?.toLowerCase() === 'remix' && (
<CustomTooltip placement="right-end" tooltipId="maintainedByTooltip" tooltipClasses="text-nowrap" tooltipText="Maintained by Remix">
<CustomTooltip placement="right-end" tooltipId="maintainedByTooltip" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="panel.maintainedByRemix" />}>
<i aria-hidden="true" className="text-success mt-1 px-1 fas fa-check"></i>
</CustomTooltip>
)}
</div>
<div className="swapitHeaderInfoSection d-flex justify-content-between" data-id="swapitHeaderInfoSectionId" onClick={toggleClass}>
<CustomTooltip placement="right-end" tooltipText="Plugin info" tooltipId="pluginInfoTooltip" tooltipClasses="text-nowrap">
<CustomTooltip placement="right-end" tooltipText={<FormattedMessage id="panel.pluginInfo" />} tooltipId="pluginInfoTooltip" tooltipClasses="text-nowrap">
{tooltipChild}
</CustomTooltip>
</div>
@ -71,7 +71,7 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
<FormattedMessage id="panel.documentation" />:
</label>
<span>
<CustomTooltip placement="right-end" tooltipId="linkToDocsTooltip" tooltipClasses=" text-nowrap " tooltipText="Link to documentation">
<CustomTooltip placement="right-end" tooltipId="linkToDocsTooltip" tooltipClasses=" text-nowrap " tooltipText={<FormattedMessage id="panel.linkToDoc" />}>
<a href={plugin?.profile?.documentation} className="titleInfo p-0 mb-2" target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-book"></i>
</a>
@ -90,7 +90,7 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
{plugin?.profile?.repo && (
<span className="d-flex flex-row align-items-center">
<a href={plugin?.profile?.repo} target="_blank" rel="noreferrer">
Make an issue
<FormattedMessage id="panel.makeAnissue" />
</a>
</span>
)}

@ -1,5 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-use-before-define
import React from 'react'
import {FormattedMessage} from 'react-intl'
import '../remix-ui-plugin-manager.css'
import {CustomTooltip} from '@remix-ui/helper'
interface PluginCardProps {
@ -17,23 +18,43 @@ function ActivePluginCard({profile, buttonText, deactivatePlugin}: PluginCardPro
<div>
{profile.displayName || profile.name}
{profile?.maintainedBy?.toLowerCase() == 'remix' && (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveTitleByRemix" tooltipClasses="text-nowrap" tooltipText="Maintained by Remix">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveTitleByRemix"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.maintainedByRemix" />}
>
<i aria-hidden="true" className="px-1 text-success fas fa-check"></i>
</CustomTooltip>
)}
{profile.documentation && (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveLinkToDoc" tooltipClasses="text-nowrap" tooltipText="Link to documentation">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveLinkToDoc"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.linkToDoc" />}
>
<a href={profile.documentation} className="px-1" target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-book" />
</a>
</CustomTooltip>
)}
{profile.version && profile.version.match(/\b(\w*alpha\w*)\b/g) ? (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveVersionAlpha" tooltipClasses="text-nowrap" tooltipText="Version Alpha">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveVersionAlpha"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.versionAlpha" />}
>
<small className="remixui_versionWarning plugin-version">alpha</small>
</CustomTooltip>
) : profile.version && profile.version.match(/\b(\w*beta\w*)\b/g) ? (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveVersionBeta" tooltipClasses="text-nowrap" tooltipText="Version Beta">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveVersionBeta"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.versionBeta" />}
>
<small className="remixui_versionWarning plugin-version">beta</small>
</CustomTooltip>
) : null}
@ -43,7 +64,7 @@ function ActivePluginCard({profile, buttonText, deactivatePlugin}: PluginCardPro
placement="right"
tooltipId={`pluginManagerInactiveActiveBtn${profile.name}`}
tooltipClasses="text-nowrap"
tooltipText={`Deactivate ${profile.displayName || profile.name}`}
tooltipText={<FormattedMessage id="pluginManager.deactivatePlugin" values={{pluginName: profile.displayName || profile.name}} />}
>
<button
onClick={() => {

@ -1,6 +1,7 @@
import {Profile} from '@remixproject/plugin-utils'
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-use-before-define
import React from 'react'
import {FormattedMessage} from 'react-intl'
import '../remix-ui-plugin-manager.css'
import {CustomTooltip} from '@remix-ui/helper'
interface PluginCardProps {
@ -20,23 +21,43 @@ function InactivePluginCard({profile, buttonText, activatePlugin}: PluginCardPro
<div>
{profile.displayName || profile.name}
{profile?.maintainedBy?.toLowerCase() == 'remix' && (
<CustomTooltip placement="right" tooltipId="pluginManagerInactiveTitleByRemix" tooltipClasses="text-nowrap" tooltipText="Maintained by Remix">
<CustomTooltip
placement="right"
tooltipId="pluginManagerInactiveTitleByRemix"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.maintainedByRemix" />}
>
<i aria-hidden="true" className="px-1 text-success fas fa-check"></i>
</CustomTooltip>
)}
{profile.documentation && (
<CustomTooltip placement="right" tooltipId="pluginManagerInactiveTitleLinkToDoc" tooltipClasses="text-nowrap" tooltipText="Link to documentation">
<CustomTooltip
placement="right"
tooltipId="pluginManagerInactiveTitleLinkToDoc"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.linkToDoc" />}
>
<a href={profile.documentation} className="px-1" target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-book" />
</a>
</CustomTooltip>
)}
{profile.version && profile.version.match(/\b(\w*alpha\w*)\b/g) ? (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveVersionAlpha" tooltipClasses="text-nowrap" tooltipText="Version Alpha">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveVersionAlpha"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.versionAlpha" />}
>
<small className="remixui_versionWarning plugin-version">alpha</small>
</CustomTooltip>
) : profile.version && profile.version.match(/\b(\w*beta\w*)\b/g) ? (
<CustomTooltip placement="right" tooltipId="pluginManagerActiveVersionBeta" tooltipClasses="text-nowrap" tooltipText="Version Beta">
<CustomTooltip
placement="right"
tooltipId="pluginManagerActiveVersionBeta"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.versionBeta" />}
>
<small className="remixui_versionWarning plugin-version">beta</small>
</CustomTooltip>
) : null}
@ -46,7 +67,7 @@ function InactivePluginCard({profile, buttonText, activatePlugin}: PluginCardPro
placement="right"
tooltipId={`pluginManagerInactiveActiveBtn${profile.name}`}
tooltipClasses="text-nowrap"
tooltipText={`Activate ${profile.displayName || profile.name}`}
tooltipText={<FormattedMessage id="pluginManager.activatePlugin" values={{pluginName: profile.displayName || profile.name}} />}
>
<button
onClick={() => {

@ -121,9 +121,9 @@ function LocalPluginForm({closeModal, visible, pluginManager}: LocalPluginFormPr
id="pluginManagerLocalPluginModalDialog"
hide={visible}
title={intl.formatMessage({id: 'pluginManager.localForm.title'})}
okLabel="OK"
okLabel={intl.formatMessage({id: 'pluginManager.localForm.ok'})}
okFn={handleModalOkClick}
cancelLabel="Cancel"
cancelLabel={intl.formatMessage({id: 'pluginManager.localForm.cancel'})}
cancelFn={closeModal}
>
<form id="local-plugin-form">
@ -172,7 +172,7 @@ function LocalPluginForm({closeModal, visible, pluginManager}: LocalPluginFormPr
value={methods || ''}
id="plugin-methods"
data-id="localPluginMethods"
placeholder="Methods"
placeholder={intl.formatMessage({id: 'pluginManager.localForm.methods'})}
/>
</div>
<div className="form-group">
@ -187,7 +187,7 @@ function LocalPluginForm({closeModal, visible, pluginManager}: LocalPluginFormPr
value={canactivate || ''}
id="plugin-canactivate"
data-id="localPluginCanActivate"
placeholder="Plugin names"
placeholder={intl.formatMessage({id: 'pluginManager.localForm.pluginNames'})}
/>
</div>

@ -144,7 +144,13 @@ function PermisssionsSettings() {
</form>
</ModalDialog>
<footer className="bg-light remixui_permissions remix-bg-opacity">
<CustomTooltip placement={'top'} tooltipId="pmPermissions" tooltipClasses="text-nowrap" tooltipText={'Manage plugins Permissions'} key={'keypmPermissions'}>
<CustomTooltip
placement={'top'}
tooltipId="pmPermissions"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="pluginManager.managePluginsPermissions" />}
key={'keypmPermissions'}
>
<button onClick={openModal} className="btn btn-primary settings-button" data-id="pluginManagerPermissionsButton">
<FormattedMessage id="pluginManager.Permissions" />
</button>

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {Fragment, ReactNode, useEffect, useState} from 'react' // eslint-disable-line no-use-before-define
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import {PluginManagerComponent, PluginManagerSettings} from '../../types'
import PermisssionsSettings from './permissionsSettings'
import {Profile} from '@remixproject/plugin-utils'
@ -22,6 +22,7 @@ export interface pluginActivated {
}
function RootView({pluginComponent, children}: RootViewProps) {
const intl = useIntl()
const [visible, setVisible] = useState<boolean>(true)
const [filterPlugins, setFilterPlugin] = useState<string>('')
@ -44,7 +45,7 @@ function RootView({pluginComponent, children}: RootViewProps) {
}}
value={filterPlugins}
className="mb-2 form-control"
placeholder="Search"
placeholder={intl.formatMessage({id: 'pluginManager.search'})}
data-id="pluginManagerComponentSearchInput"
/>
<button onClick={openModal} className="py-1 btn bg-transparent text-dark border-0 mt-2 text-underline" data-id="pluginManagerComponentPluginSearchButton">

@ -40,8 +40,6 @@
.remixui_sol.success a,
.remixui_sol.error a,
.remixui_sol.warning a {
position: absolute;
bottom: 0;
right: 0;
padding: 0.25rem;
}

@ -2,6 +2,8 @@ import React, {useEffect, useState} from 'react' //eslint-disable-line
import {CopyToClipboard} from '@remix-ui/clipboard'
import {helper} from '@remix-project/remix-solidity'
import './renderer.css'
const _paq = (window._paq = window._paq || [])
interface RendererProps {
message: any
opt?: any
@ -76,6 +78,7 @@ export const Renderer = ({message, opt = {}, plugin}: RendererProps) => {
explain why the error occurred and how to fix it.
`
await plugin.call('openaigpt', 'message', message)
_paq.push(['trackEvent', 'GPTSupport', 'askGPT'])
} catch (err) {
console.error('unable to askGtp')
console.error(err)
@ -96,8 +99,12 @@ export const Renderer = ({message, opt = {}, plugin}: RendererProps) => {
<div className="close" data-id="renderer" onClick={handleClose}>
<i className="fas fa-times"></i>
</div>
<CopyToClipboard content={messageText} className={` p-0 m-0 far fa-copy ${classList}`} direction={'top'} />
<span onClick={() => { askGtp() }}>ASK GPT</span>
<div className="d-flex pt-1 flex-row-reverse">
<span className="ml-3 pt-1 py-1" >
<CopyToClipboard content={messageText} className={` p-0 m-0 far fa-copy ${classList}`} direction={'top'} />
</span>
<span className="border border-success text-success btn-sm" onClick={() => { askGtp() }}>ASK GPT</span>
</div>
</div>
)}
</>

@ -26,36 +26,35 @@ export function AccountUI(props: AccountProps) {
case 'injected':
setPlusOpt({
classList: 'udapp_disableMouseEvents',
title:
"Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type)."
title: intl.formatMessage({id: 'udapp.injectedTitle'})
})
break
case 'vm-merge':
setPlusOpt({
classList: '',
title: 'Create a new account'
title: intl.formatMessage({id: 'udapp.createNewAccount'})
})
break
case 'vm-london':
setPlusOpt({
classList: '',
title: 'Create a new account'
title: intl.formatMessage({id: 'udapp.createNewAccount'})
})
break
case 'vm-berlin':
setPlusOpt({
classList: '',
title: 'Create a new account'
title: intl.formatMessage({id: 'udapp.createNewAccount'})
})
break
case 'vm-shanghai':
setPlusOpt({
classList: '',
title: 'Create a new account'
title: intl.formatMessage({id: 'udapp.createNewAccount'})
})
break
@ -63,12 +62,12 @@ export function AccountUI(props: AccountProps) {
if (!props.personalMode) {
setPlusOpt({
classList: 'disableMouseEvents',
title: 'Creating an account is possible only in Personal mode. Please go to Settings to enable it.'
title: intl.formatMessage({id: 'udapp.web3Title'})
})
} else {
setPlusOpt({
classList: '',
title: 'Create a new account'
title: intl.formatMessage({id: 'udapp.createNewAccount'})
})
}
break
@ -76,7 +75,7 @@ export function AccountUI(props: AccountProps) {
default:
setPlusOpt({
classList: 'disableMouseEvents',
title: `Unfortunately it's not possible to create an account using an external wallet (${props.selectExEnv}).`
title: intl.formatMessage({id: 'udapp.defaultTitle'}, {selectExEnv: props.selectExEnv})
})
}
// this._deps.config.get('settings/personal-mode')
@ -88,28 +87,28 @@ export function AccountUI(props: AccountProps) {
const signMessage = () => {
if (!accounts[0]) {
return props.tooltip('Account list is empty, please make sure the current provider is properly connected to remix')
return props.tooltip(intl.formatMessage({id: 'udapp.tooltipText1'}))
}
if (props.selectExEnv === 'web3') {
return props.modal(
'Passphrase to sign a message',
<PassphrasePrompt message="Enter your passphrase for this account to sign the message" setPassphrase={props.setPassphrase} />,
'OK',
intl.formatMessage({id: 'udapp.modalTitle1'}),
<PassphrasePrompt message={intl.formatMessage({id: 'udapp.modalMessage1'})} setPassphrase={props.setPassphrase} />,
intl.formatMessage({id: 'udapp.ok'}),
() => {
props.modal(
intl.formatMessage({id: 'udapp.signAMessage'}),
signMessagePrompt(),
'OK',
intl.formatMessage({id: 'udapp.ok'}),
() => {
props.signMessageWithAddress(selectedAccount, messageRef.current, signedMessagePrompt, props.passphrase)
props.setPassphrase('')
},
'Cancel',
intl.formatMessage({id: 'udapp.cancel'}),
null
)
},
'Cancel',
intl.formatMessage({id: 'udapp.cancel'}),
() => {
props.setPassphrase('')
}
@ -119,11 +118,11 @@ export function AccountUI(props: AccountProps) {
props.modal(
intl.formatMessage({id: 'udapp.signAMessage'}),
signMessagePrompt(),
'OK',
intl.formatMessage({id: 'udapp.ok'}),
() => {
props.signMessageWithAddress(selectedAccount, messageRef.current, signedMessagePrompt)
},
'Cancel',
intl.formatMessage({id: 'udapp.cancel'}),
null
)
}
@ -143,7 +142,7 @@ export function AccountUI(props: AccountProps) {
const passphraseCreationPrompt = () => {
return (
<div className="d-flex flex-column">
Please provide a Passphrase for the account creation
<FormattedMessage id="udapp.text1" />
<input id="prompt1" type="password" name="prompt_text" className="w-100 py-2" onInput={handlePassphrase} />
<input id="prompt2" type="password" name="prompt_text" className="w-100" onInput={handleMatchPassphrase} />
</div>
@ -216,9 +215,9 @@ export function AccountUI(props: AccountProps) {
))}
</select>
<div style={{marginLeft: -5}}>
<CopyToClipboard tip="Copy account to clipboard" content={selectedAccount} direction="top" />
<CopyToClipboard tip={intl.formatMessage({id: 'udapp.copyAccount'})} content={selectedAccount} direction="top" />
</div>
<CustomTooltip placement={'top-start'} tooltipClasses="text-nowrap" tooltipId="remixSignMsgTooltip" tooltipText={'Sign a message using this account'}>
<CustomTooltip placement={'top-start'} tooltipClasses="text-nowrap" tooltipId="remixSignMsgTooltip" tooltipText={<FormattedMessage id="udapp.signMsgUsingAccount" />}>
<i id="remixRunSignMsg" data-id="settingsRemixRunSignMsg" className="mx-1 fas fa-edit udapp_icon" aria-hidden="true" onClick={signMessage}></i>
</CustomTooltip>
</div>

@ -50,7 +50,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
enableAtAddress(false)
setAbiLabel({
display: 'none',
content: 'ABI file selected',
content: intl.formatMessage({ id: 'udapp.abiFileSelected' }),
})
}, [])
@ -427,7 +427,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
}}
>
<option value="" disabled hidden>
No compiled contracts
{intl.formatMessage({ id: 'udapp.noCompiledContracts' })}
</option>
{(contractList[currentFile] || []).map((contract, index) => {
return (
@ -453,7 +453,9 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
</span>
}
>
<span className="udapp_evmVersion badge alert-warning">evm version: {evmVersion}</span>
<span className="udapp_evmVersion badge alert-warning">
<FormattedMessage id="udapp.evmVersion" />: {evmVersion}
</span>
</CustomTooltip>
)}
<div>
@ -538,7 +540,11 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
/>
</CustomTooltip>
</div>
{!addressIsValid && <span className="text-danger text-right">The address is not valid</span>}
{!addressIsValid && (
<span className="text-danger text-right">
<FormattedMessage id="udapp.addressNotValid" />
</span>
)}
</div>
</div>
</div>

@ -87,7 +87,7 @@ export function ContractGUI(props: ContractGUIProps) {
const multiString = getMultiValsString(multiFields.current)
// copy-to-clipboard icon is only visible for method requiring input params
if (!multiString) {
return 'cannot encode empty arguments'
return intl.formatMessage({id: 'udapp.getEncodedCallError'})
}
const multiJSON = JSON.parse('[' + multiString + ']')
@ -106,7 +106,7 @@ export function ContractGUI(props: ContractGUIProps) {
const multiString = getMultiValsString(multiFields.current)
// copy-to-clipboard icon is only visible for method requiring input params
if (!multiString) {
return 'cannot encode empty arguments'
return intl.formatMessage({id: 'udapp.getEncodedCallError'})
}
const multiJSON = JSON.parse('[' + multiString + ']')
return txHelper.encodeParams(props.funcABI, multiJSON)
@ -178,7 +178,7 @@ export function ContractGUI(props: ContractGUIProps) {
props.clickCallBack(props.initializerOptions.inputs.inputs, proxyInitializeString, ['Deploy with Proxy'])
} else if (deployState.upgrade) {
if (proxyAddress === '') {
setProxyAddressError('proxy address cannot be empty')
setProxyAddressError(intl.formatMessage({id: 'udapp.proxyAddressError1'}))
} else {
const isValidProxyAddress = await props.isValidProxyAddress(proxyAddress)
if (isValidProxyAddress) {
@ -216,7 +216,7 @@ export function ContractGUI(props: ContractGUIProps) {
}
}
} else {
setProxyAddressError('not a valid contract address')
setProxyAddressError(intl.formatMessage({id: 'udapp.proxyAddressError2'}))
}
}
} else {
@ -288,7 +288,13 @@ export function ContractGUI(props: ContractGUIProps) {
placement={'right'}
tooltipClasses="text-wrap"
tooltipId="remixUdappInstanceButtonTooltip"
tooltipText={toggleUpgradeImp && !proxyAddress ? 'Proxy address cannot be empty' : props.inputs !== '' && basicInput === '' ? 'Input required' : buttonOptions.title}
tooltipText={
toggleUpgradeImp && !proxyAddress
? intl.formatMessage({id: 'udapp.tooltipText11'})
: props.inputs !== '' && basicInput === ''
? intl.formatMessage({id: 'udapp.tooltipText12'})
: buttonOptions.title
}
>
<div className="d-flex wrapperElement" onClick={handleActionClick} data-id={buttonOptions.dataId} data-title={buttonOptions.title}>
<button
@ -462,7 +468,7 @@ export function ContractGUI(props: ContractGUIProps) {
placement={'right'}
tooltipClasses="text-nowrap"
tooltipId={`proxyAddressTooltip${index}`}
tooltipText={'Deployed ' + shortenDate(deployment.date)}
tooltipText={<FormattedMessage id="udapp.tooltipText13" values={{date: shortenDate(deployment.date)}} />}
key={index}
>
<Dropdown.Item

@ -1,10 +1,11 @@
import React, {useState} from 'react'
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import {DeployButtonProps} from '../types'
import {ButtonGroup, Dropdown} from 'react-bootstrap'
import {CustomTooltip} from '@remix-ui/helper'
export function DeployButton(props: DeployButtonProps) {
const intl = useIntl()
const [showOptions, setShowOptions] = useState<boolean>(false)
const toggleOptions = () => {
@ -21,7 +22,7 @@ export function DeployButton(props: DeployButtonProps) {
className={`udapp_instanceButton ${props.buttonOptions.widthClass} btn btn-sm ${props.buttonOptions.classList}`}
data-id={props.buttonOptions.dataId}
>
{props.deployOptions[props.selectedIndex] ? props.deployOptions[props.selectedIndex].title : 'Deploy'}
{props.deployOptions[props.selectedIndex] ? props.deployOptions[props.selectedIndex].title : intl.formatMessage({id: 'udapp.deploy'})}
</button>
<Dropdown.Toggle
split

@ -24,12 +24,7 @@ export function EnvironmentUI(props: EnvironmentProps) {
<label id="selectExEnv" className="udapp_settingsLabel">
<FormattedMessage id="udapp.environment" />
<CustomTooltip
placement={'right'}
tooltipClasses="text-nowrap"
tooltipId="info-recorder"
tooltipText="Open chainlist.org and get the connection specs of the chain you want to interact with."
>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText2" />}>
<a href="https://chainlist.org/" target="_blank">
<i style={{fontSize: 'medium'}} className={'ml-2 fad fa-plug'} aria-hidden="true"></i>
</a>
@ -41,12 +36,7 @@ export function EnvironmentUI(props: EnvironmentProps) {
{isL2(currentProvider) && 'L2 - '}
{currentProvider && currentProvider.content}
{currentProvider && bridges[currentProvider.value] && (
<CustomTooltip
placement={'right'}
tooltipClasses="text-nowrap"
tooltipId="info-recorder"
tooltipText="Click to open a bridge for converting L1 mainnet ETH to the selected network currency."
>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="udapp.tooltipText3" />}>
<i
style={{fontSize: 'medium'}}
className={'ml-2 fa fa-rocket-launch'}

@ -14,7 +14,7 @@ export function GasPriceUI(props: GasPriceProps) {
<label className="udapp_settingsLabel">
<FormattedMessage id="udapp.gasLimit" />
</label>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="remixGasPriceTooltip" tooltipText={'The default gas limit is 3M. Adjust as needed.'}>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="remixGasPriceTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText4" />}>
<input type="number" className="form-control udapp_gasNval udapp_col2" id="gasLimit" value={props.gasLimit} onChange={handleGasLimit} />
</CustomTooltip>
</div>

@ -17,12 +17,7 @@ export function InstanceContainerUI(props: InstanceContainerProps) {
return (
<div className="udapp_instanceContainer mt-3 border-0 list-group-item">
<div className="d-flex justify-content-between align-items-center pl-2 mb-2">
<CustomTooltip
placement="top-start"
tooltipClasses="text-nowrap"
tooltipId="deployAndRunClearInstancesTooltip"
tooltipText={'Autogenerated generic user interfaces for interaction with deployed contracts'}
>
<CustomTooltip placement="top-start" tooltipClasses="text-nowrap" tooltipId="deployAndRunClearInstancesTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText6" />}>
<label className="udapp_deployedContracts">
<FormattedMessage id="udapp.deployedContracts" />
</label>

@ -1,10 +1,12 @@
// eslint-disable-next-line no-use-before-define
import React, {useEffect, useState} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {CopyToClipboard} from '@remix-ui/clipboard'
import {fromWei, toBigInt, toWei} from 'web3-utils'
import {MainnetProps} from '../types'
export function MainnetPrompt(props: MainnetProps) {
const intl = useIntl()
const [baseFee, setBaseFee] = useState<string>('')
const [transactionFee, setTransactionFee] = useState<string>('')
@ -26,7 +28,7 @@ export function MainnetPrompt(props: MainnetProps) {
const maxFee = value
// @ts-ignore
if (toBN(props.network.lastBlock.baseFeePerGas).gt(toBN(toWei(maxFee, 'Gwei')))) {
setTransactionFee('Transaction is invalid. Max fee should not be less than Base fee')
setTransactionFee(intl.formatMessage({id: 'udapp.transactionFeeText'}))
props.updateGasPriceStatus(false)
props.updateConfirmSettings(true)
return
@ -65,9 +67,9 @@ export function MainnetPrompt(props: MainnetProps) {
return (
<div>
<div className="text-dark">
You are about to create a transaction on {props.network.name} Network. Confirm the details to send the info to your provider.
<FormattedMessage id="udapp.mainnetText1" values={{name: props.network.name}} />
<br />
The provider for many users is MetaMask. The provider will ask you to sign the transaction before it is sent to {props.network.name} Network.
<FormattedMessage id="udapp.mainnetText2" values={{name: props.network.name}} />
</div>
<div className="mt-3">
<div>
@ -76,32 +78,40 @@ export function MainnetPrompt(props: MainnetProps) {
</div>
<div>
<span className="text-dark mr-2">To:</span>
<span>{props.tx.to ? props.tx.to : '(Contract Creation)'}</span>
<span>{props.tx.to ? props.tx.to : `(${intl.formatMessage({id: 'udapp.contractCreation'})})`}</span>
</div>
<div className="d-flex align-items-center">
<span className="text-dark mr-2">Data:</span>
<pre className="udapp_wrapword mb-0">
{props.tx.data && props.tx.data.length > 50 ? props.tx.data.substring(0, 49) + '...' : props.tx.data}
<CopyToClipboard content={props.tx.data} />
<CopyToClipboard tip={intl.formatMessage({id: 'udapp.copy'})} content={props.tx.data} />
</pre>
</div>
<div className="mb-3">
<span className="text-dark mr-2">Amount:</span>
<span className="text-dark mr-2">
<FormattedMessage id="udapp.amount" />:
</span>
<span>{props.amount} Ether</span>
</div>
<div>
<span className="text-dark mr-2">Gas estimation:</span>
<span className="text-dark mr-2">
<FormattedMessage id="udapp.gasEstimation" />:
</span>
<span>{props.gasEstimation}</span>
</div>
<div>
<span className="text-dark mr-2">Gas limit:</span>
<span className="text-dark mr-2">
<FormattedMessage id="udapp.gasLimit" />:
</span>
<span>{props.tx.gas}</span>
</div>
{props.network.lastBlock.baseFeePerGas ? (
<div>
<div className="align-items-center my-1" title="Represents the part of the tx fee that goes to the miner.">
<div className="align-items-center my-1" title={intl.formatMessage({id: 'udapp.title1'})}>
<div className="d-flex">
<span className="text-dark mr-2 text-nowrap">Max Priority fee:</span>
<span className="text-dark mr-2 text-nowrap">
<FormattedMessage id="udapp.maxPriorityFee" />:
</span>
<input
className="form-control mr-1 text-right"
style={{height: '1.2rem', width: '6rem'}}
@ -112,9 +122,11 @@ export function MainnetPrompt(props: MainnetProps) {
<span title="visit https://ethgasstation.info for current gas price info.">Gwei</span>
</div>
</div>
<div className="align-items-center my-1" title="Represents the maximum amount of fee that you will pay for this transaction. The minimun needs to be set to base fee.">
<div className="align-items-center my-1" title={intl.formatMessage({id: 'udapp.title2'})}>
<div className="d-flex">
<span className="text-dark mr-2 text-nowrap">Max fee (Not less than base fee {fromWei(toBigInt(props.network.lastBlock.baseFeePerGas), 'Gwei')} Gwei):</span>
<span className="text-dark mr-2 text-nowrap">
<FormattedMessage id="udapp.maxFee" values={{baseFeePerGas: fromWei(toBigInt(props.network.lastBlock.baseFeePerGas), 'Gwei'), 'Gwei')}} />:
</span>
<input
className="form-control mr-1 text-right"
style={{height: '1.2rem', width: '6rem'}}
@ -129,19 +141,30 @@ export function MainnetPrompt(props: MainnetProps) {
</div>
) : (
<div className="d-flex align-items-center my-1">
<span className="text-dark mr-2 text-nowrap">Gas price:</span>
<span className="text-dark mr-2 text-nowrap">
<FormattedMessage id="udapp.gasPrice" />:
</span>
<input className="form-control mr-1 text-right" style={{width: '40px', height: '28px'}} id="gasprice" onInput={(e: any) => onGasPriceChange(e.target.value)} />
<span>
Gwei (visit{' '}
<a target="_blank" href="https://ethgasstation.info" rel="noreferrer">
ethgasstation.info
</a>{' '}
for current gas price info.)
Gwei (
<FormattedMessage
id="udapp.gweiText"
values={{
a: (
<a target="_blank" href="https://ethgasstation.info" rel="noreferrer">
ethgasstation.info
</a>
)
}}
/>
)
</span>
</div>
)}
<div className="mb-3">
<span className="text-dark mr-2">Max transaction fee:</span>
<span className="text-dark mr-2">
<FormattedMessage id="udapp.maxTransactionFee" />:
</span>
<span className="text-warning" id="txfee">
{transactionFee}
</span>
@ -150,7 +173,7 @@ export function MainnetPrompt(props: MainnetProps) {
<div className="d-flex py-1 align-items-center custom-control custom-checkbox remixui_checkbox">
<input className="form-check-input custom-control-input" id="confirmsetting" type="checkbox" />
<label className="m-0 form-check-label custom-control-label" htmlFor="confirmsetting">
Do not show this warning again.
<FormattedMessage id="udapp.mainnetText3" />
</label>
</div>
</div>

@ -1,4 +1,5 @@
import {CustomTooltip} from '@remix-ui/helper'
import {FormattedMessage} from 'react-intl'
import React, {useRef} from 'react'
import {MultiDeployInputProps} from '../types'
import {DeployButton} from './deployButton'
@ -10,7 +11,9 @@ export function MultiDeployInput(props: MultiDeployInputProps) {
<div className="udapp_contractActionsContainerMulti" style={{display: 'flex'}}>
<div className="udapp_contractActionsContainerMultiInner text-dark">
<div className="pt-2 udapp_multiHeader">
<div className="udapp_multiTitle run-instance-multi-title">Deploy</div>
<div className="udapp_multiTitle run-instance-multi-title">
<FormattedMessage id="udapp.deploy" />
</div>
</div>
<div>
{props.inputs.map((inp, index) => {

@ -1,5 +1,6 @@
// eslint-disable-next-line no-use-before-define
import React, {useEffect, useState} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {UdappProps} from '../types'
import {FuncABI} from '@remix-project/core-plugin'
import {CopyToClipboard} from '@remix-ui/clipboard'
@ -13,6 +14,7 @@ import {CustomTooltip, is0XPrefixed, isHexadecimal, isNumeric, shortenAddress} f
const txHelper = remixLib.execution.txHelper
export function UniversalDappUI(props: UdappProps) {
const intl = useIntl()
const [toggleExpander, setToggleExpander] = useState<boolean>(true)
const [contractABI, setContractABI] = useState<FuncABI[]>(null)
const [address, setAddress] = useState<string>('')
@ -68,30 +70,30 @@ export function UniversalDappUI(props: UdappProps) {
if (amount !== '0') {
// check for numeric and receive/fallback
if (!isNumeric(amount)) {
return setLlIError('Value to send should be a number')
return setLlIError(intl.formatMessage({id: 'udapp.llIError1'}))
} else if (!receive && !(fallback && fallback.stateMutability === 'payable')) {
return setLlIError("In order to receive Ether transfer the contract should have either 'receive' or payable 'fallback' function")
return setLlIError(intl.formatMessage({id: 'udapp.llIError2'}))
}
}
let calldata = calldataValue
if (calldata) {
if (calldata.length < 4 && is0XPrefixed(calldata)) {
return setLlIError('The calldata should be a valid hexadecimal value with size of at least one byte.')
return setLlIError(intl.formatMessage({id: 'udapp.llIError3'}))
} else {
if (is0XPrefixed(calldata)) {
calldata = calldata.substr(2, calldata.length)
}
if (!isHexadecimal(calldata)) {
return setLlIError('The calldata should be a valid hexadecimal value.')
return setLlIError(intl.formatMessage({id: 'udapp.llIError4'}))
}
}
if (!fallback) {
return setLlIError("'Fallback' function is not defined")
return setLlIError(intl.formatMessage({id: 'udapp.llIError5'}))
}
}
if (!receive && !fallback) return setLlIError("Both 'receive' and 'fallback' functions are not defined")
if (!receive && !fallback) return setLlIError(intl.formatMessage({id: 'udapp.llIError6'}))
// we have to put the right function ABI:
// if receive is defined and that there is no calldata => receive function is called
@ -99,7 +101,7 @@ export function UniversalDappUI(props: UdappProps) {
if (receive && !calldata) args.funcABI = receive
else if (fallback) args.funcABI = fallback
if (!args.funcABI) return setLlIError("Please define a 'Fallback' function to send calldata and a either 'Receive' or payable 'Fallback' to send ethers")
if (!args.funcABI) return setLlIError(intl.formatMessage({id: 'udapp.llIError7'}))
runTransaction(false, args.funcABI, null, calldataValue)
}
@ -224,17 +226,19 @@ export function UniversalDappUI(props: UdappProps) {
</span>
</div>
<div className="btn">
<CopyToClipboard content={address} direction={'top'} />
<CopyToClipboard tip={intl.formatMessage({id: 'udapp.copy'})} content={address} direction={'top'} />
</div>
</div>
<CustomTooltip placement="right" tooltipClasses="text-nowrap" tooltipId="udapp_udappCloseTooltip" tooltipText="Remove from the list">
<CustomTooltip placement="right" tooltipClasses="text-nowrap" tooltipId="udapp_udappCloseTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText7" />}>
<i className="udapp_closeIcon m-1 fas fa-times align-self-center" aria-hidden="true" data-id="universalDappUiUdappClose" onClick={remove}></i>
</CustomTooltip>
</div>
<div className="udapp_cActionsWrapper" data-id="universalDappUiContractActionWrapper">
<div className="udapp_contractActionsContainer">
<div className="d-flex" data-id="instanceContractBal">
<label>Balance: {instanceBalance} ETH</label>
<label>
<FormattedMessage id="udapp.balance" />: {instanceBalance} ETH
</label>
</div>
{contractABI &&
contractABI.map((funcABI, index) => {
@ -277,8 +281,10 @@ export function UniversalDappUI(props: UdappProps) {
</div>
<div className="d-flex flex-column">
<div className="d-flex flex-row justify-content-between mt-2">
<div className="py-2 border-top d-flex justify-content-start flex-grow-1">Low level interactions</div>
<CustomTooltip placement={'bottom-end'} tooltipClasses="text-wrap" tooltipId="receiveEthDocstoolTip" tooltipText={"Click for docs about using 'receive'/'fallback'"}>
<div className="py-2 border-top d-flex justify-content-start flex-grow-1">
<FormattedMessage id="udapp.lowLevelInteractions" />
</div>
<CustomTooltip placement={'bottom-end'} tooltipClasses="text-wrap" tooltipId="receiveEthDocstoolTip" tooltipText={<FormattedMessage id="udapp.tooltipText8" />}>
<a href="https://solidity.readthedocs.io/en/v0.6.2/contracts.html#receive-ether-function" target="_blank" rel="noreferrer">
<i aria-hidden="true" className="fas fa-info my-2 mr-1"></i>
</a>
@ -291,11 +297,11 @@ export function UniversalDappUI(props: UdappProps) {
placement="bottom"
tooltipClasses="text-nowrap"
tooltipId="deployAndRunLLTxCalldataInputTooltip"
tooltipText="The Calldata to send to fallback function of the contract."
tooltipText={<FormattedMessage id="udapp.tooltipText9" />}
>
<input id="deployAndRunLLTxCalldata" onChange={handleCalldataChange} className="udapp_calldataInput form-control" />
</CustomTooltip>
<CustomTooltip placement="right" tooltipClasses="text-nowrap" tooltipId="deployAndRunLLTxCalldataTooltip" tooltipText="Send data to contract.">
<CustomTooltip placement="right" tooltipClasses="text-nowrap" tooltipId="deployAndRunLLTxCalldataTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText10" />}>
<button
id="deployAndRunLLTxSendTransaction"
data-id="pluginManagerSettingsDeployAndRunLLTxSendTransaction"

@ -51,7 +51,7 @@ export function ValueUI(props: ValueProps) {
<FormattedMessage id="udapp.value" />
</label>
<div className="udapp_gasValueContainer">
<CustomTooltip placement={'top-start'} tooltipClasses="text-nowrap" tooltipId="remixValueTooltip" tooltipText="Enter an amount and choose its unit">
<CustomTooltip placement={'top-start'} tooltipClasses="text-nowrap" tooltipId="remixValueTooltip" tooltipText={<FormattedMessage id="udapp.tooltipText5" />}>
<input
ref={inputValue}
type="number"

@ -1,5 +1,6 @@
// eslint-disable-next-line no-use-before-define
import React, {Fragment, useEffect, useReducer, useState} from 'react'
import {FormattedMessage} from 'react-intl'
import {ModalDialog} from '@remix-ui/modal-dialog'
// eslint-disable-next-line no-unused-vars
import {Toaster} from '@remix-ui/toaster'
@ -205,7 +206,7 @@ export function RunTabUI(props: RunTabProps) {
const gasEstimationPrompt = (msg: string) => {
return (
<div>
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? <br />
<FormattedMessage id="udapp.gasEstimationPromptText" /> <br />
{msg}
</div>
)

@ -1,5 +1,6 @@
import {CustomTooltip} from '@remix-ui/helper'
import React, {useContext, useEffect, useState} from 'react'
import {FormattedMessage} from 'react-intl'
import {SearchContext} from '../context/context'
import {Find} from './Find'
import {OverWriteCheck} from './OverWriteCheck'
@ -14,7 +15,7 @@ export const FindContainer = (props) => {
}, [expanded])
return (
<div className="search_plugin_find_container">
<CustomTooltip tooltipText="Toggle Replace" tooltipClasses="text-nowrap" tooltipId="toggleReplaceTooltip" placement="left-start">
<CustomTooltip tooltipText={<FormattedMessage id="search.toggleReplace" />} tooltipClasses="text-nowrap" tooltipId="toggleReplaceTooltip" placement="left-start">
<div
data-id="toggle_replace"
className={`codicon codicon-find-${expanded ? 'expanded' : 'collapsed'} search_plugin_find_container_arrow`}

@ -1,5 +1,5 @@
import React, {useContext, useRef} from 'react'
import {useIntl} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import {SearchContext} from '../context/context'
export const Replace = (props) => {
@ -15,7 +15,9 @@ export const Replace = (props) => {
return (
<>
<div className="search_plugin_find-part ">
<label className="d-none">replace in files</label>
<label className="d-none">
<FormattedMessage id="search.replaceInFiles" />
</label>
<input id="search_replace" placeholder={intl.formatMessage({id: 'search.replace'})} className="form-control" onChange={change}></input>
</div>
</>

@ -1,5 +1,6 @@
import React from 'react'
import {useContext} from 'react'
import {FormattedMessage} from 'react-intl'
import {SearchContext} from '../context/context'
export const StopSearch = () => {
@ -9,7 +10,7 @@ export const StopSearch = () => {
}
return (
<a className="badge badge-danger search_plugin_stop" onClick={async () => await cancel()}>
stop
<FormattedMessage id="search.stop" />
</a>
)
}

@ -1,6 +1,7 @@
import {useDialogDispatchers} from '@remix-ui/app'
import React from 'react'
import {useContext} from 'react'
import {FormattedMessage} from 'react-intl'
import {SearchContext} from '../context/context'
import * as path from 'path'
@ -30,7 +31,7 @@ export const Undo = () => {
className="undo-button btn btn-secondary btn-block my-3"
>
<div className="fas fa-undo mr-2"></div>
Undo changes to {path.basename(state.undoBuffer[`${state.workspace}/${state.currentFile}`].path)}
<FormattedMessage id="search.undoChanges" values={{path: path.basename(state.undoBuffer[`${state.workspace}/${state.currentFile}`].path)}} />
</button>
) : null}
</>

@ -1,6 +1,6 @@
import {useDialogDispatchers} from '@remix-ui/app'
import React, {useContext, useEffect, useRef, useState} from 'react'
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import {SearchContext} from '../../context/context'
import {SearchResult, SearchResultLine} from '../../types'
import {ResultFileName} from './ResultFileName'
@ -12,6 +12,7 @@ interface ResultItemProps {
}
export const ResultItem = (props: ResultItemProps) => {
const intl = useIntl()
const {state, findText, disableForceReload, updateCount, replaceAllInFile} = useContext(SearchContext)
const [loading, setLoading] = useState<boolean>(false)
const [lines, setLines] = useState<SearchResultLine[]>([])
@ -72,11 +73,18 @@ export const ResultItem = (props: ResultItemProps) => {
} else {
modal({
id: 'confirmreplace',
title: 'Replace',
message: `Are you sure you want to replace '${state.find}' by '${state.replace}' in ${props.file.filename}?`,
okLabel: 'Yes',
title: intl.formatMessage({id: 'search.replace'}),
message: intl.formatMessage(
{id: 'search.confirmreplaceMsg'},
{
find: state.find,
replace: state.replace,
filename: props.file.filename
}
),
okLabel: intl.formatMessage({id: 'search.yes'}),
okFn: confirmReplace,
cancelLabel: 'No',
cancelLabel: intl.formatMessage({id: 'search.no'}),
cancelFn: () => {},
data: null
})
@ -122,7 +130,12 @@ export const ResultItem = (props: ResultItemProps) => {
<div className="search_plugin_result_count_number badge badge-pill badge-secondary">{props.file.count}</div>
</div>
</div>
{loading ? <div className="loading">Loading...</div> : null}
{loading ? (
<div className="loading">
<FormattedMessage id="search.loading" />
...
</div>
) : null}
{!toggleExpander && !loading ? (
<div className="search_plugin_wrap_summary">
{state.replaceEnabled ? (

@ -1,6 +1,7 @@
import {useDialogDispatchers} from '@remix-ui/app'
import {CustomTooltip} from '@remix-ui/helper'
import React, {useContext} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {SearchContext} from '../../context/context'
import {SearchResult, SearchResultLine, SearchResultLineLine} from '../../types'
@ -11,6 +12,7 @@ interface ResultSummaryProps {
}
export const ResultSummary = (props: ResultSummaryProps) => {
const intl = useIntl()
const {hightLightInPath, replaceText, state} = useContext(SearchContext)
const {modal} = useDialogDispatchers()
const selectLine = async (line: SearchResultLineLine) => {
@ -32,11 +34,18 @@ export const ResultSummary = (props: ResultSummaryProps) => {
} else {
modal({
id: 'confirmreplace',
title: 'Replace',
message: `Are you sure you want to replace '${line.center}' by '${state.replace}' in ${props.searchResult.filename}?`,
okLabel: 'Yes',
title: intl.formatMessage({id: 'search.replace'}),
message: intl.formatMessage(
{id: 'search.confirmreplaceMsg'},
{
find: line.center,
replace: state.replace,
filename: props.searchResult.filename
}
),
okLabel: intl.formatMessage({id: 'search.yes'}),
okFn: confirmReplace,
cancelLabel: 'No',
cancelLabel: intl.formatMessage({id: 'search.no'}),
cancelFn: () => {},
data: line
})
@ -62,7 +71,7 @@ export const ResultSummary = (props: ResultSummaryProps) => {
</div>
{state.replaceEnabled ? (
<div className="search_plugin_search_control">
<CustomTooltip tooltipText="Replace" tooltipClasses="text-nowrap" tooltipId="replaceTooltip" placement="top-start">
<CustomTooltip tooltipText={<FormattedMessage id="search.replace" />} tooltipClasses="text-nowrap" tooltipId="replaceTooltip" placement="top-start">
<div
data-id={`replace-${props.searchResult.filename}-${lineItem.position.start.line}-${lineItem.position.start.column}`}
onClick={async () => {

@ -1,4 +1,5 @@
import React, {useContext, useEffect} from 'react'
import {FormattedMessage} from 'react-intl'
import {SearchContext} from '../../context/context'
import {StopSearch} from '../StopSearch'
import {ResultItem} from './ResultItem'
@ -14,12 +15,12 @@ export const Results = () => {
{state.find && !state.clipped ? (
<div className="search_plugin_result_count_number badge badge-pill badge-secondary">
showing {state.count} results {state.fileCount} in files
<FormattedMessage id="search.text1" values={{count: state.count, fileCount: state.fileCount}} />
</div>
) : null}
{state.find && state.clipped ? (
<div className="alert alert-warning mt-1">
Too many resuls to display...<br></br>Please narrow down your search.
<FormattedMessage id="search.text2" values={{br: <br />}} />
</div>
) : null}
{state.searchResults &&

@ -48,7 +48,9 @@ export function EtherscanSettings(props: EtherscanSettingsProps) {
</a>
</p>
<div>
<label className="mb-0 pb-0">TOKEN:</label>
<label className="mb-0 pb-0">
<FormattedMessage id="settings.token" />:
</label>
<div className="input-group text-secondary mb-0 h6">
<input
id="etherscanAccessToken"
@ -59,7 +61,13 @@ export function EtherscanSettings(props: EtherscanSettingsProps) {
value={etherscanToken}
/>
<div className="input-group-append">
<CopyToClipboard content={etherscanToken} data-id="copyToClipboardCopyIcon" className="far fa-copy ml-1 p-2 mt-1" direction={'top'} />
<CopyToClipboard
tip={intl.formatMessage({id: 'settings.copy'})}
content={etherscanToken}
data-id="copyToClipboardCopyIcon"
className="far fa-copy ml-1 p-2 mt-1"
direction={'top'}
/>
</div>
</div>
</div>
@ -75,7 +83,12 @@ export function EtherscanSettings(props: EtherscanSettingsProps) {
type="button"
disabled={etherscanToken === ''}
></input>
<CustomTooltip tooltipText="Delete Etherscan token" tooltipClasses="text-nowrap" tooltipId="removeetherscantokenTooltip" placement="left-start">
<CustomTooltip
tooltipText={<FormattedMessage id="settings.deleteEtherscanToken" />}
tooltipClasses="text-nowrap"
tooltipId="removeetherscantokenTooltip"
placement="left-start"
>
<button
className="btn btn-sm btn-secondary ml-2"
id="removeetherscantoken"

@ -66,7 +66,9 @@ export function GithubSettings(props: GithubSettingsProps) {
</a>
</p>
<div>
<label className="mb-0 pb-0">TOKEN:</label>
<label className="mb-0 pb-0">
<FormattedMessage id="settings.token" />:
</label>
<div className="input-group text-secondary mb-0 h6">
<input
id="gistaccesstoken"
@ -77,12 +79,20 @@ export function GithubSettings(props: GithubSettingsProps) {
value={githubToken}
/>
<div className="input-group-append">
<CopyToClipboard content={githubToken} data-id="copyToClipboardCopyIcon" className="far fa-copy ml-1 p-2 mt-1" direction={'top'} />
<CopyToClipboard
tip={intl.formatMessage({id: 'settings.copy'})}
content={githubToken}
data-id="copyToClipboardCopyIcon"
className="far fa-copy ml-1 p-2 mt-1"
direction={'top'}
/>
</div>
</div>
</div>
<div>
<label className="pt-2 mb-0 pb-0">USERNAME:</label>
<label className="pt-2 mb-0 pb-0">
<FormattedMessage id="settings.username" />:
</label>
<div className="text-secondary mb-0 h6">
<input
id="githubusername"
@ -95,7 +105,9 @@ export function GithubSettings(props: GithubSettingsProps) {
</div>
</div>
<div>
<label className="pt-2 mb-0 pb-0">EMAIL:</label>
<label className="pt-2 mb-0 pb-0">
<FormattedMessage id="settings.email" />:
</label>
<div className="text-secondary mb-0 h6">
<input id="githubemail" data-id="settingsTabGithubEmail" type="text" className="form-control" onChange={(e) => handleChangeEmailState(e)} value={githubEmail} />
<div className="d-flex justify-content-end pt-2">
@ -107,7 +119,12 @@ export function GithubSettings(props: GithubSettingsProps) {
value={intl.formatMessage({id: 'settings.save'})}
type="button"
></input>
<CustomTooltip tooltipText="Delete Github Credentials" tooltipClasses="text-nowrap" tooltipId="removegisttokenTooltip" placement="top-start">
<CustomTooltip
tooltipText={<FormattedMessage id="settings.deleteGithubCredentials" />}
tooltipClasses="text-nowrap"
tooltipId="removegisttokenTooltip"
placement="top-start"
>
<button className="btn btn-sm btn-secondary ml-2" id="removegisttoken" data-id="settingsTabRemoveGistToken" onClick={removeToken}>
<FormattedMessage id="settings.remove" />
</button>

@ -266,7 +266,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
</span>
<a href="https://medium.com/p/66ef69e14931/" target="_blank">
{' '}
Analytics in Remix IDE
<FormattedMessage id="settings.analyticsInRemix" />
</a>{' '}
<span>&</span>{' '}
<a target="_blank" href="https://matomo.org/free-software">
@ -305,13 +305,17 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
<FormattedMessage id="settings.swarm" />
</h6>
<div className="pt-2 pt-2 mb-0 pb-0">
<label className="m-0">PRIVATE BEE ADDRESS:</label>
<label className="m-0">
<FormattedMessage id="settings.privateBeeAddress" />:
</label>
<div className="text-secondary mb-0 h6">
<input id="swarmprivatebeeaddress" data-id="settingsPrivateBeeAddress" className="form-control" onChange={handleSavePrivateBeeAddress} value={privateBeeAddress} />
</div>
</div>
<div className="pt-2 mb-0 pb-0">
<label className="m-0">POSTAGE STAMP ID:</label>
<label className="m-0">
<FormattedMessage id="settings.postageStampID" />:
</label>
<div className="text-secondary mb-0 h6">
<input id="swarmpostagestamp" data-id="settingsPostageStampId" className="form-control" onChange={handleSavePostageStampId} value={postageStampId} />
<div className="d-flex justify-content-end pt-2"></div>
@ -380,13 +384,17 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
<FormattedMessage id="settings.ipfs" />
</h6>
<div className="pt-2 mb-0">
<label className="m-0">IPFS HOST:</label>
<label className="m-0">
IPFS <FormattedMessage id="settings.host" />:
</label>
<div className="text-secondary mb-0 h6">
<input placeholder="e.g. ipfs.infura.io" id="settingsIpfsUrl" data-id="settingsIpfsUrl" className="form-control" onChange={handleSaveIpfsUrl} value={ipfsUrl} />
</div>
</div>
<div className="pt-2 mb-0 pb-0">
<label className="m-0">IPFS PROTOCOL:</label>
<label className="m-0">
IPFS <FormattedMessage id="settings.protocol" />:
</label>
<div className="text-secondary mb-0 h6">
<input
placeholder="e.g. https"
@ -399,19 +407,25 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
</div>
</div>
<div className="pt-2 mb-0 pb-0">
<label className="m-0">IPFS PORT:</label>
<label className="m-0">
IPFS <FormattedMessage id="settings.port" />:
</label>
<div className="text-secondary mb-0 h6">
<input placeholder="e.g. 5001" id="settingsIpfsPort" data-id="settingsIpfsPort" className="form-control" onChange={handleSaveIpfsPort} value={ipfsPort} />
</div>
</div>
<div className="pt-2 mb-0 pb-0">
<label className="m-0">IPFS PROJECT ID [ INFURA ]:</label>
<label className="m-0">
IPFS <FormattedMessage id="settings.projectID" /> [ INFURA ]:
</label>
<div className="text-secondary mb-0 h6">
<input id="settingsIpfsProjectId" data-id="settingsIpfsProjectId" className="form-control" onChange={handleSaveIpfsProjectId} value={ipfsProjectId} />
</div>
</div>
<div className="pt-2 mb-0 pb-0">
<label className="m-0">IPFS PROJECT SECRET [ INFURA ]:</label>
<label className="m-0">
IPFS <FormattedMessage id="settings.projectSecret" /> [ INFURA ]:
</label>
<div className="text-secondary mb-0 h6">
<input
id="settingsIpfsProjectSecret"

@ -274,12 +274,12 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
setShowFilePathInput(false)
} else {
modal(
'New configuration file',
`The file "${configFilePathInput.current.value}" you entered does not exist. Do you want to create a new one?`,
'Create',
intl.formatMessage({id: 'solidity.newConfigFileTitle'}),
intl.formatMessage({id: 'solidity.newConfigFileMessage'}, {configFilePathInput: configFilePathInput.current.value}),
intl.formatMessage({id: 'solidity.create'}),
async () => await createNewConfigFile(),
false,
'Cancel',
intl.formatMessage({id: 'solidity.cancel'}),
() => {
setShowFilePathInput(false)
}
@ -337,9 +337,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
allVersionsWasm = wasmRes.data.builds.slice().reverse()
}
} catch (e) {
tooltip(
'Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload. Error: ' + e
)
tooltip(intl.formatMessage({id: 'solidity.tooltipText5'}) + e)
}
// replace in allVersions those compiler builds which exist in allVersionsWasm with new once
if (allVersionsWasm && allVersions) {
@ -399,7 +397,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const compilerPath = state.allversions.filter((obj) => !obj.prerelease && obj.version === compilerToLoad)[0].path
if (state.selectedVersion !== compilerPath) {
// @ts-ignore
api.call('notification', 'toast', `Updating compiler version to match current contract file pragma i.e ${_retrieveVersion(compilerPath)}`)
api.call('notification', 'toast', intl.formatMessage({id: 'solidity.toastMessage'}, {version: _retrieveVersion(compilerPath)}))
setState((prevState) => {
return {...prevState, selectedVersion: compilerPath}
})
@ -443,12 +441,12 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
const loadingCompiler = () => {
if (!compileIcon.current) return
compileIcon.current.setAttribute('title', 'compiler is loading, please wait a few moments.')
compileIcon.current.setAttribute('title', intl.formatMessage({id: 'solidity.compileIconAttribute'}))
compileIcon.current.classList.add('remixui_spinningIcon')
setState((prevState) => {
return {
...prevState,
compilerLicense: 'Compiler is loading. License will be displayed once compiler is loaded'
compilerLicense: intl.formatMessage({id: 'solidity.compilerLicenseMsg1'})
}
})
_updateLanguageSelector()
@ -462,7 +460,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
setState((prevState) => {
return {
...prevState,
compilerLicense: license ? license : 'Could not retreive license for selected compiler version'
compilerLicense: license ? license : intl.formatMessage({id: 'solidity.compilerLicenseMsg2'})
}
})
if (state.autoCompile) compile()
@ -592,16 +590,21 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
id: 'solidity.addACustomCompiler'
}),
promptMessage('URL'),
'OK',
intl.formatMessage({id: 'solidity.ok'}),
addCustomCompiler,
false,
'Cancel',
intl.formatMessage({id: 'solidity.cancel'}),
() => {}
)
}
const showCompilerLicense = () => {
modal('Compiler License', state.compilerLicense ? state.compilerLicense : 'License not available', 'OK', () => {})
modal(
intl.formatMessage({id: 'solidity.compilerLicense'}),
state.compilerLicense ? state.compilerLicense : intl.formatMessage({id: 'solidity.compilerLicenseMsg3'}),
intl.formatMessage({id: 'solidity.ok'}),
() => {}
)
}
const promptMessage = (message) => {
@ -766,7 +769,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
>
<span className="far fa-plus border-0 p-0 ml-3" onClick={() => promptCompiler()}></span>
</CustomTooltip>
<CustomTooltip placement="top" tooltipId="showCompilerTooltip" tooltipClasses="text-nowrap" tooltipText={'See compiler license'}>
<CustomTooltip placement="top" tooltipId="showCompilerTooltip" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="solidity.seeCompilerLicense" />}>
<span className="fa fa-file-text-o border-0 p-0 ml-2" onClick={() => showCompilerLicense()}></span>
</CustomTooltip>
<select
@ -928,7 +931,11 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
placement="right"
tooltipId="compilerLabelTooltip"
tooltipClasses="text-nowrap"
tooltipText={<span>{'Language specification available from Compiler >= v0.5.7'}</span>}
tooltipText={
<span>
<FormattedMessage id="solidity.tooltipText6" />
</span>
}
>
<div id="compilerLanguageSelectorWrapper">
<select
@ -991,7 +998,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
placeholder="200"
value={state.runs}
type="number"
title="Estimated number of times each opcode of the deployed code will be executed across the life-time of the contract."
title={intl.formatMessage({id: 'solidity.inputTitle2'})}
onChange={(e) => onChangeRuns(e.target.value)}
disabled={!state.optimize || state.useFileConfiguration}
/>
@ -1014,7 +1021,16 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</div>
<div className={`pt-2 ml-4 ml-2 align-items-start justify-content-between d-flex`}>
{!showFilePathInput && state.useFileConfiguration && (
<CustomTooltip placement="bottom" tooltipId="configfileTooltip" tooltipClasses="text-nowrap" tooltipText={<span>Click to open the config file</span>}>
<CustomTooltip
placement="bottom"
tooltipId="configfileTooltip"
tooltipClasses="text-nowrap"
tooltipText={
<span>
<FormattedMessage id="solidity.tooltipText4" />
</span>
}
>
<span
onClick={
configFilePath === ''
@ -1025,7 +1041,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}
className="py-2 remixui_compilerConfigPath"
>
{configFilePath === '' ? 'No file selected.' : configFilePath}
{configFilePath === '' ? intl.formatMessage({id: 'solidity.noFileSelected1'}) : configFilePath}
</span>
</CustomTooltip>
)}
@ -1034,7 +1050,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
ref={configFilePathInput}
className={`py-0 my-0 form-control ${showFilePathInput ? 'd-flex' : 'd-none'}`}
placeholder={'/folder_path/file_name.json'}
title="If the file you entered does not exist you will be able to create one in the next step."
title={intl.formatMessage({id: 'solidity.inputTitle1'})}
disabled={!state.useFileConfiguration}
data-id="scConfigFilePathInput"
onKeyPress={(event) => {
@ -1072,10 +1088,10 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<div className="text-left">
{!(configFilePath === '' && state.useFileConfiguration) && (
<div>
<b>Ctrl+S</b> to compile {state.compiledFileName.endsWith('.sol') ? state.compiledFileName : null}{' '}
<b>Ctrl+S</b> <FormattedMessage id="solidity.toCompile" /> {state.compiledFileName.endsWith('.sol') ? state.compiledFileName : null}{' '}
</div>
)}
{configFilePath === '' && state.useFileConfiguration && <div> No config file selected</div>}
{configFilePath === '' && state.useFileConfiguration && <div> <FormattedMessage id="solidity.noConfigFileSelected" /></div>}
</div>
}
>
@ -1114,10 +1130,10 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<div className="text-left">
{!(configFilePath === '' && state.useFileConfiguration) && (
<div>
<b>Ctrl+Shift+S</b> for compiling and script execution
<b>Ctrl+Shift+S</b> <FormattedMessage id="solidity.tooltipText3" />
</div>
)}
{configFilePath === '' && state.useFileConfiguration && <div> No config file selected</div>}
{configFilePath === '' && state.useFileConfiguration && <div> <FormattedMessage id="solidity.noConfigFileSelected" /></div>}
</div>
}
>
@ -1131,7 +1147,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
tooltipId="overlay-tooltip-compile-run-doc"
tooltipText={
<div className="text-left p-2">
<div>Choose the script to execute right after compilation by adding the `dev-run-script` natspec tag, as in:</div>
<div><FormattedMessage id="solidity.tooltipText1" /></div>
<pre>
<code>
/**
@ -1148,7 +1164,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<br />
</code>
</pre>
Click the "i" icon to learn more
<FormattedMessage id="solidity.tooltipText2" />
</div>
}
>
@ -1156,7 +1172,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<i className="pl-2 ml-2 fas fa-info text-dark"></i>
</a>
</CustomTooltip>
<CopyToClipboard tip="Click to copy the custom NatSpec tag" getContent={() => '@custom:dev-run-script file_path'} direction="top">
<CopyToClipboard tip={intl.formatMessage({id: 'solidity.copyNatSpecTag'})} getContent={() => '@custom:dev-run-script file_path'} direction="top">
<button className="btn remixui_copyButton ml-2 my-1 text-dark">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
</button>

@ -143,7 +143,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
} catch (e) {
node = (
<div>
Unable to display "${propertyName}": ${e.message}
<FormattedMessage id="solidity.unableToDisplay" /> "${propertyName}": ${e.message}
</div>
)
}
@ -173,6 +173,9 @@ export const ContractSelection = (props: ContractSelectionProps) => {
'abi': 'ABI: describing all the functions (input/output params, scope, ...)',
'name': 'Name of the compiled contract',
'swarmLocation': 'Swarm url where all metadata information can be found (contract needs to be published first)',
'storageLayout': 'See the Storage Layout documentation.',
'devdoc': 'Developer documentation (natspec)',
'userdoc': 'User documentation (natspec)',
'web3Deploy': 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract'
}
let contractProperties: any = {}
@ -185,7 +188,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
{Object.keys(contractProperties).map((propertyName, index) => {
const copyDetails = (
<span className="remixui_copyDetails">
<CopyToClipboard content={contractProperties[propertyName]} direction="top" />
<CopyToClipboard tip={intl.formatMessage({id: 'solidity.copy'})} content={contractProperties[propertyName]} direction="top" />
</span>
)
const questionMark = (
@ -222,7 +225,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
_paq.push(['trackEvent', 'compiler', 'compilerDetails', 'download'])
saveAs(new Blob([JSON.stringify(contractProperties, null, '\t')]), `${selectedContract}_compData.json`)
}
modal(selectedContract, log, 'Download', downloadFn, true, 'Close', null)
modal(selectedContract, log, intl.formatMessage({id: 'solidity.download'}), downloadFn, true, intl.formatMessage({id: 'solidity.close'}), null)
}
const copyBytecode = () => {
@ -238,7 +241,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
{/* Select Compiler Version */}
<div className="mb-3">
<label className="remixui_compilerLabel form-check-label" htmlFor="compiledContracts">
Contract
<FormattedMessage id="solidity.contract" />
</label>
<select onChange={(e) => handleContractChange(e.target.value)} value={selectedContract} data-id="compiledContracts" id="compiledContracts" className="custom-select">
{contractList.map(({name, file}, index) => (
@ -302,7 +305,12 @@ export const ContractSelection = (props: ContractSelectionProps) => {
details()
}}
>
<CustomTooltip placement="right" tooltipId="CompilationDetailsTooltip" tooltipClasses="text-nowrap" tooltipText="Display Contract Details">
<CustomTooltip
placement="right"
tooltipId="CompilationDetailsTooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="solidity.displayContractDetails" />}
>
<span>
<FormattedMessage id="solidity.compilationDetails" />
</span>
@ -312,13 +320,13 @@ export const ContractSelection = (props: ContractSelectionProps) => {
<div className="remixui_contractHelperButtons">
<div className="input-group">
<div className="btn-group" role="group" aria-label="Copy to Clipboard">
<CopyToClipboard tip="Copy ABI to clipboard" getContent={copyABI} direction="top">
<CopyToClipboard tip={intl.formatMessage({id: 'solidity.copyABI'})} getContent={copyABI} direction="top">
<button className="btn remixui_copyButton">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
<span>ABI</span>
</button>
</CopyToClipboard>
<CopyToClipboard tip="Copy Bytecode to clipboard" getContent={copyBytecode} direction="top">
<CopyToClipboard tip={intl.formatMessage({id: 'solidity.copyBytecode'})} getContent={copyBytecode} direction="top">
<button className="btn remixui_copyButton">
<i className="remixui_copyIcon far fa-copy" aria-hidden="true"></i>
<span>Bytecode</span>
@ -333,7 +341,7 @@ export const ContractSelection = (props: ContractSelectionProps) => {
<section className="remixui_container clearfix">
<article className="px-2 mt-2 pb-0 d-flex w-100">
<span className="mt-2 mx-3 w-100 alert alert-warning" role="alert">
No Contract Compiled Yet
<FormattedMessage id="solidity.noContractCompiled" />
</span>
</article>
</section>

@ -1,5 +1,6 @@
import {CustomTooltip} from '@remix-ui/helper'
import React, {Fragment, Ref} from 'react'
import {FormattedMessage} from 'react-intl'
import {Dropdown} from 'react-bootstrap'
import {UmlFileType} from '../utilities/UmlDownloadStrategy'
@ -76,25 +77,39 @@ export default function UmlDownload(props: UmlDownloadProps) {
}}
data-id="umlPngDownload"
>
<CustomTooltip placement="left-start" tooltipId="solUmlgenDownloadAsPngTooltip" tooltipClasses="text-nowrap" tooltipText={'Download UML diagram as a PNG file'}>
<CustomTooltip
placement="left-start"
tooltipId="solUmlgenDownloadAsPngTooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="solUmlGen.pngDownloadTooltip" />}
>
<div data-id="umlPngDownload">
<span id="umlPngDownloadBtn" data-id="umlPngDownload" className="far fa-image pl-2"></span>
<span className="pl-1">Download as PNG</span>
<span className="pl-1">
<FormattedMessage id="solUmlGen.pngDownload" />
</span>
</div>
</CustomTooltip>
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item
onClick={() => {
_paq.push(['trackEvent', 'solUmlgen', 'umlpdfdownload', 'downloadAsPdf'])
_paq.push(['trackEvent', 'solUmlGen', 'umlpdfdownload', 'downloadAsPdf'])
props.download('pdf')
}}
data-id="umlPdfDownload"
>
<CustomTooltip placement="left-start" tooltipId="solUmlgenDownloadAsPdfTooltip" tooltipClasses="text-nowrap" tooltipText={'Download UML diagram as a PDF file'}>
<CustomTooltip
placement="left-start"
tooltipId="solUmlgenDownloadAsPdfTooltip"
tooltipClasses="text-nowrap"
tooltipText={<FormattedMessage id="solUmlGen.pdfDownloadTooltip" />}
>
<div data-id="umlPdfDownload">
<span id="umlPdfDownloadBtn" data-id="umlPdfDownload" className="far fa-file-pdf pl-2"></span>
<span className="pl-2">Download as PDF</span>
<span className="pl-2">
<FormattedMessage id="solUmlGen.pdfDownload" />
</span>
</div>
</CustomTooltip>
</Dropdown.Item>

@ -1,4 +1,5 @@
import React, {Fragment, useCallback, useEffect, useState} from 'react'
import {FormattedMessage} from 'react-intl'
import {TransformComponent, TransformWrapper} from 'react-zoom-pan-pinch'
import {GlassMagnifier, MagnifierContainer} from 'react-image-magnifiers'
import {ThemeSummary} from '../types'
@ -75,18 +76,25 @@ export function RemixUiSolidityUmlGen({updatedSvg, loading, fileName, themeDark}
const DefaultInfo = () => (
<div className="d-flex flex-column justify-content-center align-items-center mt-5 ml-5">
<h3 className="h3 align-self-start text-dark">
<p>To view your contract as a UML Diagram</p>
<p>
<FormattedMessage id="solUmlGen.text1" />
</p>
</h3>
<ul className="ml-3 justify-content-start align-self-start">
<li>
<h5 className="h5 align-self-start text-dark">
<p>Right click on your contract file</p>
<p>
<FormattedMessage id="solUmlGen.text2" />
</p>
</h5>
</li>
<li>
<h5 className="h5 align-self-start text-dark">
<p>
Click on <b>Generate UML</b>
<FormattedMessage id="solUmlGen.clickOn" />{' '}
<b>
<FormattedMessage id="solUmlGen.generateUML" />
</b>
</p>
</h5>
</li>

@ -234,7 +234,7 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
if (inputPath === '') inputPath = defaultPath
setInputPathValue(path)
await testTabLogic.generateTestFolder(inputPath)
setToasterMsg('Folder created successfully')
setToasterMsg(intl.formatMessage({ id: 'solidityUnitTesting.toasterMsg' }))
setDisableCreateButton(true)
setDisableGenerateButton(false)
testTabLogic.setCurrentPath(inputPath)
@ -309,15 +309,19 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
if (index > -1) {
const className = 'alert-danger d-inline-block mb-1 mr-1 p-1 failed_' + runningTestFileName
label = (
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText="At least one contract test failed">
<div className={className}>FAIL</div>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="solidityUnitTesting.tooltipText1" />}>
<div className={className}>
<FormattedMessage id="solidityUnitTesting.fail" />
</div>
</CustomTooltip>
)
} else {
const className = 'alert-success d-inline-block mb-1 mr-1 p-1 passed_' + runningTestFileName
label = (
<CustomTooltip placement={'top-end'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText="All contract tests passed">
<div className={className}>PASS</div>
<CustomTooltip placement={'top-end'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText={<FormattedMessage id="solidityUnitTesting.tooltipText2" />}>
<div className={className}>
<FormattedMessage id="solidityUnitTesting.pass" />
</div>
</CustomTooltip>
)
}
@ -349,7 +353,12 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
const { web3, debugTxHash } = test
debugBtn = (
<div id={test.value.replaceAll(' ', '_')} className="btn border btn btn-sm ml-1" style={{ cursor: 'pointer' }} onClick={() => startDebug(debugTxHash, web3)}>
<CustomTooltip placement={'top-start'} tooltipClasses="text-nowrap" tooltipId="info-recorder" tooltipText="Start debugging">
<CustomTooltip
placement={'top-start'}
tooltipClasses="text-nowrap"
tooltipId="info-recorder"
tooltipText={<FormattedMessage id="solidityUnitTesting.tooltipText3" />}
>
<i className="fas fa-bug"></i>
</CustomTooltip>
</div>
@ -387,7 +396,9 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
<span> {test.value}</span>
{debugBtn}
</div>
<span className="text-dark">Error Message:</span>
<span className="text-dark">
<FormattedMessage id="solidityUnitTesting.errorMessage" />:
</span>
<span className="pb-2 text-break">"{test.errMsg}"</span>
</div>
)

@ -2,6 +2,7 @@ import {fileDecoration, FileDecorationIcons} from '@remix-ui/file-decorators'
import {CustomTooltip} from '@remix-ui/helper'
import {Plugin} from '@remixproject/engine'
import React, {useState, useRef, useEffect, useReducer} from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs'
import './remix-ui-tabs.css'
const _paq = (window._paq = window._paq || [])
@ -185,21 +186,23 @@ export const TabsUI = (props: TabsUIProps) => {
tooltipId="overlay-tooltip-run-script"
tooltipText={
<span>
{tabsState.currentExt === 'js' || tabsState.currentExt === 'ts'
? 'Run script (CTRL + SHIFT + S)'
: tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul'
? 'Compile CTRL + S'
: 'Select .sol or .yul file to compile or a .ts or .js file and run it'}
{tabsState.currentExt === 'js' || tabsState.currentExt === 'ts' ? (
<FormattedMessage id="remixUiTabs.tooltipText1" />
) : tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul' ? (
<FormattedMessage id="remixUiTabs.tooltipText2" />
) : (
<FormattedMessage id="remixUiTabs.tooltipText3" />
)}
</span>
}
>
<i className="fad fa-play"></i>
</CustomTooltip>
</button>
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-zoom-out" tooltipText="Zoom out">
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-zoom-out" tooltipText={<FormattedMessage id="remixUiTabs.zoomOut" />}>
<span data-id="tabProxyZoomOut" className="btn btn-sm px-2 fas fa-search-minus text-dark" onClick={() => props.onZoomOut()}></span>
</CustomTooltip>
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-run-zoom-in" tooltipText="Zoom in">
<CustomTooltip placement="bottom" tooltipId="overlay-tooltip-run-zoom-in" tooltipText={<FormattedMessage id="remixUiTabs.zoomIn" />}>
<span data-id="tabProxyZoomIn" className="btn btn-sm px-2 fas fa-search-plus text-dark" onClick={() => props.onZoomIn()}></span>
</CustomTooltip>
</div>

@ -1,4 +1,5 @@
import React from 'react' // eslint-disable-line
import {FormattedMessage, useIntl} from 'react-intl'
import {shortenHexData} from '@remix-ui/helper'
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import showTable from './Table'
@ -7,6 +8,7 @@ import {execution} from '@remix-project/remix-lib'
const typeConversion = execution.typeConversion
const RenderCall = ({tx, resolvedData, logs, index, plugin, showTableHash, txDetails, modal}) => {
const intl = useIntl()
const to = resolvedData.contractName + '.' + resolvedData.fn
const from = tx.from ? tx.from : ' - '
const input = tx.input ? shortenHexData(tx.input) : ''
@ -16,12 +18,12 @@ const RenderCall = ({tx, resolvedData, logs, index, plugin, showTableHash, txDet
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal(
'VM mode',
'Cannot debug this call. Debugging calls is only possible in Remix VM mode.',
'Ok',
intl.formatMessage({id: 'terminal.vmMode'}),
intl.formatMessage({id: 'terminal.vmModeMsg'}),
intl.formatMessage({id: 'terminal.ok'}),
false,
() => {},
'Cancel',
intl.formatMessage({id: 'terminal.cancel'}),
() => {}
)
} else {
@ -47,7 +49,7 @@ const RenderCall = ({tx, resolvedData, logs, index, plugin, showTableHash, txDet
</span>
<div className="remix_ui_terminal_buttons">
<div className="remix_ui_terminal_debug btn btn-primary btn-sm" onClick={(event) => debug(event, tx)}>
Debug
<FormattedMessage id="terminal.debug" />
</div>
</div>
<i className={`remix_ui_terminal_arrow fas ${showTableHash.includes(tx.hash) ? 'fa-angle-up' : 'fa-angle-down'}`}></i>

@ -1,5 +1,5 @@
import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import Context from './Context' // eslint-disable-line
import showTable from './Table'
@ -7,16 +7,17 @@ import {execution} from '@remix-project/remix-lib'
const typeConversion = execution.typeConversion
const RenderKnownTransactions = ({tx, receipt, resolvedData, logs, index, plugin, showTableHash, txDetails, modal, provider}) => {
const intl = useIntl()
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal(
'VM mode',
'Cannot debug this call. Debugging calls is only possible in Remix VM mode.',
'Ok',
intl.formatMessage({id: 'terminal.vmMode'}),
intl.formatMessage({id: 'terminal.vmModeMsg'}),
intl.formatMessage({id: 'terminal.ok'}),
false,
() => {},
'Cancel',
intl.formatMessage({id: 'terminal.cancel'}),
() => {}
)
} else {

@ -1,20 +1,21 @@
import React, {useState} from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {FormattedMessage, useIntl} from 'react-intl'
import CheckTxStatus from './ChechTxStatus' // eslint-disable-line
import Context from './Context' // eslint-disable-line
import showTable from './Table'
const RenderUnKnownTransactions = ({tx, receipt, index, plugin, showTableHash, txDetails, modal, provider}) => {
const intl = useIntl()
const debug = (event, tx) => {
event.stopPropagation()
if (tx.isCall && !tx.envMode.startsWith('vm')) {
modal(
'VM mode',
'Cannot debug this call. Debugging calls is only possible in Remix VM mode.',
'Ok',
intl.formatMessage({id: 'terminal.vmMode'}),
intl.formatMessage({id: 'terminal.vmModeMsg'}),
intl.formatMessage({id: 'terminal.ok'}),
false,
() => {},
'Cancel',
intl.formatMessage({id: 'terminal.cancel'}),
() => {}
)
} else {

@ -1,10 +1,12 @@
import React from 'react' // eslint-disable-line
import {FormattedMessage, useIntl} from 'react-intl'
import {CopyToClipboard} from '@remix-ui/clipboard' // eslint-disable-line
import {shortenHexData} from '@remix-ui/helper'
import {execution} from '@remix-project/remix-lib'
const typeConversion = execution.typeConversion
const showTable = (opts, showTableHash) => {
const intl = useIntl()
let msg = ''
let toHash
const data = opts.data // opts.data = data.tx
@ -15,17 +17,17 @@ const showTable = (opts, showTableHash) => {
}
let callWarning = ''
if (opts.isCall) {
callWarning = '(Cost only applies when called by a contract)'
callWarning = intl.formatMessage({id: 'terminal.callWarning'})
}
if (!opts.isCall) {
if (opts.status !== undefined && opts.status !== null) {
if (opts.status === 0 || opts.status === '0x0' || opts.status === false) {
msg = 'Transaction mined but execution failed'
msg = intl.formatMessage({id: 'terminal.msg1'})
} else if (opts.status === 1 || opts.status === '0x1' || opts.status === true) {
msg = 'Transaction mined and execution succeed'
msg = intl.formatMessage({id: 'terminal.msg2'})
}
} else {
msg = 'Status not available at the moment'
msg = intl.formatMessage({id: 'terminal.msg3'})
}
}
@ -40,7 +42,7 @@ const showTable = (opts, showTableHash) => {
{opts.status !== undefined ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
status
<FormattedMessage id="terminal.status" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableStatus${opts.hash}`} data-shared={`pair_${opts.hash}`}>{`${opts.status} ${msg}`}</td>
</tr>
@ -48,7 +50,7 @@ const showTable = (opts, showTableHash) => {
{opts.hash && !opts.isCall ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
transaction hash
<FormattedMessage id="terminal.transactionHash" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.hash}
@ -59,7 +61,7 @@ const showTable = (opts, showTableHash) => {
{opts.blockHash ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
block hash
<FormattedMessage id="terminal.blockHash" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableContractAddress${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.blockHash}
@ -70,7 +72,7 @@ const showTable = (opts, showTableHash) => {
{opts.blockNumber ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
block number
<FormattedMessage id="terminal.blockNumber" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableContractAddress${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.blockNumber}
@ -81,7 +83,7 @@ const showTable = (opts, showTableHash) => {
{opts.contractAddress ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
contract address
<FormattedMessage id="terminal.contractAddress" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableContractAddress${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.contractAddress}
@ -125,7 +127,7 @@ const showTable = (opts, showTableHash) => {
{opts.transactionCost ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
transaction cost
<FormattedMessage id="terminal.transactionCost" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableTransactionCost${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.transactionCost} gas {callWarning}
@ -136,7 +138,7 @@ const showTable = (opts, showTableHash) => {
{opts.executionCost ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
execution cost
<FormattedMessage id="terminal.executionCost" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableExecutionHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts.executionCost} gas {callWarning}
@ -147,7 +149,7 @@ const showTable = (opts, showTableHash) => {
{opts.input ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
input
<FormattedMessage id="terminal.input" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{shortenHexData(opts.input)}
@ -158,7 +160,7 @@ const showTable = (opts, showTableHash) => {
{opts['decoded input'] ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
decoded input
<FormattedMessage id="terminal.decodedInput" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts['decoded input'].trim()}
@ -169,7 +171,7 @@ const showTable = (opts, showTableHash) => {
{opts['decoded output'] ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
decoded output
<FormattedMessage id="terminal.decodedOutput" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{opts['decoded output']}
@ -180,7 +182,7 @@ const showTable = (opts, showTableHash) => {
{opts.logs ? (
<tr className="remix_ui_terminal_tr">
<td className="remix_ui_terminal_td" data-shared={`key_${opts.hash}`}>
logs
<FormattedMessage id="terminal.logs" />
</td>
<td className="remix_ui_terminal_td" data-id={`txLoggerTableHash${opts.hash}`} data-shared={`pair_${opts.hash}`}>
{JSON.stringify(stringified, null, '\t')}

@ -199,7 +199,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
const _shell = async (script, scopedCommands, done) => {
// default shell
if (script.indexOf('remix:') === 0) {
return done(null, 'This type of command has been deprecated and is not functionning anymore. Please run remix.help() to list available commands.')
return done(null, intl.formatMessage({id: 'terminal.text1'}))
}
if (script.indexOf('remix.') === 0) {
// we keep the old feature. This will basically only be called when the command is querying the "remix" object.
@ -577,7 +577,12 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
<div style={{ flexGrow: 1 }} className="remix_ui_terminal_panel" ref={panelRef}>
<div className="remix_ui_terminal_bar d-flex">
<div className="remix_ui_terminal_menu d-flex w-100 align-items-center position-relative border-top border-dark bg-light" ref={terminalMenu} data-id="terminalToggleMenu">
<CustomTooltip placement="top" tooltipId="terminalToggle" tooltipClasses="text-nowrap" tooltipText={isOpen ? 'Hide Terminal' : 'Show Terminal'}>
<CustomTooltip
placement="top"
tooltipId="terminalToggle"
tooltipClasses="text-nowrap"
tooltipText={isOpen ? <FormattedMessage id="terminal.hideTerminal" /> : <FormattedMessage id="terminal.showTerminal" />}
>
<i
className={`mx-2 remix_ui_terminal_toggleTerminal fas ${isOpen ? 'fa-angle-double-down' : 'fa-angle-double-up'}`}
data-id="terminalToggleIcon"
@ -585,11 +590,11 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
></i>
</CustomTooltip>
<div className="mx-2 remix_ui_terminal_console" id="clearConsole" data-id="terminalClearConsole" onClick={handleClearConsole}>
<CustomTooltip placement="top" tooltipId="terminalClear" tooltipClasses="text-nowrap" tooltipText="Clear console">
<CustomTooltip placement="top" tooltipId="terminalClear" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="terminal.clearConsole" />}>
<i className="fas fa-ban" aria-hidden="true"></i>
</CustomTooltip>
</div>
<CustomTooltip placement="top" tooltipId="terminalClear" tooltipClasses="text-nowrap" tooltipText="Pending Transactions">
<CustomTooltip placement="top" tooltipId="terminalClear" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="terminal.pendingTransactions" />}>
<div className="mx-2">0</div>
</CustomTooltip>
<div className="h-80 mx-3 align-items-center remix_ui_terminal_listenOnNetwork custom-control custom-checkbox">
@ -729,9 +734,13 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
if (x.typewriter && !typeWriterIndexes.current.includes(index)) {
typeWriterIndexes.current.push(index)
return (
<div className={classNameBlock} data-id="block" key={index}> <span ref={(element) => {
typewrite(element, msg ? msg.toString() : null)
}} className={x.style}></span></div>
<div className={classNameBlock} data-id="block" key={index}>
<span ref={(element) => {
typewrite(element, msg ? msg.toString() : null, () => scrollToBottom()
)
}} className={x.style}>
</span>
</div>
)
} else {
return (
@ -746,7 +755,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
typeWriterIndexes.current.push(index)
return (
<div className={classNameBlock} data-id="block" key={index}> <span ref={(element) => {
typewrite(element, x.message)
typewrite(element, x.message, () => scrollToBottom())
}} className={x.style}></span></div>
)
} else {
@ -789,19 +798,25 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
cancelFn={modalState.cancelFn}
handleHide={handleHideModal}
/>
{toaster && <Toaster message="no content to execute" />}
{toastProvider.show && <Toaster message={`provider for path ${toastProvider.fileName} not found`} />}
{toaster && <Toaster message={intl.formatMessage({id: 'terminal.toasterMsg1'})} />}
{toastProvider.show && <Toaster message={intl.formatMessage({id: 'terminal.toasterMsg2'}, {fileName: toastProvider.fileName})} />}
</div>
)
}
const typewrite = (elementsRef, message) => {
const typewrite = (elementsRef, message, callback) => {
(() => {
let count = 0
const id = setInterval(() => {
if (!elementsRef) return
count++
elementsRef.innerText = message.substr(0, count)
if (message === count) clearInterval(id)
// scroll when new line ` <br>
if (elementsRef.lastChild.tagName === `BR`) callback()
if (message.length === count) {
clearInterval(id)
callback()
}
}, 5)
})()
}

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

Loading…
Cancel
Save