Merge branch 'master' of https://github.com/ethereum/remix-project into desktopofflinenoscript

pull/4346/head
filip mertens 11 months ago
commit 2095b5e9f4
  1. 5
      apps/doc-viewer/src/app/App.tsx
  2. 13
      apps/doc-viewer/src/app/docviewer.ts
  3. 3
      apps/etherscan/src/app/AppContext.tsx
  4. 17
      apps/etherscan/src/app/EtherscanPluginClient.ts
  5. 67
      apps/etherscan/src/app/app.tsx
  6. 3
      apps/etherscan/src/app/views/HomeView.tsx
  7. 18
      apps/etherscan/src/app/views/VerifyView.tsx
  8. 20
      apps/remix-ide-e2e/src/tests/walkthrough.test.ts
  9. 30
      apps/remix-ide-e2e/src/tests/workspace_git.test.ts
  10. 2
      apps/remix-ide/src/app.js
  11. 6
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/copilot-suggestion.ts
  12. 8
      apps/remix-ide/src/app/plugins/parser/services/code-parser-compiler.ts
  13. 2
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  14. 1
      apps/remix-ide/src/app/tabs/locales/en/udapp.json
  15. 121
      apps/remix-ide/src/app/tabs/locales/fr/home.json
  16. 15
      apps/remix-ide/src/app/tabs/settings-tab.tsx
  17. 14
      apps/remix-ide/src/assets/js/loader.js
  18. 2
      apps/remix-ide/src/blockchain/blockchain.tsx
  19. 2
      apps/remix-ide/src/index.css
  20. 59
      apps/remix-ide/src/walkthroughService.js
  21. 8
      libs/remix-ui/app/src/lib/remix-app/components/modals/enter.tsx
  22. 4
      libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx
  23. 2
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  24. 12
      libs/remix-ui/home-tab/src/lib/components/homeTabGetStarted.tsx
  25. 2
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  26. 72
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  27. 1
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  28. 1
      libs/remix-ui/run-tab/src/lib/types/index.ts
  29. 10
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx
  30. 2
      libs/remix-ui/terminal/src/lib/terminalWelcome.tsx
  31. 86
      libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx
  32. 6
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css
  33. 9
      libs/remix-ui/workspace/src/lib/actions/index.ts
  34. 6
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  35. 9
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  36. 2
      libs/remix-ui/workspace/src/lib/types/index.ts
  37. 15
      libs/remix-ui/workspace/src/lib/utils/constants.ts
  38. 35
      libs/remix-ws-templates/src/templates/hashchecker/README.md
  39. 10
      libs/remix-ws-templates/src/templates/hashchecker/README.txt
  40. 2
      libs/remix-ws-templates/src/templates/hashchecker/index.ts
  41. 46
      libs/remix-ws-templates/src/templates/rln/README.md
  42. 26
      libs/remix-ws-templates/src/templates/semaphore/README.md
  43. 10
      libs/remix-ws-templates/src/templates/semaphore/README.txt
  44. 2
      libs/remix-ws-templates/src/templates/semaphore/index.ts
  45. 1
      package.json

@ -12,9 +12,14 @@ export default function App() {
setContents(fileContents)
})
}, [])
const edit = () => {
if (!client.mdFile) return
client.call('fileManager', 'open' as any, client.mdFile)
}
return (
<>
<div className="m-5 p-2">
<button className="btn btn-secondary mb-2" onClick={edit}>EDIT</button>
<ReactMarkdown children={contents} remarkPlugins={[remarkGfm]} />
</div>
</>

@ -5,6 +5,7 @@ import EventEmitter from 'events'
export class DocViewer extends PluginClient {
mdFile: string
eventEmitter: EventEmitter
refreshId: any
constructor() {
super()
this.eventEmitter = new EventEmitter()
@ -14,9 +15,17 @@ export class DocViewer extends PluginClient {
this.onload()
}
async viewDocs(docs: string[]) {
this.mdFile = docs[0]
private async refresh() {
if (!this.mdFile) return clearInterval(this.refreshId)
const contents = await this.call('fileManager', 'readFile', this.mdFile)
this.eventEmitter.emit('contentsReady', contents)
}
async viewDocs(docs: string[]) {
this.mdFile = docs[0]
this.refresh()
this.refreshId = setInterval(async () => {
this.refresh()
}, 500)
}
}

@ -20,5 +20,6 @@ export const AppContext = React.createContext({
themeType: 'dark' as ThemeType,
setThemeType: (themeType: ThemeType) => {
console.log('Calling Set Theme Type')
}
},
networkName: ''
})

@ -1,10 +1,21 @@
import {PluginClient} from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import {verify, EtherScanReturn} from './utils/verify'
import {getReceiptStatus, getEtherScanApi, getNetworkName, getProxyContractReceiptStatus} from './utils'
import EventManager from 'events'
export class RemixClient extends PluginClient {
loaded() {
return this.onload()
export class EtherscanPluginClient extends PluginClient {
public internalEvents: EventManager
constructor() {
super()
createClient(this)
this.internalEvents = new EventManager()
this.onload()
}
onActivation(): void {
this.internalEvents.emit('etherscan_activated')
}
async verify(

@ -2,8 +2,7 @@ import React, {useState, useEffect, useRef} from 'react'
import {CompilationFileSources, CompilationResult} from '@remixproject/plugin-api'
import {RemixClient} from './RemixPlugin'
import {createClient} from '@remixproject/plugin-webview'
import { EtherscanPluginClient } from './EtherscanPluginClient'
import {AppContext} from './AppContext'
import {DisplayRoutes} from './routes'
@ -21,32 +20,29 @@ export const getNewContractNames = (compilationResult: CompilationResult) => {
for (const file of Object.keys(compiledContracts)) {
const newContractNames = Object.keys(compiledContracts[file])
result = [...result, ...newContractNames]
}
return result
}
const plugin = new EtherscanPluginClient()
const App = () => {
const [apiKey, setAPIKey] = useLocalStorage('apiKey', '')
const [clientInstance, setClientInstance] = useState(undefined as any)
const [receipts, setReceipts] = useLocalStorage('receipts', [])
const [contracts, setContracts] = useState([] as string[])
const [themeType, setThemeType] = useState('dark' as ThemeType)
const [receipts, setReceipts] = useLocalStorage('receipts', [])
const [contracts, setContracts] = useState<string[]>([])
const [themeType, setThemeType] = useState<ThemeType>('dark')
const [networkName, setNetworkName] = useState('Loading...')
const timer = useRef(null)
const clientInstanceRef = useRef(clientInstance)
clientInstanceRef.current = clientInstance
const contractsRef = useRef(contracts)
contractsRef.current = contracts
useEffect(() => {
const client = new RemixClient()
createClient(client)
const loadClient = async () => {
await client.onload()
setClientInstance(client)
client.on('solidity', 'compilationFinished', (fileName: string, source: CompilationFileSources, languageVersion: string, data: CompilationResult) => {
plugin.internalEvents.on('etherscan_activated', () => {
plugin.on('solidity', 'compilationFinished', (fileName: string, source: CompilationFileSources, languageVersion: string, data: CompilationResult) => {
const newContractsNames = getNewContractNames(data)
const newContractsToSave: string[] = [...contractsRef.current, ...newContractsNames]
@ -55,21 +51,16 @@ const App = () => {
setContracts(uniqueContracts)
})
//const currentTheme = await client.call("theme", "currentTheme")
//setThemeType(currentTheme.quality)
//client.on("theme", "themeChanged", (theme) => {
// setThemeType(theme.quality)
//})
}
loadClient()
plugin.on('blockchain' as any, 'networkStatus', (result) => {
setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`)
})
// @ts-ignore
plugin.call('blockchain', 'getCurrentNetworkStatus').then((result: any) => setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`))
})
}, [])
useEffect(() => {
let receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => {
return item.status === 'Pending in queue' || item.status === 'Max rate limit reached'
})
let receiptsNotVerified: Receipt[] = receipts.filter((item: Receipt) => item.status === 'Pending in queue' || item.status === 'Max rate limit reached')
if (receiptsNotVerified.length > 0) {
if (timer.current) {
@ -77,15 +68,12 @@ const App = () => {
timer.current = null
}
timer.current = setInterval(async () => {
const {network, networkId} = await getNetworkName(clientInstanceRef.current)
if (!clientInstanceRef.current) {
return
}
const {network, networkId} = await getNetworkName(plugin)
if (network === 'vm') {
return
}
if (!plugin) return
if (network === 'vm') return
let newReceipts = receipts
for (const item of receiptsNotVerified) {
await new Promise((r) => setTimeout(r, 500)) // avoid api rate limit exceed.
let status
@ -110,9 +98,7 @@ const App = () => {
})
}
}
receiptsNotVerified = newReceipts.filter((item: Receipt) => {
return item.status === 'Pending in queue' || item.status === 'Max rate limit reached'
})
receiptsNotVerified = newReceipts.filter((item: Receipt) => item.status === 'Pending in queue' || item.status === 'Max rate limit reached')
if (timer.current && receiptsNotVerified.length === 0) {
clearInterval(timer.current)
timer.current = null
@ -127,16 +113,17 @@ const App = () => {
value={{
apiKey,
setAPIKey,
clientInstance,
clientInstance: plugin,
receipts,
setReceipts,
contracts,
setContracts,
themeType,
setThemeType
setThemeType,
networkName
}}
>
<DisplayRoutes />
{ plugin && <DisplayRoutes /> }
</AppContext.Provider>
)
}

@ -10,7 +10,7 @@ import {VerifyView} from './VerifyView'
export const HomeView: React.FC = () => {
return (
<AppContext.Consumer>
{({apiKey, clientInstance, setReceipts, receipts, contracts}) => {
{({apiKey, clientInstance, setReceipts, receipts, contracts, networkName}) => {
return !apiKey ? (
<Navigate
to={{
@ -26,6 +26,7 @@ export const HomeView: React.FC = () => {
const newReceipts = [...receipts, receipt]
setReceipts(newReceipts)
}}
networkName={networkName}
/>
)
}}

@ -14,7 +14,8 @@ interface Props {
client: PluginClient
apiKey: string
onVerifiedContract: (receipt: Receipt) => void
contracts: string[]
contracts: string[],
networkName: string
}
interface FormValues {
@ -23,27 +24,14 @@ interface FormValues {
expectedImplAddress?: string
}
export const VerifyView: React.FC<Props> = ({apiKey, client, contracts, onVerifiedContract}) => {
export const VerifyView: React.FC<Props> = ({apiKey, client, contracts, onVerifiedContract, networkName}) => {
const [results, setResults] = useState('')
const [networkName, setNetworkName] = useState('Loading...')
const [selectedContract, setSelectedContract] = useState('')
const [showConstructorArgs, setShowConstructorArgs] = useState(false)
const [isProxyContract, setIsProxyContract] = useState(false)
const [constructorInputs, setConstructorInputs] = useState([])
const verificationResult = useRef({})
useEffect(() => {
if (client && client.on) {
client.on('blockchain' as any, 'networkStatus', (result) => {
setNetworkName(`${result.network.name} ${result.network.id !== '-' ? `(Chain id: ${result.network.id})` : '(Not supported)'}`)
})
}
return () => {
// To fix memory leak
if (client && client.off) client.off('blockchain' as any, 'networkStatus')
}
}, [client])
useEffect(() => {
if (contracts.includes(selectedContract)) updateConsFields(selectedContract)
}, [contracts])

@ -0,0 +1,20 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done)
},
'Should run walkthrough for recorder': function (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="remixIdeSidePanel"]')
.clickLaunchIcon('udapp')
.waitForElementPresent('*[data-id="recorderStartWalkthrough"]')
.click('*[data-id="recorderStartWalkthrough"]')
.waitForElementPresent('*[id="remixRecorderWalkthrowTitle"]')
.waitForElementPresent('*[data-id="remixRecorderExpanded"]')
}
}

@ -339,6 +339,36 @@ module.exports = {
.waitForElementVisible('[data-id="treeViewDivtreeViewItemrecursive/plugins/build"]')
},
// GIT SUBMODULES E2E ENDS
// GIT WORKSPACE E2E STARTS
'Should create a git workspace (uniswapV4Periphery) #group4': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=uniswapV4Periphery]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100)
.waitForElementVisible('*[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts')
.openFile('contracts/hooks')
.openFile('contracts/hooks/examples')
.openFile('contracts/hooks/examples/FullRange.sol')
.pause(1000)
.getEditorValue((content) => {
browser.assert.ok(content.indexOf(`contract FullRange is BaseHook`) !== -1,
'Incorrect content')
})
},
// GIT WORKSPACE E2E ENDS
tearDown: sauce,
}

@ -166,7 +166,7 @@ class AppComponent {
this.showMatamo = matomoDomains[window.location.hostname] && !Registry.getInstance().get('config').api.exists('settings/matomo-analytics')
this.platform = isElectron() ? 'desktop' : 'web'
this.showEnter = matomoDomains[window.location.hostname] && !localStorage.getItem('hadUsageTypeAsked')
this.showEnter = this.showMatamo && !localStorage.getItem('hadUsageTypeAsked')
this.walkthroughService = new WalkthroughService(appManager, !this.showMatamo || !this.showEnter)

@ -50,8 +50,8 @@ export class CopilotSuggestion extends Plugin {
const options: SuggestOptions = {
do_sample: false,
top_k: 0,
temperature,
max_new_tokens
temperature: temperature || 0,
max_new_tokens: max_new_tokens || 0
}
return this.service.suggest(this.context ? this.context + '\n\n' + content : content, options)
}
@ -76,4 +76,4 @@ export class CopilotSuggestion extends Plugin {
async uninstall() {
this.service.terminate()
}
}
}

@ -142,6 +142,14 @@ export default class CodeParserCompiler {
this.compiler.set('runs', state.runs)
this.compiler.set('useFileConfiguration', true)
this.compiler.set('compilerRetriggerMode', CompilerRetriggerMode.retrigger)
if (await this.plugin.call('fileManager', 'exists','remappings.txt')) {
const remappings = await this.plugin.call('fileManager', 'readFile','remappings.txt')
this.compiler.set('remappings', remappings.split('\n').filter(Boolean))
} else {
this.compiler.set('remappings', [])
}
const configFileContent = {
"language": "Solidity",
"settings": {

@ -106,6 +106,8 @@
"filePanel.semaphore": "Semaphore",
"filePanel.hashchecker": "Hash Checker",
"filePanel.rln": "Rate-Limiting Nullifier",
"filePanel.breakthroughLabsUniswapv4Hooks": "Breakthrough-Labs Uniswapv4Hooks",
"filePanel.uniswapV4Periphery": "Uniswap v4 Periphery",
"filePanel.transparent": "Transparent",
"filePanel.initGitRepoTitle": "Check option to initialize workspace as a new git repository",
"filePanel.switchToBranchTitle1": "Checkout new branch from remote branch",

@ -76,6 +76,7 @@
"udapp.transactionSaveTooltip1": "No transactions to save",
"udapp.transactionSaveTooltip2": "Save {count} transaction as scenario file",
"udapp.transactionSaveTooltip3": "Save {count} transactions as scenario file",
"udapp.transactionsWalkthroughTooltip": "Start walkthrough tour for recorder.",
"udapp.infoRecorderTooltip": "Save transactions (deployed contracts and function executions) and replay them in another environment e.g Transactions created in Remix VM can be replayed in the Injected Provider.",
"udapp.livemodeRecorderTooltip": "If contracts are updated after recording transactions, checking this box will run recorded transactions with the latest copy of the compiled contracts",
"udapp.livemodeRecorderLabel": "Run transactions using the latest compilation result",

@ -1,66 +1,61 @@
{
"home.scamAlert": "Alerte arnaque",
"home.scamAlertText": "Le seul URL utilisé par Remix est remix.ethereum.org",
"home.scamAlertText2": "Méfiez-vous des vidéos en ligne qui font la promotion de \"front-runner bots\"",
"home.scamAlertText3": "Conseils de sécurité supplémentaires",
"home.learnMore": "En savoir plus",
"home.here": "ici",
"home.featured": "Recommandé",
"home.jumpIntoWeb3": "JUMP INTO WEB3",
"home.jumpIntoWeb3More": "More",
"home.jumpIntoWeb3Text": "Remix IDE is part of the Remix Project, a rich toolset that can be used for the entire journey of contract development by users of any knowledge level. Learn more on the Remix Project website.",
"home.remixYouTube": "REGARDER POUR APPRENDRE",
"home.remixYouTubeText1": "Conseils vidéo de l'équipe de Remix",
"home.remixYouTubeMore": "Regarder",
"home.remixYouTubeText2": "Remix a une bibliothèque grandissante de vidéos contenant beaucoup de conseils pour utiliser l'outil. Vérifiez-les et abonnez-vous pour obtenir nos dernieres vidéos.",
"home.betaTesting": "Tests BETA",
"home.betaTestingText1": "Notre communauté nous soutient.",
"home.betaTestingText2": "Aidez-nous à tester les versions bêta dès maintenant et à gérer les nouvelles fonctionnalités !",
"home.betaTestingMore": "S'inscrire",
"home.featuredPlugins": "Plugins recommandés",
"home.solidityPluginDesc": "Compiler, tester et analyser les smart contrats.",
"home.cookbookDesc": "Trouvez des smarts contrats, des bibliothèques solidity et découvrez des protocoles.",
"home.codeAnalyizerPluginDesc": "Analysez votre code en utilisant Remix, Solhint et Slither.",
"home.starkNetPluginDesc": "Compiler et déployer des contrats avec Cairo, le language natif pour StarkNet.",
"home.solhintPluginDesc": "Solhint est un projet open source de linter pour code solidity.",
"home.sourcifyPluginDesc": "Service de vérification de contract solidity et des métadonnées.",
"home.unitTestPluginDesc": "Écrire et exécuter des tests unitaires pour vos contrats en Solidity.",
"home.dgitPluginDesc": "Ajoutez le contrôle source à vos projets.",
"home.oneClickDappDesc": "Générer rapidement des interfaces smart contract",
"home.getStarted": "Démarrer",
"home.projectTemplates": "Template de projet",
"home.blankTemplateDesc": "Créer un espace de travail vide.",
"home.remixDefaultTemplateDesc": "Créer un espace de travail avec des exemples de fichiers.",
"home.ozerc20TemplateDesc": "Créer un token ERC20 en important la bibliothèque OpenZeppelin.",
"home.ozerc721TemplateDesc": "Créez un token NFT en important la bibliothèque OpenZeppelin.",
"home.ozerc1155TemplateDesc": "Créez un token ERC1155 en important la bibliothèque OpenZeppelin.",
"home.gnosisSafeMultisigTemplateDesc": "Créer des allet multi-signatures en utilisant ce modèle.",
"home.zeroxErc20TemplateDesc": "Créez un token ERC20 en important le contrat 0xProject.",
"home.learn": "Apprendre",
"home.learnEth1": "Bases de remix",
"home.learnEth1Desc": "Une introduction à l'interface de Remix et aux opérations de base.",
"home.learnEth2": "Introduction à Solidity",
"home.learnEth2Desc": "Apprenez de façon interactive les concepts de base de Solidity.",
"home.remixAdvanced": "Déploiement avec les librairies",
"home.remixAdvancedDesc": "Apprendre à déployer avec les librairies dans Remix",
"home.remixYoutubePlaylist": "Playlist Youtube de Remix",
"home.remixTwitterProfile": "Profile Twitter de Remix",
"home.remixLinkedinProfile": "Profil Linkedin de Remix",
"home.remixMediumPosts": "Articles Medium de Remix",
"home.joinUsOnDiscord": "Rejoignez-nous sur Discord",
"home.nativeIDE": "L’IDE natif pour le développement Web3.",
"home.website": "Site Web",
"home.scamAlert": "Scam Alert",
"home.scamAlertText": "The only URL Remix uses is remix.ethereum.org",
"home.scamAlertText2": "Beware of online videos promoting \"liquidity front runner bots\"",
"home.scamAlertText3": "Additional safety tips",
"home.learnMore": "Learn more",
"home.here": "here",
"home.featured": "Featured",
"home.jumpIntoWeb3": "WE NEED YOUR HELP",
"home.jumpIntoWeb3More": "Go to survey",
"home.jumpIntoWeb3Text": "Remixers... Have a spare moment? Please help us improve your Remix experience with this one-minute survey.",
"home.remixYouTube": "WATCH TO LEARN",
"home.remixYouTubeText1": "Video Tips from the Remix Team",
"home.remixYouTubeMore": "Watch",
"home.remixYouTubeText2": "Remix has a growing library of videos containing lots of tips for using the tool. Check them out and subscribe to get our latest uploads.",
"home.betaTesting": "BETA TESTING",
"home.betaTestingText1": "Our community supports us.",
"home.betaTestingText2": "Help us beta test releases now and get a handle on new features!",
"home.betaTestingMore": "Sign up",
"home.featuredPlugins": "Featured Plugins",
"home.solidityPluginDesc": "Compile, test, and analyze smart contracts.",
"home.starkNetPluginDesc": "Compile and deploy contracts with Cairo, a native language for StarkNet.",
"home.solhintPluginDesc": "Solhint is an open source project for linting Solidity code.",
"home.sourcifyPluginDesc": "Solidity contract and metadata verification service.",
"home.unitTestPluginDesc": "Write and run unit tests for your contracts in Solidity.",
"home.dgitPluginDesc": "Add source control to your projects.",
"home.oneClickDappDesc": "Quickly generate smart contract interfaces",
"home.getStarted": "Get Started",
"home.projectTemplates": "Project Templates",
"home.blankTemplateDesc": "Create an empty workspace.",
"home.remixDefaultTemplateDesc": "Create a workspace with sample files.",
"home.ozerc20TemplateDesc": "Create an ERC20 token by importing OpenZeppelin library.",
"home.ozerc721TemplateDesc": "Create an NFT token by importing OpenZeppelin library.",
"home.ozerc1155TemplateDesc": "Create an ERC1155 token by importing OpenZeppelin library.",
"home.gnosisSafeMultisigTemplateDesc": "Create Multi-Signature wallets using this template.",
"home.zeroxErc20TemplateDesc": "Create an ERC20 token by importing 0xProject contract.",
"home.learn": "Learn",
"home.learnEth1": "Remix Basics",
"home.learnEth1Desc": "An introduction to Remix's interface and basic operations.",
"home.learnEth2": "Intro to Solidity",
"home.learnEth2Desc": "Interactively learn Solidity beginner concepts.",
"home.remixAdvanced": "Deploying with Libraries",
"home.remixAdvancedDesc": "Learn to deploy with libraries in Remix",
"home.remixYoutubePlaylist": "Remix Youtube Playlist",
"home.remixTwitterProfile": "Remix Twitter Profile",
"home.remixLinkedinProfile": "Remix Linkedin Profile",
"home.remixMediumPosts": "Remix Medium Posts",
"home.remixGitterChannel": "Join us on Discord",
"home.nativeIDE": "The Native IDE for Web3 Development.",
"home.website": "Website",
"home.documentation": "Documentation",
"home.remixPlugin": "Plugin Remix",
"home.remixDesktop": "Version Desktop de Remix",
"home.searchDocumentation": "Rechercher dans la documentation",
"home.files": "Fichiers",
"home.newFile": "Nouveau Fichier",
"home.openFile": "Ouvrir Fichier",
"home.accessFileSystem": "Accéder au système de fichiers",
"home.loadFrom": "Charger de",
"home.resources": "Ressources",
"home.connectToLocalhost": "Se connecter à Localhost",
"home.seeAllTutorials": "Voir tous les tutoriels",
"home.maintainedByRemix": "Maintenu par Remix"
"home.remixPlugin": "Remix Plugin",
"home.remixDesktop": "Remix Desktop",
"home.searchDocumentation": "Search Documentation",
"home.files": "Files",
"home.newFile": "New File",
"home.openFile": "Open File",
"home.connectToLocalhost": "Access File System",
"home.loadFrom": "Load from",
"home.resources": "Resources"
}

@ -5,6 +5,12 @@ import * as packageJson from '../../../../../package.json'
import {RemixUiSettings} from '@remix-ui/settings' //eslint-disable-line
import {Registry} from '@remix-project/remix-lib'
import {PluginViewWrapper} from '@remix-ui/helper'
declare global {
interface Window {
_paq: any
}
}
const _paq = (window._paq = window._paq || [])
const profile = {
name: 'settings',
@ -85,6 +91,15 @@ module.exports = class SettingsTab extends ViewPlugin {
updateMatomoAnalyticsChoice(isChecked) {
this.config.set('settings/matomo-analytics', isChecked)
this.useMatomoAnalytics = isChecked
if (!isChecked) {
_paq.push(['optUserOut'])
// revoke tracking consent
_paq.push(['forgetConsentGiven']);
} else {
_paq.push(['forgetUserOptOut'])
// user has given consent to process their data
_paq.push(['setConsentGiven']);
}
this.dispatch({
...this
})

@ -17,14 +17,20 @@ if (domains[window.location.hostname]) {
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setExcludedQueryParams", ["code","gist"]]);
_paq.push(["setExcludedReferrers", ["etherscan.io"]]);
_paq.push(['disableCookies']);
_paq.push(['enableJSErrorTracking']);
// require user tracking consent before processing data
_paq.push(['requireConsent']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['enableHeartBeatTimer']);
if (!window.localStorage.getItem('config-v0.8:.remix.config') ||
(window.localStorage.getItem('config-v0.8:.remix.config') && !window.localStorage.getItem('config-v0.8:.remix.config').includes('settings/matomo-analytics'))) {
_paq.push(['optUserOut'])
} else {
_paq.push(['forgetUserOptOut'])
// user has given consent to process their data
_paq.push(['setConsentGiven'])
}
(function () {
var u = "https://ethereumfoundation.matomo.cloud/";
@ -38,17 +44,17 @@ if (domains[window.location.hostname]) {
function isElectron() {
// Renderer process
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
return true
return true
}
// Main process
if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
return true
return true
}
// Detect the user agent when the `nodeIntegration` option is set to false
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
return true
return true
}
return false

@ -23,7 +23,7 @@ const profile = {
name: 'blockchain',
displayName: 'Blockchain',
description: 'Blockchain - Logic',
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'getAccounts', 'web3VM', 'web3', 'getProvider'],
methods: ['getCode', 'getTransactionReceipt', 'addProvider', 'removeProvider', 'getCurrentFork', 'getAccounts', 'web3VM', 'web3', 'getProvider', 'getCurrentNetworkStatus'],
version: packageJson.version
}

@ -19,4 +19,4 @@
font-size: 0.8rem;
font-weight: normal;
max-width: 300px;
}
}

@ -7,14 +7,14 @@ const profile = {
displayName: 'Walkthrough',
description: 'Remix walkthrough for beginner',
version: packageJson.version,
methods: ['start']
methods: ['start', 'startRecorderW']
}
export class WalkthroughService extends Plugin {
constructor (appManager, showWalkthrough) {
super(profile)
let readyToStart = 0;
/*appManager.event.on('activate', (plugin) => {
/*let readyToStart = 0;
appManager.event.on('activate', (plugin) => {
if (plugin.name === 'udapp') readyToStart++
if (readyToStart == 2 && showWalkthrough) {
this.start()
@ -28,6 +28,59 @@ export class WalkthroughService extends Plugin {
})*/
}
startRecorderW () {
introJs().setOptions({
steps: [{
title: 'Transactions Recorder',
intro: 'Save transactions (deployed contracts and function executions) and replay them in another environment e.g Transactions created in Remix VM can be replayed in the Injected Provider.Click to launch the Home tab that contains links, tips, and shortcuts..',
element: document.querySelector('#udappRecorderCard'),
tooltipClass: 'bg-light text-dark',
position: 'right',
highlightClass: 'bg-light border border-warning'
},
{
element: document.querySelector('#udappRecorderUseLatest'),
title: 'Transactions Recorder',
intro: 'If set the recorder will run transactions using the latest compilation result.',
tooltipClass: 'bg-light text-dark',
position: 'right',
highlightClass: 'bg-light border border-warning'
},
{
element: document.querySelector('#udappRecorderSave'),
title: 'Transactions Recorder',
intro: 'Once there is a Once one or a few transactions have been executed from Remix, click this button to save these transactions as a scenario file.',
tooltipClass: 'bg-light text-dark',
position: 'right',
highlightClass: 'bg-light border border-warning'
},
{
element: document.querySelector('#udappRecorderRun'),
title: 'Transactions Recorder',
intro: 'Open a scenario file and click this button to run it against the current selected provider.',
tooltipClass: 'bg-light text-dark',
position: 'right',
highlightClass: 'bg-light border border-warning'
}
]
}).onafterchange((targetElement) => {
const header = document.getElementsByClassName('introjs-tooltip-header')[0]
if (header) {
header.classList.add('d-flex')
header.classList.add('justify-content-between')
header.classList.add('text-nowrap')
header.classList.add('pr-0')
header.id="remixRecorderWalkthrowTitle"
}
const skipbutton = document.getElementsByClassName('introjs-skipbutton')[0]
if (skipbutton) {
skipbutton.classList.add('ml-3')
skipbutton.classList.add('text-decoration-none')
skipbutton.id = 'remixTourSkipbtn'
}
}).start()
}
start () {
if (!localStorage.getItem('hadTour_initial')) {
introJs().setOptions({

@ -46,10 +46,10 @@ const EnterDialog = (props: EnterDialogProps) => {
</div>
</div>
<div className="modal-body text-break remixModalBody d-flex flex-row p-3 justify-content-between" data-id={`EnterModalDialogModalBody-react`}>
<button className="btn-secondary" data-id="beginnerbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Beginner)}}>Beginner</button>
<button className="btn-secondary" data-id="tutorbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Tutor)}}>Teacher</button>
<button className="btn-secondary" data-id="prototyperbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Prototyper)}}>Prototyper</button>
<button className="btn-secondary" data-id="productionbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Production)}}>Production User</button>
<button className="btn btn-secondary" data-id="beginnerbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Beginner)}}>Beginner</button>
<button className="btn btn-secondary" data-id="tutorbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Tutor)}}>Teacher</button>
<button className="btn btn-secondary" data-id="prototyperbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Prototyper)}}>Prototyper</button>
<button className="btn btn-secondary" data-id="productionbtn" style={{minWidth: "100px"}} onClick={() => {enterAs(UsageTypes.Production)}}>Production User</button>
</div>
</div>
</div>

@ -57,11 +57,15 @@ const MatomoDialog = (props) => {
const declineModal = async () => {
settings.updateMatomoAnalyticsChoice(false)
_paq.push(['optUserOut'])
// revoke tracking consent
_paq.push(['forgetConsentGiven']);
setVisible(false)
}
const handleModalOkClick = async () => {
_paq.push(['forgetUserOptOut'])
// user has given consent to process their data
_paq.push(['setConsentGiven']);
settings.updateMatomoAnalyticsChoice(true)
setVisible(false)
}

@ -25,7 +25,7 @@ interface IRemixAppUi {
}
const RemixApp = (props: IRemixAppUi) => {
const [appReady, setAppReady] = useState<boolean>(false)
const [showEnterDialog, setShowEnterDialog] = useState<boolean>(true)
const [showEnterDialog, setShowEnterDialog] = useState<boolean>(false)
const [hideSidePanel, setHideSidePanel] = useState<boolean>(false)
const [maximiseTrigger, setMaximiseTrigger] = useState<number>(0)
const [resetTrigger, setResetTrigger] = useState<number>(0)

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {useEffect, useRef, useContext} from 'react'
import {useIntl, FormattedMessage} from 'react-intl'
import {TEMPLATE_NAMES} from '@remix-ui/workspace'
import {TEMPLATE_NAMES,TEMPLATE_METADATA} from '@remix-ui/workspace'
import {ThemeContext} from '../themeContext'
import Carousel from 'react-multi-carousel'
import WorkspaceTemplate from './workspaceTemplate'
@ -60,15 +60,19 @@ function HomeTabGetStarted({plugin}: HomeTabGetStartedProps) {
}
const createWorkspace = async (templateName) => {
if(platform === appPlatformTypes.desktop){
await plugin.call('remix-templates', 'loadTemplateInNewWindow', templateName)
return
}
await plugin.appManager.activatePlugin('filePanel')
const timeStamp = Date.now()
let templateDisplayName = TEMPLATE_NAMES[templateName]
const metadata = TEMPLATE_METADATA[templateName]
if (metadata) {
await plugin.call('dGitProvider', 'clone', {url: metadata.url, branch: metadata.branch}, templateDisplayName)
return
}
await plugin.appManager.activatePlugin('filePanel')
templateDisplayName = await plugin.call('filePanel', 'getAvailableWorkspaceName', templateDisplayName)
await plugin.call('filePanel', 'createWorkspace', templateDisplayName, templateName)
await plugin.call('filePanel', 'setWorkspace', templateDisplayName)

@ -514,7 +514,7 @@ export function ContractDropdownUI(props: ContractDropdownProps) {
<CustomTooltip placement={'top-end'} tooltipClasses="text-wrap text-left" tooltipId="runAndDeployAddresstooltip" tooltipText={atAddressOptions.title}>
<div id="runAndDeployAtAdressButtonContainer" data-title={atAddressOptions.title}>
<button
className="udapp_atAddress btn-sm py-2 btn-primary"
className={atAddressOptions.disabled ? "disabled udapp_atAddress btn btn-sm py-2 btn-primary" : "udapp_atAddress btn btn-sm py-2 btn-primary"}
id="runAndDeployAtAdressButton"
disabled={atAddressOptions.disabled}
style={{ border: 'none' }}

@ -28,8 +28,13 @@ export function RecorderUI(props: RecorderProps) {
setToggleExpander(!toggleExpander)
}
const startWalkthrough = async () => {
setToggleExpander(true)
await props.plugin.call('walkthrough', 'startRecorderW')
}
return (
<div className="udapp_cardContainer py-1 list-group-item border-top border-bottom">
<div className="udapp_cardContainer py-1 list-group-item border-top border-bottom" id="udappRecorderCard">
<div className="udapp_recorderSection d-flex justify-content-between" onClick={toggleClass}>
<div className="d-flex justify-content-center align-items-center">
<label className="mt-1 udapp_recorderSectionLabel">
@ -47,15 +52,18 @@ export function RecorderUI(props: RecorderProps) {
</CustomTooltip>
<CustomTooltip
placement={'right'}
tooltipClasses="text-wrap"
tooltipId="info-recorder"
tooltipText={
<span>
<FormattedMessage id="udapp.infoRecorderTooltip" values={{br: <br />}} />
</span>
}
tooltipClasses="text-nowrap"
tooltipId="recordedTransactionsWalkthroughtooltip"
tooltipText={<FormattedMessage id="udapp.transactionsWalkthroughTooltip" />}
>
<i style={{fontSize: 'medium'}} className={'ml-2 fal fa-info-circle align-self-center'} aria-hidden="true"></i>
<i
style={{fontSize: 'medium'}}
className={'ml-2 fal fa-info-circle align-self-center'}
aria-hidden="true"
onClick={() => startWalkthrough()}
data-id="recorderStartWalkthrough"
>
</i>
</CustomTooltip>
</div>
<div className="p-3">
@ -64,8 +72,8 @@ export function RecorderUI(props: RecorderProps) {
</span>
</div>
</div>
<div className={`pb-2 flex-column ${toggleExpander ? 'd-flex' : 'd-none'}`}>
<div className="mb-1 mt-1 custom-control custom-checkbox mb-1">
{ toggleExpander && <div className={`pb-2 flex-column d-flex`} data-id='remixRecorderExpanded'>
<div className="mb-1 mt-1 custom-control custom-checkbox mb-1" id='udappRecorderUseLatest'>
<input ref={inputLive} type="checkbox" id="livemode-recorder" className="custom-control-input custom-select" name="input-livemode" />
<CustomTooltip
placement={'right'}
@ -95,32 +103,30 @@ export function RecorderUI(props: RecorderProps) {
: intl.formatMessage({id: 'udapp.transactionSaveTooltip3'}, {count: props.count})
}
>
<span>
<button
className="btn btn-sm btn-info savetransaction udapp_recorder"
disabled={props.count === 0 ? true : false}
onClick={triggerRecordButton}
style={{pointerEvents: props.count === 0 ? 'none' : 'auto'}}
>
<FormattedMessage id="udapp.save" />
</button>
</span>
<button
className="btn btn-sm btn-secondary savetransaction udapp_recorder"
disabled={props.count === 0 ? true : false}
onClick={triggerRecordButton}
style={{pointerEvents: props.count === 0 ? 'none' : 'auto'}}
id="udappRecorderSave"
>
<FormattedMessage id="udapp.save" />
</button>
</CustomTooltip>
<CustomTooltip placement={'right'} tooltipClasses="text-nowrap" tooltipId="tooltip-run-recorder" tooltipText={<FormattedMessage id="udapp.runRecorderTooltip" />}>
<span>
<button
className="btn btn-sm btn-info runtransaction udapp_runTxs"
data-id="runtransaction"
disabled={enableRunButton}
onClick={handleClickRunButton}
style={{pointerEvents: enableRunButton ? 'none' : 'auto'}}
>
<FormattedMessage id="udapp.run" />
</button>
</span>
<button
className={enableRunButton ? "btn btn-sm btn-secondary runtransaction udapp_runTxs" : "btn btn-sm btn-secondary runtransaction udapp_runTxs disabled"}
data-id="runtransaction"
disabled={enableRunButton}
onClick={handleClickRunButton}
style={{pointerEvents: enableRunButton ? 'none' : 'auto'}}
id="udappRecorderRun"
>
<FormattedMessage id="udapp.run" />
</button>
</CustomTooltip>
</div>
</div>
</div>}
</div>
)
}

@ -301,6 +301,7 @@ export function RunTabUI(props: RunTabProps) {
proxy={runTab.proxy}
/>
<RecorderUI
plugin={plugin}
gasEstimationPrompt={gasEstimationPrompt}
passphrasePrompt={passphrasePrompt}
mainnetPrompt={mainnetPrompt}

@ -279,6 +279,7 @@ export interface RecorderProps {
scenarioPrompt: (msg: string, defaultValue: string) => JSX.Element,
count: number
currentFile: string
plugin: RunTab
}
export interface InstanceContainerProps {

@ -190,9 +190,13 @@ export const SolidityUnitTesting = (props: Record<string, any>) => {
}, []) // eslint-disable-line
const updateDirList = (path: string) => {
testTabLogic.dirList(path).then((options: string[]) => {
setPathOptions(options)
})
try {
testTabLogic.dirList(path).then((options: string[]) => {
setPathOptions(options)
})
} catch {
console.log("No test directory has been found in the workspace.")
}
}
const handleTestDirInput = async (e: any) => {

@ -54,7 +54,7 @@ const TerminalWelcomeMessage = ({packageJson, storage}) => {
ethers.js
</a>{' '}
</li>
<li key="ethers-console">
<li key="gpt">
gpt <i>&lt;your question here&gt;</i> {' '}
</li>
</ul>

@ -84,49 +84,57 @@ const Icon = ({iconRecord, verticalIconPlugin, contextMenuAction, theme}: IconPr
}
}, [])
const stylePC = iconRecord.active ? 'flex-start' : 'center'
return (
<>
<CustomTooltip
placement={name === 'settings' ? 'right' : name === 'search' ? 'top' : name === 'udapp' ? 'bottom' : 'top'}
tooltipText={title}
delay={{show: 1000, hide: 0}}
>
<div
className={`remixui_icon m-2 pt-1`}
onClick={() => {
;(verticalIconPlugin as any).toggle(name)
}}
{...{plugin: name}}
onContextMenu={(e: any) => {
e.preventDefault()
e.stopPropagation()
handleContextMenu(e)
}}
data-id={`verticalIconsKind${name}`}
id={`verticalIconsKind${name}`}
ref={iconRef}
<div className='d-flex py-1' style={{width: 'auto', placeContent: stylePC}}>
{iconRecord.active && <div
className='pt-1 bg-primary'
style={{width: "6px", height: "36px", position: 'relative', borderRadius: '24%'}}
></div>}
<CustomTooltip
placement={name === 'settings' ? 'right' : name === 'search' ? 'top' : name === 'udapp' ? 'bottom' : 'top'}
tooltipText={title}
delay={{show: 1000, hide: 0}}
>
<img
data-id={iconRecord.active ? `selected` : ''}
className={`${theme === 'dark' ? 'invert' : ''} ${theme} remixui_image ${iconRecord.active ? `selected-${theme}` : ''}`}
src={icon}
alt={name}
<div
className={`remixui_icon m-0 pt-1`}
onClick={() => {
;(verticalIconPlugin as any).toggle(name)
}}
{...{plugin: name}}
onContextMenu={(e: any) => {
e.preventDefault()
e.stopPropagation()
handleContextMenu(e)
}}
data-id={`verticalIconsKind${name}`}
id={`verticalIconsKind${name}`}
ref={iconRef}
>
<img
data-id={iconRecord.active ? `selected` : ''}
className={`${theme === 'dark' ? 'invert' : ''} ${theme} remixui_image ${iconRecord.active ? `selected-${theme}` : ''}`}
src={icon}
alt={name}
/>
<Badge badgeStatus={badgeStatus} />
</div>
</CustomTooltip>
{showContext ? (
<VerticalIconsContextMenu
pageX={pageX}
pageY={pageY}
links={links}
profileName={name}
hideContextMenu={closeContextMenu}
canBeDeactivated={canDeactivate}
verticalIconPlugin={verticalIconPlugin}
contextMenuAction={contextMenuAction}
/>
<Badge badgeStatus={badgeStatus} />
</div>
</CustomTooltip>
{showContext ? (
<VerticalIconsContextMenu
pageX={pageX}
pageY={pageY}
links={links}
profileName={name}
hideContextMenu={closeContextMenu}
canBeDeactivated={canDeactivate}
verticalIconPlugin={verticalIconPlugin}
contextMenuAction={contextMenuAction}
/>
) : null}
) : null}
</div>
</>
)
}

@ -3,7 +3,9 @@
width: 42px;
height: 42px;
cursor: pointer;
}
justify-content: space-between;
align-self: center;
}
.remixui_homeIcon:hover {
box-shadow: 0px 0px 14px -7px;
}
@ -17,8 +19,6 @@
.remixui_icons {
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
align-items: center;
}
.remixui_icon:hover {
box-shadow: 0px 0px 14px -7px;

@ -368,8 +368,13 @@ export const emitContextMenuEvent = async (cmd: customAction) => {
}
export const handleClickFile = async (path: string, type: 'file' | 'folder' | 'gist') => {
await plugin.fileManager.open(path)
dispatch(focusElement([{ key: path, type }]))
if (type === 'file' && path.endsWith('.md')) {
// just opening the preview
await plugin.call('doc-viewer' as any, 'viewDocs', [path])
} else {
await plugin.fileManager.open(path)
dispatch(focusElement([{ key: path, type }]))
}
}
export const handleExpandPath = (paths: string[]) => {

@ -1,6 +1,7 @@
import React from 'react'
import { bufferToHex } from '@ethereumjs/util'
import { hash } from '@remix-project/remix-lib'
import { TEMPLATE_METADATA, TEMPLATE_NAMES } from '../utils/constants'
import axios, { AxiosResponse } from 'axios'
import {
addInputFieldSuccess,
@ -198,10 +199,13 @@ export const createWorkspace = async (
}
export const createWorkspaceTemplate = async (workspaceName: string, template: WorkspaceTemplate = 'remixDefault') => {
const metadata = TEMPLATE_METADATA[template]
if (!workspaceName) throw new Error('workspace name cannot be empty')
if (checkSpecialChars(workspaceName) || checkSlash(workspaceName)) throw new Error('special characters are not allowed')
if ((await workspaceExists(workspaceName)) && template === 'remixDefault') throw new Error('workspace already exists')
else {
else if (metadata) {
await plugin.call('dGitProvider', 'clone', {url: metadata.url, branch: metadata.branch}, workspaceName)
} else {
const workspaceProvider = plugin.fileProviders.workspace
await workspaceProvider.createWorkspace(workspaceName)
}

@ -773,8 +773,15 @@ export function Workspace() {
{intl.formatMessage({id: 'filePanel.rln'})}
</option>
</optgroup>
<optgroup style={{fontSize: 'medium'}} label="Uniswap">
<option style={{fontSize: 'small'}} value="uniswapV4Periphery">
{intl.formatMessage({id: 'filePanel.uniswapV4Periphery'})}
</option>
<option style={{fontSize: 'small'}} value="breakthroughLabsUniswapv4Hooks">
{intl.formatMessage({id: 'filePanel.breakthroughLabsUniswapv4Hooks'})}
</option>
</optgroup>
</select>
<div id="ozcustomization" data-id="ozCustomization" ref={displayOzCustomRef} style={{display: 'none'}} className="mb-2">
<label className="form-check-label d-block mb-2" style={{fontWeight: 'bolder'}}>
<FormattedMessage id="filePanel.customizeTemplate" />

@ -18,7 +18,7 @@ export interface JSONStandardInput {
}
}
export type MenuItems = action[]
export type WorkspaceTemplate = 'gist-template' | 'code-template' | 'remixDefault' | 'blank' | 'ozerc20' | 'zeroxErc20' | 'ozerc721' | 'playground' | 'semaphore' | 'hashchecker' | 'rln'
export type WorkspaceTemplate = 'gist-template' | 'code-template' | 'remixDefault' | 'blank' | 'ozerc20' | 'zeroxErc20' | 'ozerc721' | 'playground' | 'semaphore' | 'hashchecker' | 'rln' | 'breakthroughLabsUniswapv4Hooks' | 'uniswapV4Periphery'
export interface WorkspaceProps {
plugin: FilePanelType
}

@ -84,5 +84,18 @@ export const TEMPLATE_NAMES = {
'playground': 'Playground',
'semaphore': 'Semaphore',
'hashchecker': 'Hash Checker',
'rln': 'Rate-Limiting Nullifier'
'rln': 'Rate-Limiting Nullifier',
'breakthroughLabsUniswapv4Hooks': 'Breakthrough-Labs Uniswapv4Hooks',
'uniswapV4Periphery': 'Uniswap v4 Periphery',
}
export const TEMPLATE_METADATA = {
'breakthroughLabsUniswapv4Hooks': {
url: 'https://github.com/Breakthrough-Labs/Uniswapv4Hooks',
branch: 'foundry_pure'
},
'uniswapV4Periphery': {
url: 'https://github.com/Uniswap/v4-periphery',
branch: 'main'
}
}

@ -0,0 +1,35 @@
## CIRCOM ZKP Hash Checker WORKSPACE
Welcome to the Remix Circom ZKP Hash Checker Workspace.
The workspace comprises two main directories:
### circuits: Contains sample Hash Checker contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
### scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids in generating Solidity code, which is essential for on-chain deployment.
### first steps:
#### 1) compile the hash checker circuit using the remix circom compiler. This will generate artifacts.
#### 2) execute the file `run_setup.ts`:
This step generate a verification key that can be used for generating proof, it will also generate a Solidity contract for on-chain verification.
Note that this section should only be used for development purposes as this way of running the setup is heavily centralized (although some pieces of this script can be used to achieve that).
This generates a verification key (`./zk/build/verification_key.json`) and artifacts from the setup (`./zk/build/zk_setup.txt`).
#### 3) execute the file `run_verification.ts`:
This script:
- generate a witness and a proof of execution. The input parameters of `snarkjs.wtns.calculate` are:
- 4 values, that should remain private. We want to verify that we know a hash that satisfy these 4 values.
- a hash, this is a public signal.
The witness will be generated only if the provided hash is the poseidon hash of these 4 values.
- verify that the proof is valid `(snarkjs.groth16.verify)`

@ -1,10 +0,0 @@
CIRCOM ZKP Hash Checker WORKSPACE
Welcome to the Remix Circom ZKP Hash Checker Workspace.
The workspace comprises two main directories:
- circuits: Contains sample Hash Checker contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
- scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids in generating Solidity code,
which is essential for on-chain deployment.

@ -9,6 +9,6 @@ export default async () => {
// @ts-ignore
'templates/groth16_verifier.sol.ejs': (await import('!!raw-loader!./templates/groth16_verifier.sol.ejs')).default,
// @ts-ignore
'README.txt': (await import('raw-loader!./README.txt')).default
'README.md': (await import('raw-loader!./README.md')).default
}
}

@ -1,26 +1,38 @@
<h1 align=center>Rate-Limiting Nullifier circuits in Circom</h1>
<p align="center">
<img src="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/workflows/Test/badge.svg" width="110">
</p>
<div align="center">
## What's RLN?
*The project was audited by Veridise, yAcademy fellows and internally.*
Welcome to the Remix Circom ZKP RLN Workspace.
</div>
RLN is a zero-knowledge gadget that enables spam prevention in anonymous environments.
To learn more on RLN and how it works - check out [documentation](https://rate-limiting-nullifier.github.io/rln-docs/).
___
The workspace comprises two main directories:
## What's RLN?
### circuits: Contains sample semaphore contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
RLN is a zero-knowledge gadget that enables spam
prevention in anonymous environments.
### scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids in generating Solidity code, which is essential for on-chain deployment.
The core parts of RLN are:
* zk-circuits in Circom (this repo);
* [registry smart-contract](https://github.com/Rate-Limiting-Nullifier/rln-contract);
* set of libraries to build app with RLN ([rlnjs](https://github.com/Rate-Limiting-Nullifier/rlnjs), [zerokit](https://github.com/vacp2p/zerokit)).
### first steps:
---
#### 1) compile the semaphore circuit using the remix circom compiler. This will generate artifacts.
To learn more on RLN and how it works - check out [documentation](https://rate-limiting-nullifier.github.io/rln-docs/).
#### 2) execute the file `run_setup.ts`:
This step generate a verification key that can be used for generating proof, it will also generate a Solidity contract for on-chain verification.
Note that this section should only be used for development purposes as this way of running the setup is heavily centralized (although some pieces of this script can be used to achieve that).
This generates a verification key (`./zk/build/verification_key.json`) and artifacts from the setup (`./zk/build/zk_setup.txt`).
#### 3) execute the file `run_verification.ts`:
This script:
- create a list of identity commitments and add it to a `IncrementalMerkleTree`. The tree is used to generate a merkle proof that a specified identity is actually in the tree (see`tree.createProof(0)`).
- generate a witness and a proof of execution with `messageId`equal to 0.
- generate a witness and a proof of execution with `messageId`equal to 0.
- generating 2 proofs (two different messages) with the same `messageId` reveal the two points of the polynomial necessary to deduct the `identitySecret` (using `shamirRecovery`).

@ -0,0 +1,26 @@
## CIRCOM ZKP SEMAPHORE WORKSPACE
Welcome to the Remix Circom ZKP Semaphore Workspace.
The workspace comprises two main directories:
### circuits: Contains sample semaphore contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
### scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids in generating Solidity code, which is essential for on-chain deployment.
### first steps:
#### 1) compile the semaphore circuit using the remix circom compiler. This will generate artifacts.
#### 2) execute the file `run_setup.ts`:
This step generate a verification key that can be used for generating proof, it will also generate a Solidity contract for on-chain verification.
Note that this section should only be used for development purposes as this way of running the setup is heavily centralized (although some pieces of this script can be used to achieve that).
This generates a verification key (`./zk/build/verification_key.json`) and artifacts from the setup (`./zk/build/zk_setup.txt`).
#### 3) execute the file `run_verification.ts`:
This script:
- create a list of identity commitments and add it to a `IncrementalMerkleTree`. The tree is used to generate a merkle proof that a specified identity is actually in the tree (see`tree.createProof(0)`).
- generate a witness and a proof of execution.
- verify that the proof is valid `(snarkjs.groth16.verify)`
- ultimately verify that the hash generated by the circom compiler is the same as the root hash for the Tree. `(proof1.root.toString() === publicSignals[0]`). This assert that the identity provided to the circuit is actually part of that semaphore group.

@ -1,10 +0,0 @@
CIRCOM ZKP SEMAPHORE WORKSPACE
Welcome to the Remix Circom ZKP Semaphore Workspace.
The workspace comprises two main directories:
- circuits: Contains sample semaphore contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
- scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids
in generating Solidity code, which is essential for on-chain deployment.

@ -13,6 +13,6 @@ export default async () => {
// @ts-ignore
'templates/groth16_verifier.sol.ejs': (await import('!!raw-loader!./templates/groth16_verifier.sol.ejs')).default,
// @ts-ignore
'README.txt': (await import('raw-loader!./README.txt')).default
'README.md': (await import('raw-loader!./README.md')).default
}
}

@ -105,6 +105,7 @@
"nightwatch_local_stress_editor": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/stressEditor.test.js --env=chromeDesktop",
"nightwatch_local_search": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/search.test.js --env=chromeDesktop",
"nightwatch_local_providers": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/providers.test.js --env=chromeDesktop",
"nightwatch_local_walkthrough": "yarn run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/walkthrough.test.js --env=chromeDesktop",
"onchange": "onchange apps/remix-ide/build/app.js -- npm-run-all lint",
"remixd": "nx build remixd && chmod +x dist/libs/remixd/src/bin/remixd.js && dist/libs/remixd/src/bin/remixd.js --remix-ide http://127.0.0.1:8080",
"simulator": "nx build remix-simulator && chmod +x dist/libs/remix-simulator/bin/ethsim && dist/libs/remix-simulator/bin/ethsim start --rpc",

Loading…
Cancel
Save