adjust printWidth in prettier config

pull/4018/head
Joseph Izang 1 year ago
parent 665eb5389f
commit 3dd01f4858
  1. 1
      .prettierrc.json
  2. 31
      apps/etherscan/src/app/RemixPlugin.tsx
  3. 75
      apps/etherscan/src/app/app.tsx
  4. 54
      apps/etherscan/src/app/components/HeaderWithSettings.tsx
  5. 26
      apps/etherscan/src/app/components/SubmitButton.tsx
  6. 3
      apps/etherscan/src/app/hooks/useLocalStorage.tsx
  7. 6
      apps/etherscan/src/app/layouts/Default.tsx
  8. 25
      apps/etherscan/src/app/views/CaptureKeyView.tsx
  9. 12
      apps/etherscan/src/app/views/ErrorView.tsx
  10. 91
      apps/etherscan/src/app/views/ReceiptsView.tsx
  11. 181
      apps/etherscan/src/app/views/VerifyView.tsx
  12. 13
      apps/remix-ide-e2e/nightwatch.ts
  13. 25
      apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx
  14. 9
      apps/remix-ide/background.js
  15. 5
      apps/remix-ide/src/app/components/main-panel.tsx
  16. 87
      apps/remix-ide/src/app/components/preload.tsx
  17. 12
      apps/remix-ide/src/app/components/side-panel.tsx
  18. 35
      apps/remix-ide/src/app/components/vertical-icons.tsx
  19. 32
      apps/remix-ide/src/app/plugins/contractFlattener.tsx
  20. 11
      apps/remix-ide/src/app/plugins/notification.tsx
  21. 204
      apps/remix-ide/src/app/plugins/parser/code-parser.tsx
  22. 75
      apps/remix-ide/src/app/plugins/permission-handler-plugin.tsx
  23. 64
      apps/remix-ide/src/app/plugins/remixd-handle.tsx
  24. 11
      apps/remix-ide/src/app/plugins/solidity-script.tsx
  25. 158
      apps/remix-ide/src/app/plugins/solidity-umlgen.tsx
  26. 16
      apps/remix-ide/src/app/providers/abstract-provider.tsx
  27. 19
      apps/remix-ide/src/app/providers/custom-vm-fork-provider.tsx
  28. 33
      apps/remix-ide/src/app/providers/external-http-provider.tsx
  29. 8
      apps/remix-ide/src/app/providers/hardhat-provider.tsx
  30. 16
      apps/remix-ide/src/app/providers/injected-L2-provider.tsx
  31. 13
      apps/remix-ide/src/app/providers/injected-provider-default.tsx
  32. 34
      apps/remix-ide/src/app/providers/injected-provider.tsx
  33. 3
      apps/remix-ide/src/app/providers/mainnet-vm-fork-provider.tsx
  34. 25
      apps/remix-ide/src/app/providers/vm-provider.tsx
  35. 469
      apps/remix-ide/src/blockchain/blockchain.tsx
  36. 19
      apps/remix-ide/webpack.config.js
  37. 5
      apps/solidity-compiler/webpack.config.js
  38. 49
      apps/vyper/src/app/app.tsx
  39. 30
      apps/vyper/src/app/components/CompilerButton.tsx
  40. 11
      apps/vyper/src/app/components/LocalUrl.tsx
  41. 12
      apps/vyper/src/app/components/VyperResult.tsx
  42. 5
      apps/vyper/src/app/components/WarnRemote.tsx
  43. 22
      apps/vyper/src/app/utils/compiler.tsx
  44. 39
      apps/vyper/src/app/utils/remix-client.tsx
  45. 8
      apps/walletconnect/src/app/app.tsx
  46. 6
      apps/walletconnect/src/app/walletConnectUI.tsx
  47. 4
      apps/walletconnect/webpack.config.js
  48. 16
      libs/remix-debug/test.ts
  49. 21
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx
  50. 6
      libs/remix-ui/app/src/lib/remix-app/components/modals/dialogs.tsx
  51. 31
      libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx
  52. 26
      libs/remix-ui/app/src/lib/remix-app/components/modals/modal-wrapper.tsx
  53. 11
      libs/remix-ui/app/src/lib/remix-app/components/modals/origin-warning.tsx
  54. 12
      libs/remix-ui/app/src/lib/remix-app/components/splashscreen.tsx
  55. 16
      libs/remix-ui/app/src/lib/remix-app/context/context.tsx
  56. 36
      libs/remix-ui/app/src/lib/remix-app/context/provider.tsx
  57. 32
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  58. 40
      libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx
  59. 23
      libs/remix-ui/clipboard/src/lib/copy-to-clipboard/copy-to-clipboard.tsx
  60. 29
      libs/remix-ui/debugger-ui/src/hooks/extract-data.tsx
  61. 66
      libs/remix-ui/debugger-ui/src/lib/button-navigator/button-navigator.tsx
  62. 254
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  63. 6
      libs/remix-ui/debugger-ui/src/lib/step-manager/step-manager.tsx
  64. 20
      libs/remix-ui/debugger-ui/src/lib/tx-browser/tx-browser.tsx
  65. 62
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/assembly-items.tsx
  66. 100
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/dropdown-panel.tsx
  67. 5
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/full-storages-changes.tsx
  68. 11
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/global-variables.tsx
  69. 7
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/memory-panel.tsx
  70. 19
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-locals.tsx
  71. 20
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/solidity-state.tsx
  72. 7
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/stack-panel.tsx
  73. 7
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/step-detail.tsx
  74. 6
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/storage-panel.tsx
  75. 39
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
  76. 32
      libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger.tsx
  77. 9
      libs/remix-ui/drag-n-drop/src/lib/drag-n-drop.tsx
  78. 425
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  79. 46
      libs/remix-ui/file-decorators/src/lib/components/file-decoration-icon.tsx
  80. 5
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-custom-icon.tsx
  81. 5
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-error-icon.tsx
  82. 16
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-tooltip.tsx
  83. 5
      libs/remix-ui/file-decorators/src/lib/components/filedecorationicons/file-decoration-warning-icon.tsx
  84. 4
      libs/remix-ui/file-decorators/src/lib/helper/index.tsx
  85. 38
      libs/remix-ui/helper/src/lib/components/custom-dropdown.tsx
  86. 26
      libs/remix-ui/helper/src/lib/components/custom-tooltip.tsx
  87. 33
      libs/remix-ui/helper/src/lib/components/web3Dialog.tsx
  88. 60
      libs/remix-ui/helper/src/lib/helper-components.tsx
  89. 20
      libs/remix-ui/home-tab/src/lib/components/customNavButtons.tsx
  90. 70
      libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx
  91. 42
      libs/remix-ui/home-tab/src/lib/components/homeTabFeaturedPlugins.tsx
  92. 74
      libs/remix-ui/home-tab/src/lib/components/homeTabFile.tsx
  93. 29
      libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx
  94. 67
      libs/remix-ui/home-tab/src/lib/components/homeTabLearn.tsx
  95. 13
      libs/remix-ui/home-tab/src/lib/components/homeTabScamAlert.tsx
  96. 63
      libs/remix-ui/home-tab/src/lib/components/homeTabTitle.tsx
  97. 34
      libs/remix-ui/home-tab/src/lib/components/pluginButton.tsx
  98. 11
      libs/remix-ui/home-tab/src/lib/components/workspaceTemplate.tsx
  99. 12
      libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
  100. 15
      libs/remix-ui/locale-module/src/lib/remix-ui-locale-module.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,6 +1,7 @@
{
"tabWidth": 2,
"useTabs": false,
"printWidth": 180,
"semi": false,
"singleQuote": true,
"quoteProps": "consistent",

@ -1,11 +1,6 @@
import {PluginClient} from '@remixproject/plugin'
import {verify, EtherScanReturn} from './utils/verify'
import {
getReceiptStatus,
getEtherScanApi,
getNetworkName,
getProxyContractReceiptStatus
} from './utils'
import {getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus} from './utils'
export class RemixClient extends PluginClient {
loaded() {
@ -38,33 +33,17 @@ export class RemixClient extends PluginClient {
return result
}
async receiptStatus(
receiptGuid: string,
apiKey: string,
isProxyContract: boolean
) {
async receiptStatus(receiptGuid: string, apiKey: string, isProxyContract: boolean) {
try {
const {network, networkId} = await getNetworkName(this)
if (network === 'vm') {
throw new Error(
'Cannot check the receipt status in the selected network'
)
throw new Error('Cannot check the receipt status in the selected network')
}
const etherscanApi = getEtherScanApi(networkId)
let receiptStatus
if (isProxyContract)
receiptStatus = await getProxyContractReceiptStatus(
receiptGuid,
apiKey,
etherscanApi
)
else
receiptStatus = await getReceiptStatus(
receiptGuid,
apiKey,
etherscanApi
)
if (isProxyContract) receiptStatus = await getProxyContractReceiptStatus(receiptGuid, apiKey, etherscanApi)
else receiptStatus = await getReceiptStatus(receiptGuid, apiKey, etherscanApi)
return {
message: receiptStatus.result,
succeed: receiptStatus.status === '0' ? false : true

@ -1,9 +1,6 @@
import React, {useState, useEffect, useRef} from 'react'
import {
CompilationFileSources,
CompilationResult
} from '@remixproject/plugin-api'
import {CompilationFileSources, CompilationResult} from '@remixproject/plugin-api'
import {RemixClient} from './RemixPlugin'
import {createClient} from '@remixproject/plugin-webview'
@ -13,12 +10,7 @@ import {DisplayRoutes} from './routes'
import {useLocalStorage} from './hooks/useLocalStorage'
import {
getReceiptStatus,
getEtherScanApi,
getNetworkName,
getProxyContractReceiptStatus
} from './utils'
import {getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus} from './utils'
import {Receipt, ThemeType} from './types'
import './App.css'
@ -54,27 +46,15 @@ const App = () => {
const loadClient = async () => {
await client.onload()
setClientInstance(client)
client.on(
'solidity',
'compilationFinished',
(
fileName: string,
source: CompilationFileSources,
languageVersion: string,
data: CompilationResult
) => {
const newContractsNames = getNewContractNames(data)
const newContractsToSave: string[] = [
...contractsRef.current,
...newContractsNames
]
const uniqueContracts: string[] = [...new Set(newContractsToSave)]
setContracts(uniqueContracts)
}
)
client.on('solidity', 'compilationFinished', (fileName: string, source: CompilationFileSources, languageVersion: string, data: CompilationResult) => {
const newContractsNames = getNewContractNames(data)
const newContractsToSave: string[] = [...contractsRef.current, ...newContractsNames]
const uniqueContracts: string[] = [...new Set(newContractsToSave)]
setContracts(uniqueContracts)
})
//const currentTheme = await client.call("theme", "currentTheme")
//setThemeType(currentTheme.quality)
@ -88,10 +68,7 @@ const App = () => {
useEffect(() => {
let receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => {
return (
item.status === 'Pending in queue' ||
item.status === 'Max rate limit reached'
)
return item.status === 'Pending in queue' || item.status === 'Max rate limit reached'
})
if (receiptsNotVerified.length > 0) {
@ -100,9 +77,7 @@ const App = () => {
timer.current = null
}
timer.current = setInterval(async () => {
const {network, networkId} = await getNetworkName(
clientInstanceRef.current
)
const {network, networkId} = await getNetworkName(clientInstanceRef.current)
if (!clientInstanceRef.current) {
return
}
@ -115,26 +90,13 @@ const App = () => {
await new Promise((r) => setTimeout(r, 500)) // avoid api rate limit exceed.
let status
if (item.isProxyContract) {
status = await getProxyContractReceiptStatus(
item.guid,
apiKey,
getEtherScanApi(networkId)
)
status = await getProxyContractReceiptStatus(item.guid, apiKey, getEtherScanApi(networkId))
if (status.status === '1') {
status.message = status.result
status.result = 'Successfully Updated'
}
} else
status = await getReceiptStatus(
item.guid,
apiKey,
getEtherScanApi(networkId)
)
if (
status.result === 'Pass - Verified' ||
status.result === 'Already Verified' ||
status.result === 'Successfully Updated'
) {
} else status = await getReceiptStatus(item.guid, apiKey, getEtherScanApi(networkId))
if (status.result === 'Pass - Verified' || status.result === 'Already Verified' || status.result === 'Successfully Updated') {
newReceipts = newReceipts.map((currentReceipt: Receipt) => {
if (currentReceipt.guid === item.guid) {
const res = {
@ -149,10 +111,7 @@ const App = () => {
}
}
receiptsNotVerified = newReceipts.filter((item: Receipt) => {
return (
item.status === 'Pending in queue' ||
item.status === 'Max rate limit reached'
)
return item.status === 'Pending in queue' || item.status === 'Max rate limit reached'
})
if (timer.current && receiptsNotVerified.length === 0) {
clearInterval(timer.current)

@ -20,23 +20,11 @@ const HomeIcon: React.FC<IconProps> = ({from}: IconProps) => {
to={{
pathname: '/'
}}
className={({isActive}) =>
isActive
? 'border border-secondary shadow-none btn p-1 m-0'
: 'border-0 shadow-none btn p-1 m-0'
}
style={({isActive}) =>
!isActive
? {width: '1.8rem', filter: 'contrast(0.5)'}
: {width: '1.8rem'}
}
className={({isActive}) => (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')}
style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})}
state={from}
>
<CustomTooltip
tooltipText="Home"
tooltipId="etherscan-nav-home"
placement="bottom"
>
<CustomTooltip tooltipText="Home" tooltipId="etherscan-nav-home" placement="bottom">
<i className="fas fa-home"></i>
</CustomTooltip>
</NavLink>
@ -50,23 +38,11 @@ const ReceiptsIcon: React.FC<IconProps> = ({from}: IconProps) => {
to={{
pathname: '/receipts'
}}
className={({isActive}) =>
isActive
? 'border border-secondary shadow-none btn p-1 m-0'
: 'border-0 shadow-none btn p-1 m-0'
}
style={({isActive}) =>
!isActive
? {width: '1.8rem', filter: 'contrast(0.5)'}
: {width: '1.8rem'}
}
className={({isActive}) => (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')}
style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})}
state={from}
>
<CustomTooltip
tooltipText="Receipts"
tooltipId="etherscan-nav-receipts"
placement="bottom"
>
<CustomTooltip tooltipText="Receipts" tooltipId="etherscan-nav-receipts" placement="bottom">
<i className="fas fa-receipt"></i>
</CustomTooltip>
</NavLink>
@ -80,23 +56,11 @@ const SettingsIcon: React.FC<IconProps> = ({from}: IconProps) => {
to={{
pathname: '/settings'
}}
className={({isActive}) =>
isActive
? 'border border-secondary shadow-none btn p-1 m-0'
: 'border-0 shadow-none btn p-1 m-0'
}
style={({isActive}) =>
!isActive
? {width: '1.8rem', filter: 'contrast(0.5)'}
: {width: '1.8rem'}
}
className={({isActive}) => (isActive ? 'border border-secondary shadow-none btn p-1 m-0' : 'border-0 shadow-none btn p-1 m-0')}
style={({isActive}) => (!isActive ? {width: '1.8rem', filter: 'contrast(0.5)'} : {width: '1.8rem'})}
state={from}
>
<CustomTooltip
tooltipText="Settings"
tooltipId="etherscan-nav-settings"
placement="bottom"
>
<CustomTooltip tooltipText="Settings" tooltipId="etherscan-nav-settings" placement="bottom">
<i className="fas fa-cog"></i>
</CustomTooltip>
</NavLink>

@ -8,26 +8,12 @@ interface Props {
disable?: boolean
}
export const SubmitButton: React.FC<Props> = ({
text,
dataId,
isSubmitting = false,
disable = true
}) => {
export const SubmitButton: React.FC<Props> = ({text, dataId, isSubmitting = false, disable = true}) => {
return (
<div>
<button
data-id={dataId}
type="submit"
className="btn btn-primary btn-block p-1 text-decoration-none"
disabled={disable}
>
<button data-id={dataId} type="submit" className="btn btn-primary btn-block p-1 text-decoration-none" disabled={disable}>
<CustomTooltip
tooltipText={
disable
? 'Fill in the valid value(s) and select a supported network'
: 'Click to proceed'
}
tooltipText={disable ? 'Fill in the valid value(s) and select a supported network' : 'Click to proceed'}
tooltipId={'etherscan-submit-button-' + dataId}
tooltipTextClasses="border bg-light text-dark p-1 pr-3"
placement="bottom"
@ -36,11 +22,7 @@ export const SubmitButton: React.FC<Props> = ({
{!isSubmitting && text}
{isSubmitting && (
<div>
<span
className="spinner-border spinner-border-sm mr-1"
role="status"
aria-hidden="true"
/>
<span className="spinner-border spinner-border-sm mr-1" role="status" aria-hidden="true" />
Verifying... Please wait
</div>
)}

@ -21,8 +21,7 @@ export function useLocalStorage(key: string, initialValue: any) {
const setValue = (value: any) => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value
const valueToStore = value instanceof Function ? value(storedValue) : value
// Save state
setStoredValue(valueToStore)
// Save to local storage

@ -7,11 +7,7 @@ interface Props {
title?: string
}
export const DefaultLayout: React.FC<PropsWithChildren<Props>> = ({
children,
from,
title
}) => {
export const DefaultLayout: React.FC<PropsWithChildren<Props>> = ({children, from, title}) => {
return (
<div>
<HeaderWithSettings from={from} title={title} />

@ -40,39 +40,22 @@ export const CaptureKeyView: React.FC = () => {
<div className="form-group mb-2">
<label htmlFor="apikey">API Key</label>
<Field
className={
errors.apiKey && touched.apiKey
? 'form-control form-control-sm is-invalid'
: 'form-control form-control-sm'
}
className={errors.apiKey && touched.apiKey ? 'form-control form-control-sm is-invalid' : 'form-control form-control-sm'}
type="password"
name="apiKey"
placeholder="e.g. GM1T20XY6JGSAPWKDCYZ7B2FJXKTJRFVGZ"
/>
<ErrorMessage
className="invalid-feedback"
name="apiKey"
component="div"
/>
<ErrorMessage className="invalid-feedback" name="apiKey" component="div" />
</div>
<div>
<SubmitButton
text="Save"
dataId="save-api-key"
disable={errors && errors.apiKey ? true : false}
/>
<SubmitButton text="Save" dataId="save-api-key" disable={errors && errors.apiKey ? true : false} />
</div>
</form>
)}
</Formik>
<div
data-id="api-key-result"
className="text-primary mt-4 text-center"
style={{fontSize: '0.8em'}}
dangerouslySetInnerHTML={{__html: msg}}
/>
<div data-id="api-key-result" className="text-primary mt-4 text-center" style={{fontSize: '0.8em'}} dangerouslySetInnerHTML={{__html: msg}} />
</div>
)
}}

@ -3,19 +3,11 @@ import React from 'react'
export const ErrorView: React.FC = () => {
return (
<div className="d-flex w-100 flex-column align-items-center">
<img
className="pb-4"
width="250"
src="https://res.cloudinary.com/key-solutions/image/upload/v1580400635/solid/error-png.png"
alt="Error page"
/>
<img className="pb-4" width="250" src="https://res.cloudinary.com/key-solutions/image/upload/v1580400635/solid/error-png.png" alt="Error page" />
<h5>Sorry, something unexpected happened.</h5>
<h5>
Please raise an issue:{' '}
<a
className="text-danger"
href="https://github.com/ethereum/remix-project/issues"
>
<a className="text-danger" href="https://github.com/ethereum/remix-project/issues">
Here
</a>
</h5>

@ -1,12 +1,7 @@
import React, {useState} from 'react'
import {Formik, ErrorMessage, Field} from 'formik'
import {
getEtherScanApi,
getNetworkName,
getReceiptStatus,
getProxyContractReceiptStatus
} from '../utils'
import {getEtherScanApi, getNetworkName, getReceiptStatus, getProxyContractReceiptStatus} from '../utils'
import {Receipt} from '../types'
import {AppContext} from '../AppContext'
import {SubmitButton} from '../components'
@ -22,11 +17,7 @@ export const ReceiptsView: React.FC = () => {
const [results, setResults] = useState({succeed: false, message: ''})
const [isProxyContractReceipt, setIsProxyContractReceipt] = useState(false)
const onGetReceiptStatus = async (
values: FormValues,
clientInstance: any,
apiKey: string
) => {
const onGetReceiptStatus = async (values: FormValues, clientInstance: any, apiKey: string) => {
try {
const {network, networkId} = await getNetworkName(clientInstance)
if (network === 'vm') {
@ -39,26 +30,15 @@ export const ReceiptsView: React.FC = () => {
const etherscanApi = getEtherScanApi(networkId)
let result
if (isProxyContractReceipt) {
result = await getProxyContractReceiptStatus(
values.receiptGuid,
apiKey,
etherscanApi
)
result = await getProxyContractReceiptStatus(values.receiptGuid, apiKey, etherscanApi)
if (result.status === '1') {
result.message = result.result
result.result = 'Successfully Updated'
}
} else
result = await getReceiptStatus(
values.receiptGuid,
apiKey,
etherscanApi
)
} else result = await getReceiptStatus(values.receiptGuid, apiKey, etherscanApi)
setResults({
succeed: result.status === '1' ? true : false,
message:
result.result ||
(result.status === '0' ? 'Verification failed' : result.message)
message: result.result || (result.status === '0' ? 'Verification failed' : result.message)
})
} catch (error: any) {
setResults({
@ -88,28 +68,18 @@ export const ReceiptsView: React.FC = () => {
}
return errors
}}
onSubmit={(values) =>
onGetReceiptStatus(values, clientInstance, apiKey)
}
onSubmit={(values) => onGetReceiptStatus(values, clientInstance, apiKey)}
>
{({errors, touched, handleSubmit, handleChange}) => (
<form onSubmit={handleSubmit}>
<div className="form-group mb-2">
<label htmlFor="receiptGuid">Receipt GUID</label>
<Field
className={
errors.receiptGuid && touched.receiptGuid
? 'form-control form-control-sm is-invalid'
: 'form-control form-control-sm'
}
className={errors.receiptGuid && touched.receiptGuid ? 'form-control form-control-sm is-invalid' : 'form-control form-control-sm'}
type="text"
name="receiptGuid"
/>
<ErrorMessage
className="invalid-feedback"
name="receiptGuid"
component="div"
/>
<ErrorMessage className="invalid-feedback" name="receiptGuid" component="div" />
</div>
<div className="d-flex mb-2 custom-control custom-checkbox">
@ -124,32 +94,17 @@ export const ReceiptsView: React.FC = () => {
else setIsProxyContractReceipt(false)
}}
/>
<label
className="form-check-label custom-control-label"
htmlFor="isProxyReceipt"
>
<label className="form-check-label custom-control-label" htmlFor="isProxyReceipt">
It's a proxy contract GUID
</label>
</div>
<SubmitButton
text="Check"
disable={
!touched.receiptGuid ||
(touched.receiptGuid && errors.receiptGuid)
? true
: false
}
/>
<SubmitButton text="Check" disable={!touched.receiptGuid || (touched.receiptGuid && errors.receiptGuid) ? true : false} />
</form>
)}
</Formik>
<div
className={
results['succeed']
? 'text-success mt-3 text-center'
: 'text-danger mt-3 text-center'
}
className={results['succeed'] ? 'text-success mt-3 text-center' : 'text-danger mt-3 text-center'}
dangerouslySetInnerHTML={{
__html: results.message ? results.message : ''
}}
@ -157,11 +112,7 @@ export const ReceiptsView: React.FC = () => {
<ReceiptsTable receipts={receipts} />
<br />
<CustomTooltip
tooltipText="Clear the list of receipts"
tooltipId="etherscan-clear-receipts"
placement="bottom"
>
<CustomTooltip tooltipText="Clear the list of receipts" tooltipId="etherscan-clear-receipts" placement="bottom">
<Button
className="btn-sm"
onClick={() => {
@ -197,8 +148,7 @@ const ReceiptsTable: React.FC<{receipts: Receipt[]}> = ({receipts}) => {
<tr key={item.guid}>
<td
className={
item.status === 'Pass - Verified' ||
item.status === 'Successfully Updated'
item.status === 'Pass - Verified' || item.status === 'Successfully Updated'
? 'text-success'
: item.status === 'Pending in queue'
? 'text-warning'
@ -209,19 +159,8 @@ const ReceiptsTable: React.FC<{receipts: Receipt[]}> = ({receipts}) => {
>
{item.status}
{item.status === 'Successfully Updated' && (
<CustomTooltip
placement={'bottom'}
tooltipClasses="text-wrap"
tooltipId="etherscan-receipt-proxy-status"
tooltipText={item.message}
>
<i
style={{fontSize: 'small'}}
className={
'ml-1 fal fa-info-circle align-self-center'
}
aria-hidden="true"
></i>
<CustomTooltip placement={'bottom'} tooltipClasses="text-wrap" tooltipId="etherscan-receipt-proxy-status" tooltipText={item.message}>
<i style={{fontSize: 'small'}} className={'ml-1 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
</CustomTooltip>
)}
</td>

@ -23,12 +23,7 @@ interface FormValues {
expectedImplAddress?: string
}
export const VerifyView: React.FC<Props> = ({
apiKey,
client,
contracts,
onVerifiedContract
}) => {
export const VerifyView: React.FC<Props> = ({apiKey, client, contracts, onVerifiedContract}) => {
const [results, setResults] = useState('')
const [networkName, setNetworkName] = useState('Loading...')
const [selectedContract, setSelectedContract] = useState('')
@ -40,13 +35,7 @@ export const VerifyView: React.FC<Props> = ({
useEffect(() => {
if (client && client.on) {
client.on('blockchain' as any, 'networkStatus', (result) => {
setNetworkName(
`${result.network.name} ${
result.network.id !== '-'
? `(Chain id: ${result.network.id})`
: '(Not supported)'
}`
)
setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`)
})
}
return () => {
@ -60,36 +49,20 @@ export const VerifyView: React.FC<Props> = ({
}, [contracts])
const updateConsFields = (contractName) => {
client
.call(
'compilerArtefacts' as any,
'getArtefactsByContractName',
contractName
)
.then((result) => {
const {artefact} = result
if (
artefact &&
artefact.abi &&
artefact.abi[0] &&
artefact.abi[0].type &&
artefact.abi[0].type === 'constructor' &&
artefact.abi[0].inputs.length > 0
) {
setConstructorInputs(artefact.abi[0].inputs)
setShowConstructorArgs(true)
} else {
setConstructorInputs([])
setShowConstructorArgs(false)
}
})
client.call('compilerArtefacts' as any, 'getArtefactsByContractName', contractName).then((result) => {
const {artefact} = result
if (artefact && artefact.abi && artefact.abi[0] && artefact.abi[0].type && artefact.abi[0].type === 'constructor' && artefact.abi[0].inputs.length > 0) {
setConstructorInputs(artefact.abi[0].inputs)
setShowConstructorArgs(true)
} else {
setConstructorInputs([])
setShowConstructorArgs(false)
}
})
}
const onVerifyContract = async (values: FormValues) => {
const compilationResult = (await client.call(
'solidity',
'getCompilationResult'
)) as any
const compilationResult = (await client.call('solidity', 'getCompilationResult')) as any
if (!compilationResult) {
throw new Error('no compilation result available')
@ -97,15 +70,11 @@ export const VerifyView: React.FC<Props> = ({
const constructorValues = []
for (const key in values) {
if (key.startsWith('contractArgValue'))
constructorValues.push(values[key])
if (key.startsWith('contractArgValue')) constructorValues.push(values[key])
}
const web3 = new Web3()
const constructorTypes = constructorInputs.map((e) => e.type)
let contractArguments = web3.eth.abi.encodeParameters(
constructorTypes,
constructorValues
)
let contractArguments = web3.eth.abi.encodeParameters(constructorTypes, constructorValues)
contractArguments = contractArguments.replace('0x', '')
verificationResult.current = await verify(
@ -139,11 +108,7 @@ export const VerifyView: React.FC<Props> = ({
if (!values.contractAddress) {
errors.contractAddress = 'Required'
}
if (
values.contractAddress.trim() === '' ||
!values.contractAddress.startsWith('0x') ||
values.contractAddress.length !== 42
) {
if (values.contractAddress.trim() === '' || !values.contractAddress.startsWith('0x') || values.contractAddress.length !== 42) {
errors.contractAddress = 'Please enter a valid contract address'
}
return errors
@ -160,26 +125,14 @@ export const VerifyView: React.FC<Props> = ({
tooltipId="etherscan-impl-address2"
placement="bottom"
>
<Field
className="form-control"
type="text"
name="network"
value={networkName}
disabled={true}
/>
<Field className="form-control" type="text" name="network" value={networkName} disabled={true} />
</CustomTooltip>
</div>
<div className="form-group">
<label htmlFor="contractName">Contract Name</label>
<Field
as="select"
className={
errors.contractName &&
touched.contractName &&
contracts.length
? 'form-control is-invalid'
: 'form-control'
}
className={errors.contractName && touched.contractName && contracts.length ? 'form-control is-invalid' : 'form-control'}
name="contractName"
onChange={async (e) => {
handleChange(e)
@ -188,9 +141,7 @@ export const VerifyView: React.FC<Props> = ({
}}
>
<option disabled={true} value="">
{contracts.length
? 'Select a contract'
: `--- No compiled contracts ---`}
{contracts.length ? 'Select a contract' : `--- No compiled contracts ---`}
</option>
{contracts.map((item) => (
<option key={item} value={item}>
@ -198,43 +149,16 @@ export const VerifyView: React.FC<Props> = ({
</option>
))}
</Field>
<ErrorMessage
className="invalid-feedback"
name="contractName"
component="div"
/>
<ErrorMessage className="invalid-feedback" name="contractName" component="div" />
</div>
<div
className={
showConstructorArgs
? 'form-group d-block'
: 'form-group d-none'
}
>
<div className={showConstructorArgs ? 'form-group d-block' : 'form-group d-none'}>
<label>Constructor Arguments</label>
{constructorInputs.map((item, index) => {
return (
<div className="d-flex">
<Field
className="form-control m-1"
type="text"
key={`contractArgName${index}`}
name={`contractArgName${index}`}
value={item.name}
disabled={true}
/>
<CustomTooltip
tooltipText={`value of ${item.name}`}
tooltipId={`etherscan-constructor-value${index}`}
placement="top"
>
<Field
className="form-control m-1"
type="text"
key={`contractArgValue${index}`}
name={`contractArgValue${index}`}
placeholder={item.type}
/>
<Field className="form-control m-1" type="text" key={`contractArgName${index}`} name={`contractArgName${index}`} value={item.name} disabled={true} />
<CustomTooltip tooltipText={`value of ${item.name}`} tooltipId={`etherscan-constructor-value${index}`} placement="top">
<Field className="form-control m-1" type="text" key={`contractArgValue${index}`} name={`contractArgValue${index}`} placeholder={item.type} />
</CustomTooltip>
</div>
)
@ -243,20 +167,12 @@ export const VerifyView: React.FC<Props> = ({
<div className="form-group">
<label htmlFor="contractAddress">Contract Address</label>
<Field
className={
errors.contractAddress && touched.contractAddress
? 'form-control is-invalid'
: 'form-control'
}
className={errors.contractAddress && touched.contractAddress ? 'form-control is-invalid' : 'form-control'}
type="text"
name="contractAddress"
placeholder="e.g. 0x11b79afc03baf25c631dd70169bb6a3160b2706e"
/>
<ErrorMessage
className="invalid-feedback"
name="contractAddress"
component="div"
/>
<ErrorMessage className="invalid-feedback" name="contractAddress" component="div" />
<div className="d-flex mb-2 custom-control custom-checkbox">
<Field
className="custom-control-input"
@ -269,43 +185,22 @@ export const VerifyView: React.FC<Props> = ({
else setIsProxyContract(false)
}}
/>
<label
className="form-check-label custom-control-label"
htmlFor="isProxy"
>
<label className="form-check-label custom-control-label" htmlFor="isProxy">
It's a proxy contract address
</label>
</div>
</div>
<div
className={
isProxyContract ? 'form-group d-block' : 'form-group d-none'
}
>
<label htmlFor="expectedImplAddress">
Expected Implementation Address
</label>
<div className={isProxyContract ? 'form-group d-block' : 'form-group d-none'}>
<label htmlFor="expectedImplAddress">Expected Implementation Address</label>
<CustomTooltip
tooltipText="Providing expected implementation address enforces a check to ensure the returned implementation contract address is same as address picked up by the verifier"
tooltipId="etherscan-impl-address"
placement="bottom"
>
<Field
className="form-control"
type="text"
name="expectedImplAddress"
placeholder="verified implementation contract address"
/>
<Field className="form-control" type="text" name="expectedImplAddress" placeholder="verified implementation contract address" />
</CustomTooltip>
<i
style={{fontSize: 'x-small'}}
className={'ml-1 fal fa-info-circle align-self-center'}
aria-hidden="true"
></i>
<label>
{' '}
&nbsp;Make sure contract is already verified on Etherscan
</label>
<i style={{fontSize: 'x-small'}} className={'ml-1 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
<label> &nbsp;Make sure contract is already verified on Etherscan</label>
</div>
<SubmitButton
dataId="verify-contract"
@ -323,11 +218,7 @@ export const VerifyView: React.FC<Props> = ({
}
/>
<br />
<CustomTooltip
tooltipText="Generate the required TS scripts to verify a contract on Etherscan"
tooltipId="etherscan-generate-scripts"
placement="bottom"
>
<CustomTooltip tooltipText="Generate the required TS scripts to verify a contract on Etherscan" tooltipId="etherscan-generate-scripts" placement="bottom">
<button
type="button"
className="mr-2 mb-2 py-1 px-2 btn btn-secondary btn-block"
@ -344,11 +235,7 @@ export const VerifyView: React.FC<Props> = ({
</Formik>
<div
data-id="verify-result"
className={
verificationResult.current['succeed']
? 'text-success mt-4 text-center'
: 'text-danger mt-4 text-center'
}
className={verificationResult.current['succeed'] ? 'text-success mt-4 text-center' : 'text-danger mt-4 text-center'}
style={{fontSize: '0.8em'}}
dangerouslySetInnerHTML={{__html: results}}
/>

@ -20,10 +20,7 @@ module.exports = {
on_failure: true,
on_error: true
},
exclude: [
'dist/apps/remix-ide-e2e/src/tests/runAndDeploy.test.js',
'dist/apps/remix-ide-e2e/src/tests/pluginManager.test.ts'
]
exclude: ['dist/apps/remix-ide-e2e/src/tests/runAndDeploy.test.js', 'dist/apps/remix-ide-e2e/src/tests/pluginManager.test.ts']
},
'chrome': {
@ -61,13 +58,7 @@ module.exports = {
'javascriptEnabled': true,
'acceptSslCerts': true,
'goog:chromeOptions': {
args: [
'window-size=2560,1440',
'start-fullscreen',
'--no-sandbox',
'--headless',
'--verbose'
]
args: ['window-size=2560,1440', 'start-fullscreen', '--no-sandbox', '--headless', '--verbose']
}
}
},

@ -43,13 +43,7 @@ function App() {
useEffect(() => {
client.onload(async () => {
const customProfiles = [
'menuicons',
'tabs',
'solidityUnitTesting',
'hardhat-provider',
'notification'
]
const customProfiles = ['menuicons', 'tabs', 'solidityUnitTesting', 'hardhat-provider', 'notification']
client.testCommand = async (data: any) => {
console.log(data)
@ -122,24 +116,11 @@ function App() {
<Logger id="methods" log={log}></Logger>
<label>events</label>
<Logger id="events" log={events}></Logger>
<input
className="form-control w-100"
type="text"
id="payload"
placeholder="Enter payload here..."
value={payload}
onChange={handleChange}
data-id="payload-input"
/>
<input className="form-control w-100" type="text" id="payload" placeholder="Enter payload here..." value={payload} onChange={handleChange} data-id="payload-input" />
{profiles.map((profile: Profile) => {
const methods = profile.methods.map((method: string) => {
return (
<button
data-id={`${profile.name}:${method}`}
key={method}
className="btn btn-primary btn-sm ml-1 mb-1"
onClick={async () => await clientMethod(profile, method)}
>
<button data-id={`${profile.name}:${method}`} key={method} className="btn btn-primary btn-sm ml-1 mb-1" onClick={async () => await clientMethod(profile, method)}>
{method}
</button>
)

@ -4,10 +4,7 @@
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.storage.sync.set({'chrome-app-sync': true})
chrome.tabs.create(
{url: chrome.extension.getURL('index.html')},
function (tab) {
// tab opened
}
)
chrome.tabs.create({url: chrome.extension.getURL('index.html')}, function (tab) {
// tab opened
})
})

@ -60,10 +60,7 @@ export class MainPanel extends AbstractPanel {
render() {
return (
<div
style={{height: '100%', width: '100%'}}
data-id="mainPanelPluginsContainer"
>
<div style={{height: '100%', width: '100%'}} data-id="mainPanelPluginsContainer">
<PluginViewWrapper plugin={this} />
</div>
)

@ -5,10 +5,7 @@ import * as packageJson from '../../../../../package.json'
import {fileSystem, fileSystems} from '../files/fileSystem'
import {indexedDBFileSystem} from '../files/filesystems/indexedDB'
import {localStorageFS} from '../files/filesystems/localStorage'
import {
fileSystemUtility,
migrationTestData
} from '../files/filesystems/fileSystemUtility'
import {fileSystemUtility, migrationTestData} from '../files/filesystems/fileSystemUtility'
import './styles/preload.css'
const _paq = (window._paq = window._paq || [])
@ -21,19 +18,13 @@ export const Preload = () => {
const localStorageFileSystem = useRef<fileSystem>(new localStorageFS())
// url parameters to e2e test the fallbacks and error warnings
const testmigrationFallback = useRef<boolean>(
window.location.hash.includes('e2e_testmigration_fallback=true') &&
window.location.host === '127.0.0.1:8080' &&
window.location.protocol === 'http:'
window.location.hash.includes('e2e_testmigration_fallback=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
)
const testmigrationResult = useRef<boolean>(
window.location.hash.includes('e2e_testmigration=true') &&
window.location.host === '127.0.0.1:8080' &&
window.location.protocol === 'http:'
window.location.hash.includes('e2e_testmigration=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
)
const testBlockStorage = useRef<boolean>(
window.location.hash.includes('e2e_testblock_storage=true') &&
window.location.host === '127.0.0.1:8080' &&
window.location.protocol === 'http:'
window.location.hash.includes('e2e_testblock_storage=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
)
function loadAppComponent() {
@ -59,33 +50,21 @@ export const Preload = () => {
const downloadBackup = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
await fsUtility.downloadBackup(
remixFileSystems.current.fileSystems['localstorage']
)
await fsUtility.downloadBackup(remixFileSystems.current.fileSystems['localstorage'])
await migrateAndLoad()
}
const migrateAndLoad = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
const migrationResult = await fsUtility.migrate(
localStorageFileSystem.current,
remixIndexedDB.current
)
_paq.push([
'trackEvent',
'Migrate',
'result',
migrationResult ? 'success' : 'fail'
])
const migrationResult = await fsUtility.migrate(localStorageFileSystem.current, remixIndexedDB.current)
_paq.push(['trackEvent', 'Migrate', 'result', migrationResult ? 'success' : 'fail'])
await setFileSystems()
}
const setFileSystems = async () => {
const fsLoaded = await remixFileSystems.current.setFileSystem([
testmigrationFallback.current || testBlockStorage.current
? null
: remixIndexedDB.current,
testmigrationFallback.current || testBlockStorage.current ? null : remixIndexedDB.current,
testBlockStorage.current ? null : localStorageFileSystem.current
])
if (fsLoaded) {
@ -101,36 +80,18 @@ export const Preload = () => {
const testmigration = async () => {
if (testmigrationResult.current) {
const fsUtility = new fileSystemUtility()
fsUtility.populateWorkspace(
migrationTestData,
remixFileSystems.current.fileSystems['localstorage'].fs
)
fsUtility.populateWorkspace(migrationTestData, remixFileSystems.current.fileSystems['localstorage'].fs)
}
}
useEffect(() => {
async function loadStorage() {
;(await remixFileSystems.current.addFileSystem(remixIndexedDB.current)) ||
_paq.push(['trackEvent', 'Storage', 'error', 'indexedDB not supported'])
;(await remixFileSystems.current.addFileSystem(
localStorageFileSystem.current
)) ||
_paq.push([
'trackEvent',
'Storage',
'error',
'localstorage not supported'
])
;(await remixFileSystems.current.addFileSystem(remixIndexedDB.current)) || _paq.push(['trackEvent', 'Storage', 'error', 'indexedDB not supported'])
;(await remixFileSystems.current.addFileSystem(localStorageFileSystem.current)) || _paq.push(['trackEvent', 'Storage', 'error', 'localstorage not supported'])
await testmigration()
remixIndexedDB.current.loaded &&
(await remixIndexedDB.current.checkWorkspaces())
localStorageFileSystem.current.loaded &&
(await localStorageFileSystem.current.checkWorkspaces())
remixIndexedDB.current.loaded &&
(remixIndexedDB.current.hasWorkSpaces ||
!localStorageFileSystem.current.hasWorkSpaces
? await setFileSystems()
: setShowDownloader(true))
remixIndexedDB.current.loaded && (await remixIndexedDB.current.checkWorkspaces())
localStorageFileSystem.current.loaded && (await localStorageFileSystem.current.checkWorkspaces())
remixIndexedDB.current.loaded && (remixIndexedDB.current.hasWorkSpaces || !localStorageFileSystem.current.hasWorkSpaces ? await setFileSystems() : setShowDownloader(true))
!remixIndexedDB.current.loaded && (await setFileSystems())
}
loadStorage()
@ -149,9 +110,7 @@ export const Preload = () => {
</div>
{!supported ? (
<div className="preload-info-container alert alert-warning">
Your browser does not support any of the filesystems required by
Remix. Either change the settings in your browser or use a supported
browser.
Your browser does not support any of the filesystems required by Remix. Either change the settings in your browser or use a supported browser.
</div>
) : null}
{error ? (
@ -164,8 +123,7 @@ export const Preload = () => {
<br></br>- Firefox: CTRL + SHIFT + R or CTRL + F5<br></br>
</div>
<div className="pt-2">
MacOS:<br></br>- Chrome & FireFox: CMD + SHIFT + R or SHIFT +
Reload Button<br></br>
MacOS:<br></br>- Chrome & FireFox: CMD + SHIFT + R or SHIFT + Reload Button<br></br>
</div>
<div className="pt-2">
Linux:<br></br>- Chrome & FireFox: CTRL + SHIFT + R<br></br>
@ -174,11 +132,9 @@ export const Preload = () => {
) : null}
{showDownloader ? (
<div className="preload-info-container alert alert-info">
This app will be updated now. Please download a backup of your files
now to make sure you don't lose your work.
This app will be updated now. Please download a backup of your files now to make sure you don't lose your work.
<br></br>
You don't need to do anything else, your files will be available
when the app loads.
You don't need to do anything else, your files will be available when the app loads.
<div
onClick={async () => {
await downloadBackup()
@ -210,12 +166,7 @@ export const Preload = () => {
}
const logo = (
<svg
id="Ebene_2"
data-name="Ebene 2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 105 100"
>
<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100">
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z" />
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z" />
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z" />

@ -56,8 +56,7 @@ export class SidePanel extends AbstractPanel {
}
removeView(profile) {
if (this.plugins[profile.name].active)
this.call('menuicons', 'select', 'filePanel')
if (this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
super.removeView(profile)
this.emit('pluginDisabled', profile.name)
this.call('menuicons', 'unlinkContent', profile)
@ -94,14 +93,7 @@ export class SidePanel extends AbstractPanel {
}
updateComponent(state: any) {
return (
<RemixPluginPanel
header={
<RemixUIPanelHeader plugins={state.plugins}></RemixUIPanelHeader>
}
plugins={state.plugins}
/>
)
return <RemixPluginPanel header={<RemixUIPanelHeader plugins={state.plugins}></RemixUIPanelHeader>} plugins={state.plugins} />
}
renderComponent() {

@ -3,10 +3,7 @@ import React from 'react'
import packageJson from '../../../../../package.json'
import {Plugin} from '@remixproject/engine'
import {EventEmitter} from 'events'
import {
IconRecord,
RemixUiVerticalIconsPanel
} from '@remix-ui/vertical-icons-panel'
import {IconRecord, RemixUiVerticalIconsPanel} from '@remix-ui/vertical-icons-panel'
import {Profile} from '@remixproject/plugin-utils'
import {PluginViewWrapper} from '@remix-ui/helper'
@ -32,16 +29,7 @@ export class VerticalIcons extends Plugin {
}
renderComponent() {
const fixedOrder = [
'filePanel',
'search',
'solidity',
'udapp',
'debugger',
'solidityStaticAnalysis',
'solidityUnitTesting',
'pluginManager'
]
const fixedOrder = ['filePanel', 'search', 'solidity', 'udapp', 'debugger', 'solidityStaticAnalysis', 'solidityUnitTesting', 'pluginManager']
const divived = Object.values(this.icons)
.map((value) => {
@ -57,10 +45,7 @@ export class VerticalIcons extends Plugin {
const required = divived
.filter((value) => value.isRequired)
.sort((a, b) => {
return (
fixedOrder.indexOf(a.profile.name) -
fixedOrder.indexOf(b.profile.name)
)
return fixedOrder.indexOf(a.profile.name) - fixedOrder.indexOf(b.profile.name)
})
const sorted: IconRecord[] = [
@ -97,12 +82,7 @@ export class VerticalIcons extends Plugin {
this.icons[profile.name] = {
profile: profile,
active: false,
canbeDeactivated: await this.call(
'manager',
'canDeactivate',
this.profile,
profile
),
canbeDeactivated: await this.call('manager', 'canDeactivate', this.profile, profile),
timestamp: Date.now()
}
this.renderComponent()
@ -139,12 +119,7 @@ export class VerticalIcons extends Plugin {
}
updateComponent(state: any) {
return (
<RemixUiVerticalIconsPanel
verticalIconsPlugin={state.verticalIconsPlugin}
icons={state.icons}
/>
)
return <RemixUiVerticalIconsPanel verticalIconsPlugin={state.verticalIconsPlugin} icons={state.icons} />
}
render() {

@ -1,11 +1,7 @@
import React from 'react'
import {Plugin} from '@remixproject/engine'
import {customAction} from '@remixproject/plugin-api'
import {
concatSourceFiles,
getDependencyGraph,
normalizeContractPath
} from '@remix-ui/solidity-compiler'
import {concatSourceFiles, getDependencyGraph, normalizeContractPath} from '@remix-ui/solidity-compiler'
const _paq = (window._paq = window._paq || [])
@ -25,18 +21,14 @@ export class ContractFlattener extends Plugin {
}
onActivation(): void {
this.on(
'solidity',
'compilationFinished',
async (file, source, languageVersion, data, input, version) => {
if (data.sources && Object.keys(data.sources).length > 1) {
if (this.triggerFlattenContract) {
this.triggerFlattenContract = false
await this.flattenContract(source, file, data)
}
this.on('solidity', 'compilationFinished', async (file, source, languageVersion, data, input, version) => {
if (data.sources && Object.keys(data.sources).length > 1) {
if (this.triggerFlattenContract) {
this.triggerFlattenContract = false
await this.flattenContract(source, file, data)
}
}
)
})
_paq.push(['trackEvent', 'plugin', 'activated', 'contractFlattener'])
}
@ -55,11 +47,7 @@ export class ContractFlattener extends Plugin {
* Takes the flattened result, writes it to a file and returns the result.
* @returns {Promise<string>}
*/
async flattenContract(
source: {sources: any; target: string},
filePath: string,
data: {contracts: any; sources: any}
): Promise<string> {
async flattenContract(source: {sources: any; target: string}, filePath: string, data: {contracts: any; sources: any}): Promise<string> {
const appendage = '_flattened.sol'
const normalized = normalizeContractPath(filePath)
const path = `${normalized[normalized.length - 2]}${appendage}`
@ -70,9 +58,7 @@ export class ContractFlattener extends Plugin {
let sources
try {
dependencyGraph = getDependencyGraph(ast, filePath)
sorted = dependencyGraph.isEmpty()
? [filePath]
: dependencyGraph.sort().reverse()
sorted = dependencyGraph.isEmpty() ? [filePath] : dependencyGraph.sort().reverse()
sources = source.sources
result = concatSourceFiles(sorted, sources)
} catch (err) {

@ -1,9 +1,5 @@
import {Plugin} from '@remixproject/engine'
import {
LibraryProfile,
MethodApi,
StatusEvents
} from '@remixproject/plugin-utils'
import {LibraryProfile, MethodApi, StatusEvents} from '@remixproject/plugin-utils'
import {AppModal} from '@remix-ui/app'
import {AlertModal} from '@remix-ui/app'
import {dispatchModalInterface} from '@remix-ui/app'
@ -24,10 +20,7 @@ const profile: LibraryProfile<INotificationApi> = {
methods: ['modal', 'alert', 'toast']
}
export class NotificationPlugin
extends Plugin
implements MethodApi<INotificationApi>
{
export class NotificationPlugin extends Plugin implements MethodApi<INotificationApi> {
dispatcher: dispatchModalInterface
constructor() {
super(profile)

@ -6,9 +6,7 @@ import {CompilationResult} from '@remix-project/remix-solidity'
import CodeParserGasService from './services/code-parser-gas-service'
import CodeParserCompiler from './services/code-parser-compiler'
import CodeParserAntlrService from './services/code-parser-antlr-service'
import CodeParserImports, {
CodeParserImportsData
} from './services/code-parser-imports'
import CodeParserImports, {CodeParserImportsData} from './services/code-parser-imports'
import React from 'react'
import {Profile} from '@remixproject/plugin-utils'
import {
@ -138,32 +136,15 @@ export class CodeParser extends Plugin {
}
async handleChangeEvents() {
const completionSettings = await this.call(
'config',
'getAppParameter',
'auto-completion'
)
const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion')
if (completionSettings) {
this.antlrService.enableWorker()
} else {
this.antlrService.disableWorker()
}
const showGasSettings = await this.call(
'config',
'getAppParameter',
'show-gas'
)
const showErrorSettings = await this.call(
'config',
'getAppParameter',
'display-errors'
)
if (
showGasSettings ||
showErrorSettings ||
completionSettings ||
this.debuggerIsOn
) {
const showGasSettings = await this.call('config', 'getAppParameter', 'show-gas')
const showErrorSettings = await this.call('config', 'getAppParameter', 'display-errors')
if (showGasSettings || showErrorSettings || completionSettings || this.debuggerIsOn) {
await this.compilerService.compile()
}
}
@ -175,15 +156,10 @@ export class CodeParser extends Plugin {
this.importService = new CodeParserImports(this)
this.parseSolidity = this.antlrService.parseSolidity.bind(this.antlrService)
this.getLastNodeInLine = this.antlrService.getLastNodeInLine.bind(
this.antlrService
)
this.getLastNodeInLine = this.antlrService.getLastNodeInLine.bind(this.antlrService)
this.listAstNodes = this.antlrService.listAstNodes.bind(this.antlrService)
this.getANTLRBlockAtPosition =
this.antlrService.getANTLRBlockAtPosition.bind(this.antlrService)
this.setCurrentFileAST = this.antlrService.setCurrentFileAST.bind(
this.antlrService
)
this.getANTLRBlockAtPosition = this.antlrService.getANTLRBlockAtPosition.bind(this.antlrService)
this.setCurrentFileAST = this.antlrService.setCurrentFileAST.bind(this.antlrService)
this.getImports = this.importService.getImports.bind(this.importService)
this.on('editor', 'didChangeFile', async (file) => {
@ -205,11 +181,7 @@ export class CodeParser extends Plugin {
this.on('fileManager', 'currentFileChanged', async () => {
await this.call('editor', 'discardLineTexts')
const completionSettings = await this.call(
'config',
'getAppParameter',
'auto-completion'
)
const completionSettings = await this.call('config', 'getAppParameter', 'auto-completion')
if (completionSettings) {
this.antlrService.setCurrentFileAST()
}
@ -271,11 +243,7 @@ export class CodeParser extends Plugin {
_buildIndex(compilationResult: CompilationResult, source) {
if (compilationResult && compilationResult.sources) {
const callback = (node: genericASTNode) => {
if (
node &&
'referencedDeclaration' in node &&
node.referencedDeclaration
) {
if (node && 'referencedDeclaration' in node && node.referencedDeclaration) {
if (!this.nodeIndex.declarations[node.referencedDeclaration]) {
this.nodeIndex.declarations[node.referencedDeclaration] = []
}
@ -305,32 +273,14 @@ export class CodeParser extends Plugin {
return '(' + params.toString() + ')'
}
_flatNodeList(
contractNode: ContractDefinitionAstNode,
fileName: string,
inScope: boolean,
compilatioResult: any
) {
_flatNodeList(contractNode: ContractDefinitionAstNode, fileName: string, inScope: boolean, compilatioResult: any) {
const index = {}
const contractName: string = contractNode.name
const callback = (node) => {
if (
inScope &&
node.scope !== contractNode.id &&
!(
node.nodeType === 'EnumDefinition' ||
node.nodeType === 'EventDefinition' ||
node.nodeType === 'ModifierDefinition'
)
)
if (inScope && node.scope !== contractNode.id && !(node.nodeType === 'EnumDefinition' || node.nodeType === 'EventDefinition' || node.nodeType === 'ModifierDefinition'))
return
if (inScope) node.isClassNode = true
node.gasEstimate = this._getContractGasEstimate(
node,
contractName,
fileName,
compilatioResult
)
node.gasEstimate = this._getContractGasEstimate(node, contractName, fileName, compilatioResult)
node.functionName = node.name + this._getInputParams(node)
node.contractName = contractName
node.contractId = contractNode.id
@ -340,33 +290,16 @@ export class CodeParser extends Plugin {
return index
}
_extractFileNodes(
fileName: string,
compilationResult: lastCompilationResult
) {
if (
compilationResult &&
compilationResult.data.sources &&
compilationResult.data.sources[fileName]
) {
_extractFileNodes(fileName: string, compilationResult: lastCompilationResult) {
if (compilationResult && compilationResult.data.sources && compilationResult.data.sources[fileName]) {
const source = compilationResult.data.sources[fileName]
const nodesByContract: any = {}
nodesByContract.imports = {}
nodesByContract.contracts = {}
this.astWalker.walkFull(source.ast, async (node) => {
if (node.nodeType === 'ContractDefinition') {
const flatNodes = this._flatNodeList(
node,
fileName,
false,
compilationResult
)
node.gasEstimate = this._getContractGasEstimate(
node,
node.name,
fileName,
compilationResult
)
const flatNodes = this._flatNodeList(node, fileName, false, compilationResult)
node.gasEstimate = this._getContractGasEstimate(node, node.name, fileName, compilationResult)
nodesByContract.contracts[node.name] = {
contractDefinition: node,
contractNodes: flatNodes
@ -382,11 +315,7 @@ export class CodeParser extends Plugin {
node.contractId = (baseContract as any).id
node.isBaseNode = true
baseNodes[node.id] = node
if (
(node.scope && node.scope === baseContract.id) ||
node.nodeType === 'EnumDefinition' ||
node.nodeType === 'EventDefinition'
) {
if ((node.scope && node.scope === baseContract.id) || node.nodeType === 'EnumDefinition' || node.nodeType === 'EventDefinition') {
baseNodesWithBaseContractScope[node.id] = node
}
if (node.members) {
@ -402,10 +331,8 @@ export class CodeParser extends Plugin {
}
}
nodesByContract.contracts[node.name].baseNodes = baseNodes
nodesByContract.contracts[node.name].baseNodesWithBaseContractScope =
baseNodesWithBaseContractScope
nodesByContract.contracts[node.name].contractScopeNodes =
this._flatNodeList(node, fileName, true, compilationResult)
nodesByContract.contracts[node.name].baseNodesWithBaseContractScope = baseNodesWithBaseContractScope
nodesByContract.contracts[node.name].contractScopeNodes = this._flatNodeList(node, fileName, true, compilationResult)
}
if (node.nodeType === 'ImportDirective') {
const imported = await this.resolveImports(node, {})
@ -422,15 +349,8 @@ export class CodeParser extends Plugin {
}
}
_getContractGasEstimate(
node: ContractDefinitionAstNode | FunctionDefinitionAstNode,
contractName: string,
fileName: string,
compilationResult: lastCompilationResult
) {
const contracts =
compilationResult.data.contracts &&
compilationResult.data.contracts[this.currentFile]
_getContractGasEstimate(node: ContractDefinitionAstNode | FunctionDefinitionAstNode, contractName: string, fileName: string, compilationResult: lastCompilationResult) {
const contracts = compilationResult.data.contracts && compilationResult.data.contracts[this.currentFile]
for (const name in contracts) {
if (name === contractName) {
const contract = contracts[name]
@ -444,21 +364,15 @@ export class CodeParser extends Plugin {
const fn = fnName + this._getInputParams(node)
if (visibility === 'public' || visibility === 'external') {
executionCost =
estimationObj === null ? '-' : estimationObj.external[fn]
executionCost = estimationObj === null ? '-' : estimationObj.external[fn]
} else if (visibility === 'private' || visibility === 'internal') {
executionCost =
estimationObj === null ? '-' : estimationObj.internal[fn]
executionCost = estimationObj === null ? '-' : estimationObj.internal[fn]
}
return {executionCost}
} else {
return {
creationCost:
estimationObj === null ? '-' : estimationObj.creation.totalCost,
codeDepositCost:
estimationObj === null
? '-'
: estimationObj.creation.codeDepositCost
creationCost: estimationObj === null ? '-' : estimationObj.creation.totalCost,
codeDepositCost: estimationObj === null ? '-' : estimationObj.creation.codeDepositCost
}
}
}
@ -472,25 +386,14 @@ export class CodeParser extends Plugin {
* @param type
* @returns
*/
async nodesAtPosition(
position: number,
type = ''
): Promise<genericASTNode[]> {
async nodesAtPosition(position: number, type = ''): Promise<genericASTNode[]> {
let lastCompilationResult = this.compilerAbstract
if (this.debuggerIsOn) {
lastCompilationResult = await this.call(
'compilerArtefacts',
'get',
'__last'
)
lastCompilationResult = await this.call('compilerArtefacts', 'get', '__last')
this.currentFile = await this.call('fileManager', 'file')
}
if (!lastCompilationResult) return []
const urlFromPath = await this.call(
'fileManager',
'getUrlFromPath',
this.currentFile
)
const urlFromPath = await this.call('fileManager', 'getUrlFromPath', this.currentFile)
if (
lastCompilationResult &&
lastCompilationResult.languageversion.indexOf('soljson') === 0 &&
@ -501,8 +404,7 @@ export class CodeParser extends Plugin {
const nodes: genericASTNode[] = sourceMappingDecoder.nodesAtPosition(
type,
position,
lastCompilationResult.data.sources[this.currentFile] ||
lastCompilationResult.data.sources[urlFromPath.file]
lastCompilationResult.data.sources[this.currentFile] || lastCompilationResult.data.sources[urlFromPath.file]
)
return nodes
}
@ -528,8 +430,7 @@ export class CodeParser extends Plugin {
* @returns
*/
async getDeclaration(id: number) {
if (this.nodeIndex.declarations && this.nodeIndex.declarations[id])
return this.nodeIndex.declarations[id]
if (this.nodeIndex.declarations && this.nodeIndex.declarations[id]) return this.nodeIndex.declarations[id]
}
/**
@ -603,11 +504,7 @@ export class CodeParser extends Plugin {
if (!nodeDefinition) nodeDefinition = node
}
}
if (
nodeDefinition &&
nodeDefinition.type &&
nodeDefinition.type === 'Identifier'
) {
if (nodeDefinition && nodeDefinition.type && nodeDefinition.type === 'Identifier') {
const nodeForIdentifier = await this.findIdentifier(nodeDefinition)
if (nodeForIdentifier) nodeDefinition = nodeForIdentifier
}
@ -621,21 +518,15 @@ export class CodeParser extends Plugin {
this.nodeIndex.nodesPerFile &&
this.nodeIndex.nodesPerFile[this.currentFile] &&
this.nodeIndex.nodesPerFile[this.currentFile].contracts[contractName] &&
this.nodeIndex.nodesPerFile[this.currentFile].contracts[contractName]
.contractNodes
this.nodeIndex.nodesPerFile[this.currentFile].contracts[contractName].contractNodes
) {
return this.nodeIndex.nodesPerFile[this.currentFile].contracts[
contractName
]
return this.nodeIndex.nodesPerFile[this.currentFile].contracts[contractName]
}
return false
}
async getCurrentFileNodes() {
if (
this.nodeIndex.nodesPerFile &&
this.nodeIndex.nodesPerFile[this.currentFile]
) {
if (this.nodeIndex.nodesPerFile && this.nodeIndex.nodesPerFile[this.currentFile]) {
return this.nodeIndex.nodesPerFile[this.currentFile]
}
return false
@ -750,9 +641,7 @@ export class CodeParser extends Plugin {
const position = await this.positionOfDefinition(node)
if (this.compilerAbstract && this.compilerAbstract.source && position) {
const fileName = this.compilerAbstract.getSourceName(position.file)
return lineColumn
? `${fileName} ${lineColumn.start.line}:${lineColumn.start.column}`
: null
return lineColumn ? `${fileName} ${lineColumn.start.line}:${lineColumn.start.column}` : null
}
return ''
}
@ -771,13 +660,8 @@ export class CodeParser extends Plugin {
async getLineColumnOfPosition(position: any) {
if (position) {
const fileName = this.compilerAbstract.getSourceName(position.file)
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(
this.compilerAbstract.source.sources[fileName].content
)
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn(
position,
lineBreaks
)
const lineBreaks = sourceMappingDecoder.getLinebreakPositions(this.compilerAbstract.source.sources[fileName].content)
const lineColumn = sourceMappingDecoder.convertOffsetToLineColumn(position, lineBreaks)
return lineColumn
}
}
@ -788,11 +672,7 @@ export class CodeParser extends Plugin {
* @returns
*/
async getNodeDocumentation(node: genericASTNode) {
if (
'documentation' in node &&
node.documentation &&
(node.documentation as any).text
) {
if ('documentation' in node && node.documentation && (node.documentation as any).text) {
let text = ''
;(node.documentation as any).text.split('\n').forEach((line) => {
text += `${line.trim()}\n`
@ -807,8 +687,7 @@ export class CodeParser extends Plugin {
* @returns
*/
async getVariableDeclaration(node: any) {
const nodeVisibility =
node.visibility && node.visibility.length ? node.visibility + ' ' : ''
const nodeVisibility = node.visibility && node.visibility.length ? node.visibility + ' ' : ''
const nodeName = node.name && node.name.length ? node.name : ''
if (node.typeDescriptions && node.typeDescriptions.typeString) {
return `${node.typeDescriptions.typeString} ${nodeVisibility}${nodeName}`
@ -829,8 +708,7 @@ export class CodeParser extends Plugin {
* @returns
*/
async getFunctionParamaters(node: any) {
const localParam =
(node.parameters && node.parameters.parameters) || node.parameters
const localParam = (node.parameters && node.parameters.parameters) || node.parameters
if (localParam) {
const params = []
for (const param of localParam) {

@ -2,10 +2,7 @@ import React from 'react' // eslint-disable-line
import {FormattedMessage} from 'react-intl'
import {Plugin} from '@remixproject/engine'
import {AppModal} from '@remix-ui/app'
import {
PermissionHandlerDialog,
PermissionHandlerValue
} from '@remix-ui/permission-handler'
import {PermissionHandlerDialog, PermissionHandlerValue} from '@remix-ui/permission-handler'
import {Profile} from '@remixproject/plugin-utils'
const profile = {
@ -49,21 +46,11 @@ export class PermissionHandlerPlugin extends Plugin {
}
}
switchMode(
from: Profile,
to: Profile,
method: string,
set: boolean,
sensitiveCall: boolean
) {
switchMode(from: Profile, to: Profile, method: string, set: boolean, sensitiveCall: boolean) {
if (sensitiveCall) {
set
? (this.sessionPermissions[to.name][method][from.name] = {})
: delete this.sessionPermissions[to.name][method][from.name]
set ? (this.sessionPermissions[to.name][method][from.name] = {}) : delete this.sessionPermissions[to.name][method][from.name]
} else {
set
? (this.permissions[to.name][method][from.name] = {})
: delete this.permissions[to.name][method][from.name]
set ? (this.permissions[to.name][method][from.name] = {}) : delete this.permissions[to.name][method][from.name]
}
}
@ -74,9 +61,7 @@ export class PermissionHandlerPlugin extends Plugin {
}
notAllowWarning(from: Profile, to: Profile, method: string) {
return `${
from.displayName || from.name
} is not allowed to call ${method} method of ${to.displayName || to.name}.`
return `${from.displayName || from.name} is not allowed to call ${method} method of ${to.displayName || to.name}.`
}
async getTheme() {
@ -91,33 +76,20 @@ export class PermissionHandlerPlugin extends Plugin {
* @param {string} message from the caller plugin to add more details if needed
* @returns {Promise<boolean>}
*/
async askPermission(
from: Profile,
to: Profile,
method: string,
message: string,
sensitiveCall: boolean
) {
async askPermission(from: Profile, to: Profile, method: string, message: string, sensitiveCall: boolean) {
try {
if (sensitiveCall) {
if (!this.sessionPermissions[to.name])
this.sessionPermissions[to.name] = {}
if (!this.sessionPermissions[to.name][method])
this.sessionPermissions[to.name][method] = {}
if (!this.sessionPermissions[to.name][method][from.name])
return this.openPermission(from, to, method, message, sensitiveCall)
if (!this.sessionPermissions[to.name]) this.sessionPermissions[to.name] = {}
if (!this.sessionPermissions[to.name][method]) this.sessionPermissions[to.name][method] = {}
if (!this.sessionPermissions[to.name][method][from.name]) return this.openPermission(from, to, method, message, sensitiveCall)
} else {
this.permissions = this._getFromLocal()
if (!this.permissions[to.name]) this.permissions[to.name] = {}
if (!this.permissions[to.name][method])
this.permissions[to.name][method] = {}
if (!this.permissions[to.name][method][from.name])
return this.openPermission(from, to, method, message, sensitiveCall)
if (!this.permissions[to.name][method]) this.permissions[to.name][method] = {}
if (!this.permissions[to.name][method][from.name]) return this.openPermission(from, to, method, message, sensitiveCall)
}
const {allow, hash} = sensitiveCall
? this.sessionPermissions[to.name][method][from.name]
: this.permissions[to.name][method][from.name]
const {allow, hash} = sensitiveCall ? this.sessionPermissions[to.name][method][from.name] : this.permissions[to.name][method][from.name]
if (!allow) {
const warning = this.notAllowWarning(from, to, method)
this.call('notification', 'toast', warning)
@ -131,13 +103,7 @@ export class PermissionHandlerPlugin extends Plugin {
}
}
async openPermission(
from: Profile,
to: Profile,
method: string,
message: string,
sensitiveCall: boolean
) {
async openPermission(from: Profile, to: Profile, method: string, message: string, sensitiveCall: boolean) {
let remember
if (sensitiveCall) {
remember = this.sessionPermissions[to.name][method][from.name]
@ -154,19 +120,8 @@ export class PermissionHandlerPlugin extends Plugin {
}
const modal: AppModal = {
id: 'PermissionHandler',
title: (
<FormattedMessage
id="permissionHandler.permissionNeededFor"
values={{to: to.displayName || to.name}}
/>
),
message: (
<PermissionHandlerDialog
plugin={this}
theme={await this.getTheme()}
value={value}
></PermissionHandlerDialog>
),
title: <FormattedMessage id="permissionHandler.permissionNeededFor" values={{to: to.displayName || to.name}} />,
message: <PermissionHandlerDialog plugin={this} theme={await this.getTheme()} value={value}></PermissionHandlerDialog>,
okLabel: <FormattedMessage id="permissionHandler.accept" />,
cancelLabel: <FormattedMessage id="permissionHandler.decline" />
}

@ -14,19 +14,7 @@ const profile = {
name: 'remixd',
displayName: 'RemixD',
url: 'ws://127.0.0.1:65520',
methods: [
'folderIsReadOnly',
'resolveDirectory',
'get',
'exists',
'isFile',
'set',
'rename',
'remove',
'isDirectory',
'list',
'createDir'
],
methods: ['folderIsReadOnly', 'resolveDirectory', 'get', 'exists', 'isFile', 'set', 'rename', 'remove', 'isDirectory', 'list', 'createDir'],
events: [],
description: 'Using Remixd daemon, allow to access file system',
kind: 'other',
@ -96,8 +84,7 @@ export class RemixdHandle extends WebsocketPlugin {
console.log(error)
const alert: AlertModal = {
id: 'connectionAlert',
message:
'Cannot connect to the remixd daemon. Please make sure you have the remixd running in the background.'
message: 'Cannot connect to the remixd daemon. Please make sure you have the remixd running in the background.'
}
this.call('notification', 'alert', alert)
this.canceled()
@ -108,20 +95,14 @@ export class RemixdHandle extends WebsocketPlugin {
clearInterval(intervalId)
const alert: AlertModal = {
id: 'connectionAlert',
message:
'Connection to remixd terminated. Please make sure remixd is still running in the background.'
message: 'Connection to remixd terminated. Please make sure remixd is still running in the background.'
}
this.call('notification', 'alert', alert)
this.canceled()
}
}, 3000)
this.localhostProvider.init(() => {
this.call(
'filePanel',
'setWorkspace',
{name: LOCALHOST, isLocalhost: true},
true
)
this.call('filePanel', 'setWorkspace', {name: LOCALHOST, isLocalhost: true}, true)
})
for (const plugin of this.dependentPlugins) {
await this.appManager.activatePlugin(plugin)
@ -173,27 +154,20 @@ export class RemixdHandle extends WebsocketPlugin {
function remixdDialog() {
const commandText = 'remixd'
const fullCommandText =
'remixd -s <path-to-the-shared-folder> -u <remix-ide-instance-URL>'
const fullCommandText = 'remixd -s <path-to-the-shared-folder> -u <remix-ide-instance-URL>'
return (
<>
<div className="">
<div className="mb-2 text-break">
Access your local file system from Remix IDE using{' '}
<a
target="_blank"
href="https://www.npmjs.com/package/@remix-project/remixd"
>
<a target="_blank" href="https://www.npmjs.com/package/@remix-project/remixd">
Remixd NPM package
</a>
.
</div>
<div className="mb-2 text-break">
Remixd{' '}
<a
target="_blank"
href="https://remix-ide.readthedocs.io/en/latest/remixd.html"
>
<a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html">
documentation
</a>
.
@ -204,10 +178,8 @@ function remixdDialog() {
<b>{commandText}</b>
</div>
<div className="mb-2 text-break">
The remixd command without options uses the terminal's current
directory as the shared directory and the shared Remix domain can only
be https://remix.ethereum.org, https://remix-alpha.ethereum.org, or
https://remix-beta.ethereum.org
The remixd command without options uses the terminal's current directory as the shared directory and the shared Remix domain can only be https://remix.ethereum.org,
https://remix-alpha.ethereum.org, or https://remix-beta.ethereum.org
</div>
<div className="mb-2 text-break">
Example command with flags: <br />
@ -215,26 +187,16 @@ function remixdDialog() {
</div>
<div className="mb-2 text-break">
For info about ports, see{' '}
<a
target="_blank"
href="https://remix-ide.readthedocs.io/en/latest/remixd.html#ports-usage"
>
<a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#ports-usage">
Remixd ports usage
</a>
</div>
<div className="mb-2 text-break">
This feature is still in Alpha. We recommend to keep a backup of the
shared folder.
</div>
<div className="mb-2 text-break">This feature is still in Alpha. We recommend to keep a backup of the shared folder.</div>
<div className="mb-2 text-break">
<h6 className="text-danger">
Before using, make sure remixd version is latest i.e.{' '}
<b>v{remixdVersion}</b>
Before using, make sure remixd version is latest i.e. <b>v{remixdVersion}</b>
<br></br>
<a
target="_blank"
href="https://remix-ide.readthedocs.io/en/latest/remixd.html#update-to-the-latest-remixd"
>
<a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#update-to-the-latest-remixd">
Read here how to update it
</a>
</h6>

@ -19,11 +19,7 @@ export class SolidityScript extends Plugin {
async execute(path: string, functionName: string = 'run') {
_paq.push(['trackEvent', 'SolidityScript', 'execute', 'script'])
this.call(
'terminal',
'log',
`Running free function '${functionName}' from ${path}...`
)
this.call('terminal', 'log', `Running free function '${functionName}' from ${path}...`)
let content = await this.call('fileManager', 'readFile', path)
const params = await this.call('solidity', 'getCompilerParameters')
@ -99,10 +95,7 @@ export class SolidityScript extends Plugin {
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (
typeof log[0] === 'string' &&
(log[0].includes('%s') || log[0].includes('%d'))
) {
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')

@ -3,11 +3,7 @@ import {ViewPlugin} from '@remixproject/engine-web'
import React from 'react'
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import {RemixUiSolidityUmlGen} from '@remix-ui/solidity-uml-gen'
import {
ISolidityUmlGen,
ThemeQualityType,
ThemeSummary
} from 'libs/remix-ui/solidity-uml-gen/src/types'
import {ISolidityUmlGen, ThemeQualityType, ThemeSummary} from 'libs/remix-ui/solidity-uml-gen/src/types'
import {RemixAppManager} from 'libs/remix-ui/plugin-manager/src/types'
import {normalizeContractPath} from 'libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities'
import {convertAST2UmlClasses} from 'sol2uml/lib/converterAST2Classes'
@ -22,8 +18,7 @@ const _paq = (window._paq = window._paq || [])
const profile = {
name: 'solidityumlgen',
displayName: 'Solidity UML Generator',
description:
'Generates UML diagram in svg format from last compiled contract',
description: 'Generates UML diagram in svg format from last compiled contract',
location: 'mainPanel',
methods: ['showUmlDiagram', 'generateUml', 'generateCustomAction'],
events: []
@ -67,55 +62,43 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
onActivation(): void {
this.handleThemeChange()
this.on(
'solidity',
'compilationFinished',
async (file: string, source, languageVersion, data, input, version) => {
if (!this.triggerGenerateUml) return
this.triggerGenerateUml = false
const currentTheme: ThemeQualityType = await this.call(
'theme',
'currentTheme'
)
this.currentlySelectedTheme = currentTheme.quality
this.themeName = currentTheme.name
let result = ''
const normalized = normalizeContractPath(file)
this.currentFile = normalized[normalized.length - 1]
try {
if (data.sources && Object.keys(data.sources).length > 1) {
// we should flatten first as there are multiple asts
result = await this.flattenContract(source, file, data)
}
const ast =
result.length > 1
? parser.parse(result)
: parser.parse(source.sources[file].content)
this.umlClasses = convertAST2UmlClasses(ast, this.currentFile)
let umlDot = ''
this.activeTheme = await this.call('theme', 'currentTheme')
umlDot = convertUmlClasses2Dot(this.umlClasses, false, {
backColor: this.activeTheme.backgroundColor,
textColor: this.activeTheme.textColor,
shapeColor: this.activeTheme.shapeColor,
fillColor: this.activeTheme.fillColor
})
const payload = vizRenderStringSync(umlDot)
this.updatedSvg = payload
_paq.push(['trackEvent', 'solidityumlgen', 'umlgenerated'])
this.renderComponent()
await this.call('tabs', 'focus', 'solidityumlgen')
} catch (error) {
console.log('error', error)
this.on('solidity', 'compilationFinished', async (file: string, source, languageVersion, data, input, version) => {
if (!this.triggerGenerateUml) return
this.triggerGenerateUml = false
const currentTheme: ThemeQualityType = await this.call('theme', 'currentTheme')
this.currentlySelectedTheme = currentTheme.quality
this.themeName = currentTheme.name
let result = ''
const normalized = normalizeContractPath(file)
this.currentFile = normalized[normalized.length - 1]
try {
if (data.sources && Object.keys(data.sources).length > 1) {
// we should flatten first as there are multiple asts
result = await this.flattenContract(source, file, data)
}
const ast = result.length > 1 ? parser.parse(result) : parser.parse(source.sources[file].content)
this.umlClasses = convertAST2UmlClasses(ast, this.currentFile)
let umlDot = ''
this.activeTheme = await this.call('theme', 'currentTheme')
umlDot = convertUmlClasses2Dot(this.umlClasses, false, {
backColor: this.activeTheme.backgroundColor,
textColor: this.activeTheme.textColor,
shapeColor: this.activeTheme.shapeColor,
fillColor: this.activeTheme.fillColor
})
const payload = vizRenderStringSync(umlDot)
this.updatedSvg = payload
_paq.push(['trackEvent', 'solidityumlgen', 'umlgenerated'])
this.renderComponent()
await this.call('tabs', 'focus', 'solidityumlgen')
} catch (error) {
console.log('error', error)
}
)
})
}
getThemeCssVariables(cssVars: string) {
return window
.getComputedStyle(document.documentElement)
.getPropertyValue(cssVars)
return window.getComputedStyle(document.documentElement).getPropertyValue(cssVars)
}
private handleThemeChange() {
@ -160,13 +143,7 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen {
* @returns {Promise<string>}
*/
async flattenContract(source: any, filePath: string, data: any) {
const result = await this.call(
'contractflattener',
'flattenContract',
source,
filePath,
data
)
const result = await this.call('contractflattener', 'flattenContract', source, filePath, data)
return result
}
@ -231,12 +208,7 @@ interface Sol2umlClassOptions extends ClassOptions {
import {dirname} from 'path'
import {convertClass2Dot} from 'sol2uml/lib/converterClass2Dot'
import {
Association,
ClassStereotype,
ReferenceType,
UmlClass
} from 'sol2uml/lib/umlClass'
import {Association, ClassStereotype, ReferenceType, UmlClass} from 'sol2uml/lib/umlClass'
import {findAssociatedClass} from 'sol2uml/lib/associations'
// const debug = require('debug')('sol2uml')
@ -249,11 +221,7 @@ import {findAssociatedClass} from 'sol2uml/lib/associations'
* @param classOptions command line options for the `class` command
* @return dotString Graphviz's DOT format for defining nodes, edges and clusters.
*/
export function convertUmlClasses2Dot(
umlClasses: UmlClass[],
clusterFolders: boolean = false,
classOptions: Sol2umlClassOptions = {}
): string {
export function convertUmlClasses2Dot(umlClasses: UmlClass[], clusterFolders: boolean = false, classOptions: Sol2umlClassOptions = {}): string {
let dotString: string = `
digraph UmlClassDiagram {
rankdir=BT
@ -318,10 +286,7 @@ function sortUmlClassesByCodePath(umlClasses: UmlClass[]): UmlClass[] {
})
}
export function addAssociationsToDot(
umlClasses: UmlClass[],
classOptions: ClassOptions = {}
): string {
export function addAssociationsToDot(umlClasses: UmlClass[], classOptions: ClassOptions = {}): string {
let dotString: string = ''
// for each class
@ -351,18 +316,9 @@ export function addAssociationsToDot(
// for each association in that class
for (const association of Object.values(sourceUmlClass.associations)) {
const targetUmlClass = findAssociatedClass(
association,
sourceUmlClass,
umlClasses
)
const targetUmlClass = findAssociatedClass(association, sourceUmlClass, umlClasses)
if (targetUmlClass) {
dotString += addAssociationToDot(
sourceUmlClass,
targetUmlClass,
association,
classOptions
)
dotString += addAssociationToDot(sourceUmlClass, targetUmlClass, association, classOptions)
}
}
}
@ -370,41 +326,23 @@ export function addAssociationsToDot(
return dotString
}
function addAssociationToDot(
sourceUmlClass: UmlClass,
targetUmlClass: UmlClass,
association: Association,
classOptions: ClassOptions = {}
): string {
function addAssociationToDot(sourceUmlClass: UmlClass, targetUmlClass: UmlClass, association: Association, classOptions: ClassOptions = {}): string {
// do not include library or interface associations if hidden
// Or associations to Structs, Enums or Constants if they are hidden
if (
(classOptions.hideLibraries &&
(sourceUmlClass.stereotype === ClassStereotype.Library ||
targetUmlClass.stereotype === ClassStereotype.Library)) ||
(classOptions.hideInterfaces &&
(targetUmlClass.stereotype === ClassStereotype.Interface ||
sourceUmlClass.stereotype === ClassStereotype.Interface)) ||
(classOptions.hideAbstracts &&
(targetUmlClass.stereotype === ClassStereotype.Abstract ||
sourceUmlClass.stereotype === ClassStereotype.Abstract)) ||
(classOptions.hideStructs &&
targetUmlClass.stereotype === ClassStereotype.Struct) ||
(classOptions.hideEnums &&
targetUmlClass.stereotype === ClassStereotype.Enum) ||
(classOptions.hideConstants &&
targetUmlClass.stereotype === ClassStereotype.Constant)
(classOptions.hideLibraries && (sourceUmlClass.stereotype === ClassStereotype.Library || targetUmlClass.stereotype === ClassStereotype.Library)) ||
(classOptions.hideInterfaces && (targetUmlClass.stereotype === ClassStereotype.Interface || sourceUmlClass.stereotype === ClassStereotype.Interface)) ||
(classOptions.hideAbstracts && (targetUmlClass.stereotype === ClassStereotype.Abstract || sourceUmlClass.stereotype === ClassStereotype.Abstract)) ||
(classOptions.hideStructs && targetUmlClass.stereotype === ClassStereotype.Struct) ||
(classOptions.hideEnums && targetUmlClass.stereotype === ClassStereotype.Enum) ||
(classOptions.hideConstants && targetUmlClass.stereotype === ClassStereotype.Constant)
) {
return ''
}
let dotString = `\n${sourceUmlClass.id} -> ${targetUmlClass.id} [`
if (
association.referenceType == ReferenceType.Memory ||
(association.realization &&
targetUmlClass.stereotype === ClassStereotype.Interface)
) {
if (association.referenceType == ReferenceType.Memory || (association.realization && targetUmlClass.stereotype === ClassStereotype.Interface)) {
dotString += 'style=dashed, '
}

@ -70,8 +70,7 @@ export abstract class AbstractProvider extends Plugin implements IProvider {
} else {
return {
valid: false,
message:
'the provided value should contain the protocol ( e.g starts with http:// or https:// )'
message: 'the provided value should contain the protocol ( e.g starts with http:// or https:// )'
}
}
},
@ -119,22 +118,13 @@ export abstract class AbstractProvider extends Plugin implements IProvider {
return
}
private async sendAsyncInternal(
data: JsonDataRequest,
resolve: SuccessRequest,
reject: RejectRequest
): Promise<void> {
private async sendAsyncInternal(data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise<void> {
if (this.provider) {
try {
const result = await this.provider.send(data.method, data.params)
resolve({jsonrpc: '2.0', result, id: data.id})
} catch (error) {
if (
error &&
error.message &&
error.message.includes('net_version') &&
error.message.includes('SERVER_ERROR')
) {
if (error && error.message && error.message.includes('net_version') && error.message.includes('SERVER_ERROR')) {
this.switchAway(true)
}
reject(error)

@ -32,18 +32,10 @@ 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>Please provide information about the custom fork. If the node URL is not provided, the VM will start with an empty state.</span>
<div>
<label className="mt-3 mb-1">Node URL</label>
<input
data-id="CustomForkNodeUrl"
name="nodeUrl"
type="text"
className="border form-control border-right-0"
/>
<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>
@ -58,12 +50,7 @@ export class CustomForkVMProvider extends BasicVMProvider {
</div>
<div>
<label className="mt-3 mb-1">EVM</label>
<select
data-id="CustomForkEvmType"
name="evmType"
defaultValue="merge"
className="border form-control border-right-0"
>
<select data-id="CustomForkEvmType" name="evmType" defaultValue="merge" className="border form-control border-right-0">
{Object.keys(Hardfork).map((value, index) => {
return (
<option value={Hardfork[value]} key={index}>

@ -21,46 +21,27 @@ 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"
>
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>
)<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"
>
<a href="https://geth.ethereum.org/getting-started/dev-mode" target="_blank" rel="noreferrer">
Geth Docs on Dev mode
</a>
)
<div className="border p-1">
geth --http --http.corsdomain="{window.origin}" --http.api
web3,eth,debug,personal,net --vmdebug --datadir {thePath} --dev
console
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>
<b>WARNING:</b> It is not safe to use the --http.corsdomain flag with a wildcard: <b>--http.corsdomain *</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"
>
<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>
<br />

@ -20,17 +20,13 @@ export class HardhatProvider extends AbstractProvider {
return (
<div>
{' '}
Note: To run Hardhat network node on your system, go to hardhat project
folder and run command:
Note: To run Hardhat network node on your system, go to hardhat project folder and run command:
<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"
>
<a href="https://hardhat.org/getting-started/#connecting-a-wallet-or-dapp-to-hardhat-network" target="_blank">
Hardhat Documentation
</a>
</div>

@ -5,12 +5,7 @@ export class InjectedL2Provider extends InjectedProviderDefaultBase {
chainId: string
rpcUrls: Array<string>
constructor(
profile: any,
chainName: string,
chainId: string,
rpcUrls: Array<string>
) {
constructor(profile: any, chainName: string, chainId: string, rpcUrls: Array<string>) {
super(profile)
this.chainName = chainName
this.chainId = chainId
@ -19,18 +14,13 @@ export class InjectedL2Provider extends InjectedProviderDefaultBase {
async init() {
await super.init()
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0)
await addL2Network(this.chainName, this.chainId, this.rpcUrls)
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0) await addL2Network(this.chainName, this.chainId, this.rpcUrls)
else throw new Error('Cannot add the L2 network to main injected provider')
return {}
}
}
export const addL2Network = async (
chainName: string,
chainId: string,
rpcUrls: Array<string>
) => {
export const addL2Network = async (chainName: string, chainId: string, rpcUrls: Array<string>) => {
try {
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',

@ -9,17 +9,8 @@ export class InjectedProviderDefaultBase extends InjectedProvider {
async init() {
const injectedProvider = this.getInjectedProvider()
if (
injectedProvider &&
injectedProvider._metamask &&
injectedProvider._metamask.isUnlocked
) {
if (!(await injectedProvider._metamask.isUnlocked()))
this.call(
'notification',
'toast',
'Please make sure the injected provider is unlocked (e.g Metamask).'
)
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!(await injectedProvider._metamask.isUnlocked())) this.call('notification', 'toast', 'Please make sure the injected provider is unlocked (e.g Metamask).')
}
return super.init()
}

@ -1,11 +1,7 @@
/* global ethereum */
import React from 'react' // eslint-disable-line
import {Plugin} from '@remixproject/engine'
import {
JsonDataRequest,
RejectRequest,
SuccessRequest
} from '../providers/abstract-provider'
import {JsonDataRequest, RejectRequest, SuccessRequest} from '../providers/abstract-provider'
import {IProvider} from './abstract-provider'
export abstract class InjectedProvider extends Plugin implements IProvider {
@ -39,10 +35,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
onDeactivation(): void {
try {
const web3Provider = this.getInjectedProvider()
web3Provider.removeListener(
'accountsChanged',
this.listenerAccountsChanged
)
web3Provider.removeListener('accountsChanged', this.listenerAccountsChanged)
web3Provider.removeListener('chainChanged', this.listenerChainChanged)
} catch (error) {
console.log('unable to remove listener on context changed')
@ -51,10 +44,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
askPermission(throwIfNoInjectedProvider) {
const web3Provider = this.getInjectedProvider()
if (
typeof web3Provider !== 'undefined' &&
typeof web3Provider.request === 'function'
) {
if (typeof web3Provider !== 'undefined' && typeof web3Provider.request === 'function') {
web3Provider.request({method: 'eth_requestAccounts'})
} else if (throwIfNoInjectedProvider) {
throw new Error(this.notFound())
@ -82,20 +72,12 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
})
}
private async sendAsyncInternal(
data: JsonDataRequest,
resolve: SuccessRequest,
reject: RejectRequest
): Promise<void> {
private async sendAsyncInternal(data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise<void> {
// Check the case where current environment is VM on UI and it still sends RPC requests
// This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!'
const web3Provider = this.getInjectedProvider()
if (!web3Provider) {
this.call(
'notification',
'toast',
'No injected provider (e.g Metamask) has been found.'
)
this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.')
return resolve({
jsonrpc: '2.0',
error: 'no injected provider found',
@ -104,8 +86,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
}
try {
let resultData
if (web3Provider.send)
resultData = await web3Provider.send(data.method, data.params)
if (web3Provider.send) resultData = await web3Provider.send(data.method, data.params)
else if (web3Provider.request)
resultData = await web3Provider.request({
method: data.method,
@ -126,8 +107,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider {
} catch (error) {
resolve({
jsonrpc: '2.0',
error:
error.data && error.data.message ? error.data.message : error.message,
error: error.data && error.data.message ? error.data.message : error.message,
id: data.id
})
}

@ -18,8 +18,7 @@ export class MainnetForkVMProvider extends BasicVMProvider {
)
this.blockchain = blockchain
this.fork = 'shanghai'
this.nodeUrl =
'https://mainnet.infura.io/v3/08b2a484451e4635a28b3d8234f24332'
this.nodeUrl = 'https://mainnet.infura.io/v3/08b2a484451e4635a28b3d8234f24332'
this.blockNumber = 'latest'
}

@ -1,10 +1,6 @@
import React from 'react' // eslint-disable-line
import * as packageJson from '../../../../../package.json'
import {
JsonDataRequest,
RejectRequest,
SuccessRequest
} from '../providers/abstract-provider'
import {JsonDataRequest, RejectRequest, SuccessRequest} from '../providers/abstract-provider'
import {Plugin} from '@remixproject/engine'
import {IProvider} from './abstract-provider'
@ -32,21 +28,14 @@ export class BasicVMProvider extends Plugin implements IProvider {
})
}
private async sendAsyncInternal(
data: JsonDataRequest,
resolve: SuccessRequest,
reject: RejectRequest
): Promise<void> {
private async sendAsyncInternal(data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise<void> {
try {
await this.blockchain.providers.vm.provider.sendAsync(
data,
(error, result) => {
if (error) return reject(error)
else {
resolve({jsonrpc: '2.0', result, id: data.id})
}
await this.blockchain.providers.vm.provider.sendAsync(data, (error, result) => {
if (error) return reject(error)
else {
resolve({jsonrpc: '2.0', result, id: data.id})
}
)
})
} catch (error) {
reject(error)
}

@ -11,21 +11,8 @@ import {InjectedProvider} from './providers/injected'
import {NodeProvider} from './providers/node'
import {execution, EventManager, helpers} from '@remix-project/remix-lib'
import {etherScanLink} from './helper'
import {
logBuilder,
cancelUpgradeMsg,
cancelProxyMsg,
addressToString
} from '@remix-ui/helper'
const {
txFormat,
txExecution,
typeConversion,
txListener: Txlistener,
TxRunner,
TxRunnerWeb3,
txHelper
} = execution
import {logBuilder, cancelUpgradeMsg, cancelProxyMsg, addressToString} from '@remix-ui/helper'
const {txFormat, txExecution, typeConversion, txListener: Txlistener, TxRunner, TxRunnerWeb3, txHelper} = execution
const {txResultHelper} = helpers
const {resultToRemixTx} = txResultHelper
import * as packageJson from '../../../../package.json'
@ -36,16 +23,7 @@ const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: [
'getCode',
'getTransactionReceipt',
'addProvider',
'removeProvider',
'getCurrentFork',
'getAccounts',
'web3VM',
'getProvider'
],
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'getAccounts', 'web3VM', 'getProvider'],
version: packageJson.version
}
@ -103,9 +81,7 @@ export class Blockchain extends Plugin {
return this.executionContext.isVM()
},
personalMode: () => {
return this.getProvider() === 'web3'
? this.config.get('settings/personal-mode')
: false
return this.getProvider() === 'web3' ? this.config.get('settings/personal-mode') : false
}
},
(_) => this.executionContext.web3(),
@ -218,14 +194,7 @@ export class Blockchain extends Plugin {
})
}
deployContractAndLibraries(
selectedContract,
args,
contractMetadata,
compilerContracts,
callbacks,
confirmationCb
) {
deployContractAndLibraries(selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) {
const {continueCb, promptCb, statusCb, finalCb} = callbacks
const constructor = selectedContract.getConstructorInterface()
txFormat.buildData(
@ -237,22 +206,11 @@ export class Blockchain extends Plugin {
args,
(error, data) => {
if (error) {
return statusCb(
`creation of ${selectedContract.name} errored: ${
error.message ? error.message : error
}`
)
return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(
selectedContract,
data,
continueCb,
promptCb,
confirmationCb,
finalCb
)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
},
statusCb,
(data, runTxCallback) => {
@ -262,14 +220,7 @@ export class Blockchain extends Plugin {
)
}
deployContractWithLibrary(
selectedContract,
args,
contractMetadata,
compilerContracts,
callbacks,
confirmationCb
) {
deployContractWithLibrary(selectedContract, args, contractMetadata, compilerContracts, callbacks, confirmationCb) {
const {continueCb, promptCb, statusCb, finalCb} = callbacks
const constructor = selectedContract.getConstructorInterface()
txFormat.encodeConstructorCallAndLinkLibraries(
@ -280,22 +231,11 @@ export class Blockchain extends Plugin {
selectedContract.bytecodeLinkReferences,
(error, data) => {
if (error) {
return statusCb(
`creation of ${selectedContract.name} errored: ${
error.message ? error.message : error
}`
)
return statusCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
statusCb(`creation of ${selectedContract.name} pending...`)
this.createContract(
selectedContract,
data,
continueCb,
promptCb,
confirmationCb,
finalCb
)
this.createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb)
}
)
}
@ -311,21 +251,11 @@ export class Blockchain extends Plugin {
cancelLabel: 'Cancel',
okFn: () => {
this.runProxyTx(proxyData, implementationContractObject)
_paq.push([
'trackEvent',
'blockchain',
'Deploy With Proxy',
'modal ok confirmation'
])
_paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'modal ok confirmation'])
},
cancelFn: () => {
this.call('notification', 'toast', cancelProxyMsg())
_paq.push([
'trackEvent',
'blockchain',
'Deploy With Proxy',
'cancel proxy deployment'
])
_paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'cancel proxy deployment'])
},
hideFn: () => null
}
@ -335,13 +265,7 @@ export class Blockchain extends Plugin {
async runProxyTx(proxyData, implementationContractObject) {
const args = {useCall: false, data: proxyData}
let networkInfo
const confirmationCb = (
network,
tx,
gasEstimation,
continueTxExecution,
cancelCb
) => {
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
networkInfo = network
// continue using original authorization given by user
continueTxExecution(null)
@ -356,49 +280,19 @@ export class Blockchain extends Plugin {
if (error) {
const log = logBuilder(error)
_paq.push([
'trackEvent',
'blockchain',
'Deploy With Proxy',
'Proxy deployment failed: ' + error
])
_paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'Proxy deployment failed: ' + error])
return this.call('terminal', 'logHtml', log)
}
await this.saveDeployedContractStorageLayout(
implementationContractObject,
address,
networkInfo
)
this.events.emit(
'newProxyDeployment',
address,
new Date().toISOString(),
implementationContractObject.contractName
)
_paq.push([
'trackEvent',
'blockchain',
'Deploy With Proxy',
'Proxy deployment successful'
])
this.call(
'udapp',
'addInstance',
addressToString(address),
implementationContractObject.abi,
implementationContractObject.name
)
await this.saveDeployedContractStorageLayout(implementationContractObject, address, networkInfo)
this.events.emit('newProxyDeployment', address, new Date().toISOString(), implementationContractObject.contractName)
_paq.push(['trackEvent', 'blockchain', 'Deploy With Proxy', 'Proxy deployment successful'])
this.call('udapp', 'addInstance', addressToString(address), implementationContractObject.abi, implementationContractObject.name)
}
this.runTx(args, confirmationCb, continueCb, promptCb, finalCb)
}
async upgradeProxy(
proxyAddress,
newImplAddress,
data,
newImplementationContractObject
) {
async upgradeProxy(proxyAddress, newImplAddress, data, newImplementationContractObject) {
const upgradeModal = {
id: 'confirmProxyDeployment',
title: 'Confirm Update Proxy (ERC1967)',
@ -408,21 +302,11 @@ export class Blockchain extends Plugin {
cancelLabel: 'Cancel',
okFn: () => {
this.runUpgradeTx(proxyAddress, data, newImplementationContractObject)
_paq.push([
'trackEvent',
'blockchain',
'Upgrade With Proxy',
'proxy upgrade confirmation click'
])
_paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'proxy upgrade confirmation click'])
},
cancelFn: () => {
this.call('notification', 'toast', cancelUpgradeMsg())
_paq.push([
'trackEvent',
'blockchain',
'Upgrade With Proxy',
'proxy upgrade cancel click'
])
_paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'proxy upgrade cancel click'])
},
hideFn: () => null
}
@ -432,13 +316,7 @@ export class Blockchain extends Plugin {
async runUpgradeTx(proxyAddress, data, newImplementationContractObject) {
const args = {useCall: false, data, to: proxyAddress}
let networkInfo
const confirmationCb = (
network,
tx,
gasEstimation,
continueTxExecution,
cancelCb
) => {
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
// continue using original authorization given by user
networkInfo = network
continueTxExecution(null)
@ -453,75 +331,31 @@ export class Blockchain extends Plugin {
if (error) {
const log = logBuilder(error)
_paq.push([
'trackEvent',
'blockchain',
'Upgrade With Proxy',
'Upgrade failed'
])
_paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'Upgrade failed'])
return this.call('terminal', 'logHtml', log)
}
await this.saveDeployedContractStorageLayout(
newImplementationContractObject,
proxyAddress,
networkInfo
)
_paq.push([
'trackEvent',
'blockchain',
'Upgrade With Proxy',
'Upgrade Successful'
])
this.call(
'udapp',
'addInstance',
addressToString(proxyAddress),
newImplementationContractObject.abi,
newImplementationContractObject.name
)
await this.saveDeployedContractStorageLayout(newImplementationContractObject, proxyAddress, networkInfo)
_paq.push(['trackEvent', 'blockchain', 'Upgrade With Proxy', 'Upgrade Successful'])
this.call('udapp', 'addInstance', addressToString(proxyAddress), newImplementationContractObject.abi, newImplementationContractObject.name)
}
this.runTx(args, confirmationCb, continueCb, promptCb, finalCb)
}
async saveDeployedContractStorageLayout(
contractObject,
proxyAddress,
networkInfo
) {
async saveDeployedContractStorageLayout(contractObject, proxyAddress, networkInfo) {
const {contractName, implementationAddress} = contractObject
const networkName =
networkInfo.name === 'custom'
? networkInfo.name + '-' + networkInfo.id
: networkInfo.name
const hasPreviousDeploys = await this.call(
'fileManager',
'exists',
`.deploys/upgradeable-contracts/${networkName}/UUPS.json`
)
const networkName = networkInfo.name === 'custom' ? networkInfo.name + '-' + networkInfo.id : networkInfo.name
const hasPreviousDeploys = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
// TODO: make deploys folder read only.
if (hasPreviousDeploys) {
const deployments = await this.call(
'fileManager',
'readFile',
`.deploys/upgradeable-contracts/${networkName}/UUPS.json`
)
const deployments = await this.call('fileManager', 'readFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`)
const parsedDeployments = JSON.parse(deployments)
const proxyDeployment = parsedDeployments.deployments[proxyAddress]
if (proxyDeployment) {
const oldImplementationAddress = proxyDeployment.implementationAddress
const hasPreviousBuild = await this.call(
'fileManager',
'exists',
`.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`
)
const hasPreviousBuild = await this.call('fileManager', 'exists', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
if (hasPreviousBuild)
await this.call(
'fileManager',
'remove',
`.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`
)
if (hasPreviousBuild) await this.call('fileManager', 'remove', `.deploys/upgradeable-contracts/${networkName}/solc-${oldImplementationAddress}.json`)
}
parsedDeployments.deployments[proxyAddress] = {
date: new Date().toISOString(),
@ -544,12 +378,7 @@ export class Blockchain extends Plugin {
2
)
)
await this.call(
'fileManager',
'writeFile',
`.deploys/upgradeable-contracts/${networkName}/UUPS.json`,
JSON.stringify(parsedDeployments, null, 2)
)
await this.call('fileManager', 'writeFile', `.deploys/upgradeable-contracts/${networkName}/UUPS.json`, JSON.stringify(parsedDeployments, null, 2))
} else {
await this.call(
'fileManager',
@ -606,57 +435,29 @@ export class Blockchain extends Plugin {
})
}
createContract(
selectedContract,
data,
continueCb,
promptCb,
confirmationCb,
finalCb
) {
createContract(selectedContract, data, continueCb, promptCb, confirmationCb, finalCb) {
if (data) {
data.contractName = selectedContract.name
data.linkReferences = selectedContract.bytecodeLinkReferences
data.contractABI = selectedContract.abi
}
this.runTx(
{data: data, useCall: false},
confirmationCb,
continueCb,
promptCb,
(error, txResult, address) => {
if (error) {
return finalCb(
`creation of ${selectedContract.name} errored: ${
error.message ? error.message : error
}`
)
}
if (
txResult.receipt.status === false ||
txResult.receipt.status === '0x0' ||
txResult.receipt.status === 0
) {
return finalCb(
`creation of ${selectedContract.name} errored: transaction execution failed`
)
}
finalCb(null, selectedContract, address)
this.runTx({data: data, useCall: false}, confirmationCb, continueCb, promptCb, (error, txResult, address) => {
if (error) {
return finalCb(`creation of ${selectedContract.name} errored: ${error.message ? error.message : error}`)
}
)
if (txResult.receipt.status === false || txResult.receipt.status === '0x0' || txResult.receipt.status === 0) {
return finalCb(`creation of ${selectedContract.name} errored: transaction execution failed`)
}
finalCb(null, selectedContract, address)
})
}
determineGasPrice(cb) {
this.getCurrentProvider().getGasPrice((error, gasPrice) => {
const warnMessage =
' Please fix this issue before sending any transaction. '
const warnMessage = ' Please fix this issue before sending any transaction. '
if (error) {
return cb(
'Unable to retrieve the current network gas price.' +
warnMessage +
error
)
return cb('Unable to retrieve the current network gas price.' + warnMessage + error)
}
try {
const gasPriceValue = this.fromWei(gasPrice, false, 'gwei')
@ -686,13 +487,7 @@ export class Blockchain extends Plugin {
}
calculateFee(gas, gasPrice, unit?) {
return Web3.utils
.toBN(gas)
.mul(
Web3.utils.toBN(
Web3.utils.toWei(gasPrice.toString(10) as string, unit || 'gwei')
)
)
return Web3.utils.toBN(gas).mul(Web3.utils.toBN(Web3.utils.toWei(gasPrice.toString(10) as string, unit || 'gwei')))
}
determineGasFees(tx) {
@ -705,8 +500,7 @@ export class Blockchain extends Plugin {
txFeeText = ' ' + this.fromWei(fee, false, 'ether') + ' Ether'
priceStatus = true
} catch (e) {
txFeeText =
' Please fix this issue before sending any transaction. ' + e.message
txFeeText = ' Please fix this issue before sending any transaction. ' + e.message
priceStatus = false
}
cb(txFeeText, priceStatus)
@ -716,13 +510,7 @@ export class Blockchain extends Plugin {
}
changeExecutionContext(context, confirmCb, infoCb, cb) {
return this.executionContext.executionContextChange(
context,
null,
confirmCb,
infoCb,
cb
)
return this.executionContext.executionContextChange(context, null, confirmCb, infoCb, cb)
}
detectNetwork(cb) {
@ -781,22 +569,7 @@ export class Blockchain extends Plugin {
return txlistener
}
runOrCallContractMethod(
contractName,
contractAbi,
funABI,
contract,
value,
address,
callType,
lookupOnly,
logMsg,
logCallback,
outputCb,
confirmationCb,
continueCb,
promptCb
) {
runOrCallContractMethod(contractName, contractAbi, funABI, contract, value, address, callType, lookupOnly, logMsg, logCallback, outputCb, confirmationCb, continueCb, promptCb) {
// contractsDetails is used to resolve libraries
txFormat.buildData(
contractName,
@ -807,9 +580,7 @@ export class Blockchain extends Plugin {
callType,
(error, data) => {
if (error) {
return logCallback(
`${logMsg} errored: ${error.message ? error.message : error}`
)
return logCallback(`${logMsg} errored: ${error.message ? error.message : error}`)
}
if (!lookupOnly) {
logCallback(`${logMsg} pending ... `)
@ -823,24 +594,15 @@ export class Blockchain extends Plugin {
data.contractABI = contractAbi
data.contract = contract
}
const useCall =
funABI.stateMutability === 'view' || funABI.stateMutability === 'pure'
this.runTx(
{to: address, data, useCall},
confirmationCb,
continueCb,
promptCb,
(error, txResult, _address, returnValue) => {
if (error) {
return logCallback(
`${logMsg} errored: ${error.message ? error.message : error}`
)
}
if (lookupOnly) {
outputCb(returnValue)
}
const useCall = funABI.stateMutability === 'view' || funABI.stateMutability === 'pure'
this.runTx({to: address, data, useCall}, confirmationCb, continueCb, promptCb, (error, txResult, _address, returnValue) => {
if (error) {
return logCallback(`${logMsg} errored: ${error.message ? error.message : error}`)
}
)
if (lookupOnly) {
outputCb(returnValue)
}
})
},
(msg) => {
logCallback(msg)
@ -859,10 +621,7 @@ export class Blockchain extends Plugin {
}
// NOTE: the config is only needed because exectuionContext.init does
async resetAndInit(
config: Config,
transactionContextAPI: TransactionContextAPI
) {
async resetAndInit(config: Config, transactionContextAPI: TransactionContextAPI) {
this.transactionContextAPI = transactionContextAPI
this.executionContext.init(config)
this.executionContext.stopListenOnLastBlock()
@ -898,9 +657,7 @@ export class Blockchain extends Plugin {
return this.executionContext.isVM()
},
personalMode: () => {
return this.getProvider() === 'web3'
? this.config.get('settings/personal-mode')
: false
return this.getProvider() === 'web3' ? this.config.get('settings/personal-mode') : false
}
},
(_) => this.executionContext.web3(),
@ -933,9 +690,7 @@ export class Blockchain extends Plugin {
*/
createVMAccount(newAccount) {
if (!this.executionContext.isVM()) {
throw new Error(
'plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed'
)
throw new Error('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed')
}
return (this.providers.vm as VMProvider).createVMAccount(newAccount)
}
@ -972,9 +727,7 @@ export class Blockchain extends Plugin {
this.executionContext.detectNetwork((error, network) => {
if (error) return reject(error)
if (network.name === 'Main' && network.id === '1') {
return reject(
new Error('It is not allowed to make this action against mainnet')
)
return reject(new Error('It is not allowed to make this action against mainnet'))
}
this.txRunner.rawRun(
@ -996,10 +749,7 @@ export class Blockchain extends Plugin {
if (error) return reject(error)
try {
if (this.executionContext.isVM()) {
const execResult =
await this.web3().eth.getExecutionResultFromSimulator(
result.transactionHash
)
const execResult = await this.web3().eth.getExecutionResultFromSimulator(result.transactionHash)
resolve(resultToRemixTx(result, execResult))
} else resolve(resultToRemixTx(result))
} catch (e) {
@ -1057,10 +807,7 @@ export class Blockchain extends Plugin {
const address = accounts[0]
if (!address) return reject('No accounts available')
if (
this.executionContext.isVM() &&
!this.providers.vm.RemixSimulatorProvider.Accounts.accounts[address]
) {
if (this.executionContext.isVM() && !this.providers.vm.RemixSimulatorProvider.Accounts.accounts[address]) {
return reject('Invalid account selected')
}
return resolve(address)
@ -1105,52 +852,34 @@ export class Blockchain extends Plugin {
this._triggerEvent('initiatingTransaction', [timestamp, tx, payLoad])
try {
this.txRunner.rawRun(
tx,
confirmationCb,
continueCb,
promptCb,
async (error, result) => {
if (error) {
if (typeof error !== 'string') {
if (error.message) error = error.message
else {
try {
error = 'error: ' + JSON.stringify(error)
} catch (e) {
console.log(e)
}
this.txRunner.rawRun(tx, confirmationCb, continueCb, promptCb, async (error, result) => {
if (error) {
if (typeof error !== 'string') {
if (error.message) error = error.message
else {
try {
error = 'error: ' + JSON.stringify(error)
} catch (e) {
console.log(e)
}
}
return reject(error)
}
return reject(error)
}
const isVM = this.executionContext.isVM()
if (isVM && tx.useCall) {
try {
result.transactionHash =
await this.web3().eth.getHashFromTagBySimulator(timestamp)
} catch (e) {
console.log('unable to retrieve back the "call" hash', e)
}
const isVM = this.executionContext.isVM()
if (isVM && tx.useCall) {
try {
result.transactionHash = await this.web3().eth.getHashFromTagBySimulator(timestamp)
} catch (e) {
console.log('unable to retrieve back the "call" hash', e)
}
const eventName = tx.useCall
? 'callExecuted'
: 'transactionExecuted'
this._triggerEvent(eventName, [
error,
tx.from,
tx.to,
tx.data,
tx.useCall,
result,
timestamp,
payLoad
])
return resolve({result, tx})
}
)
const eventName = tx.useCall ? 'callExecuted' : 'transactionExecuted'
this._triggerEvent(eventName, [error, tx.from, tx.to, tx.data, tx.useCall, result, timestamp, payLoad])
return resolve({result, tx})
})
} catch (err) {
let error = err
if (error && typeof error !== 'string') {
@ -1182,9 +911,7 @@ export class Blockchain extends Plugin {
let execResult
let returnValue = null
if (isVM) {
const hhlogs = await this.web3().eth.getHHLogsForTx(
txResult.transactionHash
)
const hhlogs = await this.web3().eth.getHHLogsForTx(txResult.transactionHash)
if (hhlogs && hhlogs.length) {
const finalLogs = (
@ -1198,10 +925,7 @@ export class Blockchain extends Plugin {
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (
typeof log[0] === 'string' &&
(log[0].includes('%s') || log[0].includes('%d'))
) {
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
@ -1213,25 +937,14 @@ export class Blockchain extends Plugin {
_paq.push(['trackEvent', 'udapp', 'hardhat', 'console.log'])
this.call('terminal', 'logHtml', finalLogs)
}
execResult = await this.web3().eth.getExecutionResultFromSimulator(
txResult.transactionHash
)
execResult = await this.web3().eth.getExecutionResultFromSimulator(txResult.transactionHash)
if (execResult) {
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
returnValue = execResult
? toBuffer(execResult.returnValue)
: toBuffer(
addHexPrefix(txResult.result) ||
'0x0000000000000000000000000000000000000000000000000000000000000000'
)
const compiledContracts = await this.call(
'compilerArtefacts',
'getAllContractDatas'
)
const vmError = txExecution.checkVMError(
execResult,
compiledContracts
)
: toBuffer(addHexPrefix(txResult.result) || '0x0000000000000000000000000000000000000000000000000000000000000000')
const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas')
const vmError = txExecution.checkVMError(execResult, compiledContracts)
if (vmError.error) {
return cb(vmError.message)
}

@ -16,18 +16,12 @@ const versionData = {
const loadLocalSolJson = async () => {
// execute apps/remix-ide/ci/downloadsoljson.sh
const child = require('child_process').execSync(
'bash ./apps/remix-ide/ci/downloadsoljson.sh',
{encoding: 'utf8', cwd: process.cwd(), shell: true}
)
const child = require('child_process').execSync('bash ./apps/remix-ide/ci/downloadsoljson.sh', {encoding: 'utf8', cwd: process.cwd(), shell: true})
// show output
console.log(child)
}
fs.writeFileSync(
'./apps/remix-ide/src/assets/version.json',
JSON.stringify(versionData)
)
fs.writeFileSync('./apps/remix-ide/src/assets/version.json', JSON.stringify(versionData))
loadLocalSolJson()
@ -150,16 +144,11 @@ class CopyFileAfterBuild {
const files = fs.readdirSync('./dist/apps/etherscan')
files.forEach((file) => {
if (file.includes('plugin-etherscan')) {
fs.copyFileSync(
'./dist/apps/etherscan/' + file,
'./dist/apps/remix-ide/' + file
)
fs.copyFileSync('./dist/apps/etherscan/' + file, './dist/apps/remix-ide/' + file)
}
})
} catch (e) {
console.error(
'running CopyFileAfterBuild failed with error: ' + e.message
)
console.error('running CopyFileAfterBuild failed with error: ' + e.message)
}
}
compiler.hooks.afterEmit.tapPromise('FileManagerPlugin', onEnd)

@ -12,10 +12,7 @@ const versionData = {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
}
fs.writeFileSync(
'./apps/remix-ide/src/assets/version.json',
JSON.stringify(versionData)
)
fs.writeFileSync('./apps/remix-ide/src/assets/version.json', JSON.stringify(versionData))
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), withReact(), (config) => {

@ -61,9 +61,7 @@ const App: React.FC = () => {
}
function compilerUrl() {
return state.environment === 'remote'
? 'https://vyper.remixproject.org/compile'
: state.localUrl
return state.environment === 'remote' ? 'https://vyper.remixproject.org/compile' : state.localUrl
}
return (
@ -73,59 +71,28 @@ const App: React.FC = () => {
<img src={'assets/logo.svg'} alt="Vyper logo" />
<h4>yper Compiler</h4>
</div>
<a
rel="noopener noreferrer"
href="https://github.com/ethereum/remix-project/tree/master/apps/vyper"
target="_blank"
>
<a rel="noopener noreferrer" href="https://github.com/ethereum/remix-project/tree/master/apps/vyper" target="_blank">
<i className="fab fa-github"></i>
</a>
</header>
<section>
<div className="px-4 w-100">
<Button
data-id="add-repository"
className="w-100 text-dark w-100 bg-light btn-outline-primary "
onClick={() => remixClient.cloneVyperRepo()}
>
<Button data-id="add-repository" className="w-100 text-dark w-100 bg-light btn-outline-primary " onClick={() => remixClient.cloneVyperRepo()}>
Clone Vyper examples repository
</Button>
</div>
<ToggleButtonGroup
name="remote"
onChange={setEnvironment}
type="radio"
value={state.environment}
>
<ToggleButton
data-id="remote-compiler"
variant="secondary"
name="remote"
value="remote"
>
<ToggleButtonGroup name="remote" onChange={setEnvironment} type="radio" value={state.environment}>
<ToggleButton data-id="remote-compiler" variant="secondary" name="remote" value="remote">
Remote Compiler v0.2.16
</ToggleButton>
<ToggleButton
data-id="local-compiler"
variant="secondary"
name="local"
value="local"
>
<ToggleButton data-id="local-compiler" variant="secondary" name="local" value="local">
Local Compiler
</ToggleButton>
</ToggleButtonGroup>
<LocalUrlInput
url={state.localUrl}
setUrl={setLocalUrl}
environment={state.environment}
/>
<LocalUrlInput url={state.localUrl} setUrl={setLocalUrl} environment={state.environment} />
<WarnRemote environment={state.environment} />
<div className="px-4" id="compile-btn">
<CompilerButton
compilerUrl={compilerUrl()}
contract={contract}
setOutput={(name, update) => setOutput({...output, [name]: update})}
/>
<CompilerButton compilerUrl={compilerUrl()} contract={contract} setOutput={(name, update) => setOutput({...output, [name]: update})} />
</div>
<article id="result" className="px-2">
<VyperResult output={contract ? output[contract] : undefined} />

@ -1,12 +1,5 @@
import React from 'react'
import {
isVyper,
compile,
toStandardOutput,
VyperCompilationOutput,
isCompilationError,
remixClient
} from '../utils'
import {isVyper, compile, toStandardOutput, VyperCompilationOutput, isCompilationError, remixClient} from '../utils'
import Button from 'react-bootstrap/Button'
interface Props {
@ -68,8 +61,7 @@ function CompilerButton({contract, setOutput, compilerUrl}: Props) {
errorIndex = errorIndex + 4
if (message && message.split('\n\n').length > 0) {
try {
message =
message.split('\n\n')[message.split('\n\n').length - 1]
message = message.split('\n\n')[message.split('\n\n').length - 1]
} catch (e) {}
}
if (location.length > 0) {
@ -77,11 +69,7 @@ function CompilerButton({contract, setOutput, compilerUrl}: Props) {
start: {line: parseInt(location[0]) - 1, column: 10},
end: {line: parseInt(location[0]) - 1, column: 10}
}
remixClient.highlight(
lineColumnPos as any,
_contract.name,
message
)
remixClient.highlight(lineColumnPos as any, _contract.name, message)
}
})
}
@ -107,17 +95,9 @@ function CompilerButton({contract, setOutput, compilerUrl}: Props) {
}
return (
<Button
data-id="compile"
onClick={compileContract}
variant="primary"
title={contract}
className="d-flex flex-column"
>
<Button data-id="compile" onClick={compileContract} variant="primary" title={contract} className="d-flex flex-column">
<span>Compile</span>
<span className="overflow-hidden text-truncate text-nowrap">
{contract}
</span>
<span className="overflow-hidden text-truncate text-nowrap">{contract}</span>
</Button>
)
}

@ -19,16 +19,9 @@ function LocalUrlInput({url, setUrl, environment}: Props) {
return (
<Form id="local-url">
<Form.Group controlId="localUrl">
<Form.Text className="text-warning pb-2">
{'Currently we support vyper version > 0.2.16'}
</Form.Text>
<Form.Text className="text-warning pb-2">{'Currently we support vyper version > 0.2.16'}</Form.Text>
<Form.Label>Local Compiler Url</Form.Label>
<Form.Control
onBlur={updateUrl}
defaultValue={url}
type="email"
placeholder="eg http://localhost:8000/compile"
/>
<Form.Control onBlur={updateUrl} defaultValue={url} type="email" placeholder="eg http://localhost:8000/compile" />
<Form.Text className="text-muted"></Form.Text>
</Form.Group>
</Form>

@ -1,9 +1,5 @@
import React, {useState} from 'react'
import {
VyperCompilationResult,
VyperCompilationOutput,
isCompilationError
} from '../utils'
import {VyperCompilationResult, VyperCompilationOutput, isCompilationError} from '../utils'
import Tabs from 'react-bootstrap/Tabs'
import Tab from 'react-bootstrap/Tab'
import Button from 'react-bootstrap/Button'
@ -49,11 +45,7 @@ function VyperResult({output}: VyperResultProps) {
}
return (
<Tabs
id="result"
activeKey={active}
onSelect={(key: any) => setActive(key)}
>
<Tabs id="result" activeKey={active} onSelect={(key: any) => setActive(key)}>
<Tab eventKey="abi" title="ABI">
<CopyToClipboard getContent={() => JSON.stringify(output.abi)}>
<Button variant="info" className="copy" data-id="copy-abi">

@ -10,10 +10,7 @@ function WarnRemoteLabel({environment}: Props) {
}
return (
<small className="mx-4 text-warning pb-4">
The remote compiler should only be used for testing NOT for production
environments. For production, use a local compiler.
</small>
<small className="mx-4 text-warning pb-4">The remote compiler should only be used for testing NOT for production environments. For production, use a local compiler.</small>
)
}

@ -23,14 +23,10 @@ export interface VyperCompilationError {
message: string
}
export type VyperCompilationOutput =
| VyperCompilationResult
| VyperCompilationError
export type VyperCompilationOutput = VyperCompilationResult | VyperCompilationError
/** Check if the output is an error */
export function isCompilationError(
output: VyperCompilationOutput
): output is VyperCompilationError {
export function isCompilationError(output: VyperCompilationOutput): output is VyperCompilationError {
return output.status === 'failed'
}
@ -39,10 +35,7 @@ export function isCompilationError(
* @param url The url of the compiler
* @param contract The name and content of the contract
*/
export async function compile(
url: string,
contract: Contract
): Promise<VyperCompilationOutput> {
export async function compile(url: string, contract: Contract): Promise<VyperCompilationOutput> {
if (!contract.name) {
throw new Error('Set your Vyper contract file.')
}
@ -70,14 +63,9 @@ export async function compile(
* @param name Name of the contract file
* @param compilationResult Result returned by the compiler
*/
export function toStandardOutput(
fileName: string,
compilationResult: VyperCompilationResult
): CompilationResult {
export function toStandardOutput(fileName: string, compilationResult: VyperCompilationResult): CompilationResult {
const contractName = fileName.split('/').slice(-1)[0].split('.')[0]
const methodIdentifiers = JSON.parse(
JSON.stringify(compilationResult['method_identifiers']).replace(/0x/g, '')
)
const methodIdentifiers = JSON.parse(JSON.stringify(compilationResult['method_identifiers']).replace(/0x/g, ''))
return {
sources: {
[fileName]: {

@ -1,8 +1,4 @@
import {
HighlightPosition,
CompilationResult,
RemixApi
} from '@remixproject/plugin-api'
import {HighlightPosition, CompilationResult, RemixApi} from '@remixproject/plugin-api'
import {Api, Status} from '@remixproject/plugin-utils'
import {createClient} from '@remixproject/plugin-webview'
import {PluginClient} from '@remixproject/plugin'
@ -18,13 +14,9 @@ export class RemixClient extends PluginClient {
/** Emit an event when file changed */
async onFileChange(cb: (contract: string) => any) {
this.client.on(
'fileManager',
'currentFileChanged',
async (name: string) => {
cb(name)
}
)
this.client.on('fileManager', 'currentFileChanged', async (name: string) => {
cb(name)
})
}
/** Emit an event when file changed */
@ -37,17 +29,8 @@ export class RemixClient extends PluginClient {
/** Load Ballot contract example into the file manager */
async loadContract({name, address}: ExampleContract) {
try {
const content = await this.client.call(
'contentImport',
'resolve',
address
)
await this.client.call(
'fileManager',
'setFile',
content.cleanUrl,
content.content
)
const content = await this.client.call('contentImport', 'resolve', address)
await this.client.call('fileManager', 'setFile', content.cleanUrl, content.content)
await this.client.call('fileManager', 'switchFile', content.cleanUrl)
} catch (err) {
console.log(err)
@ -59,15 +42,15 @@ export class RemixClient extends PluginClient {
// @ts-ignore
this.call('notification', 'toast', 'cloning Vyper repository...')
await this.call('manager', 'activatePlugin', 'dGitProvider')
// @ts-ignore
await this.call(
'dGitProvider',
'clone',
{url: 'https://github.com/vyperlang/vyper', token: null},
// @ts-ignore
'vyper-lang'
)
// @ts-ignore
this.call(
// @ts-ignore
'notification',
'toast',
'Vyper repository cloned, the workspace Vyper has been created.'
@ -84,11 +67,7 @@ export class RemixClient extends PluginClient {
}
/** Highlight a part of the editor */
async highlight(
lineColumnPos: HighlightPosition,
name: string,
message: string
) {
async highlight(lineColumnPos: HighlightPosition, name: string, message: string) {
await this.client.call('editor', 'highlight', lineColumnPos, name)
/*
column: -1

@ -27,13 +27,7 @@ function App() {
return (
<div className="App">
<h4 className="mt-1">WalletConnect</h4>
{ethereumClient && wagmiConfig && (
<WalletConnectUI
wagmiConfig={wagmiConfig}
ethereumClient={ethereumClient}
theme={theme}
/>
)}
{ethereumClient && wagmiConfig && <WalletConnectUI wagmiConfig={wagmiConfig} ethereumClient={ethereumClient} theme={theme} />}
</div>
)
}

@ -10,11 +10,7 @@ export function WalletConnectUI({ethereumClient, wagmiConfig, theme}) {
<Web3Button label="Connect to a wallet" />
</WagmiConfig>
</div>
<Web3Modal
projectId={PROJECT_ID}
ethereumClient={ethereumClient}
themeMode={theme}
/>
<Web3Modal projectId={PROJECT_ID} ethereumClient={ethereumClient} themeMode={theme} />
</div>
)
}

@ -50,9 +50,7 @@ module.exports = composePlugins(withNx(), (config) => {
// set the define plugin to load the WALLET_CONNECT_PROJECT_ID
config.plugins.push(
new webpack.DefinePlugin({
WALLET_CONNECT_PROJECT_ID: JSON.stringify(
process.env.WALLET_CONNECT_PROJECT_ID
)
WALLET_CONNECT_PROJECT_ID: JSON.stringify(process.env.WALLET_CONNECT_PROJECT_ID)
})
)

@ -19,17 +19,7 @@ const inputJson = {
outputSelection: {
'*': {
'': ['ast'],
'*': [
'abi',
'metadata',
'devdoc',
'userdoc',
'evm.legacyAssembly',
'evm.bytecode',
'evm.deployedBytecode',
'evm.methodIdentifiers',
'evm.gasEstimates'
]
'*': ['abi', 'metadata', 'devdoc', 'userdoc', 'evm.legacyAssembly', 'evm.bytecode', 'evm.deployedBytecode', 'evm.methodIdentifiers', 'evm.gasEstimates']
}
}
}
@ -43,9 +33,7 @@ console.dir(inputJson)
console.log('compiling...')
const compilationData = JSON.parse(
solc.compileStandardWrapper(JSON.stringify(inputJson))
)
const compilationData = JSON.parse(solc.compileStandardWrapper(JSON.stringify(inputJson)))
console.dir(Object.keys(compilationData))
const compilation = {}
compilation['data'] = compilationData

@ -19,9 +19,7 @@ const DragBar = (props: IRemixDragBarUi) => {
const nodeRef = React.useRef(null) // fix for strictmode
useEffect(() => {
setDragBarPosX(
offset + (props.hidden ? 0 : props.refObject.current.offsetWidth)
)
setDragBarPosX(offset + (props.hidden ? 0 : props.refObject.current.offsetWidth))
}, [props.hidden, offset])
useEffect(() => {
@ -49,9 +47,7 @@ const DragBar = (props: IRemixDragBarUi) => {
const handleResize = () => {
if (!props.refObject.current) return
setOffSet(props.refObject.current.offsetLeft)
setDragBarPosX(
props.refObject.current.offsetLeft + props.refObject.current.offsetWidth
)
setDragBarPosX(props.refObject.current.offsetLeft + props.refObject.current.offsetWidth)
}
useEffect(() => {
@ -81,17 +77,8 @@ const DragBar = (props: IRemixDragBarUi) => {
return (
<>
<div className={`overlay ${dragState ? '' : 'd-none'}`}></div>
<Draggable
nodeRef={nodeRef}
position={{x: dragBarPosX, y: 0}}
onStart={startDrag}
onStop={stopDrag}
axis="x"
>
<div
ref={nodeRef}
className={`dragbar ${dragState ? 'ondrag' : ''}`}
></div>
<Draggable nodeRef={nodeRef} position={{x: dragBarPosX, y: 0}} onStart={startDrag} onStop={stopDrag} axis="x">
<div ref={nodeRef} className={`dragbar ${dragState ? 'ondrag' : ''}`}></div>
</Draggable>
</>
)

@ -10,11 +10,7 @@ const AppDialogs = () => {
return (
<>
<ModalWrapper {...focusModal} handleHide={handleHideModal}></ModalWrapper>
<Toaster
message={focusToaster.message}
timestamp={focusToaster.timestamp}
handleHide={handleToaster}
/>
<Toaster message={focusToaster.message} timestamp={focusToaster.timestamp} handleHide={handleToaster} />
</>
)
}

@ -21,36 +21,20 @@ const MatomoDialog = (props) => {
<a href="https://matomo.org" target="_blank" rel="noreferrer">
Matomo
</a>
, an open source data analytics platform is being used to improve
Remix IDE.
, an open source data analytics platform is being used to improve Remix IDE.
</p>
<p>We realize that our users have sensitive information in their code and that their privacy - your privacy - must be protected.</p>
<p>
We realize that our users have sensitive information in their code and
that their privacy - your privacy - must be protected.
</p>
<p>
All data collected through Matomo is stored on our own server - no
data is ever given to third parties. Our analytics reports are public:{' '}
<a
href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday"
target="_blank"
rel="noreferrer"
>
All data collected through Matomo is stored on our own server - no data is ever given to third parties. Our analytics reports are public:{' '}
<a href="https://matomo.ethereum.org/index.php?module=MultiSites&action=index&idSite=23&period=day&date=yesterday" target="_blank" rel="noreferrer">
take a look
</a>
.
</p>
<p>
We do not collect nor store any personally identifiable information
(PII).
</p>
<p>We do not collect nor store any personally identifiable information (PII).</p>
<p>
For more info, see:{' '}
<a
href="https://medium.com/p/66ef69e14931/"
target="_blank"
rel="noreferrer"
>
<a href="https://medium.com/p/66ef69e14931/" target="_blank" rel="noreferrer">
Matomo Analyitcs on Remix iDE
</a>
.
@ -84,8 +68,7 @@ const MatomoDialog = (props) => {
const handleModalOkClick = async () => {
_paq.push(['forgetUserOptOut'])
// @TODO remove next line when https://github.com/matomo-org/matomo/commit/9e10a150585522ca30ecdd275007a882a70c6df5 is used
document.cookie =
'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
document.cookie = 'mtm_consent_removed=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'
settings.updateMatomoAnalyticsChoice(true)
appManager.call('walkthrough', 'start')
setVisible(false)

@ -1,9 +1,5 @@
import React, {useEffect, useRef, useState} from 'react'
import {
ModalDialog,
ModalDialogProps,
ValidationResult
} from '@remix-ui/modal-dialog'
import {ModalDialog, ModalDialogProps, ValidationResult} from '@remix-ui/modal-dialog'
import {ModalTypes} from '../../types'
interface ModalWrapperProps extends ModalDialogProps {
@ -34,10 +30,11 @@ const ModalWrapper = (props: ModalWrapperProps) => {
} else if (formRef.current) {
props.okFn ? props.okFn(getFormData()) : props.resolve(getFormData())
} else if (ref.current) {
// @ts-ignore: Object is possibly 'null'.
props.okFn
? props.okFn(ref.current.value)
: props.resolve(ref.current.value)
? // @ts-ignore: Object is possibly 'null'.
props.okFn(ref.current.value)
: // @ts-ignore: Object is possibly 'null'.
props.resolve(ref.current.value)
}
}
@ -62,10 +59,7 @@ const ModalWrapper = (props: ModalWrapperProps) => {
}
}
const createModalMessage = (
defaultValue: string,
validation: ValidationResult
) => {
const createModalMessage = (defaultValue: string, validation: ValidationResult) => {
return (
<>
{props.message}
@ -77,9 +71,7 @@ const ModalWrapper = (props: ModalWrapperProps) => {
ref={ref}
className="form-control"
/>
{validation && !validation.valid && (
<span className="text-warning">{validation.message}</span>
)}
{validation && !validation.valid && <span className="text-warning">{validation.message}</span>}
</>
)
}
@ -99,9 +91,7 @@ const ModalWrapper = (props: ModalWrapperProps) => {
<form onChange={onFormChanged} ref={formRef}>
{props.message}
</form>
{validation && !validation.valid && (
<span className="text-warning">{validation.message}</span>
)}
{validation && !validation.valid && <span className="text-warning">{validation.message}</span>}
</>
)
}

@ -9,17 +9,12 @@ const OriginWarning = () => {
useEffect(() => {
// check the origin and warn message
if (window.location.hostname === 'yann300.github.io') {
setContent(
'This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.'
)
setContent('This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.')
} else if (
window.location.hostname === 'remix-alpha.ethereum.org' ||
(window.location.hostname === 'ethereum.github.io' &&
window.location.pathname.indexOf('/remix-live-alpha') === 0)
(window.location.hostname === 'ethereum.github.io' && window.location.pathname.indexOf('/remix-live-alpha') === 0)
) {
setContent(
'Welcome to the Remix alpha instance. Please use it to try out latest features. But use preferably https://remix.ethereum.org for any production work.'
)
setContent('Welcome to the Remix alpha instance. Please use it to try out latest features. But use preferably https://remix.ethereum.org for any production work.')
} else if (
window.location.protocol.indexOf('http') === 0 &&
window.location.hostname !== 'remix.ethereum.org' &&

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

@ -12,14 +12,12 @@ export interface dispatchModalInterface {
handleToaster: () => void
}
export const dispatchModalContext = React.createContext<dispatchModalInterface>(
{
modal: (data: AppModal) => {},
toast: (message: string | JSX.Element) => {},
alert: (data: AlertModal) => {},
handleHideModal: () => {},
handleToaster: () => {}
}
)
export const dispatchModalContext = React.createContext<dispatchModalInterface>({
modal: (data: AppModal) => {},
toast: (message: string | JSX.Element) => {},
alert: (data: AlertModal) => {},
handleHideModal: () => {},
handleToaster: () => {}
})
export const modalContext = React.createContext(ModalInitialState)

@ -6,15 +6,8 @@ import {ModalInitialState} from '../state/modals'
import {ModalTypes} from '../types'
import {AppContext, dispatchModalContext, modalContext} from './context'
export const ModalProvider = ({
children = [],
reducer = modalReducer,
initialState = ModalInitialState
} = {}) => {
const [{modals, toasters, focusModal, focusToaster}, dispatch] = useReducer(
reducer,
initialState
)
export const ModalProvider = ({children = [], reducer = modalReducer, initialState = ModalInitialState} = {}) => {
const [{modals, toasters, focusModal, focusToaster}, dispatch] = useReducer(reducer, initialState)
const onNextFn = async () => {
dispatch({
@ -23,20 +16,7 @@ export const ModalProvider = ({
}
const modal = (modalData: AppModal) => {
const {
id,
title,
message,
validationFn,
okLabel,
okFn,
cancelLabel,
cancelFn,
modalType,
defaultValue,
hideFn,
data
} = modalData
const {id, title, message, validationFn, okLabel, okFn, cancelLabel, cancelFn, modalType, defaultValue, hideFn, data} = modalData
return new Promise((resolve, reject) => {
dispatch({
type: modalActionTypes.setModal,
@ -94,14 +74,8 @@ export const ModalProvider = ({
}
return (
<dispatchModalContext.Provider
value={{modal, toast, alert, handleHideModal, handleToaster}}
>
<modalContext.Provider
value={{modals, toasters, focusModal, focusToaster}}
>
{children}
</modalContext.Provider>
<dispatchModalContext.Provider value={{modal, toast, alert, handleHideModal, handleToaster}}>
<modalContext.Provider value={{modals, toasters, focusModal, focusToaster}}>{children}</modalContext.Provider>
</dispatchModalContext.Provider>
)
}

@ -87,25 +87,11 @@ const RemixApp = (props: IRemixAppUi) => {
<AppProvider value={value}>
<OriginWarning></OriginWarning>
<MatomoDialog hide={!appReady}></MatomoDialog>
<div
className={`remixIDE ${appReady ? '' : 'd-none'}`}
data-id="remixIDE"
>
<div
id="icon-panel"
data-id="remixIdeIconPanel"
className="custom_icon_panel iconpanel bg-light"
>
<div className={`remixIDE ${appReady ? '' : 'd-none'}`} data-id="remixIDE">
<div id="icon-panel" data-id="remixIdeIconPanel" className="custom_icon_panel iconpanel bg-light">
{props.app.menuicons.render()}
</div>
<div
ref={sidePanelRef}
id="side-panel"
data-id="remixIdeSidePanel"
className={`sidepanel border-right border-left ${
hideSidePanel ? 'd-none' : ''
}`}
>
<div ref={sidePanelRef} id="side-panel" data-id="remixIdeSidePanel" className={`sidepanel border-right border-left ${hideSidePanel ? 'd-none' : ''}`}>
{props.app.sidePanel.render()}
</div>
<DragBar
@ -116,17 +102,9 @@ const RemixApp = (props: IRemixAppUi) => {
hidden={hideSidePanel}
setHideStatus={setHideSidePanel}
></DragBar>
<div
id="main-panel"
data-id="remixIdeMainPanel"
className="mainpanel d-flex"
>
<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="Scroll to see all tabs">
<div className="remix-ui-tabs_end remix-bg-opacity position-absolute position-fixed"></div>
</CustomTooltip>
</div>

@ -40,11 +40,7 @@ export const RemixUiCheckbox = ({
tooltipPlacement = 'right'
}: RemixUiCheckboxProps) => {
const childJSXWithTooltip = (
<CustomTooltip
tooltipText={title}
tooltipId={`${name}Tooltip`}
placement={tooltipPlacement}
>
<CustomTooltip tooltipText={title} tooltipId={`${name}Tooltip`} placement={tooltipPlacement}>
<div
className={`listenOnNetwork_2A0YE0 custom-control custom-checkbox ${optionalClassName}`}
style={
@ -56,22 +52,8 @@ export const RemixUiCheckbox = ({
}
onClick={onClick}
>
<input
id={id}
type={inputType}
onChange={onChange}
style={{verticalAlign: 'bottom'}}
name={name}
className="custom-control-input"
checked={checked}
disabled={disabled}
/>
<label
className="form-check-label custom-control-label"
id={`heading${categoryId}`}
style={{paddingTop: '0.15rem'}}
aria-disabled={disabled}
>
<input id={id} type={inputType} onChange={onChange} style={{verticalAlign: 'bottom'}} name={name} className="custom-control-input" checked={checked} disabled={disabled} />
<label className="form-check-label custom-control-label" id={`heading${categoryId}`} style={{paddingTop: '0.15rem'}} aria-disabled={disabled}>
{name ? <div className="font-weight-bold">{itemName}</div> : ''}
{label}
</label>
@ -90,20 +72,8 @@ export const RemixUiCheckbox = ({
}
onClick={onClick}
>
<input
id={id}
type={inputType}
onChange={onChange}
style={{verticalAlign: 'bottom'}}
name={name}
className="custom-control-input"
checked={checked}
/>
<label
className="form-check-label custom-control-label"
id={`heading${categoryId}`}
style={{paddingTop: '0.15rem'}}
>
<input id={id} type={inputType} onChange={onChange} style={{verticalAlign: 'bottom'}} name={name} className="custom-control-input" checked={checked} />
<label className="form-check-label custom-control-label" id={`heading${categoryId}`} style={{paddingTop: '0.15rem'}}>
{name ? <div className="font-weight-bold">{itemName}</div> : ''}
{label}
</label>

@ -16,14 +16,7 @@ interface ICopyToClipboard {
getContent?: () => any
}
export const CopyToClipboard = (props: ICopyToClipboard) => {
const {
tip = 'Copy',
icon = 'fa-copy',
direction = 'right',
getContent,
children,
...otherProps
} = props
const {tip = 'Copy', icon = 'fa-copy', direction = 'right', getContent, children, ...otherProps} = props
let {content} = props
const [message, setMessage] = useState(tip)
@ -58,21 +51,11 @@ export const CopyToClipboard = (props: ICopyToClipboard) => {
setTimeout(() => setMessage(tip), 500)
}
const childJSX = children || (
<i
className={`far ${icon} ml-1 p-2`}
aria-hidden="true"
{...otherProps}
></i>
)
const childJSX = children || <i className={`far ${icon} ml-1 p-2`} aria-hidden="true" {...otherProps}></i>
return (
<a href="#" onClick={handleClick} onMouseLeave={reset}>
<CustomTooltip
tooltipText={message}
tooltipId="overlay-tooltip"
placement={direction}
>
<CustomTooltip tooltipText={message} tooltipId="overlay-tooltip" placement={direction}>
{childJSX}
</CustomTooltip>
</a>

@ -1,28 +1,23 @@
import React, {useState, useEffect} from 'react' // eslint-disable-line
import {ExtractData, ExtractFunc} from '../types' // eslint-disable-line
export const useExtractData = (
json,
extractFunc?: ExtractFunc
): Array<{key: string; data: ExtractData}> => {
export const useExtractData = (json, extractFunc?: ExtractFunc): Array<{key: string; data: ExtractData}> => {
const [data, setData] = useState([])
useEffect(() => {
const data: Array<{key: string; data: ExtractData}> = Object.keys(json).map(
(innerKey) => {
if (extractFunc) {
return {
key: innerKey,
data: extractFunc(json[innerKey], json)
}
} else {
return {
key: innerKey,
data: extractDataDefault(json[innerKey], json)
}
const data: Array<{key: string; data: ExtractData}> = Object.keys(json).map((innerKey) => {
if (extractFunc) {
return {
key: innerKey,
data: extractFunc(json[innerKey], json)
}
} else {
return {
key: innerKey,
data: extractDataDefault(json[innerKey], json)
}
}
)
})
setData(data)

@ -58,27 +58,19 @@ export const ButtonNavigation = ({
intoForwardDisabled: stepState === 'end',
overForwardDisabled: stepState === 'end',
jumpNextBreakpointDisabled: stepState === 'end',
jumpOutDisabled:
jumpOutDisabled !== null && jumpOutDisabled !== undefined
? jumpOutDisabled
: true
jumpOutDisabled: jumpOutDisabled !== null && jumpOutDisabled !== undefined ? jumpOutDisabled : true
}
})
}
const stepBtnStyle =
'd-flex align-items-center justify-content-center btn btn-primary btn-sm stepButton h-75 m-0 p-1'
const stepBtnStyle = 'd-flex align-items-center justify-content-center btn btn-primary btn-sm stepButton h-75 m-0 p-1'
const disableStepBtnStyle = 'stepButtonDisabled'
const disableJumpBtnStyle = 'jumpButtonDisabled'
const stepMarkupStructure = {
stepOverBackJSX: {
markup: (
<div
className={
state.overBackDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.overBackDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
stepOverBack && stepOverBack()
}}
@ -103,11 +95,7 @@ export const ButtonNavigation = ({
stepBackJSX: {
markup: (
<div
className={
state.intoBackDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.intoBackDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
stepIntoBack && stepIntoBack()
}}
@ -136,11 +124,7 @@ export const ButtonNavigation = ({
stepIntoJSX: {
markup: (
<div
className={
state.intoForwardDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.intoForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
stepIntoForward && stepIntoForward()
}}
@ -168,11 +152,7 @@ export const ButtonNavigation = ({
stepOverForwardJSX: {
markup: (
<div
className={
state.overForwardDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.overForwardDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
stepOverForward && stepOverForward()
}}
@ -201,11 +181,7 @@ export const ButtonNavigation = ({
jumpPreviousBreakpointJSX: {
markup: (
<div
className={
state.jumpPreviousBreakpointDisabled
? `${stepBtnStyle} ${disableJumpBtnStyle}`
: `${stepBtnStyle}`
}
className={state.jumpPreviousBreakpointDisabled ? `${stepBtnStyle} ${disableJumpBtnStyle}` : `${stepBtnStyle}`}
id="buttonNavigatorJumpPreviousBreakpointContainer"
onClick={() => {
jumpPreviousBreakpoint && jumpPreviousBreakpoint()
@ -237,11 +213,7 @@ export const ButtonNavigation = ({
jumpOutJSX: {
markup: (
<div
className={
state.jumpOutDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.jumpOutDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
jumpOut && jumpOut()
}}
@ -273,11 +245,7 @@ export const ButtonNavigation = ({
jumpNextBreakpointJSX: {
markup: (
<div
className={
state.jumpNextBreakpointDisabled
? `${stepBtnStyle} ${disableStepBtnStyle}`
: `${stepBtnStyle}`
}
className={state.jumpNextBreakpointDisabled ? `${stepBtnStyle} ${disableStepBtnStyle}` : `${stepBtnStyle}`}
onClick={() => {
jumpNextBreakpoint && jumpNextBreakpoint()
}}
@ -331,19 +299,9 @@ export const ButtonNavigation = ({
</CustomTooltip>
))}
</div>
<div
id="reverted"
style={{display: revertedReason === '' ? 'none' : 'block'}}
>
<span className="text-warning">
This call has reverted, state changes made during the call will be
reverted.
</span>
<span
className="text-warning"
id="outofgas"
style={{display: revertedReason === 'outofgas' ? 'inline' : 'none'}}
>
<div id="reverted" style={{display: revertedReason === '' ? 'none' : 'block'}}>
<span className="text-warning">This call has reverted, state changes made during the call will be reverted.</span>
<span className="text-warning" id="outofgas" style={{display: revertedReason === 'outofgas' ? 'inline' : 'none'}}>
This call will run out of gas.
</span>
<span

@ -54,12 +54,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const handleResize = () => {
if (panelsRef.current && debuggerTopRef.current) {
panelsRef.current.style.height =
window.innerHeight -
debuggerTopRef.current.clientHeight -
debuggerTopRef.current.offsetTop -
7 +
'px'
panelsRef.current.style.height = window.innerHeight - debuggerTopRef.current.clientHeight - debuggerTopRef.current.offsetTop - 7 + 'px'
}
}
@ -97,8 +92,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
})
debuggerModule.onBreakpointAdded((fileName, row) => {
if (state.debugger)
state.debugger.breakPointManager.add({fileName: fileName, row: row})
if (state.debugger) state.debugger.breakPointManager.add({fileName: fileName, row: row})
})
debuggerModule.onEditorContentChanged(() => {
@ -111,8 +105,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const providerChanged = () => {
debuggerModule.onEnvChanged((provider) => {
setState((prevState) => {
const isLocalNodeUsed =
!provider.startsWith('vm') && provider !== 'injected'
const isLocalNodeUsed = !provider.startsWith('vm') && provider !== 'injected'
return {...prevState, isLocalNodeUsed: isLocalNodeUsed}
})
})
@ -135,8 +128,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
setState((prevState) => {
return {
...prevState,
sourceLocationStatus:
'Locating breakpoint, this might take a while...'
sourceLocationStatus: 'Locating breakpoint, this might take a while...'
}
})
})
@ -147,69 +139,48 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
})
})
debuggerInstance.event.register(
'newSourceLocation',
async (
lineColumnPos,
rawLocation,
generatedSources,
address,
stepDetail,
lineGasCost
) => {
if (!lineColumnPos) {
await debuggerModule.discardHighlight()
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.'
}
})
return
}
const contracts = await debuggerModule.fetchContractAndCompile(
address || currentReceipt.contractAddress || currentReceipt.to,
currentReceipt
)
if (contracts) {
let path = contracts.getSourceName(rawLocation.file)
if (!path) {
// check in generated sources
for (const source of generatedSources) {
if (source.id === rawLocation.file) {
path = `browser/.debugger/generated-sources/${source.name}`
let content
try {
content = await debuggerModule.getFile(path)
} catch (e) {
const message =
"Unable to fetch generated sources, the file probably doesn't exist yet."
console.log(message, ' ', e)
}
if (content !== source.contents) {
await debuggerModule.setFile(path, source.contents)
}
break
debuggerInstance.event.register('newSourceLocation', async (lineColumnPos, rawLocation, generatedSources, address, stepDetail, lineGasCost) => {
if (!lineColumnPos) {
await debuggerModule.discardHighlight()
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.'
}
})
return
}
const contracts = await debuggerModule.fetchContractAndCompile(address || currentReceipt.contractAddress || currentReceipt.to, currentReceipt)
if (contracts) {
let path = contracts.getSourceName(rawLocation.file)
if (!path) {
// check in generated sources
for (const source of generatedSources) {
if (source.id === rawLocation.file) {
path = `browser/.debugger/generated-sources/${source.name}`
let content
try {
content = await debuggerModule.getFile(path)
} catch (e) {
const message = "Unable to fetch generated sources, the file probably doesn't exist yet."
console.log(message, ' ', e)
}
if (content !== source.contents) {
await debuggerModule.setFile(path, source.contents)
}
break
}
}
if (path) {
setState((prevState) => {
return {...prevState, sourceLocationStatus: ''}
})
await debuggerModule.discardHighlight()
await debuggerModule.highlight(
lineColumnPos,
path,
rawLocation,
stepDetail,
lineGasCost
)
}
}
if (path) {
setState((prevState) => {
return {...prevState, sourceLocationStatus: ''}
})
await debuggerModule.discardHighlight()
await debuggerModule.highlight(lineColumnPos, path, rawLocation, stepDetail, lineGasCost)
}
}
)
})
debuggerInstance.event.register('debuggerUnloaded', () => unLoad())
}
@ -284,11 +255,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
return
}
const web3 =
optWeb3 ||
(state.opt.debugWithLocalNode
? await debuggerModule.web3()
: await debuggerModule.getDebugWeb3())
const web3 = optWeb3 || (state.opt.debugWithLocalNode ? await debuggerModule.web3() : await debuggerModule.getDebugWeb3())
try {
const networkId = await web3.eth.net.getId()
_paq.push(['trackEvent', 'debugger', 'startDebugging', networkId])
@ -296,8 +263,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
setState((prevState) => {
return {
...prevState,
validationError:
'Unfortunately, the Kovan network is not supported.'
validationError: 'Unfortunately, the Kovan network is not supported.'
}
})
return
@ -328,11 +294,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
offsetToLineColumnConverter: debuggerModule.offsetToLineColumnConverter,
compilationResult: async (address) => {
try {
if (!localCache[address])
localCache[address] = await debuggerModule.fetchContractAndCompile(
address,
currentReceipt
)
if (!localCache[address]) localCache[address] = await debuggerModule.fetchContractAndCompile(address, currentReceipt)
return localCache[address]
} catch (e) {
// debuggerModule.showMessage('Debugging error', 'Unable to fetch a transaction.')
@ -368,9 +330,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
setState((prevState) => {
let errorMsg = error.message || error
if (typeof errorMsg !== 'string') {
errorMsg =
JSON.stringify(errorMsg) +
'. Possible error: the current endpoint does not support retrieving the trace of a transaction.'
errorMsg = JSON.stringify(errorMsg) + '. Possible error: the current endpoint does not support retrieving the trace of a transaction.'
}
return {
...prevState,
@ -397,81 +357,22 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}
const stepManager = {
jumpTo:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.jumpTo.bind(state.debugger.step_manager)
: null,
stepOverBack:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.stepOverBack.bind(
state.debugger.step_manager
)
: null,
stepIntoBack:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.stepIntoBack.bind(
state.debugger.step_manager
)
: null,
stepIntoForward:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.stepIntoForward.bind(
state.debugger.step_manager
)
: null,
stepOverForward:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.stepOverForward.bind(
state.debugger.step_manager
)
: null,
jumpOut:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.jumpOut.bind(state.debugger.step_manager)
: null,
jumpPreviousBreakpoint:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.jumpPreviousBreakpoint.bind(
state.debugger.step_manager
)
: null,
jumpNextBreakpoint:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.jumpNextBreakpoint.bind(
state.debugger.step_manager
)
: null,
jumpToException:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.jumpToException.bind(
state.debugger.step_manager
)
: null,
traceLength:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.traceLength
: null,
registerEvent:
state.debugger && state.debugger.step_manager
? state.debugger.step_manager.event.register.bind(
state.debugger.step_manager.event
)
: null
jumpTo: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.jumpTo.bind(state.debugger.step_manager) : null,
stepOverBack: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.stepOverBack.bind(state.debugger.step_manager) : null,
stepIntoBack: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.stepIntoBack.bind(state.debugger.step_manager) : null,
stepIntoForward: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.stepIntoForward.bind(state.debugger.step_manager) : null,
stepOverForward: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.stepOverForward.bind(state.debugger.step_manager) : null,
jumpOut: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.jumpOut.bind(state.debugger.step_manager) : null,
jumpPreviousBreakpoint: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.jumpPreviousBreakpoint.bind(state.debugger.step_manager) : null,
jumpNextBreakpoint: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.jumpNextBreakpoint.bind(state.debugger.step_manager) : null,
jumpToException: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.jumpToException.bind(state.debugger.step_manager) : null,
traceLength: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.traceLength : null,
registerEvent: state.debugger && state.debugger.step_manager ? state.debugger.step_manager.event.register.bind(state.debugger.step_manager.event) : null
}
const vmDebugger = {
registerEvent:
state.debugger && state.debugger.vmDebuggerLogic
? state.debugger.vmDebuggerLogic.event.register.bind(
state.debugger.vmDebuggerLogic.event
)
: null,
triggerEvent:
state.debugger && state.debugger.vmDebuggerLogic
? state.debugger.vmDebuggerLogic.event.trigger.bind(
state.debugger.vmDebuggerLogic.event
)
: null
registerEvent: state.debugger && state.debugger.vmDebuggerLogic ? state.debugger.vmDebuggerLogic.event.register.bind(state.debugger.vmDebuggerLogic.event) : null,
triggerEvent: state.debugger && state.debugger.vmDebuggerLogic ? state.debugger.vmDebuggerLogic.event.trigger.bind(state.debugger.vmDebuggerLogic.event) : null
}
const customJSX = (
@ -489,11 +390,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
}}
type="checkbox"
/>
<label
data-id="debugGeneratedSourcesLabel"
className="form-check-label custom-control-label"
htmlFor="debugGeneratedSourcesInput"
>
<label data-id="debugGeneratedSourcesLabel" className="form-check-label custom-control-label" htmlFor="debugGeneratedSourcesInput">
<FormattedMessage id="debugger.useGeneratedSources" />
(Solidity {'>='} v0.7.2)
</label>
@ -505,23 +402,13 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
<div className="px-2" ref={debuggerTopRef}>
<div>
<div className="mt-2 mb-2 debuggerConfig custom-control custom-checkbox">
<CustomTooltip
tooltipId="debuggerGenSourceCheckbox"
tooltipText={
<FormattedMessage id="debugger.debugWithGeneratedSources" />
}
placement="bottom-start"
>
<CustomTooltip tooltipId="debuggerGenSourceCheckbox" tooltipText={<FormattedMessage id="debugger.debugWithGeneratedSources" />} placement="bottom-start">
{customJSX}
</CustomTooltip>
</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="Force the debugger to use the current local node" placement="right">
<input
className="custom-control-input"
id="debugWithLocalNodeInput"
@ -536,20 +423,12 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
type="checkbox"
/>
</CustomTooltip>
<label
data-id="debugLocaNodeLabel"
className="form-check-label custom-control-label"
htmlFor="debugWithLocalNodeInput"
>
<label data-id="debugLocaNodeLabel" className="form-check-label custom-control-label" htmlFor="debugWithLocalNodeInput">
<FormattedMessage id="debugger.debugLocaNodeLabel" />
</label>
</div>
)}
{state.validationError && (
<span className="w-100 py-1 text-danger validationError">
{state.validationError}
</span>
)}
{state.validationError && <span className="w-100 py-1 text-danger validationError">{state.validationError}</span>}
</div>
<TxBrowser
requestDebug={requestDebug}
@ -560,8 +439,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
/>
{state.debugging && state.sourceLocationStatus && (
<div className="text-warning">
<i className="fas fa-exclamation-triangle" aria-hidden="true"></i>{' '}
{state.sourceLocationStatus}
<i className="fas fa-exclamation-triangle" aria-hidden="true"></i> {state.sourceLocationStatus}
</div>
)}
{!state.debugging && (
@ -582,9 +460,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
{state.debugging && <StepManager stepManager={stepManager} />}
</div>
<div className="debuggerPanels" ref={panelsRef}>
{state.debugging && (
<VmDebuggerHead debugging={state.debugging} vmDebugger={vmDebugger} />
)}
{state.debugging && <VmDebuggerHead debugging={state.debugging} vmDebugger={vmDebugger} />}
{state.debugging && (
<VmDebugger
debugging={state.debugging}

@ -44,11 +44,7 @@ export const StepManager = ({
return (
<div className="py-1">
<Slider
jumpTo={jumpTo}
sliderValue={sliderValue}
traceLength={traceLength}
/>
<Slider jumpTo={jumpTo} sliderValue={sliderValue} traceLength={traceLength} />
<ButtonNavigator
stepIntoBack={stepIntoBack}
stepIntoForward={stepIntoForward}

@ -3,13 +3,7 @@ import React, {useState, useEffect, useRef} from 'react' //eslint-disable-line
import {useIntl, FormattedMessage} from 'react-intl'
import './tx-browser.css'
export const TxBrowser = ({
requestDebug,
updateTxNumberFlag,
unloadRequested,
transactionNumber,
debugging
}) => {
export const TxBrowser = ({requestDebug, updateTxNumberFlag, unloadRequested, transactionNumber, debugging}) => {
const [state, setState] = useState({
txNumber: ''
})
@ -72,9 +66,7 @@ export const TxBrowser = ({
style={{pointerEvents: 'none', color: 'white'}}
>
<span>
<FormattedMessage
id={`debugger.${debugging ? 'stopDebugging' : 'startDebugging'}`}
/>
<FormattedMessage id={`debugger.${debugging ? 'stopDebugging' : 'startDebugging'}`} />
</span>
</button>
</div>
@ -99,13 +91,7 @@ export const TxBrowser = ({
<div className="d-flex justify-content-center w-100 btn-group py-1">
<CustomTooltip
placement="bottom"
tooltipText={
<FormattedMessage
id={`debugger.${
debugging ? 'stopDebugging' : 'startDebugging'
}`}
/>
}
tooltipText={<FormattedMessage id={`debugger.${debugging ? 'stopDebugging' : 'startDebugging'}`} />}
tooltipId={'debuggingButtontooltip'}
tooltipClasses="text-nowrap"
>

@ -8,49 +8,34 @@ export const AssemblyItems = ({registerEvent}) => {
const [selectedItem, setSelectedItem] = useState(0)
const [nextSelectedItems, setNextSelectedItems] = useState([1])
const [returnInstructionIndexes, setReturnInstructionIndexes] = useState([])
const [outOfGasInstructionIndexes, setOutOfGasInstructionIndexes] = useState(
[]
)
const [outOfGasInstructionIndexes, setOutOfGasInstructionIndexes] = useState([])
const [opcodeTooltipText, setOpcodeTooltipText] = useState('')
const refs = useRef({})
const asmItemsRef = useRef(null)
useEffect(() => {
registerEvent &&
registerEvent(
'codeManagerChanged',
(
code,
address,
index,
nextIndexes,
returnInstructionIndexes,
outOfGasInstructionIndexes
) => {
dispatch({
type: 'FETCH_OPCODES_SUCCESS',
payload: {
code,
address,
index,
nextIndexes,
returnInstructionIndexes,
outOfGasInstructionIndexes
}
})
}
)
registerEvent('codeManagerChanged', (code, address, index, nextIndexes, returnInstructionIndexes, outOfGasInstructionIndexes) => {
dispatch({
type: 'FETCH_OPCODES_SUCCESS',
payload: {
code,
address,
index,
nextIndexes,
returnInstructionIndexes,
outOfGasInstructionIndexes
}
})
})
registerEvent &&
registerEvent(
'lineGasCostChanged',
(instructionsIndexes: number[], line: []) => {
dispatch({
type: 'FETCH_INDEXES_FOR_NEW_LINE',
payload: {currentLineIndexes: instructionsIndexes || [], line}
})
}
)
registerEvent('lineGasCostChanged', (instructionsIndexes: number[], line: []) => {
dispatch({
type: 'FETCH_INDEXES_FOR_NEW_LINE',
payload: {currentLineIndexes: instructionsIndexes || [], line}
})
})
}, [])
useEffect(() => {
@ -161,12 +146,7 @@ export const AssemblyItems = ({registerEvent}) => {
<div className="dropdownpanel">
<div className="dropdowncontent pb-2">
{assemblyItems.display.length == 0 && <div>No data available</div>}
<div
className="pl-2 my-1 small instructions"
data-id="asmitems"
id="asmitems"
ref={asmItemsRef}
>
<div className="pl-2 my-1 small instructions" data-id="asmitems" id="asmitems" ref={asmItemsRef}>
{assemblyItems.display.map((item, i) => {
return (
<div

@ -61,29 +61,21 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
<span>
<span className="m-0 label_value">0x</span>
<span className="m-0 label_value">{split[1]}</span>
{split[2] && (
<span className="m-0 label_value font-weight-bold text-dark">
{split[2]}
</span>
)}
{split[2] && <span className="m-0 label_value font-weight-bold text-dark">{split[2]}</span>}
</span>
)
} else
value = (
<span>
<span className="m-0 label_value">0x</span>
<span className="m-0 label_value font-weight-bold text-dark">
{data.self.replace('0x', '')}
</span>
<span className="m-0 label_value font-weight-bold text-dark">{data.self.replace('0x', '')}</span>
</span>
)
} else value = <span className="m-0 label_value">{data.self}</span>
} else value = <span className="m-0 label_value">{data.self}</span>
return (
<div className="d-flex mr-1 flex-row label_item">
<label className="small font-weight-bold mb-0 pr-1 label_key">
{key}:
</label>
<label className="small font-weight-bold mb-0 pr-1 label_key">{key}:</label>
<label className="m-0 label_value">{value}</label>
</div>
)
@ -145,9 +137,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
if (!state.expandPath.includes(keyPath)) {
state.expandPath.push(keyPath)
} else {
state.expandPath = state.expandPath.filter(
(path) => !path.startsWith(keyPath)
)
state.expandPath = state.expandPath.filter((path) => !path.startsWith(keyPath))
}
}
@ -186,14 +176,8 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
const update = function (calldata) {
let isEmpty = !calldata
if (calldata && Array.isArray(calldata) && calldata.length === 0)
isEmpty = true
else if (
calldata &&
Object.keys(calldata).length === 0 &&
calldata.constructor === Object
)
isEmpty = true
if (calldata && Array.isArray(calldata) && calldata.length === 0) isEmpty = true
else if (calldata && Object.keys(calldata).length === 0 && calldata.constructor === Object) isEmpty = true
setState((prevState) => {
return {
@ -203,10 +187,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
display: 'block'
},
// replace 0xNaN with 0x0
copiableContent: JSON.stringify(calldata, null, '\t').replace(
/0xNaN/g,
'0x0'
),
copiableContent: JSON.stringify(calldata, null, '\t').replace(/0xNaN/g, '0x0'),
message: {
innerText: isEmpty ? 'No data available' : '',
display: isEmpty ? 'block' : 'none'
@ -218,15 +199,8 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
})
}
const renderData = (
item: ExtractData,
parent,
key: string | number,
keyPath: string
) => {
const data = extractFunc
? extractFunc(item, parent)
: extractDataDefault(item, parent)
const renderData = (item: ExtractData, parent, key: string | number, keyPath: string) => {
const data = extractFunc ? extractFunc(item, parent) : extractDataDefault(item, parent)
const children = (data.children || []).map((child) => {
return renderData(child.value, data, child.key, keyPath + '/' + child.key)
})
@ -236,11 +210,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
<TreeViewItem
id={`treeViewItem${key}`}
key={keyPath}
label={
formatSelfFunc
? formatSelfFunc(key, data)
: formatSelfDefault(key, data)
}
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
>
@ -265,11 +235,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
<TreeViewItem
id={key.toString()}
key={keyPath}
label={
formatSelfFunc
? formatSelfFunc(key, data)
: formatSelfDefault(key, data)
}
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
/>
@ -282,49 +248,19 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
return (
<div className={className + ' border rounded px-1 mt-1 bg-light'}>
<div className="py-0 px-1 title" style={headStyle}>
<div
className={
state.toggleDropdown
? 'icon fas fa-caret-down'
: 'icon fas fa-caret-right'
}
onClick={handleToggle}
></div>
<div
className="name"
data-id={`dropdownPanel${uniquePanelName}`}
onClick={handleToggle}
>
<div className={state.toggleDropdown ? 'icon fas fa-caret-down' : 'icon fas fa-caret-right'} onClick={handleToggle}></div>
<div className="name" data-id={`dropdownPanel${uniquePanelName}`} onClick={handleToggle}>
{dropdownName}
</div>
<span className="nameDetail" onClick={handleToggle}>
{header}
</span>
<CopyToClipboard
content={state.copiableContent}
data-id={`dropdownPanelCopyToClipboard${uniquePanelName}`}
/>
<CopyToClipboard 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>
<div
className="dropdowncontent pb-2"
style={{display: state.dropdownContent.display, ...bodyStyle}}
>
{state.data && (
<TreeView id="treeView">
{Object.keys(state.data).map((innerkey) =>
renderData(state.data[innerkey], state.data, innerkey, innerkey)
)}
</TreeView>
)}
<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>
<div className="dropdowncontent pb-2" style={{display: state.dropdownContent.display, ...bodyStyle}}>
{state.data && <TreeView id="treeView">{Object.keys(state.data).map((innerkey) => renderData(state.data[innerkey], state.data, innerkey, innerkey))}</TreeView>}
</div>
<div className="dropdownrawcontent" hidden={true}>
{state.copiableContent}

@ -4,10 +4,7 @@ import {DropdownPanel} from './dropdown-panel' // eslint-disable-line
export const FullStoragesChanges = ({calldata, className = ''}) => {
return (
<div className={className} id="fullstorageschangespanel">
<DropdownPanel
dropdownName="Full Storage Changes"
calldata={calldata || {}}
/>
<DropdownPanel dropdownName="Full Storage Changes" calldata={calldata || {}} />
</div>
)
}

@ -18,19 +18,12 @@ export const GlobalVariables = ({block, receipt, tx, className}) => {
'tx.origin': tx && tx.from
}
if (block && block.baseFeePerGas) {
globals['block.basefee'] =
Web3.utils.toBN(block.baseFeePerGas).toString(10) +
` Wei (${block.baseFeePerGas})`
globals['block.basefee'] = Web3.utils.toBN(block.baseFeePerGas).toString(10) + ` Wei (${block.baseFeePerGas})`
}
return (
<div id="globalvariable" data-id="globalvariable" className={className}>
<DropdownPanel
hexHighlight={false}
bodyStyle={{fontFamily: 'monospace'}}
dropdownName="Global Variables"
calldata={globals || {}}
/>
<DropdownPanel hexHighlight={false} bodyStyle={{fontFamily: 'monospace'}} dropdownName="Global Variables" calldata={globals || {}} />
</div>
)
}

@ -4,12 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const MemoryPanel = ({calldata, className}) => {
return (
<div className={className}>
<DropdownPanel
hexHighlight={true}
bodyStyle={{fontFamily: 'monospace'}}
dropdownName="Memory"
calldata={calldata || {}}
/>
<DropdownPanel hexHighlight={true} bodyStyle={{fontFamily: 'monospace'}} dropdownName="Memory" calldata={calldata || {}} />
</div>
)
}

@ -3,13 +3,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
import {extractData} from '../../utils/solidityTypeFormatter' // eslint-disable-line
import {ExtractData} from '../../types' // eslint-disable-line
export const SolidityLocals = ({
data,
message,
registerEvent,
triggerEvent,
className = ''
}) => {
export const SolidityLocals = ({data, message, registerEvent, triggerEvent, className = ''}) => {
const [calldata, setCalldata] = useState(null)
useEffect(() => {
@ -20,12 +14,7 @@ export const SolidityLocals = ({
let color = 'var(--primary)'
if (data.isArray || data.isStruct || data.isMapping) {
color = 'var(--info)'
} else if (
data.type.indexOf('uint') === 0 ||
data.type.indexOf('int') === 0 ||
data.type.indexOf('bool') === 0 ||
data.type.indexOf('enum') === 0
) {
} else if (data.type.indexOf('uint') === 0 || data.type.indexOf('int') === 0 || data.type.indexOf('bool') === 0 || data.type.indexOf('enum') === 0) {
color = 'var(--green)'
} else if (data.type === 'string') {
color = 'var(--teal)'
@ -48,9 +37,7 @@ export const SolidityLocals = ({
<label className="mb-0" style={{color}}>
{' ' + data.self}
</label>
<label style={{fontStyle: 'italic'}}>
{data.isProperty || !data.type ? '' : ' ' + data.type}
</label>
<label style={{fontStyle: 'italic'}}>{data.isProperty || !data.type ? '' : ' ' + data.type}</label>
</label>
)
}

@ -9,12 +9,7 @@ export const SolidityState = ({calldata, message, className}) => {
let color = 'var(--primary)'
if (data.isArray || data.isStruct || data.isMapping) {
color = 'var(--info)'
} else if (
data.type.indexOf('uint') === 0 ||
data.type.indexOf('int') === 0 ||
data.type.indexOf('bool') === 0 ||
data.type.indexOf('enum') === 0
) {
} else if (data.type.indexOf('uint') === 0 || data.type.indexOf('int') === 0 || data.type.indexOf('bool') === 0 || data.type.indexOf('enum') === 0) {
color = 'var(--green)'
} else if (data.type === 'string') {
color = 'var(--teal)'
@ -34,9 +29,7 @@ export const SolidityState = ({calldata, message, className}) => {
<label className="mb-0" style={{color}}>
{' ' + data.self}
</label>
<label style={{fontStyle: 'italic'}}>
{data.isProperty || !data.type ? '' : ' ' + data.type}
</label>
<label style={{fontStyle: 'italic'}}>{data.isProperty || !data.type ? '' : ' ' + data.type}</label>
</label>
)
} catch (e) {
@ -46,14 +39,7 @@ export const SolidityState = ({calldata, message, className}) => {
return (
<div id="soliditystate" data-id="soliditystate" className={className}>
{
<DropdownPanel
dropdownName="Solidity State"
calldata={calldata || {}}
formatSelfFunc={formatSelf}
extractFunc={extractData}
/>
}
{<DropdownPanel dropdownName="Solidity State" calldata={calldata || {}} formatSelfFunc={formatSelf} extractFunc={extractData} />}
</div>
)
}

@ -4,12 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StackPanel = ({calldata, className}) => {
return (
<div id="stackpanel" className={className}>
<DropdownPanel
hexHighlight={true}
bodyStyle={{fontFamily: 'monospace'}}
dropdownName="Stack"
calldata={calldata || {}}
/>
<DropdownPanel hexHighlight={true} bodyStyle={{fontFamily: 'monospace'}} dropdownName="Stack" calldata={calldata || {}} />
</div>
)
}

@ -4,12 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StepDetail = ({stepDetail, className = ''}) => {
return (
<div className={className} id="stepdetail" data-id="stepdetail">
<DropdownPanel
className={className}
hexHighlight={false}
dropdownName="Step details"
calldata={stepDetail || {}}
/>
<DropdownPanel className={className} hexHighlight={false} dropdownName="Step details" calldata={stepDetail || {}} />
</div>
)
}

@ -4,11 +4,7 @@ import DropdownPanel from './dropdown-panel' // eslint-disable-line
export const StoragePanel = ({calldata, header, className}) => {
return (
<div id="storagepanel" className={className}>
<DropdownPanel
dropdownName="Storage"
calldata={calldata || {}}
header={header}
/>
<DropdownPanel dropdownName="Storage" calldata={calldata || {}} header={header} />
</div>
)
}

@ -5,10 +5,7 @@ import StepDetail from './step-detail' // eslint-disable-line
import SolidityState from './solidity-state' // eslint-disable-line
import SolidityLocals from './solidity-locals' // eslint-disable-line
export const VmDebuggerHead = ({
vmDebugger: {registerEvent, triggerEvent},
debugging
}) => {
export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debugging}) => {
const [functionPanel, setFunctionPanel] = useState(null)
const [stepDetail, setStepDetail] = useState({
'vm trace step': '-',
@ -35,15 +32,7 @@ export const VmDebuggerHead = ({
const functions = []
for (const func of stack) {
functions.push(
(func.functionDefinition.name || func.functionDefinition.kind) +
'(' +
func.inputs.join(', ') +
')' +
' - ' +
func.gasCost +
' gas'
)
functions.push((func.functionDefinition.name || func.functionDefinition.kind) + '(' + func.inputs.join(', ') + ')' + ' - ' + func.gasCost + ' gas')
}
setFunctionPanel(() => functions)
})
@ -139,28 +128,12 @@ export const VmDebuggerHead = ({
<div id="vmheadView" className="mt-1 px-2 d-flex">
<div className="d-flex flex-column pr-2" style={{flex: 1}}>
<FunctionPanel className="pb-1" data={functionPanel} />
<SolidityLocals
className="pb-1"
data={solidityLocals.calldata}
message={solidityLocals.message}
registerEvent={registerEvent}
triggerEvent={triggerEvent}
/>
<CodeListView
className="pb-2 flex-grow-1"
registerEvent={registerEvent}
/>
<SolidityLocals className="pb-1" data={solidityLocals.calldata} message={solidityLocals.message} registerEvent={registerEvent} triggerEvent={triggerEvent} />
<CodeListView className="pb-2 flex-grow-1" registerEvent={registerEvent} />
</div>
<div className="d-flex flex-column pl-2" style={{flex: 1}}>
<SolidityState
className="pb-1"
calldata={solidityState.calldata}
message={solidityState.message}
/>
<StepDetail
className="pb-1 pb-2 h-100 flex-grow-1"
stepDetail={stepDetail}
/>
<SolidityState className="pb-1" calldata={solidityState.calldata} message={solidityState.message} />
<StepDetail className="pb-1 pb-2 h-100 flex-grow-1" stepDetail={stepDetail} />
</div>
</div>
)

@ -8,13 +8,7 @@ import ReturnValuesPanel from './dropdown-panel' // eslint-disable-line
import FullStoragesChangesPanel from './full-storages-changes' // eslint-disable-line
import GlobalVariables from './global-variables' // eslint-disable-line
export const VmDebugger = ({
vmDebugger: {registerEvent},
currentBlock,
currentReceipt,
currentTransaction,
debugging
}) => {
export const VmDebugger = ({vmDebugger: {registerEvent}, currentBlock, currentReceipt, currentTransaction, debugging}) => {
const [calldataPanel, setCalldataPanel] = useState(null)
const [memoryPanel, setMemoryPanel] = useState(null)
const [callStackPanel, setCallStackPanel] = useState(null)
@ -78,22 +72,9 @@ export const VmDebugger = ({
<CallstackPanel className="pb-1" calldata={callStackPanel} />
<StackPanel className="pb-1" calldata={stackPanel} />
<MemoryPanel className="pb-1" calldata={memoryPanel} />
<StoragePanel
className="pb-1"
calldata={storagePanel.calldata}
header={storagePanel.header}
/>
<ReturnValuesPanel
className="pb-1"
dropdownName="Return Value"
calldata={returnValuesPanel || {}}
/>
<GlobalVariables
className="pb-1"
block={currentBlock}
receipt={currentReceipt}
tx={currentTransaction}
/>
<StoragePanel className="pb-1" calldata={storagePanel.calldata} header={storagePanel.header} />
<ReturnValuesPanel className="pb-1" dropdownName="Return Value" calldata={returnValuesPanel || {}} />
<GlobalVariables className="pb-1" block={currentBlock} receipt={currentReceipt} tx={currentTransaction} />
</div>
<div
className="d-flex flex-column px-2 pl-2"
@ -103,10 +84,7 @@ export const VmDebugger = ({
textOverflow: 'ellipsis'
}}
>
<FullStoragesChangesPanel
className="pb-1"
calldata={fullStoragesChangesPanel}
/>
<FullStoragesChangesPanel className="pb-1" calldata={fullStoragesChangesPanel} />
<CalldataPanel className="pb-1" calldata={calldataPanel} />
</div>
</div>

@ -4,9 +4,7 @@ import {MoveContext} from './context/moveContext'
import {DraggableType, DragType} from './types'
export const Drag = (props: DragType) => {
const [dragged, setDragged] = useState<{path: string; isDirectory: boolean}>(
{} as {path: string; isDirectory: boolean}
)
const [dragged, setDragged] = useState<{path: string; isDirectory: boolean}>({} as {path: string; isDirectory: boolean})
return (
<MoveContext.Provider
@ -52,10 +50,7 @@ export const Draggable = (props: DraggableType) => {
const handleDragover = (event: React.DragEvent<HTMLSpanElement>) => {
//Checks if the folder is opened
event.preventDefault()
if (
destination.isDirectory &&
!props.expandedPath.includes(destination.path)
) {
if (destination.isDirectory && !props.expandedPath.includes(destination.path)) {
props.handleClickFolder(destination.path, destination.type)
}
}

@ -3,15 +3,9 @@ import {isArray} from 'lodash'
import Editor, {loader, Monaco} from '@monaco-editor/react'
import {AlertModal} from '@remix-ui/app'
import {reducerActions, reducerListener, initialState} from './actions/editor'
import {
solidityTokensProvider,
solidityLanguageConfig
} from './syntaxes/solidity'
import {solidityTokensProvider, solidityLanguageConfig} from './syntaxes/solidity'
import {cairoTokensProvider, cairoLanguageConfig} from './syntaxes/cairo'
import {
zokratesTokensProvider,
zokratesLanguageConfig
} from './syntaxes/zokrates'
import {zokratesTokensProvider, zokratesLanguageConfig} from './syntaxes/zokrates'
import {moveTokenProvider, moveLanguageConfig} from './syntaxes/move'
import {monacoTypes} from '@remix-ui/editor'
import {loadTypes} from './web-types'
@ -100,14 +94,7 @@ export type DecorationsReturn = {
export type PluginType = {
on: (plugin: string, event: string, listener: any) => void
call: (
plugin: string,
method: string,
arg1?: any,
arg2?: any,
arg3?: any,
arg4?: any
) => any
call: (plugin: string, method: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any) => any
}
export type EditorAPIType = {
@ -116,30 +103,11 @@ export type EditorAPIType = {
getValue: (uri: string) => string
getCursorPosition: (offset?: boolean) => number | monacoTypes.IPosition
getHoverPosition: (position: monacoTypes.IPosition) => number
addDecoration: (
marker: sourceMarker,
filePath: string,
typeOfDecoration: string
) => DecorationsReturn
clearDecorationsByPlugin: (
filePath: string,
plugin: string,
typeOfDecoration: string,
registeredDecorations: any,
currentDecorations: any
) => DecorationsReturn
keepDecorationsFor: (
filePath: string,
plugin: string,
typeOfDecoration: string,
registeredDecorations: any,
currentDecorations: any
) => DecorationsReturn
addDecoration: (marker: sourceMarker, filePath: string, typeOfDecoration: string) => DecorationsReturn
clearDecorationsByPlugin: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
keepDecorationsFor: (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => DecorationsReturn
addErrorMarker: (errors: errorMarker[], from: string) => void
clearErrorMarkers: (
sources: string[] | {[fileName: string]: any},
from: string
) => void
clearErrorMarkers: (sources: string[] | {[fileName: string]: any}, from: string) => void
}
/* eslint-disable-next-line */
@ -191,10 +159,7 @@ export const EditorUI = (props: EditorUIProps) => {
const [editorModelsState, dispatch] = useReducer(reducerActions, initialState)
const formatColor = (name) => {
let color = window
.getComputedStyle(document.documentElement)
.getPropertyValue(name)
.trim()
let color = window.getComputedStyle(document.documentElement).getPropertyValue(name).trim()
if (color.length === 4) {
color = color.concat(color.substr(1))
}
@ -320,8 +285,7 @@ export const EditorUI = (props: EditorUIProps) => {
'editorSuggestWidget.highlightForeground': primaryColor,
'editorSuggestWidget.focusHighlightForeground': infoColor,
'editor.lineHighlightBorder': secondaryColor,
'editor.lineHighlightBackground':
textbackground === darkColor ? lightColor : secondaryColor,
'editor.lineHighlightBackground': textbackground === darkColor ? lightColor : secondaryColor,
'editorGutter.background': lightColor,
//'editor.selectionHighlightBackground': secondaryColor,
'minimap.background': lightColor,
@ -343,9 +307,7 @@ export const EditorUI = (props: EditorUIProps) => {
useEffect(() => {
if (!editorRef.current || !props.currentFile) return
currentFileRef.current = props.currentFile
props.plugin
.call('fileManager', 'getUrlFromPath', currentFileRef.current)
.then((url) => (currentUrlRef.current = url.file))
props.plugin.call('fileManager', 'getUrlFromPath', currentFileRef.current).then((url) => (currentUrlRef.current = url.file))
const file = editorModelsState[props.currentFile]
editorRef.current.setModel(file.model)
@ -365,34 +327,18 @@ export const EditorUI = (props: EditorUIProps) => {
}
}, [props.currentFile])
const convertToMonacoDecoration = (
decoration: lineText | sourceAnnotation | sourceMarker,
typeOfDecoration: string
) => {
const convertToMonacoDecoration = (decoration: lineText | sourceAnnotation | sourceMarker, typeOfDecoration: string) => {
if (typeOfDecoration === 'sourceAnnotationsPerFile') {
decoration = decoration as sourceAnnotation
return {
type: typeOfDecoration,
range: new monacoRef.current.Range(
decoration.row + 1,
1,
decoration.row + 1,
1
),
range: new monacoRef.current.Range(decoration.row + 1, 1, decoration.row + 1, 1),
options: {
isWholeLine: false,
glyphMarginHoverMessage: {
value:
(decoration.from ? `from ${decoration.from}:\n` : '') +
decoration.text
value: (decoration.from ? `from ${decoration.from}:\n` : '') + decoration.text
},
glyphMarginClassName: `fal fa-exclamation-square text-${
decoration.type === 'error'
? 'danger'
: decoration.type === 'warning'
? 'warning'
: 'info'
}`
glyphMarginClassName: `fal fa-exclamation-square text-${decoration.type === 'error' ? 'danger' : decoration.type === 'warning' ? 'warning' : 'info'}`
}
}
}
@ -400,9 +346,7 @@ export const EditorUI = (props: EditorUIProps) => {
decoration = decoration as sourceMarker
let isWholeLine = false
if (
(decoration.position.start.line === decoration.position.end.line &&
decoration.position.end.column - decoration.position.start.column <
2) ||
(decoration.position.start.line === decoration.position.end.line && decoration.position.end.column - decoration.position.start.column < 2) ||
decoration.position.start.line !== decoration.position.end.line
) {
// in this case we force highlighting the whole line (doesn't make sense to highlight 2 chars)
@ -418,9 +362,7 @@ export const EditorUI = (props: EditorUIProps) => {
),
options: {
isWholeLine,
inlineClassName: `${
isWholeLine ? 'alert-info' : 'inline-class'
} border-0 highlightLine${decoration.position.start.line + 1}`
inlineClassName: `${isWholeLine ? 'alert-info' : 'inline-class'} border-0 highlightLine${decoration.position.start.line + 1}`
}
}
}
@ -466,13 +408,7 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
props.editorAPI.clearDecorationsByPlugin = (
filePath: string,
plugin: string,
typeOfDecoration: string,
registeredDecorations: any,
currentDecorations: any
) => {
props.editorAPI.clearDecorationsByPlugin = (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => {
const model = editorModelsState[filePath]?.model
if (!model)
return {
@ -483,33 +419,19 @@ export const EditorUI = (props: EditorUIProps) => {
const newRegisteredDecorations = []
if (registeredDecorations) {
for (const decoration of registeredDecorations) {
if (
decoration.type === typeOfDecoration &&
decoration.value.from !== plugin
) {
decorations.push(
convertToMonacoDecoration(decoration.value, typeOfDecoration)
)
if (decoration.type === typeOfDecoration && decoration.value.from !== plugin) {
decorations.push(convertToMonacoDecoration(decoration.value, typeOfDecoration))
newRegisteredDecorations.push(decoration)
}
}
}
return {
currentDecorations: model.deltaDecorations(
currentDecorations,
decorations
),
currentDecorations: model.deltaDecorations(currentDecorations, decorations),
registeredDecorations: newRegisteredDecorations
}
}
props.editorAPI.keepDecorationsFor = (
filePath: string,
plugin: string,
typeOfDecoration: string,
registeredDecorations: any,
currentDecorations: any
) => {
props.editorAPI.keepDecorationsFor = (filePath: string, plugin: string, typeOfDecoration: string, registeredDecorations: any, currentDecorations: any) => {
const model = editorModelsState[filePath]?.model
if (!model)
return {
@ -519,63 +441,37 @@ export const EditorUI = (props: EditorUIProps) => {
if (registeredDecorations) {
for (const decoration of registeredDecorations) {
if (decoration.value.from === plugin) {
decorations.push(
convertToMonacoDecoration(decoration.value, typeOfDecoration)
)
decorations.push(convertToMonacoDecoration(decoration.value, typeOfDecoration))
}
}
}
return {
currentDecorations: model.deltaDecorations(
currentDecorations,
decorations
)
currentDecorations: model.deltaDecorations(currentDecorations, decorations)
}
}
const addDecoration = (
decoration: sourceAnnotation | sourceMarker,
filePath: string,
typeOfDecoration: string
) => {
const addDecoration = (decoration: sourceAnnotation | sourceMarker, filePath: string, typeOfDecoration: string) => {
const model = editorModelsState[filePath]?.model
if (!model) return {currentDecorations: []}
const monacoDecoration = convertToMonacoDecoration(
decoration,
typeOfDecoration
)
const monacoDecoration = convertToMonacoDecoration(decoration, typeOfDecoration)
return {
currentDecorations: model.deltaDecorations([], [monacoDecoration]),
registeredDecorations: [{value: decoration, type: typeOfDecoration}]
}
}
props.editorAPI.addDecoration = (
marker: sourceMarker,
filePath: string,
typeOfDecoration: string
) => {
props.editorAPI.addDecoration = (marker: sourceMarker, filePath: string, typeOfDecoration: string) => {
return addDecoration(marker, filePath, typeOfDecoration)
}
props.editorAPI.addErrorMarker = async (
errors: errorMarker[],
from: string
) => {
const allMarkersPerfile: Record<
string,
Array<monacoTypes.editor.IMarkerData>
> = {}
props.editorAPI.addErrorMarker = async (errors: errorMarker[], from: string) => {
const allMarkersPerfile: Record<string, Array<monacoTypes.editor.IMarkerData>> = {}
for (const error of errors) {
let filePath = error.file
if (!filePath) return
const fileFromUrl = await props.plugin.call(
'fileManager',
'getPathFromUrl',
filePath
)
const fileFromUrl = await props.plugin.call('fileManager', 'getPathFromUrl', filePath)
filePath = fileFromUrl.file
const model = editorModelsState[filePath]?.model
const errorServerityMap = {
@ -585,14 +481,9 @@ export const EditorUI = (props: EditorUIProps) => {
}
if (model) {
const markerData: monacoTypes.editor.IMarkerData = {
severity:
typeof error.severity === 'string'
? errorServerityMap[error.severity]
: error.severity,
startLineNumber:
(error.position.start && error.position.start.line) || 0,
startColumn:
(error.position.start && error.position.start.column) || 0,
severity: typeof error.severity === 'string' ? errorServerityMap[error.severity] : error.severity,
startLineNumber: (error.position.start && error.position.start.line) || 0,
startColumn: (error.position.start && error.position.start.column) || 0,
endLineNumber: (error.position.end && error.position.end.line) || 0,
endColumn: (error.position.end && error.position.end.column) || 0,
message: error.message
@ -606,23 +497,14 @@ export const EditorUI = (props: EditorUIProps) => {
for (const filePath in allMarkersPerfile) {
const model = editorModelsState[filePath]?.model
if (model) {
monacoRef.current.editor.setModelMarkers(
model,
from,
allMarkersPerfile[filePath]
)
monacoRef.current.editor.setModelMarkers(model, from, allMarkersPerfile[filePath])
}
}
}
props.editorAPI.clearErrorMarkers = async (
sources: string[] | {[fileName: string]: any},
from: string
) => {
props.editorAPI.clearErrorMarkers = async (sources: string[] | {[fileName: string]: any}, from: string) => {
if (sources) {
for (const source of Array.isArray(sources)
? sources
: Object.keys(sources)) {
for (const source of Array.isArray(sources) ? sources : Object.keys(sources)) {
const filePath = source
const model = editorModelsState[filePath]?.model
if (model) {
@ -650,9 +532,7 @@ export const EditorUI = (props: EditorUIProps) => {
if (!monacoRef.current) return
const model = editorModelsState[currentFileRef.current]?.model
if (model) {
return offset
? model.getOffsetAt(editorRef.current.getPosition())
: editorRef.current.getPosition()
return offset ? model.getOffsetAt(editorRef.current.getPosition()) : editorRef.current.getPosition()
}
}
@ -677,15 +557,10 @@ export const EditorUI = (props: EditorUIProps) => {
setCurrentBreakpoints((prevState) => {
const currentFile = currentUrlRef.current
if (!prevState[currentFile]) prevState[currentFile] = {}
const decoration = Object.keys(prevState[currentFile]).filter(
(line) => parseInt(line) === position.lineNumber
)
const decoration = Object.keys(prevState[currentFile]).filter((line) => parseInt(line) === position.lineNumber)
if (decoration.length) {
props.events.onBreakPointCleared(currentFile, position.lineNumber)
model.deltaDecorations(
[prevState[currentFile][position.lineNumber]],
[]
)
model.deltaDecorations([prevState[currentFile][position.lineNumber]], [])
delete prevState[currentFile][position.lineNumber]
} else {
props.events.onBreakPointAdded(currentFile, position.lineNumber)
@ -693,12 +568,7 @@ export const EditorUI = (props: EditorUIProps) => {
[],
[
{
range: new monacoRef.current.Range(
position.lineNumber,
1,
position.lineNumber,
1
),
range: new monacoRef.current.Range(position.lineNumber, 1, position.lineNumber, 1),
options: {
isWholeLine: false,
glyphMarginClassName: 'fas fa-circle text-info'
@ -716,13 +586,7 @@ export const EditorUI = (props: EditorUIProps) => {
function handleEditorDidMount(editor) {
editorRef.current = editor
defineAndSetTheme(monacoRef.current)
reducerListener(
props.plugin,
dispatch,
monacoRef.current,
editorRef.current,
props.events
)
reducerListener(props.plugin, dispatch, monacoRef.current, editorRef.current, props.events)
props.events.onEditorMounted()
editor.onMouseUp((e) => {
// see https://microsoft.github.io/monaco-editor/typedoc/enums/editor.MouseTargetType.html
@ -734,14 +598,7 @@ export const EditorUI = (props: EditorUIProps) => {
})
editor.onDidPaste((e) => {
if (
!pasteCodeRef.current &&
e &&
e.range &&
e.range.startLineNumber >= 0 &&
e.range.endLineNumber >= 0 &&
e.range.endLineNumber - e.range.startLineNumber > 10
) {
if (!pasteCodeRef.current && e && e.range && e.range.startLineNumber >= 0 && e.range.endLineNumber >= 0 && e.range.endLineNumber - e.range.startLineNumber > 10) {
const modalContent: AlertModal = {
id: 'newCodePasted',
title: 'Pasted Code Alert',
@ -751,28 +608,16 @@ export const EditorUI = (props: EditorUIProps) => {
<i className="fas fa-exclamation-triangle text-danger mr-1"></i>
You have just pasted a code snippet or contract in the editor.
<div>
Make sure you fully understand this code before deploying or
interacting with it. Don't get scammed!
Make sure you fully understand this code before deploying or interacting with it. Don't get scammed!
<div className="mt-2">
Running untrusted code can put your wallet{' '}
<span className="text-warning"> at risk </span>. In a
worst-case scenario, you could{' '}
Running untrusted code can put your wallet <span className="text-warning"> at risk </span>. In a worst-case scenario, you could{' '}
<span className="text-warning">lose all your money</span>.
</div>
<div className="text-warning mt-2">
If you don't fully understand it, please don't run this code.
</div>
<div className="mt-2">
If you are not a smart contract developer, ask someone you
trust who has the skills to determine if this code is safe to
use.
</div>
<div className="text-warning mt-2">If you don't fully understand it, please don't run this code.</div>
<div className="mt-2">If you are not a smart contract developer, ask someone you trust who has the skills to determine if this code is safe to use.</div>
<div className="mt-2">
See{' '}
<a
target="_blank"
href="https://remix-ide.readthedocs.io/en/latest/security.html"
>
<a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/security.html">
{' '}
these recommendations{' '}
</a>{' '}
@ -788,20 +633,12 @@ export const EditorUI = (props: EditorUIProps) => {
})
// zoomin zoomout
editor.addCommand(
monacoRef.current.KeyMod.CtrlCmd |
(monacoRef.current.KeyCode as any).US_EQUAL,
() => {
editor.updateOptions({fontSize: editor.getOption(43).fontSize + 1})
}
)
editor.addCommand(
monacoRef.current.KeyMod.CtrlCmd |
(monacoRef.current.KeyCode as any).US_MINUS,
() => {
editor.updateOptions({fontSize: editor.getOption(43).fontSize - 1})
}
)
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | (monacoRef.current.KeyCode as any).US_EQUAL, () => {
editor.updateOptions({fontSize: editor.getOption(43).fontSize + 1})
})
editor.addCommand(monacoRef.current.KeyMod.CtrlCmd | (monacoRef.current.KeyCode as any).US_MINUS, () => {
editor.updateOptions({fontSize: editor.getOption(43).fontSize - 1})
})
// add context menu items
const zoominAction = {
@ -837,9 +674,7 @@ export const EditorUI = (props: EditorUIProps) => {
contextMenuGroupId: 'formatting', // create a new grouping
keybindings: [
// eslint-disable-next-line no-bitwise
monacoRef.current.KeyMod.Shift |
monacoRef.current.KeyMod.Alt |
monacoRef.current.KeyCode.KeyF
monacoRef.current.KeyMod.Shift | monacoRef.current.KeyMod.Alt | monacoRef.current.KeyCode.KeyF
],
run: async () => {
const file = await props.plugin.call('fileManager', 'getCurrentFile')
@ -847,10 +682,7 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
const freeFunctionCondition = editor.createContextKey(
'freeFunctionCondition',
false
)
const freeFunctionCondition = editor.createContextKey('freeFunctionCondition', false)
let freeFunctionAction
const executeFreeFunctionAction = {
id: 'executeFreeFunction',
@ -860,48 +692,21 @@ export const EditorUI = (props: EditorUIProps) => {
precondition: 'freeFunctionCondition',
keybindings: [
// eslint-disable-next-line no-bitwise
monacoRef.current.KeyMod.Shift |
monacoRef.current.KeyMod.Alt |
monacoRef.current.KeyCode.KeyR
monacoRef.current.KeyMod.Shift | monacoRef.current.KeyMod.Alt | monacoRef.current.KeyCode.KeyR
],
run: async () => {
const {nodesAtPosition} = await retrieveNodesAtPosition(
props.editorAPI,
props.plugin
)
const {nodesAtPosition} = await retrieveNodesAtPosition(props.editorAPI, props.plugin)
// find the contract and get the nodes of the contract and the base contracts and imports
if (
nodesAtPosition &&
isArray(nodesAtPosition) &&
nodesAtPosition.length
) {
const freeFunctionNode = nodesAtPosition.find(
(node) => node.kind === 'freeFunction'
)
if (nodesAtPosition && isArray(nodesAtPosition) && nodesAtPosition.length) {
const freeFunctionNode = nodesAtPosition.find((node) => node.kind === 'freeFunction')
if (freeFunctionNode) {
const file = await props.plugin.call(
'fileManager',
'getCurrentFile'
)
props.plugin.call(
'solidity-script',
'execute',
file,
freeFunctionNode.name
)
const file = await props.plugin.call('fileManager', 'getCurrentFile')
props.plugin.call('solidity-script', 'execute', file, freeFunctionNode.name)
} else {
props.plugin.call(
'notification',
'toast',
'This can only execute free function'
)
props.plugin.call('notification', 'toast', 'This can only execute free function')
}
} else {
props.plugin.call(
'notification',
'toast',
'Please go to Remix settings and activate the code editor features or wait that the current editor context is loaded.'
)
props.plugin.call('notification', 'toast', 'Please go to Remix settings and activate the code editor features or wait that the current editor context is loaded.')
}
}
}
@ -911,12 +716,7 @@ export const EditorUI = (props: EditorUIProps) => {
freeFunctionAction = editor.addAction(executeFreeFunctionAction)
// we have to add the command because the menu action isn't always available (see onContextMenuHandlerForFreeFunction)
editor.addCommand(
monacoRef.current.KeyMod.Shift |
monacoRef.current.KeyMod.Alt |
monacoRef.current.KeyCode.KeyR,
() => executeFreeFunctionAction.run()
)
editor.addCommand(monacoRef.current.KeyMod.Shift | monacoRef.current.KeyMod.Alt | monacoRef.current.KeyCode.KeyR, () => executeFreeFunctionAction.run())
const contextmenu = editor.getContribution('editor.contrib.contextmenu')
const orgContextMenuMethod = contextmenu._onContextMenu
@ -930,13 +730,8 @@ export const EditorUI = (props: EditorUIProps) => {
freeFunctionCondition.set(false)
return
}
const {nodesAtPosition} = await retrieveNodesAtPosition(
props.editorAPI,
props.plugin
)
const freeFunctionNode = nodesAtPosition.find(
(node) => node.kind === 'freeFunction'
)
const {nodesAtPosition} = await retrieveNodesAtPosition(props.editorAPI, props.plugin)
const freeFunctionNode = nodesAtPosition.find((node) => node.kind === 'freeFunction')
if (freeFunctionNode) {
executeFreeFunctionAction.label = `Run the free function "${freeFunctionNode.name}" in the Remix VM`
freeFunctionAction = editor.addAction(executeFreeFunctionAction)
@ -986,75 +781,27 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.register({id: 'remix-circom'})
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider(
'remix-solidity',
solidityTokensProvider as any
)
monacoRef.current.languages.setLanguageConfiguration(
'remix-solidity',
solidityLanguageConfig as any
)
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', solidityTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-solidity', solidityLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider(
'remix-cairo',
cairoTokensProvider as any
)
monacoRef.current.languages.setLanguageConfiguration(
'remix-cairo',
cairoLanguageConfig as any
)
monacoRef.current.languages.setMonarchTokensProvider('remix-cairo', cairoTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-cairo', cairoLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider(
'remix-zokrates',
zokratesTokensProvider as any
)
monacoRef.current.languages.setLanguageConfiguration(
'remix-zokrates',
zokratesLanguageConfig as any
)
monacoRef.current.languages.setMonarchTokensProvider('remix-zokrates', zokratesTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-zokrates', zokratesLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider(
'remix-move',
moveTokenProvider as any
)
monacoRef.current.languages.setLanguageConfiguration(
'remix-move',
moveLanguageConfig as any
)
monacoRef.current.languages.setMonarchTokensProvider('remix-move', moveTokenProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-move', moveLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider(
'remix-circom',
circomTokensProvider as any
)
monacoRef.current.languages.setLanguageConfiguration(
'remix-circom',
circomLanguageConfig(monacoRef.current) as any
)
monacoRef.current.languages.setMonarchTokensProvider('remix-circom', circomTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-circom', circomLanguageConfig(monacoRef.current) as any)
monacoRef.current.languages.registerDefinitionProvider(
'remix-solidity',
new RemixDefinitionProvider(props, monaco)
)
monacoRef.current.languages.registerDocumentHighlightProvider(
'remix-solidity',
new RemixHighLightProvider(props, monaco)
)
monacoRef.current.languages.registerReferenceProvider(
'remix-solidity',
new RemixReferenceProvider(props, monaco)
)
monacoRef.current.languages.registerHoverProvider(
'remix-solidity',
new RemixHoverProvider(props, monaco)
)
monacoRef.current.languages.registerCompletionItemProvider(
'remix-solidity',
new RemixCompletionProvider(props, monaco)
)
monaco.languages.registerCodeActionProvider(
'remix-solidity',
new RemixCodeActionProvider(props, monaco)
)
monacoRef.current.languages.registerDefinitionProvider('remix-solidity', new RemixDefinitionProvider(props, monaco))
monacoRef.current.languages.registerDocumentHighlightProvider('remix-solidity', new RemixHighLightProvider(props, monaco))
monacoRef.current.languages.registerReferenceProvider('remix-solidity', new RemixReferenceProvider(props, monaco))
monacoRef.current.languages.registerHoverProvider('remix-solidity', new RemixHoverProvider(props, monaco))
monacoRef.current.languages.registerCompletionItemProvider('remix-solidity', new RemixCompletionProvider(props, monaco))
monaco.languages.registerCodeActionProvider('remix-solidity', new RemixCodeActionProvider(props, monaco))
loadTypes(monacoRef.current)
}
@ -1064,18 +811,12 @@ export const EditorUI = (props: EditorUIProps) => {
<Editor
width="100%"
path={props.currentFile}
language={
editorModelsState[props.currentFile]
? editorModelsState[props.currentFile].language
: 'text'
}
language={editorModelsState[props.currentFile] ? editorModelsState[props.currentFile].language : 'text'}
onMount={handleEditorDidMount}
beforeMount={handleEditorWillMount}
options={{
glyphMargin: true,
readOnly:
(!editorRef.current || !props.currentFile) &&
editorModelsState[props.currentFile]?.readOnly
readOnly: (!editorRef.current || !props.currentFile) && editorModelsState[props.currentFile]?.readOnly
}}
defaultValue={defaultEditorValue}
/>

@ -16,12 +16,7 @@ export const FileDecorationIcons = (props: fileDecorationProps) => {
const [states, setStates] = useState<fileDecoration[]>([])
useEffect(() => {
setStates(
props.fileDecorations.filter(
(fileDecoration) =>
fileDecoration.path === props.file.path ||
`${fileDecoration.workspace.name}/${fileDecoration.path}` ===
props.file.path
)
props.fileDecorations.filter((fileDecoration) => fileDecoration.path === props.file.path || `${fileDecoration.workspace.name}/${fileDecoration.path}` === props.file.path)
)
}, [props.fileDecorations])
@ -32,46 +27,13 @@ export const FileDecorationIcons = (props: fileDecorationProps) => {
for (const [index, state] of states.entries()) {
switch (state.fileStateType) {
case fileDecorationType.Error:
elements.push(
<FileDecorationTooltip
key={index}
index={index}
fileDecoration={state}
icon={
<FileDecorationErrorIcon fileDecoration={state} key={index} />
}
/>
)
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationErrorIcon fileDecoration={state} key={index} />} />)
break
case fileDecorationType.Warning:
elements.push(
<FileDecorationTooltip
key={index}
index={index}
fileDecoration={state}
icon={
<FileDecorationWarningIcon
fileDecoration={state}
key={index}
/>
}
/>
)
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationWarningIcon fileDecoration={state} key={index} />} />)
break
case fileDecorationType.Custom:
elements.push(
<FileDecorationTooltip
key={index}
index={index}
fileDecoration={state}
icon={
<FileDecorationCustomIcon
fileDecoration={state}
key={index}
/>
}
/>
)
elements.push(<FileDecorationTooltip key={index} index={index} fileDecoration={state} icon={<FileDecorationCustomIcon fileDecoration={state} key={index} />} />)
break
}
}

@ -5,10 +5,7 @@ import {fileDecoration} from '../../types'
const FileDecorationCustomIcon = (props: {fileDecoration: fileDecoration}) => {
return (
<>
<span
data-id={`file-decoration-custom-${props.fileDecoration.path}`}
className={`${props.fileDecoration.fileStateIconClass} pr-2`}
>
<span data-id={`file-decoration-custom-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} pr-2`}>
<>{props.fileDecoration.fileStateIcon}</>
</span>
</>

@ -6,10 +6,7 @@ import {fileDecoration} from '../../types'
const FileDecorationErrorIcon = (props: {fileDecoration: fileDecoration}) => {
return (
<>
<span
data-id={`file-decoration-error-${props.fileDecoration.path}`}
className={`${props.fileDecoration.fileStateIconClass} text-danger pr-2`}
>
<span data-id={`file-decoration-error-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-danger pr-2`}>
{props.fileDecoration.text}
</span>
</>

@ -2,16 +2,10 @@ import React from 'react'
import {OverlayTrigger, Popover} from 'react-bootstrap'
import {fileDecoration} from '../../types'
const FileDecorationTooltip = (props: {
fileDecoration: fileDecoration
icon: JSX.Element
index: number
}) => {
const FileDecorationTooltip = (props: {fileDecoration: fileDecoration; icon: JSX.Element; index: number}) => {
const getComments = function (fileDecoration: fileDecoration) {
if (fileDecoration.comment) {
const comments = Array.isArray(fileDecoration.comment)
? fileDecoration.comment
: [fileDecoration.comment]
const comments = Array.isArray(fileDecoration.comment) ? fileDecoration.comment : [fileDecoration.comment]
return comments.map((comment, index) => {
return (
<div className="bg-secondary text-left p-1 mx-1 my-0" key={index}>
@ -28,11 +22,7 @@ const FileDecorationTooltip = (props: {
placement="auto"
overlay={
<Popover id={`popover-positioned-auto}`}>
<Popover.Content
id={`error-tooltip-${props.fileDecoration.path}`}
style={{minWidth: 'fit-content'}}
className={'text-wrap bg-secondary w-100 p-1 m-0'}
>
<Popover.Content id={`error-tooltip-${props.fileDecoration.path}`} style={{minWidth: 'fit-content'}} className={'text-wrap bg-secondary w-100 p-1 m-0'}>
<pre>{getComments(props.fileDecoration)}</pre>
</Popover.Content>
</Popover>

@ -5,10 +5,7 @@ import {fileDecoration} from '../../types'
const FileDecorationWarningIcon = (props: {fileDecoration: fileDecoration}) => {
return (
<>
<span
data-id={`file-decoration-warning-${props.fileDecoration.path}`}
className={`${props.fileDecoration.fileStateIconClass} text-warning pr-2`}
>
<span data-id={`file-decoration-warning-${props.fileDecoration.path}`} className={`${props.fileDecoration.fileStateIconClass} text-warning pr-2`}>
{props.fileDecoration.text}
</span>
</>

@ -3,9 +3,7 @@ import {fileDecoration} from '../types'
export const getComments = function (fileDecoration: fileDecoration) {
if (fileDecoration.comment) {
const comments = Array.isArray(fileDecoration.comment)
? fileDecoration.comment
: [fileDecoration.comment]
const comments = Array.isArray(fileDecoration.comment) ? fileDecoration.comment : [fileDecoration.comment]
return comments.map((comment, index) => {
return (
<div key={index}>

@ -62,24 +62,12 @@ export const CustomIconsToggle = React.forwardRef(
e.preventDefault()
onClick()
}}
className={`${className.replace(
'dropdown-toggle',
''
)} mr-1 mb-0 pb-0 d-flex justify-content-end align-items-end remixuimenuicon_shadow remixuimenuicon_hamburger_menu fs-3`}
className={`${className.replace('dropdown-toggle', '')} mr-1 mb-0 pb-0 d-flex justify-content-end align-items-end remixuimenuicon_shadow remixuimenuicon_hamburger_menu fs-3`}
data-id="workspaceMenuDropdown"
>
{icon && (
<CustomTooltip
placement={'top'}
tooltipClasses="text-nowrap text-left"
tooltipId="remixHamburgerTooltip"
tooltipText="Workspace actions"
>
<i
style={{fontSize: 'large'}}
className={`${icon}`}
data-id="workspaceDropdownMenuIcon"
></i>
<CustomTooltip placement={'top'} tooltipClasses="text-nowrap text-left" tooltipId="remixHamburgerTooltip" tooltipText="Workspace actions">
<i style={{fontSize: 'large'}} className={`${icon}`} data-id="workspaceDropdownMenuIcon"></i>
</CustomTooltip>
)}
</span>
@ -107,17 +95,8 @@ export const CustomMenu = React.forwardRef(
) => {
const height = window.innerHeight * 0.6
return (
<div
ref={ref}
style={style}
className={className}
aria-labelledby={labeledBy}
data-id={dataId}
>
<ul
className="overflow-auto list-unstyled mb-0"
style={{maxHeight: height + 'px'}}
>
<div ref={ref} style={style} className={className} aria-labelledby={labeledBy} data-id={dataId}>
<ul className="overflow-auto list-unstyled mb-0" style={{maxHeight: height + 'px'}}>
{children}
</ul>
</div>
@ -180,12 +159,7 @@ export const ProxyDropdownMenu = React.forwardRef(
ref: Ref<HTMLDivElement>
) => {
return (
<div
ref={ref}
style={style}
className={className}
aria-labelledby={labeledBy}
>
<div ref={ref} style={style} className={className} aria-labelledby={labeledBy}>
<ul className="list-unstyled mb-0">{children}</ul>
</div>
)

@ -3,15 +3,7 @@ import {Fragment} from 'react'
import {OverlayTrigger, Popover} from 'react-bootstrap'
import {CustomTooltipType} from '../../types/customtooltip'
export function CustomTooltip({
children,
placement,
tooltipId,
tooltipClasses,
tooltipText,
tooltipTextClasses,
delay
}: CustomTooltipType) {
export function CustomTooltip({children, placement, tooltipId, tooltipClasses, tooltipText, tooltipTextClasses, delay}: CustomTooltipType) {
if (typeof tooltipText !== 'string') {
const newTooltipText = React.cloneElement(tooltipText, {
className: ' bg-secondary text-wrap p-1 px-2 '
@ -28,21 +20,9 @@ export function CustomTooltip({
<Popover.Content
id={!tooltipId ? `${tooltipText}Tooltip` : tooltipId}
style={{minWidth: 'fit-content'}}
className={
'text-wrap p-1 px-2 bg-secondary w-100' + tooltipClasses
}
className={'text-wrap p-1 px-2 bg-secondary w-100' + tooltipClasses}
>
{typeof tooltipText === 'string' ? (
<span
className={
'text-wrap p-1 px-2 bg-secondary ' + {tooltipTextClasses}
}
>
{tooltipText}
</span>
) : (
tooltipText
)}
{typeof tooltipText === 'string' ? <span className={'text-wrap p-1 px-2 bg-secondary ' + {tooltipTextClasses}}>{tooltipText}</span> : tooltipText}
</Popover.Content>
</Popover>
}

@ -15,46 +15,27 @@ export function Web3ProviderDialog(props: web3ProviderDialogProps) {
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"
>
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>
)<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"
>
<a href="https://geth.ethereum.org/getting-started/dev-mode" target="_blank" rel="noreferrer">
Geth Docs on Dev mode
</a>
)
<div className="border p-1">
geth --http --http.corsdomain="{window.origin}" --http.api
web3,eth,debug,personal,net --vmdebug --datadir {thePath} --dev
console
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>
<b>WARNING:</b> It is not safe to use the --http.corsdomain flag with a wildcard: <b>--http.corsdomain *</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"
>
<a href="https://remix-ide.readthedocs.io/en/latest/run.html#more-about-web3-provider" target="_blank" rel="noreferrer">
Remix Docs on Remix Provider
</a>
<br />

@ -5,16 +5,14 @@ export const fileChangedToastMsg = (from: string, path: string) => (
<div>
<i className="fas fa-exclamation-triangle text-danger mr-1"></i>
<span>
{from} <span className="font-weight-bold text-warning">is modifying</span>{' '}
{path}
{from} <span className="font-weight-bold text-warning">is modifying</span> {path}
</span>
</div>
)
export const compilerConfigChangedToastMsg = (from: string, value: string) => (
<div>
<b>{from}</b> is updating the <b>Solidity compiler configuration</b>.
<pre className="text-left">{value}</pre>
<b>{from}</b> is updating the <b>Solidity compiler configuration</b>.<pre className="text-left">{value}</pre>
</div>
)
@ -33,15 +31,13 @@ export const compilingToastMsg = (settings: string) => (
export const compilationFinishedToastMsg = () => (
<div>
<b>Compilation failed...</b> continuing <i>without</i> source code
debugging.
<b>Compilation failed...</b> continuing <i>without</i> source code debugging.
</div>
)
export const notFoundToastMsg = (address: string) => (
<div>
<b>Contract {address} not found in source code repository</b> continuing{' '}
<i>without</i> source code debugging.
<b>Contract {address} not found in source code repository</b> continuing <i>without</i> source code debugging.
</div>
)
@ -53,23 +49,16 @@ export const localCompilationToastMsg = () => (
export const sourceVerificationNotAvailableToastMsg = () => (
<div>
<b>Source verification plugin not activated or not available.</b> continuing{' '}
<i>without</i> source code debugging.
<b>Source verification plugin not activated or not available.</b> continuing <i>without</i> source code debugging.
</div>
)
export const envChangeNotification = (
env: {context: string; fork: string},
from: string
) => (
export const envChangeNotification = (env: {context: string; fork: string}, from: string) => (
<div>
<i className="fas fa-exclamation-triangle text-danger mr-1"></i>
<span>
{from + ' '}
<span className="font-weight-bold text-warning">
set your environment to
</span>{' '}
{env && env.context}
<span className="font-weight-bold text-warning">set your environment to</span> {env && env.context}
</span>
</div>
)
@ -78,17 +67,12 @@ export const storageFullMessage = () => (
<div>
<i className="fas fa-exclamation-triangle text-danger mr-1"></i>
<span className="font-weight-bold">
<span>
Cannot save this file due to full LocalStorage. Backup existing files
and free up some space.
</span>
<span>Cannot save this file due to full LocalStorage. Backup existing files and free up some space.</span>
</span>
</div>
)
export const recursivePasteToastMsg = () => (
<div>File(s) to paste is an ancestor of the destination folder</div>
)
export const recursivePasteToastMsg = () => <div>File(s) to paste is an ancestor of the destination folder</div>
export const logBuilder = (msg: string) => {
return <pre>{msg}</pre>
@ -121,10 +105,7 @@ export const upgradeWithProxyMsg = () => (
<b>Upgrade with Proxy</b> will initiate two (2) transactions:
<ol className="pl-3">
<li key="new-impl-contract">Deploying the new implementation contract</li>
<li key="update-proxy-contract">
Updating the proxy contract with the address of the new implementation
contract
</li>
<li key="update-proxy-contract">Updating the proxy contract with the address of the new implementation contract</li>
</ol>
</div>
)
@ -132,8 +113,7 @@ export const upgradeWithProxyMsg = () => (
export const unavailableProxyLayoutMsg = () => (
<div>
<p>
The previous contract implementation is NOT available for an upgrade
comparison
The previous contract implementation is NOT available for an upgrade comparison
<br /> A new storage layout will be saved for future upgrades.
</p>
</div>
@ -143,22 +123,12 @@ export const upgradeReportMsg = (report: LayoutCompatibilityReport) => (
<div>
<div className="py-2 ml-2 mb-1 align-self-end mb-2 d-flex">
<span className="align-self-center pl-4 mt-1">
<i
className="pr-2 text-warning far fa-exclamation-triangle"
aria-hidden="true"
style={{fontSize: 'xxx-large', fontWeight: 'lighter'}}
></i>
<i className="pr-2 text-warning far fa-exclamation-triangle" aria-hidden="true" style={{fontSize: 'xxx-large', fontWeight: 'lighter'}}></i>
</span>
<div className="d-flex flex-column">
<span className="pl-4 mt-1">
The storage layout of new implementation is NOT
</span>
<span className="pl-4 mt-1">
compatible with the previous implementation.
</span>
<span className="pl-4 mt-1">
Your contract's storage may be partially or fully erased!
</span>
<span className="pl-4 mt-1">The storage layout of new implementation is NOT</span>
<span className="pl-4 mt-1">compatible with the previous implementation.</span>
<span className="pl-4 mt-1">Your contract's storage may be partially or fully erased!</span>
</div>
</div>
<div className="pl-4 text-danger">{report.explain()}</div>

@ -7,29 +7,15 @@ const CustomNavButtons = ({parent, next, previous, goToSlide, ...rest}) => {
} = rest
return (
<div className="mt-1 d-flex justify-content-end carousel-button-group">
<button
className={
currentSlide === 0 ? 'disable py-1 border btn' : 'py-1 border btn'
}
disabled={currentSlide === 0}
onClick={() => previous()}
>
<button className={currentSlide === 0 ? 'disable py-1 border btn' : 'py-1 border btn'} disabled={currentSlide === 0} onClick={() => previous()}>
<i className="fas fa-angle-left"></i>
</button>
<button
className={
Math.abs(transform) >=
parent?.current?.containerRef?.current?.scrollWidth - containerWidth
? 'disable py-1 border btn'
: 'py-1 border btn'
}
className={Math.abs(transform) >= parent?.current?.containerRef?.current?.scrollWidth - containerWidth ? 'disable py-1 border btn' : 'py-1 border btn'}
onClick={() => {
if (currentSlide + 1 < totalItems) goToSlide(currentSlide + 1)
}}
disabled={
Math.abs(transform) >=
parent?.current?.containerRef?.current?.scrollWidth - containerWidth
}
disabled={Math.abs(transform) >= parent?.current?.containerRef?.current?.scrollWidth - containerWidth}
>
<i className="fas fa-angle-right"></i>
</button>

@ -42,16 +42,9 @@ function HomeTabFeatured() {
>
<div className="mx-1 px-1 d-flex">
<a href="https://remix-project.org" target="__blank">
<img
src={'assets/img/bgRemi_small.webp'}
style={{flex: '1', height: '170px', maxWidth: '170px'}}
alt=""
></img>
<img src={'assets/img/bgRemi_small.webp'} style={{flex: '1', height: '170px', maxWidth: '170px'}} alt=""></img>
</a>
<div
className="h6 w-50 p-2 pl-4 align-self-center"
style={{flex: '1'}}
>
<div className="h6 w-50 p-2 pl-4 align-self-center" style={{flex: '1'}}>
<h5>
<FormattedMessage id="home.jumpIntoWeb3" />
</h5>
@ -60,14 +53,7 @@ function HomeTabFeatured() {
</div>
<a
className="remixui_home_text btn-sm btn-secondary mt-2 text-decoration-none mb-3"
onClick={() =>
_paq.push([
'trackEvent',
'hometab',
'featuredSection',
'jumpIntoWeb3'
])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'featuredSection', 'jumpIntoWeb3'])}
target="__blank"
href="https://us8.list-manage.com/survey?u=5a84beb6d688fe180c0da482a&id=1148d10f8c"
>
@ -76,20 +62,10 @@ function HomeTabFeatured() {
</div>
</div>
<div className="mx-1 px-1 d-flex">
<a
href="https://www.youtube.com/@EthereumRemix/videos"
target="__blank"
>
<img
src={'/assets/img/YouTubeLogo.webp'}
style={{flex: '1', height: '170px', maxWidth: '170px'}}
alt=""
></img>
<a href="https://www.youtube.com/@EthereumRemix/videos" target="__blank">
<img src={'/assets/img/YouTubeLogo.webp'} style={{flex: '1', height: '170px', maxWidth: '170px'}} alt=""></img>
</a>
<div
className="h6 w-50 p-2 pl-4 align-self-center"
style={{flex: '1'}}
>
<div className="h6 w-50 p-2 pl-4 align-self-center" style={{flex: '1'}}>
<h5>
<FormattedMessage id="home.remixYouTube" />
</h5>
@ -101,14 +77,7 @@ function HomeTabFeatured() {
</div>
<a
className="remixui_home_text btn-sm btn-secondary mt-2 text-decoration-none mb-3"
onClick={() =>
_paq.push([
'trackEvent',
'hometab',
'featuredSection',
'youTubeMore'
])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'featuredSection', 'youTubeMore'])}
target="__blank"
href="https://www.youtube.com/@EthereumRemix/videos"
>
@ -117,20 +86,10 @@ function HomeTabFeatured() {
</div>
</div>
<div className="mx-1 px-1 d-flex">
<a
href="https://docs.google.com/forms/d/e/1FAIpQLSd0WsJnKbeJo-BGrnf7WijxAdmE4PnC_Z4M0IApbBfHLHZdsQ/viewform"
target="__blank"
>
<img
src={'/assets/img/remixRewardBetaTester_small.webp'}
style={{flex: '1', height: '170px', maxWidth: '170px'}}
alt=""
></img>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSd0WsJnKbeJo-BGrnf7WijxAdmE4PnC_Z4M0IApbBfHLHZdsQ/viewform" target="__blank">
<img src={'/assets/img/remixRewardBetaTester_small.webp'} style={{flex: '1', height: '170px', maxWidth: '170px'}} alt=""></img>
</a>
<div
className="h6 w-50 p-2 pl-4 align-self-center"
style={{flex: '1'}}
>
<div className="h6 w-50 p-2 pl-4 align-self-center" style={{flex: '1'}}>
<h5>
<FormattedMessage id="home.betaTesting" />
</h5>
@ -142,14 +101,7 @@ function HomeTabFeatured() {
</div>
<a
className="remixui_home_text btn-sm btn-secondary mt-2 text-decoration-none mb-3"
onClick={() =>
_paq.push([
'trackEvent',
'hometab',
'featuredSection',
'betatesting'
])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'featuredSection', 'betatesting'])}
target="__blank"
href="https://docs.google.com/forms/d/e/1FAIpQLSd0WsJnKbeJo-BGrnf7WijxAdmE4PnC_Z4M0IApbBfHLHZdsQ/viewform"
>

@ -47,12 +47,7 @@ function HomeTabFeaturedPlugins({plugin}: HomeTabFeaturedPluginsProps) {
let nextSlide = 0
if (e.wheelDelta < 0) {
nextSlide = carouselRef.current.state.currentSlide + 1
if (
Math.abs(carouselRef.current.state.transform) >=
carouselRef.current.containerRef.current.scrollWidth -
carouselRef.current.state.containerWidth
)
return
if (Math.abs(carouselRef.current.state.transform) >= carouselRef.current.containerRef.current.scrollWidth - carouselRef.current.state.containerWidth) return
carouselRef.current.goToSlide(nextSlide)
} else {
nextSlide = carouselRef.current.state.currentSlide - 1
@ -63,27 +58,14 @@ function HomeTabFeaturedPlugins({plugin}: HomeTabFeaturedPluginsProps) {
}
const startSolidity = async () => {
await plugin.appManager.activatePlugin([
'solidity',
'udapp',
'solidityStaticAnalysis',
'solidityUnitTesting'
])
await plugin.appManager.activatePlugin(['solidity', 'udapp', 'solidityStaticAnalysis', 'solidityUnitTesting'])
plugin.verticalIcons.select('solidity')
_paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'solidity'])
}
const startCodeAnalyzer = async () => {
await plugin.appManager.activatePlugin([
'solidity',
'solidityStaticAnalysis'
])
await plugin.appManager.activatePlugin(['solidity', 'solidityStaticAnalysis'])
plugin.verticalIcons.select('solidityStaticAnalysis')
_paq.push([
'trackEvent',
'hometabActivate',
'userActivate',
'solidityStaticAnalysis'
])
_paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'solidityStaticAnalysis'])
}
const startSourceVerify = async () => {
await plugin.appManager.activatePlugin(['solidity', 'sourcify'])
@ -98,12 +80,7 @@ function HomeTabFeaturedPlugins({plugin}: HomeTabFeaturedPluginsProps) {
const startSolidityUnitTesting = async () => {
await plugin.appManager.activatePlugin(['solidity', 'solidityUnitTesting'])
plugin.verticalIcons.select('solidityUnitTesting')
_paq.push([
'trackEvent',
'hometabActivate',
'userActivate',
'solidityUnitTesting'
])
_paq.push(['trackEvent', 'hometabActivate', 'userActivate', 'solidityUnitTesting'])
}
return (
@ -116,14 +93,7 @@ function HomeTabFeaturedPlugins({plugin}: HomeTabFeaturedPluginsProps) {
<Carousel
ref={carouselRef}
focusOnSelect={true}
customButtonGroup={
<CustomNavButtons
next={undefined}
previous={undefined}
goToSlide={undefined}
parent={carouselRef}
/>
}
customButtonGroup={<CustomNavButtons next={undefined} previous={undefined} goToSlide={undefined} parent={carouselRef} />}
arrows={false}
swipeable={false}
draggable={true}

@ -55,11 +55,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
const workspace = plugin.fileManager.getProvider('workspace')
const startsWith = state.importSource.substring(0, 4)
if (
(type === 'ipfs' || type === 'IPFS') &&
startsWith !== 'ipfs' &&
startsWith !== 'IPFS'
) {
if ((type === 'ipfs' || type === 'IPFS') && startsWith !== 'ipfs' && startsWith !== 'IPFS') {
setState((prevState) => {
return {...prevState, importSource: startsWith + state.importSource}
})
@ -72,8 +68,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
toast(error.message || error)
} else {
try {
if (await workspace.exists(type + '/' + cleanUrl))
toast('File already exists in workspace')
if (await workspace.exists(type + '/' + cleanUrl)) toast('File already exists in workspace')
else {
workspace.addExternal(type + '/' + cleanUrl, content, url)
plugin.call('menuicons', 'select', 'filePanel')
@ -116,12 +111,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
plugin.verticalIcons.select('filePanel')
}
const showFullMessage = (
title: string,
loadItem: string,
examples: Array<string>,
prefix = ''
) => {
const showFullMessage = (title: string, loadItem: string, examples: Array<string>, prefix = '') => {
setState((prevState) => {
return {
...prevState,
@ -160,11 +150,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
okFn={() => processLoading(state.modalInfo.title)}
>
<div className="p-2 user-select-auto">
{state.modalInfo.loadItem !== '' && (
<span>
Enter the {state.modalInfo.loadItem} you would like to load.
</span>
)}
{state.modalInfo.loadItem !== '' && <span>Enter the {state.modalInfo.loadItem} you would like to load.</span>}
{state.modalInfo.examples.length !== 0 && (
<>
<div>e.g</div>
@ -172,11 +158,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
</>
)}
<div className="d-flex flex-row">
{state.modalInfo.prefix && (
<span className="text-nowrap align-self-center mr-2">
ipfs://
</span>
)}
{state.modalInfo.prefix && <span className="text-nowrap align-self-center mr-2">ipfs://</span>}
<input
ref={inputValue}
type="text"
@ -195,27 +177,15 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
</div>
</ModalDialog>
<Toaster message={state.toasterMsg} />
<div
className="justify-content-start mt-1 p-2 d-flex flex-column"
id="hTFileSection"
>
<div className="justify-content-start mt-1 p-2 d-flex flex-column" id="hTFileSection">
<label style={{fontSize: '1.2rem'}}>
<FormattedMessage id="home.files" />
</label>
<div className="dflex">
<button
className="btn btn-primary p-2 mr-2 border my-1"
data-id="homeTabNewFile"
style={{width: 'fit-content'}}
onClick={() => createNewFile()}
>
<button className="btn btn-primary p-2 mr-2 border my-1" data-id="homeTabNewFile" style={{width: 'fit-content'}} onClick={() => createNewFile()}>
<FormattedMessage id="home.newFile" />
</button>
<label
className="btn p-2 mr-2 border my-1"
style={{width: 'fit-content', cursor: 'pointer'}}
htmlFor="openFileInput"
>
<label className="btn p-2 mr-2 border my-1" style={{width: 'fit-content', cursor: 'pointer'}} htmlFor="openFileInput">
<FormattedMessage id="home.openFile" />
</label>
<input
@ -236,11 +206,7 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
tooltipText={'Connect to Localhost'}
tooltipTextClasses="border bg-light text-dark p-1 pr-3"
>
<button
className="btn p-2 border my-1"
style={{width: 'fit-content'}}
onClick={() => connectToLocalhost()}
>
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => connectToLocalhost()}>
<FormattedMessage id="home.connectToLocalhost" />
</button>
</CustomTooltip>
@ -261,32 +227,16 @@ function HomeTabFile({plugin}: HomeTabFileProps) {
>
GitHub
</button>
<button
className="btn p-2 border mr-2"
data-id="landingPageImportFromGistButton"
onClick={() => importFromGist()}
>
<button className="btn p-2 border mr-2" data-id="landingPageImportFromGistButton" onClick={() => importFromGist()}>
Gist
</button>
<button
className="btn p-2 border mr-2"
onClick={() =>
showFullMessage(
'Ipfs',
'ipfs hash',
['ipfs://QmQQfBMkpDgmxKzYaoAtqfaybzfgGm9b2LWYyT56Chv6xH'],
'ipfs://'
)
}
>
<button className="btn p-2 border mr-2" onClick={() => showFullMessage('Ipfs', 'ipfs hash', ['ipfs://QmQQfBMkpDgmxKzYaoAtqfaybzfgGm9b2LWYyT56Chv6xH'], 'ipfs://')}>
IPFS
</button>
<button
className="btn p-2 border"
onClick={() =>
showFullMessage('Https', 'http/https raw content', [
'https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'
])
showFullMessage('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])
}
>
HTTPS

@ -47,12 +47,7 @@ function HomeTabGetStarted({plugin}: HomeTabGetStartedProps) {
let nextSlide = 0
if (e.wheelDelta < 0) {
nextSlide = carouselRef.current.state.currentSlide + 1
if (
Math.abs(carouselRef.current.state.transform) >=
carouselRef.current.containerRef.current.scrollWidth -
carouselRef.current.state.containerWidth
)
return
if (Math.abs(carouselRef.current.state.transform) >= carouselRef.current.containerRef.current.scrollWidth - carouselRef.current.state.containerWidth) return
carouselRef.current.goToSlide(nextSlide)
} else {
nextSlide = carouselRef.current.state.currentSlide - 1
@ -66,17 +61,8 @@ function HomeTabGetStarted({plugin}: HomeTabGetStartedProps) {
await plugin.appManager.activatePlugin('filePanel')
const timeStamp = Date.now()
let templateDisplayName = TEMPLATE_NAMES[templateName]
templateDisplayName = await plugin.call(
'filePanel',
'getAvailableWorkspaceName',
templateDisplayName
)
await plugin.call(
'filePanel',
'createWorkspace',
templateDisplayName,
templateName
)
templateDisplayName = await plugin.call('filePanel', 'getAvailableWorkspaceName', templateDisplayName)
await plugin.call('filePanel', 'createWorkspace', templateDisplayName, templateName)
await plugin.call('filePanel', 'setWorkspace', templateDisplayName)
plugin.verticalIcons.select('filePanel')
_paq.push(['trackEvent', 'hometab', 'homeGetStarted', templateName])
@ -95,14 +81,7 @@ function HomeTabGetStarted({plugin}: HomeTabGetStartedProps) {
<Carousel
ref={carouselRef}
focusOnSelect={true}
customButtonGroup={
<CustomNavButtons
next={undefined}
previous={undefined}
goToSlide={undefined}
parent={carouselRef}
/>
}
customButtonGroup={<CustomNavButtons next={undefined} previous={undefined} goToSlide={undefined} parent={carouselRef} />}
arrows={false}
swipeable={false}
draggable={true}

@ -28,22 +28,10 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
const themeFilter = useContext(ThemeContext)
const startLearnEthTutorial = async (
tutorial: 'basics' | 'soliditybeginner' | 'deploylibraries'
) => {
await plugin.appManager.activatePlugin([
'solidity',
'LearnEth',
'solidityUnitTesting'
])
const startLearnEthTutorial = async (tutorial: 'basics' | 'soliditybeginner' | 'deploylibraries') => {
await plugin.appManager.activatePlugin(['solidity', 'LearnEth', 'solidityUnitTesting'])
plugin.verticalIcons.select('LearnEth')
plugin.call(
'LearnEth',
'startTutorial',
'ethereum/remix-workshops',
'master',
tutorial
)
plugin.call('LearnEth', 'startTutorial', 'ethereum/remix-workshops', 'master', tutorial)
_paq.push(['trackEvent', 'hometab', 'startLearnEthTutorial', tutorial])
}
@ -52,26 +40,16 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
plugin.verticalIcons.select('LearnEth')
await plugin.call('LearnEth', 'home')
} else {
await plugin.appManager.activatePlugin([
'LearnEth',
'solidity',
'solidityUnitTesting'
])
await plugin.appManager.activatePlugin(['LearnEth', 'solidity', 'solidityUnitTesting'])
plugin.verticalIcons.select('LearnEth')
await plugin.call('LearnEth', 'home')
}
}
return (
<div
className="d-flex px-2 pb-2 pt-2 d-flex flex-column"
id="hTLearnSection"
>
<div className="d-flex px-2 pb-2 pt-2 d-flex flex-column" id="hTLearnSection">
<div className="d-flex justify-content-between">
<label
className="py-2 pt-3 align-self-center m-0"
style={{fontSize: '1.2rem'}}
>
<label className="py-2 pt-3 align-self-center m-0" style={{fontSize: '1.2rem'}}>
<FormattedMessage id="home.learn" />
</label>
<CustomTooltip
@ -109,10 +87,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
})
}
>
<label
className="card-title align-self-start m-0 float-left"
style={{fontSize: '1rem'}}
>
<label className="card-title align-self-start m-0 float-left" style={{fontSize: '1rem'}}>
<FormattedMessage id="home.learnEth1" />
</label>
{state.visibleTutorial === VisibleTutorial.Basics && (
@ -120,11 +95,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
<span className="py-1" style={{fontSize: '0.8rem'}}>
<FormattedMessage id="home.learnEth1Desc" />
</span>
<button
className="btn btn-sm btn-secondary mt-2"
style={{width: 'fit-content'}}
onClick={() => startLearnEthTutorial('basics')}
>
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('basics')}>
<FormattedMessage id="home.getStarted" />
</button>
</div>
@ -141,10 +112,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
})
}
>
<label
className="card-title align-self-start m-0 float-left"
style={{fontSize: '1rem'}}
>
<label className="card-title align-self-start m-0 float-left" style={{fontSize: '1rem'}}>
<FormattedMessage id="home.learnEth2" />
</label>
{state.visibleTutorial === VisibleTutorial.Intermediate && (
@ -152,11 +120,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
<span className="py-1" style={{fontSize: '0.8rem'}}>
<FormattedMessage id="home.learnEth2Desc" />
</span>
<button
className="btn btn-sm btn-secondary mt-2"
style={{width: 'fit-content'}}
onClick={() => startLearnEthTutorial('soliditybeginner')}
>
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('soliditybeginner')}>
<FormattedMessage id="home.getStarted" />
</button>
</div>
@ -170,10 +134,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
})
}
>
<label
className="card-title align-self-start m-0 float-left"
style={{fontSize: '1rem'}}
>
<label className="card-title align-self-start m-0 float-left" style={{fontSize: '1rem'}}>
<FormattedMessage id="home.remixAdvanced" />
</label>
{state.visibleTutorial === VisibleTutorial.Advanced && (
@ -181,11 +142,7 @@ function HomeTabLearn({plugin}: HomeTabLearnProps) {
<span className="py-1" style={{fontSize: '0.8rem'}}>
<FormattedMessage id="home.remixAdvancedDesc" />
</span>
<button
className="btn btn-sm btn-secondary mt-2"
style={{width: 'fit-content'}}
onClick={() => startLearnEthTutorial('deploylibraries')}
>
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('deploylibraries')}>
<FormattedMessage id="home.getStarted" />
</button>
</div>

@ -12,10 +12,7 @@ function HomeTabScamAlert() {
</label>
<div className="py-2 ml-2 mb-1 align-self-end mb-2 d-flex border border-danger">
<span className="align-self-center pl-4 mt-1">
<i
style={{fontSize: 'xxx-large', fontWeight: 'lighter'}}
className="pr-2 text-danger far fa-exclamation-triangle"
></i>
<i style={{fontSize: 'xxx-large', fontWeight: 'lighter'}} className="pr-2 text-danger far fa-exclamation-triangle"></i>
</span>
<div className="d-flex flex-column">
<span className="pl-4 mt-1">
@ -25,9 +22,7 @@ function HomeTabScamAlert() {
<FormattedMessage id="home.scamAlertText2" />:
<a
className="pl-2 remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'scamAlert', 'learnMore'])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'scamAlert', 'learnMore'])}
target="__blank"
href="https://medium.com/remix-ide/remix-in-youtube-crypto-scams-71c338da32d"
>
@ -38,9 +33,7 @@ function HomeTabScamAlert() {
<FormattedMessage id="home.scamAlertText3" />: &nbsp;
<a
className="remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'scamAlert', 'safetyTips'])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'scamAlert', 'safetyTips'])}
target="__blank"
href="https://remix-ide.readthedocs.io/en/latest/security.html"
>

@ -43,45 +43,24 @@ function HomeTabTitle() {
const openLink = (url = '') => {
if (url === '') {
window.open(
'https://remix-ide.readthedocs.io/en/latest/search.html?q=' +
searchInputRef.current.value +
'&check_keywords=yes&area=default',
'_blank'
)
window.open('https://remix-ide.readthedocs.io/en/latest/search.html?q=' + searchInputRef.current.value + '&check_keywords=yes&area=default', '_blank')
} else {
window.open(url, '_blank')
}
}
return (
<div
className="px-2 pb-2 pt-2 d-flex flex-column border-bottom"
id="hTTitleSection"
>
<div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection">
<div className="d-flex py-2 justify-content-between">
<div className="d-flex justify-content-start">
<span
className="h-80 text-uppercase"
style={{fontSize: 'xx-large', fontFamily: 'Noah, sans-serif'}}
>
<span className="h-80 text-uppercase" style={{fontSize: 'xx-large', fontFamily: 'Noah, sans-serif'}}>
Remix
</span>
<div className="ml-2 d-flex">
<div onClick={() => playRemi()}>
<img
className=""
src="assets/img/guitarRemiCroped.webp"
style={{height: '3rem'}}
alt=""
></img>
<img className="" src="assets/img/guitarRemiCroped.webp" style={{height: '3rem'}} alt=""></img>
</div>
<audio
id="remiAudio"
muted={false}
src="assets/audio/remiGuitar-single-power-chord-A-minor.mp3"
ref={remiAudioEl}
></audio>
<audio id="remiAudio" muted={false} src="assets/audio/remiGuitar-single-power-chord-A-minor.mp3" ref={remiAudioEl}></audio>
</div>
</div>
<span className="d-flex flex-nowrap align-self-end">
@ -94,9 +73,7 @@ function HomeTabTitle() {
>
<button
onClick={() => {
openLink(
'https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA'
)
openLink('https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA')
_paq.push(['trackEvent', 'hometab', 'socialMedia', 'youtube'])
}}
className="border-0 px-1 h-100 btn fab fa-youtube"
@ -169,21 +146,12 @@ function HomeTabTitle() {
<FormattedMessage id="home.nativeIDE" />
</b>
<div className="pb-1" id="hTGeneralLinks">
<a
className="remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'header', 'webSite'])
}
target="__blank"
href="https://remix-project.org"
>
<a className="remixui_home_text" onClick={() => _paq.push(['trackEvent', 'hometab', 'header', 'webSite'])} target="__blank" href="https://remix-project.org">
<FormattedMessage id="home.website" />
</a>
<a
className="pl-2 remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'header', 'documentation'])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'header', 'documentation'])}
target="__blank"
href="https://remix-ide.readthedocs.io/en/latest"
>
@ -191,9 +159,7 @@ function HomeTabTitle() {
</a>
<a
className="pl-2 remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'header', 'remixPlugin'])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'header', 'remixPlugin'])}
target="__blank"
href="https://remix-plugin-docs.readthedocs.io/en/latest/"
>
@ -201,9 +167,7 @@ function HomeTabTitle() {
</a>
<a
className="pl-2 remixui_home_text"
onClick={() =>
_paq.push(['trackEvent', 'hometab', 'header', 'remixDesktop'])
}
onClick={() => _paq.push(['trackEvent', 'hometab', 'header', 'remixDesktop'])}
target="__blank"
href="https://github.com/ethereum/remix-desktop/releases"
>
@ -222,12 +186,7 @@ function HomeTabTitle() {
<button
className="form-control border d-flex align-items-center p-2 justify-content-center fas fa-search bg-light"
onClick={(e) => {
_paq.push([
'trackEvent',
'hometab',
'header',
'searchDocumentation'
])
_paq.push(['trackEvent', 'hometab', 'header', 'searchDocumentation'])
openLink()
}}
disabled={state.searchDisable}

@ -12,15 +12,7 @@ interface PluginButtonProps {
remixMaintained?: boolean
}
function PluginButton({
imgPath,
envID,
envText,
callback,
l2,
description,
remixMaintained
}: PluginButtonProps) {
function PluginButton({imgPath, envID, envText, callback, l2, description, remixMaintained}: PluginButtonProps) {
const themeFilter = useContext(ThemeContext)
return (
@ -30,31 +22,15 @@ function PluginButton({
data-id={'landingPageStart' + envText}
onClick={() => callback()}
>
<img
className="px-2 mb-2 align-self-center remixui_home_envLogo"
id={envID}
src={imgPath}
alt=""
style={{filter: themeFilter.filter}}
/>
<img className="px-2 mb-2 align-self-center remixui_home_envLogo" id={envID} src={imgPath} alt="" style={{filter: themeFilter.filter}} />
<div className="mb-2 h-100 d-flex flex-column">
<label className="text-uppercase text-dark remixui_home_cursorStyle">
{envText}
</label>
<label className="text-uppercase text-dark remixui_home_cursorStyle">{envText}</label>
<div className="remixui_home_envLogoDescription">{description}</div>
</div>
</button>
{l2 && (
<label className="bg-light mx-1 px-1 mb-0 mx-2 position-absolute remixui_home_l2Label">
L2
</label>
)}
{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={'Maintained by Remix'}>
<i className="bg-light text-success mx-1 px-1 mb-0 mx-2 position-absolute remixui_home_maintainedLabel fas fa-check"></i>
</CustomTooltip>
)}

@ -7,12 +7,7 @@ interface WorkspaceTemplateProps {
description: string
}
function WorkspaceTemplate({
gsID,
workspaceTitle,
description,
callback
}: WorkspaceTemplateProps) {
function WorkspaceTemplate({gsID, workspaceTitle, description, callback}: WorkspaceTemplateProps) {
return (
<div className="d-flex remixui_home_workspaceTemplate">
<button
@ -21,9 +16,7 @@ function WorkspaceTemplate({
onClick={() => callback()}
>
<div className="mb-2 w-100 p-2 h-100 align-items-start d-flex flex-column">
<label className="h6 pb-1 text-uppercase text-dark remixui_home_cursorStyle">
{workspaceTitle}
</label>
<label className="h6 pb-1 text-uppercase text-dark remixui_home_cursorStyle">{workspaceTitle}</label>
<div className="remixui_home_gtDescription">{description}</div>
</div>
</button>

@ -54,20 +54,12 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
<div className="d-flex flex-column w-100" data-id="remixUIHTAll">
<ThemeContext.Provider value={state.themeQuality}>
<div className="d-flex flex-row w-100 custom_home_bg">
<div
className="px-2 pl-3 justify-content-start d-flex border-right flex-column"
id="remixUIHTLeft"
style={{width: 'inherit'}}
>
<div className="px-2 pl-3 justify-content-start d-flex border-right flex-column" id="remixUIHTLeft" style={{width: 'inherit'}}>
<HomeTabTitle />
<HomeTabFile plugin={plugin} />
<HomeTabLearn plugin={plugin} />
</div>
<div
className="pl-2 pr-3 justify-content-start d-flex flex-column"
style={{width: '65%'}}
id="remixUIHTRight"
>
<div className="pl-2 pr-3 justify-content-start d-flex flex-column" style={{width: '65%'}} id="remixUIHTRight">
<HomeTabFeatured></HomeTabFeatured>
<HomeTabGetStarted plugin={plugin}></HomeTabGetStarted>
<HomeTabFeaturedPlugins plugin={plugin}></HomeTabFeaturedPlugins>

@ -23,10 +23,7 @@ export function RemixUiLocaleModule({localeModule}: RemixUiLocaleModuleProps) {
<div className="card-text locales-container">
{localeModule.getLocales()
? localeModule.getLocales().map((locale, idx) => (
<div
className="radio custom-control custom-radio mb-1 form-check"
key={idx}
>
<div className="radio custom-control custom-radio mb-1 form-check" key={idx}>
<input
type="radio"
onChange={(event) => {
@ -37,15 +34,9 @@ export function RemixUiLocaleModule({localeModule}: RemixUiLocaleModuleProps) {
name="locale"
id={locale.code}
data-id={`settingsTabLocale${locale.code}`}
checked={
localeModule.active === locale.code.toLocaleLowerCase()
}
checked={localeModule.active === locale.code.toLocaleLowerCase()}
/>
<label
className="form-check-label custom-control-label"
data-id={`settingsTabLocaleLabel${locale.code}`}
htmlFor={locale.code}
>
<label className="form-check-label custom-control-label" data-id={`settingsTabLocaleLabel${locale.code}`} htmlFor={locale.code}>
{locale.name.toLocaleUpperCase()}-{locale.localeName}
</label>
</div>

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

Loading…
Cancel
Save