add_templates

fix E2E
pull/5042/head
yann300 7 months ago committed by Aniket
parent 3bbedd600d
commit 2ac386a2f4
  1. 2
      apps/etherscan/src/app/views/VerifyView.tsx
  2. 2
      apps/remix-ide-e2e/src/tests/ballot.test.ts
  3. 12
      apps/remix-ide-e2e/src/tests/circom.test.ts
  4. 4
      apps/remix-ide-e2e/src/tests/erc721.test.ts
  5. 2
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  6. 47
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  7. 8
      apps/remix-ide-e2e/src/tests/workspace_git.test.ts
  8. 7
      apps/remix-ide/src/app.js
  9. 2
      apps/remix-ide/src/app/panels/file-panel.js
  10. 473
      apps/remix-ide/src/app/plugins/templates-selection.tsx
  11. 14
      libs/remix-ui/workspace/src/lib/actions/events.ts
  12. 62
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  13. 41
      libs/remix-ui/workspace/src/lib/components/workspace-hamburger.tsx
  14. 203
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  15. 18
      libs/remix-ui/workspace/src/lib/utils/constants.ts
  16. 2
      libs/remix-ws-templates/src/script-templates/contract-deployer/index.ts
  17. 2
      libs/remix-ws-templates/src/script-templates/create2-solidity-factory/index.ts
  18. 2
      libs/remix-ws-templates/src/script-templates/etherscan/index.ts
  19. 2
      libs/remix-ws-templates/src/script-templates/sindri/index.ts

@ -211,7 +211,7 @@ export const VerifyView = ({apiKey, client, contracts, onVerifiedContract, netwo
type="button" type="button"
className="mr-2 mb-2 py-1 px-2 btn btn-secondary btn-block" className="mr-2 mb-2 py-1 px-2 btn btn-secondary btn-block"
onClick={async () => { onClick={async () => {
etherscanScripts(client) etherscanScripts({}, client)
}} }}
> >
Generate Verification Scripts Generate Verification Scripts

@ -97,6 +97,8 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation

@ -13,10 +13,8 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementPresent('*[data-id="create-semaphore"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .scrollAndClick('*[data-id="create-semaphore"]')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=semaphore]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -155,10 +153,8 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementPresent('*[data-id="create-hashchecker"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .scrollAndClick('*[data-id="create-hashchecker"]')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=hashchecker]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)

@ -17,12 +17,12 @@ module.exports = {
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
// create contract // create contract
.waitForElementPresent('*[data-id="create-hashchecker"]')
.scrollAndClick('*[data-id="create-hashchecker"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc721' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc721' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc721]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)

@ -180,6 +180,8 @@ module.exports = {
// creating a new workspace // creating a new workspace
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]') .click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_new') .setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_new')

@ -38,6 +38,8 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
@ -110,12 +112,12 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-blank"]')
.scrollAndClick('*[data-id="create-blank"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_blank' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_blank' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=blank]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -133,12 +135,12 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc20"]')
.scrollAndClick('*[data-id="create-ozerc20"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc20' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc20' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc20]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -194,12 +196,12 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc721"]')
.scrollAndClick('*[data-id="create-ozerc721"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc721' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc721' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc721]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -255,12 +257,12 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc1155"]')
.scrollAndClick('*[data-id="create-ozerc1155"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc1155' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_erc1155' })
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -316,15 +318,10 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc1155-{"upgradeable":"uups","mintable":true,"burnable":true,"pausable":true}"]')
.scrollAndClick('*[data-id="create-ozerc1155-{"upgradeable":"uups","mintable":true,"burnable":true,"pausable":true}')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.waitForElementPresent('*[data-id="ozCustomization"]')
.click('*[data-id="featureTypeMintable"]')
.click('*[data-id="featureTypeBurnable"]')
.click('*[data-id="featureTypePausable"]')
.click('*[data-id="upgradeTypeUups"]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -386,10 +383,10 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-hashchecker"]')
.scrollAndClick('*[data-id="create-hashchecker"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=hashchecker]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)
@ -424,6 +421,8 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]') .click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name') .setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name')
@ -438,6 +437,8 @@ module.exports = {
}) })
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]') .click('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1') .setValue('*[data-id="fileSystemModalDialogContainer-react"] input[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1')
@ -494,10 +495,10 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc1155"]')
.scrollAndClick('*[data-id="create-ozerc1155"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'sometestworkspace' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'sometestworkspace' })
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
@ -521,11 +522,11 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-ozerc1155"]')
.scrollAndClick('*[data-id="create-ozerc1155"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=ozerc1155]')
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_db_test' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_db_test' })
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
@ -551,10 +552,10 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-uniswapV4HookBookMultiSigSwapHook"]')
.scrollAndClick('*[data-id="create-uniswapV4HookBookMultiSigSwapHook"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=uniswapV4HookBookMultiSigSwapHook]')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'multisig cookbook' }) .execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'multisig cookbook' })
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')

@ -13,6 +13,8 @@ module.exports = {
.clickLaunchIcon('filePanel') .clickLaunchIcon('filePanel')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-remixDefault"]')
.scrollAndClick('*[data-id="create-remixDefault"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.waitForElementVisible({ .waitForElementVisible({
@ -47,6 +49,8 @@ module.exports = {
.waitForElementNotVisible('[data-id="workspaceGitPanel"]') .waitForElementNotVisible('[data-id="workspaceGitPanel"]')
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-blank"]')
.scrollAndClick('*[data-id="create-blank"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
@ -391,10 +395,10 @@ module.exports = {
browser browser
.click('*[data-id="workspacesMenuDropdown"]') .click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]') .click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-uniswapV4Template"]')
.scrollAndClick('*[data-id="create-uniswapV4Template"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button') .waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > button')
.click('select[id="wstemplate"]')
.click('select[id="wstemplate"] option[value=uniswapV4Template]')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') .waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() }) .execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.pause(100) .pause(100)

@ -61,6 +61,8 @@ import { Matomo } from './app/plugins/matomo'
import {SolCoder} from './app/plugins/solcoderAI' import {SolCoder} from './app/plugins/solcoderAI'
import {TemplatesSelection} from './app/plugins/templates-selection'
const isElectron = require('is-electron') const isElectron = require('is-electron')
const remixLib = require('@remix-project/remix-lib') const remixLib = require('@remix-project/remix-lib')
@ -315,6 +317,8 @@ class AppComponent {
// ----------------- run script after each compilation results ----------- // ----------------- run script after each compilation results -----------
const pluginStateLogger = new PluginStateLogger() const pluginStateLogger = new PluginStateLogger()
const templateSelection = new TemplatesSelection()
this.engine.register([ this.engine.register([
permissionHandler, permissionHandler,
this.layout, this.layout,
@ -366,7 +370,8 @@ class AppComponent {
solcoder, solcoder,
git, git,
pluginStateLogger, pluginStateLogger,
matomo matomo,
templateSelection
]) ])
//---- fs plugin //---- fs plugin

@ -195,7 +195,7 @@ module.exports = class Filepanel extends ViewPlugin {
if (err) reject(err) if (err) reject(err)
else resolve(data || true) else resolve(data || true)
}) })
}) }, false)
} }
renameWorkspace(oldName, workspaceName) { renameWorkspace(oldName, workspaceName) {

@ -0,0 +1,473 @@
import React from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import { AppModal } from '@remix-ui/app'
import { ViewPlugin } from '@remixproject/engine-web'
import { PluginViewWrapper } from '@remix-ui/helper'
import { RemixUIGridView } from '@remix-ui/remix-ui-grid-view'
import { RemixUIGridSection } from '@remix-ui/remix-ui-grid-section'
import { RemixUIGridCell } from '@remix-ui/remix-ui-grid-cell'
import type { TemplateGroup } from '@remix-ui/workspace'
const isElectron = require('is-electron')
//@ts-ignore
const _paq = (window._paq = window._paq || [])
const profile = {
name: 'templateSelection',
displayName: 'Template Selection',
description: 'templateSelection',
location: 'mainPanel',
methods: [],
events: []
}
export class TemplatesSelection extends ViewPlugin {
templates: Array<TemplateGroup>
dispatch: React.Dispatch<any> = () => { }
constructor() {
super(profile)
}
async onActivation() {
this.handleThemeChange()
await this.call('tabs', 'focus', 'remixGuide')
this.renderComponent()
_paq.push(['trackEvent', 'plugin', 'activated', 'remixGuide'])
}
onDeactivation(): void {
}
private handleThemeChange() {
this.on('theme', 'themeChanged', (theme: any) => {
this.renderComponent()
})
}
setDispatch(dispatch: React.Dispatch<any>): void {
this.dispatch = dispatch
this.renderComponent()
}
render() {
return (
<div className="bg-dark" id="remixGuide">
<PluginViewWrapper plugin={this} />
</div>
)
}
renderComponent() {
this.dispatch({
...this,
})
}
updateComponent() {
/*
const opts = {
// @ts-ignore: Object is possibly 'null'.
mintable: mintableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
burnable: burnableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
pausable: pausableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
upgradeable: transparentRadioRef.current.checked ? transparentRadioRef.current.value : uupsRadioRef.current.checked ? uupsRadioRef.current.value : false
}
*/
this.templates = [
{
name: "Generic",
items: [
{ value: "remixDefault", displayName: window._intl.formatMessage({ id: 'filePanel.basic' }) },
{ value: "blank", displayName: window._intl.formatMessage({ id: 'filePanel.blank' }) }
]
},
{
name: "OpenZeppelin",
items: [
{
value: "ozerc20",
displayName: "ERC20"
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)"
},
{
value: "ozerc1155",
displayName: "ERC1155"
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
mintable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
mintable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
mintable: true
}
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
mintable: true,
burnable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
mintable: true,
burnable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
mintable: true,
burnable: true
}
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
mintable: true,
pausable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
mintable: true,
pausable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
mintable: true,
pausable: true
}
}
]
},
{
name: "OpenZeppelin Proxy",
items: [
{
value: "ozerc20",
displayName: "ERC20",
opts: {
upgradeable: 'uups'
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
upgradeable: 'uups'
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
upgradeable: 'uups'
}
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
upgradeable: 'uups',
mintable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
upgradeable: 'uups',
mintable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
upgradeable: 'uups',
mintable: true
}
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
upgradeable: 'uups',
mintable: true,
burnable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
upgradeable: 'uups',
mintable: true,
burnable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
upgradeable: 'uups',
mintable: true,
burnable: true
}
},
{
value: "ozerc20",
displayName: "ERC20",
opts: {
upgradeable: 'uups',
mintable: true,
pausable: true
}
},
{
value: "ozerc721",
displayName: "ERC721 (NFT)",
opts: {
upgradeable: 'uups',
mintable: true,
pausable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
upgradeable: 'uups',
mintable: true,
pausable: true
}
},
{
value: "ozerc1155",
displayName: "ERC1155",
opts: {
upgradeable: 'uups',
mintable: true,
burnable: true,
pausable: true
}
}
]
},
{
name: "OxProject",
items: [
{ value: "zeroxErc20", displayName: "ERC20" }
]
},
{
name: "Gnosis Safe",
items: [
{ value: "gnosisSafeMultisig", displayName: window._intl.formatMessage({ id: 'filePanel.multiSigWallet' }) }
]
},
{
name: "Circom ZKP",
items: [
{ value: "semaphore", displayName: window._intl.formatMessage({ id: 'filePanel.semaphore' }) },
{ value: "hashchecker", displayName: window._intl.formatMessage({ id: 'filePanel.hashchecker' }) },
{ value: "rln", displayName: window._intl.formatMessage({ id: 'filePanel.rln' }) }
]
},
{
name: "Generic ZKP",
items: [
{ value: "sindriScripts", displayName: window._intl.formatMessage({ id: 'filePanel.addscriptsindri' }) },
]
},
{
name: "Uniswap V4",
items: [
{ value: "uniswapV4Template", displayName: window._intl.formatMessage({ id: 'filePanel.uniswapV4Template' }) },
{ value: "breakthroughLabsUniswapv4Hooks", displayName: window._intl.formatMessage({ id: 'filePanel.breakthroughLabsUniswapv4Hooks' }) },
{ value: "uniswapV4HookBookMultiSigSwapHook", displayName: window._intl.formatMessage({ id: 'filePanel.uniswapV4HookBookMultiSigSwapHook' }) }
]
},
{
name: "Solidity CREATE2",
items: [
{ value: "contractCreate2Factory", displayName: window._intl.formatMessage({ id: 'filePanel.addcreate2solidityfactory' }) },
{ value: "contractDeployerScripts", displayName: window._intl.formatMessage({ id: 'filePanel.addscriptdeployer' }) }
]
},
{
name: "Contract Verification",
items: [
{ value: "etherscanScripts", displayName: window._intl.formatMessage({ id: 'filePanel.addscriptetherscan' }) },
]
}
]
const createWorkspace = async (item) => {
const defaultName = await this.call('filePanel', 'getAvailableWorkspaceName', item.displayName)
const username = await this.call('settings', 'get', 'settings/github-user-name')
const email = await this.call('settings', 'get', 'settings/github-email')
const gitNotSet = !username || !email
let workspaceName = defaultName
let initGit = true
const modal: AppModal = {
id: 'TemplatesSelection',
title: window._intl.formatMessage({ id: !isElectron() ? 'filePanel.workspace.create': 'filePanel.workspace.create.desktop' }),
message: await createModalMessage(defaultName, gitNotSet, (value) => workspaceName = value, (value) => initGit = !!value),
okLabel: window._intl.formatMessage({ id: !isElectron() ? 'filePanel.ok':'filePanel.selectFolder' }),
}
const modalResult = await this.call('notification', 'modal', modal)
if (!modalResult) return
this.emit('createWorkspaceReducerEvent', workspaceName, item.value, item.opts, false, (e, data) => {
if (e) {
const modal: AppModal = {
id: 'TemplatesSelection',
title: window._intl.formatMessage({ id: !isElectron() ? 'filePanel.workspace.create': 'filePanel.workspace.create.desktop' }),
message: e.message,
okLabel: window._intl.formatMessage({ id: 'filePanel.ok' }),
cancelLabel: window._intl.formatMessage({ id: 'filePanel.cancel' })
}
this.call('notification', 'modal', modal)
console.error(e)
}
}, initGit)
}
const addToExistingWorkspace = async (item) => {
this.emit('addTemplateToWorkspaceReducerEvent', item.value, item.opts, false, (e, data) => {
if (e) {
const modal: AppModal = {
id: 'TemplatesSelection',
title: window._intl.formatMessage({ id: !isElectron() ? 'filePanel.workspace.create': 'filePanel.workspace.create.desktop' }),
message: e.message,
okLabel: window._intl.formatMessage({ id: 'filePanel.ok' }),
cancelLabel: window._intl.formatMessage({ id: 'filePanel.cancel' })
}
this.call('notification', 'modal', modal)
console.error(e)
}
})
}
return (
<RemixUIGridView
plugin={this}
styleList={""}
logo='/assets/img/YouTubeLogo.webp'
enableFilter={true}
showUntagged={true}
showPin={false}
tagList={[]}
title='Remix Guide'
description="Template Selection"
>
{
this.templates.map(template => {
return <RemixUIGridSection
plugin={this}
title={template.name}
hScrollable= {true}
>
{template.items.map(item => {
return <RemixUIGridCell
plugin={this}
title={item.displayName}
>
<div>
{item.displayName}
{JSON.stringify(item.opts)}
<div><button data-id={`create-${item.value}${item.opts ? JSON.stringify(item.opts) : ''}`} onClick={async () => createWorkspace(item)} className="btn btn-secondary" >Create a new workspace</button><button data-id={`add-${item.value}`} onClick={async () => addToExistingWorkspace(item)} className="btn btn-primary" >Add to existing workspace</button></div>
</div>
</RemixUIGridCell>
})}
</RemixUIGridSection>
})}
</RemixUIGridView>
)
}
}
const createModalMessage = async (
defaultName: string,
gitConfigNotSet: boolean,
onChangeTemplateName: (name: string) => void,
onChangeInitGit: (name: string) => void) => {
return (
<>
<label id="wsName" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="filePanel.workspaceName" />
</label>
<input
type="text"
data-id="modalDialogCustomPromptTextCreate"
defaultValue={defaultName}
className="form-control"
onChange={(e) => onChangeTemplateName(e.target.value)}
/>
<div className="d-flex py-2 align-items-center custom-control custom-checkbox">
<input
id="initGitRepository"
data-id="initGitRepository"
className="form-check-input custom-control-input"
type="checkbox"
disabled={gitConfigNotSet}
onChange={(e) => onChangeInitGit(e.target.value)}
/>
<label
htmlFor="initGitRepository"
data-id="initGitRepositoryLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title={window._intl.formatMessage({ id: 'filePanel.initGitRepoTitle' })}
>
<FormattedMessage id="filePanel.initGitRepositoryLabel" />
</label>
</div>
{gitConfigNotSet ? (
<div className="text-warning">
<FormattedMessage id="filePanel.initGitRepositoryWarning" />
</div>
) : (
<></>
)}
</>
)
}

@ -5,7 +5,7 @@ import React from 'react'
import { action, FileTree, WorkspaceTemplate } from '../types' import { action, FileTree, WorkspaceTemplate } from '../types'
import { ROOT_PATH } from '../utils/constants' import { ROOT_PATH } from '../utils/constants'
import { displayNotification, displayPopUp, fileAddedSuccess, fileRemovedSuccess, fileRenamedSuccess, folderAddedSuccess, loadLocalhostError, loadLocalhostRequest, loadLocalhostSuccess, removeContextMenuItem, removeFocus, rootFolderChangedSuccess, setContextMenuItem, setMode, setReadOnlyMode, setFileDecorationSuccess } from './payload' import { displayNotification, displayPopUp, fileAddedSuccess, fileRemovedSuccess, fileRenamedSuccess, folderAddedSuccess, loadLocalhostError, loadLocalhostRequest, loadLocalhostSuccess, removeContextMenuItem, removeFocus, rootFolderChangedSuccess, setContextMenuItem, setMode, setReadOnlyMode, setFileDecorationSuccess } from './payload'
import { addInputField, createWorkspace, deleteWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from './workspace' import { addInputField, createWorkspace, populateWorkspace, deleteWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from './workspace'
const LOCALHOST = ' - connect to localhost - ' const LOCALHOST = ' - connect to localhost - '
let plugin, dispatch: React.Dispatch<any> let plugin, dispatch: React.Dispatch<any>
@ -13,8 +13,16 @@ let plugin, dispatch: React.Dispatch<any>
export const listenOnPluginEvents = (filePanelPlugin) => { export const listenOnPluginEvents = (filePanelPlugin) => {
plugin = filePanelPlugin plugin = filePanelPlugin
plugin.on('filePanel', 'createWorkspaceReducerEvent', (name: string, workspaceTemplateName: WorkspaceTemplate, isEmpty = false, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => { plugin.on('templateSelection', 'createWorkspaceReducerEvent', (name: string, workspaceTemplateName: WorkspaceTemplate, opts: any, isEmpty = false, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void, isGitRepo: boolean) => {
createWorkspace(name, workspaceTemplateName, null, isEmpty, cb) createWorkspace(name, workspaceTemplateName, opts, isEmpty, cb, isGitRepo)
})
plugin.on('templateSelection', 'addTemplateToWorkspaceReducerEvent', (workspaceTemplateName: WorkspaceTemplate, opts: any, isEmpty = false, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => {
populateWorkspace(workspaceTemplateName, opts, isEmpty, cb)
})
plugin.on('filePanel', 'createWorkspaceReducerEvent', (name: string, workspaceTemplateName: WorkspaceTemplate, isEmpty = false, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void, isGitRepo: boolean) => {
createWorkspace(name, workspaceTemplateName, null, isEmpty, cb, isGitRepo)
}) })
plugin.on('filePanel', 'renameWorkspaceReducerEvent', (oldName: string, workspaceName: string, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => { plugin.on('filePanel', 'renameWorkspaceReducerEvent', (oldName: string, workspaceName: string, cb: (err: Error, result?: string | number | boolean | Record<string, any>) => void) => {

@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import { bytesToHex } from '@ethereumjs/util' import { bytesToHex } from '@ethereumjs/util'
import { hash } from '@remix-project/remix-lib' import { hash } from '@remix-project/remix-lib'
import { createNonClashingNameAsync } from '@remix-ui/helper'
import { TEMPLATE_METADATA, TEMPLATE_NAMES } from '../utils/constants' import { TEMPLATE_METADATA, TEMPLATE_NAMES } from '../utils/constants'
import { TemplateType } from '../types' import { TemplateType } from '../types'
import IpfsHttpClient from 'ipfs-http-client' import IpfsHttpClient from 'ipfs-http-client'
@ -154,6 +155,7 @@ export const createWorkspace = async (
await plugin.workspaceCreated(workspaceName) await plugin.workspaceCreated(workspaceName)
if (isGitRepo && createCommit) { if (isGitRepo && createCommit) {
console.log('CREATE COMMIT')
const name = await plugin.call('settings', 'get', 'settings/github-user-name') const name = await plugin.call('settings', 'get', 'settings/github-user-name')
const email = await plugin.call('settings', 'get', 'settings/github-email') const email = await plugin.call('settings', 'get', 'settings/github-email')
const currentBranch: branch = await dgitPlugin.call('dgitApi', 'currentbranch') const currentBranch: branch = await dgitPlugin.call('dgitApi', 'currentbranch')
@ -191,25 +193,7 @@ export const createWorkspace = async (
} }
} }
} }
if (metadata && metadata.type === 'plugin') { await populateWorkspace(workspaceTemplateName, opts, isEmpty, (err: Error) => { cb && cb(err, workspaceName) }, isGitRepo, createCommit)
plugin.call('notification', 'toast', 'Please wait while the workspace is being populated with the template.')
dispatch(cloneRepositoryRequest())
setTimeout(() => {
plugin.call(metadata.name, metadata.endpoint, ...metadata.params).then(() => {
dispatch(cloneRepositorySuccess())
}).catch((e) => {
dispatch(cloneRepositorySuccess())
plugin.call('notification', 'toast', 'error adding template ' + e.message || e)
})
}, 5000)
} else if (!isEmpty && !(isGitRepo && createCommit)) await loadWorkspacePreset(workspaceTemplateName, opts)
cb && cb(null, workspaceName)
if (workspaceTemplateName === 'semaphore' || workspaceTemplateName === 'hashchecker' || workspaceTemplateName === 'rln') {
const isCircomActive = await plugin.call('manager', 'isActive', 'circuit-compiler')
if (!isCircomActive) await plugin.call('manager', 'activatePlugin', 'circuit-compiler')
_paq.push(['trackEvent', 'circuit-compiler', 'template', 'create', workspaceTemplateName])
}
// this call needs to be here after the callback because it calls dGitProvider which also calls this function and that would cause an infinite loop // this call needs to be here after the callback because it calls dGitProvider which also calls this function and that would cause an infinite loop
await plugin.setWorkspaces(await getWorkspaces()) await plugin.setWorkspaces(await getWorkspaces())
}).catch((error) => { }).catch((error) => {
@ -219,6 +203,40 @@ export const createWorkspace = async (
return promise return promise
} }
export const populateWorkspace = async (
workspaceTemplateName: WorkspaceTemplate,
opts = null,
isEmpty = false,
cb?: (err: Error, result?: string | number | boolean | Record<string, any>) => void,
isGitRepo: boolean = false,
createCommit: boolean = false
) => {
const metadata = TEMPLATE_METADATA[workspaceTemplateName]
if (metadata && metadata.type === 'plugin') {
plugin.call('notification', 'toast', 'Please wait while the workspace is being populated with the template.')
dispatch(cloneRepositoryRequest())
setTimeout(() => {
plugin.call(metadata.name, metadata.endpoint, ...metadata.params).then(() => {
dispatch(cloneRepositorySuccess())
}).catch((e) => {
dispatch(cloneRepositorySuccess())
plugin.call('notification', 'toast', 'error adding template ' + e.message || e)
})
}, 5000)
} else if (!isEmpty && !(isGitRepo && createCommit)) await loadWorkspacePreset(workspaceTemplateName, opts)
cb && cb(null)
if (isGitRepo) {
await checkGit()
const isActive = await plugin.call('manager', 'isActive', 'dgit')
if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit')
}
if (workspaceTemplateName === 'semaphore' || workspaceTemplateName === 'hashchecker' || workspaceTemplateName === 'rln') {
const isCircomActive = await plugin.call('manager', 'isActive', 'circuit-compiler')
if (!isCircomActive) await plugin.call('manager', 'activatePlugin', 'circuit-compiler')
_paq.push(['trackEvent', 'circuit-compiler', 'template', 'create', workspaceTemplateName])
}
}
export const createWorkspaceTemplate = async (workspaceName: string, template: WorkspaceTemplate = 'remixDefault', metadata?: TemplateType) => { export const createWorkspaceTemplate = async (workspaceName: string, template: WorkspaceTemplate = 'remixDefault', metadata?: TemplateType) => {
if (!workspaceName) throw new Error('workspace name cannot be empty') if (!workspaceName) throw new Error('workspace name cannot be empty')
if (checkSpecialChars(workspaceName) || checkSlash(workspaceName)) throw new Error('special characters are not allowed') if (checkSpecialChars(workspaceName) || checkSlash(workspaceName)) throw new Error('special characters are not allowed')
@ -388,12 +406,14 @@ export const loadWorkspacePreset = async (template: WorkspaceTemplate = 'remixDe
try { try {
const templateList = Object.keys(templateWithContent) const templateList = Object.keys(templateWithContent)
if (!templateList.includes(template)) break if (!templateList.includes(template)) break
_paq.push(['trackEvent', 'workspace', 'template', template]) _paq.push(['trackEvent', 'workspace', 'template', template])
// @ts-ignore // @ts-ignore
const files = await templateWithContent[template](opts) const files = await templateWithContent[template](opts, plugin)
for (const file in files) { for (const file in files) {
try { try {
await workspaceProvider.set(file, files[file]) const uniqueFileName = await createNonClashingNameAsync(file, plugin.fileManager)
await workspaceProvider.set(uniqueFileName, files[file])
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }

@ -163,47 +163,6 @@ export function HamburgerMenu(props: HamburgerMenuProps) {
}} }}
platforms={[appPlatformTypes.web, appPlatformTypes.desktop]} platforms={[appPlatformTypes.web, appPlatformTypes.desktop]}
></HamburgerMenuItem> ></HamburgerMenuItem>
<Dropdown.Divider className="border mb-0 mt-0 remixui_menuhr" style={{ pointerEvents: 'none' }} />
<HamburgerMenuItem
kind="addscriptetherscan"
fa="fa-kit fa-ts-logo"
hideOption={hideWorkspaceOptions || hideFileOperations}
actionOnClick={() => {
props.addHelperScripts('etherscanScripts')
props.hideIconsMenu(!showIconsMenu)
}}
platforms={[appPlatformTypes.web, appPlatformTypes.desktop]}
></HamburgerMenuItem>
<HamburgerMenuItem
kind="addscriptdeployer"
fa="fa-kit fa-ts-logo"
hideOption={hideWorkspaceOptions || hideFileOperations}
actionOnClick={() => {
props.addHelperScripts('contractDeployerScripts')
props.hideIconsMenu(!showIconsMenu)
}}
platforms={[appPlatformTypes.web, appPlatformTypes.desktop]}
></HamburgerMenuItem>
<HamburgerMenuItem
kind="addscriptsindri"
fa="fa-kit fa-ts-logo"
hideOption={hideWorkspaceOptions || hideFileOperations}
actionOnClick={() => {
props.addHelperScripts('sindriScripts')
props.hideIconsMenu(!showIconsMenu)
}}
platforms={[appPlatformTypes.web, appPlatformTypes.desktop]}
></HamburgerMenuItem>
<HamburgerMenuItem
kind="addcreate2solidityfactory"
fa="fa-kit fa-ts-logo"
hideOption={hideWorkspaceOptions || hideFileOperations}
actionOnClick={() => {
props.addHelperScripts('contractCreate2Factory')
props.hideIconsMenu(!showIconsMenu)
}}
platforms={[appPlatformTypes.web, appPlatformTypes.desktop]}
></HamburgerMenuItem>
</> </>
) )
} }

@ -42,11 +42,8 @@ export function Workspace() {
const uupsRadioRef = useRef() const uupsRadioRef = useRef()
const global = useContext(FileSystemContext) const global = useContext(FileSystemContext)
const workspaceRenameInput = useRef() const workspaceRenameInput = useRef()
const workspaceCreateInput = useRef()
const workspaceCreateTemplateInput = useRef()
const intl = useIntl() const intl = useIntl()
const cloneUrlRef = useRef<HTMLInputElement>() const cloneUrlRef = useRef<HTMLInputElement>()
const initGitRepoRef = useRef<HTMLInputElement>()
const filteredBranches = selectedWorkspace ? (selectedWorkspace.branches || []).filter((branch) => branch.name.includes(branchFilter) && branch.name !== 'HEAD').slice(0, 20) : [] const filteredBranches = selectedWorkspace ? (selectedWorkspace.branches || []).filter((branch) => branch.name.includes(branchFilter) && branch.name !== 'HEAD').slice(0, 20) : []
const currentBranch = selectedWorkspace ? selectedWorkspace.currentBranch : null const currentBranch = selectedWorkspace ? selectedWorkspace.currentBranch : null
@ -321,14 +318,9 @@ export function Workspace() {
intl.formatMessage({ id: 'filePanel.cancel' }) intl.formatMessage({ id: 'filePanel.cancel' })
) )
} }
const createWorkspace = () => { const createWorkspace = async () => {
global.modal( await global.plugin.call('manager', 'activatePlugin', 'templateSelection')
intl.formatMessage({ id: (platform !== appPlatformTypes.desktop)? 'filePanel.workspace.create': 'filePanel.workspace.create.desktop' }), await global.plugin.call('tabs', 'focus', 'templateSelection')
createModalMessage(),
intl.formatMessage({ id: (platform !== appPlatformTypes.desktop)? 'filePanel.ok':'filePanel.selectFolder' }),
onFinishCreateWorkspace,
intl.formatMessage({ id: 'filePanel.cancel' })
)
} }
const deleteCurrentWorkspace = () => { const deleteCurrentWorkspace = () => {
@ -448,38 +440,6 @@ export function Workspace() {
} }
} }
const onFinishCreateWorkspace = async () => {
if (workspaceCreateInput.current === undefined) return
// @ts-ignore: Object is possibly 'null'.
const workspaceName = workspaceCreateInput.current.value
// @ts-ignore: Object is possibly 'null'.
const workspaceTemplateName = workspaceCreateTemplateInput.current.value || 'remixDefault'
const initGitRepo = initGitRepoRef.current.checked
const opts = {
// @ts-ignore: Object is possibly 'null'.
mintable: mintableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
burnable: burnableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
pausable: pausableCheckboxRef.current.checked,
// @ts-ignore: Object is possibly 'null'.
upgradeable: transparentRadioRef.current.checked ? transparentRadioRef.current.value : uupsRadioRef.current.checked ? uupsRadioRef.current.value : false
}
try {
await global.dispatchCreateWorkspace(workspaceName, workspaceTemplateName, opts, initGitRepo)
} catch (e) {
global.modal(
intl.formatMessage({ id: (platform !== appPlatformTypes.desktop)? 'filePanel.workspace.create': 'filePanel.workspace.create.desktop' }),
e.message,
intl.formatMessage({ id: 'filePanel.ok' }),
() => {},
intl.formatMessage({ id: 'filePanel.cancel' })
)
console.error(e)
}
}
const onFinishDeleteWorkspace = async () => { const onFinishDeleteWorkspace = async () => {
try { try {
await global.dispatchDeleteWorkspace(global.fs.browser.currentWorkspace) await global.dispatchDeleteWorkspace(global.fs.browser.currentWorkspace)
@ -868,163 +828,6 @@ export function Workspace() {
} }
} }
const createModalMessage = () => {
return (
<>
<label id="selectWsTemplate" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="filePanel.workspace.chooseTemplate" />
</label>
<select
name="wstemplate"
className="mb-3 form-control custom-select"
id="wstemplate"
defaultValue="remixDefault"
ref={workspaceCreateTemplateInput}
onChange={updateWsName}
>
<optgroup style={{ fontSize: 'medium' }} label="General">
<option style={{ fontSize: 'small' }} value="remixDefault">
{intl.formatMessage({ id: 'filePanel.basic' })}
</option>
<option style={{ fontSize: 'small' }} value="blank">
{intl.formatMessage({ id: 'filePanel.blank' })}
</option>
</optgroup>
<optgroup style={{ fontSize: 'medium' }} label="OpenZeppelin">
<option style={{ fontSize: 'small' }} value="ozerc20">
ERC20
</option>
<option style={{ fontSize: 'small' }} value="ozerc721">
ERC721
</option>
<option style={{ fontSize: 'small' }} value="ozerc1155">
ERC1155
</option>
</optgroup>
<optgroup style={{ fontSize: 'medium' }} label="0xProject">
<option style={{ fontSize: 'small' }} value="zeroxErc20">
ERC20
</option>
</optgroup>
<optgroup style={{ fontSize: 'medium' }} label="GnosisSafe">
<option style={{ fontSize: 'small' }} value="gnosisSafeMultisig">
{intl.formatMessage({ id: 'filePanel.multiSigWallet' })}
</option>
</optgroup>
<optgroup style={{ fontSize: 'medium' }} label="Circom ZKP">
<option style={{ fontSize: 'small' }} value="semaphore">
{intl.formatMessage({ id: 'filePanel.semaphore' })}
</option>
<option style={{ fontSize: 'small' }} value="hashchecker">
{intl.formatMessage({ id: 'filePanel.hashchecker' })}
</option>
<option style={{ fontSize: 'small' }} value="rln">
{intl.formatMessage({ id: 'filePanel.rln' })}
</option>
</optgroup>
<optgroup style={{ fontSize: 'medium' }} label="Uniswap V4">
<option style={{ fontSize: 'small' }} value="uniswapV4Template">
{intl.formatMessage({ id: 'filePanel.uniswapV4Template' })}
</option>
<option style={{ fontSize: 'small' }} value="breakthroughLabsUniswapv4Hooks">
{intl.formatMessage({ id: 'filePanel.breakthroughLabsUniswapv4Hooks' })}
</option>
<option style={{ fontSize: 'small' }} value="uniswapV4HookBookMultiSigSwapHook">
{intl.formatMessage({ id: 'filePanel.uniswapV4HookBookMultiSigSwapHook' })}
</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" />
</label>
<label id="wsName" className="form-check-label d-block mb-1">
<FormattedMessage id="filePanel.features" />
</label>
<div className="mb-2">
<div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="mintable" id="mintable" ref={mintableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="mintable" data-id="featureTypeMintable">
<FormattedMessage id="filePanel.mintable" />
</label>
</div>
<div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="burnable" id="burnable" ref={burnableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="burnable" data-id="featureTypeBurnable">
<FormattedMessage id="filePanel.burnable" />
</label>
</div>
<div className="d-flex ml-2 custom-control custom-checkbox">
<input className="custom-control-input" type="checkbox" name="feature" value="pausable" id="pausable" ref={pausableCheckboxRef} />
<label className="form-check-label custom-control-label" htmlFor="pausable" data-id="featureTypePausable">
<FormattedMessage id="filePanel.pausable" />
</label>
</div>
</div>
<label id="wsName" className="form-check-label d-block mb-1">
<FormattedMessage id="filePanel.upgradeability" />
</label>
<div>
<div className="d-flex ml-2 custom-control custom-radio">
<input className="custom-control-input" type="radio" name="upgradeability" value="transparent" id="transparent" ref={transparentRadioRef} />
<label className="form-check-label custom-control-label" htmlFor="transparent" data-id="upgradeTypeTransparent">
<FormattedMessage id="filePanel.transparent" />
</label>
</div>
<div className="d-flex ml-2 custom-control custom-radio">
<input className="custom-control-input" type="radio" name="upgradeability" value="uups" id="uups" ref={uupsRadioRef} />
<label className="form-check-label custom-control-label" htmlFor="uups" data-id="upgradeTypeUups">
UUPS
</label>
</div>
</div>
</div>
<label id="wsName" className="form-check-label" style={{ fontWeight: 'bolder' }}>
<FormattedMessage id="filePanel.workspaceName" />
</label>
<input
type="text"
data-id="modalDialogCustomPromptTextCreate"
defaultValue={global.plugin.getAvailableWorkspaceName(TEMPLATE_NAMES['remixDefault'])}
ref={workspaceCreateInput}
className="form-control"
/>
<div className="d-flex py-2 align-items-center custom-control custom-checkbox">
<input
ref={initGitRepoRef}
id="initGitRepository"
data-id="initGitRepository"
className="form-check-input custom-control-input"
type="checkbox"
disabled={!global.fs.gitConfig.username || !global.fs.gitConfig.email}
onChange={() => { }}
/>
<label
htmlFor="initGitRepository"
data-id="initGitRepositoryLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title={intl.formatMessage({ id: 'filePanel.initGitRepoTitle' })}
>
<FormattedMessage id="filePanel.initGitRepositoryLabel" />
</label>
</div>
{!global.fs.gitConfig.username || !global.fs.gitConfig.email ? (
<div className="text-warning">
<FormattedMessage id="filePanel.initGitRepositoryWarning" />
</div>
) : (
<></>
)}
</>
)
}
const renameModalMessage = (workspaceName?: string) => { const renameModalMessage = (workspaceName?: string) => {
return ( return (
<div className='d-flex flex-column'> <div className='d-flex flex-column'>

@ -110,3 +110,21 @@ export const TEMPLATE_METADATA: Record<string, TemplateType> = {
} }
} }
export type TemplateOption = {
mintable?: boolean
burnable?: boolean
pausable?: boolean
upgradeable?: 'uups' | 'transparent'
}
export type Template = {
value: string
displayName: string
opts?: TemplateOption
}
export type TemplateGroup = {
name: string
items: Array<Template>
}

@ -1,4 +1,4 @@
export const contractDeployerScripts = async (plugin) => { export const contractDeployerScripts = async (opts, plugin) => {
await plugin.call('fileManager', 'writeFile', await plugin.call('fileManager', 'writeFile',
'scripts/contract-deployer/create2-factory-deploy.ts' , 'scripts/contract-deployer/create2-factory-deploy.ts' ,
// @ts-ignore // @ts-ignore

@ -1,4 +1,4 @@
export const contractCreate2Factory = async (plugin) => { export const contractCreate2Factory = async (opts, plugin) => {
await plugin.call('fileManager', 'writeFile', await plugin.call('fileManager', 'writeFile',
'contracts/libs/create2-factory.sol' , 'contracts/libs/create2-factory.sol' ,
// @ts-ignore // @ts-ignore

@ -1,4 +1,4 @@
export const etherscanScripts = async (plugin) => { export const etherscanScripts = async (opts, plugin) => {
await plugin.call('fileManager', 'writeFile', await plugin.call('fileManager', 'writeFile',
'scripts/etherscan/verifyScript.ts' , 'scripts/etherscan/verifyScript.ts' ,
// @ts-ignore // @ts-ignore

@ -18,7 +18,7 @@ const getWorkspaceFilesByPath = async (plugin: any, pathRegex: RegExp | null = n
return filesByPath return filesByPath
} }
export const sindriScripts = async (plugin: any) => { export const sindriScripts = async (opts, plugin: any) => {
// Load in all of the Sindri or circuit-related files in the workspace. // Load in all of the Sindri or circuit-related files in the workspace.
const existingFilesByPath = await getWorkspaceFilesByPath(plugin, /sindri|\.circom$/i) const existingFilesByPath = await getWorkspaceFilesByPath(plugin, /sindri|\.circom$/i)
const writeIfNotExists = async (path: string, content: string) => { const writeIfNotExists = async (path: string, content: string) => {

Loading…
Cancel
Save