diff --git a/README.md b/README.md index a080e66..dad5efa 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,12 @@ OpenZeppelin Logo

-# Deploy with Defender - Remix Plugin +# Defender Deploy Plugin -Remix plugin to deploy smart contracts using OpenZeppelin Defender. For documentation about usage please visit the [Defender Docs](https://docs.openzeppelin.com/defender/remix-plugin). +Plugin to deploy smart contracts using OpenZeppelin Defender. Currently supported in: + +- [Remix IDE](https://remix.ethereum.org/) - As a plugin listed in plugins directory, for more information please visit [our docs](https://docs.openzeppelin.com/defender/remix-plugin). +- [Contracts Wizard](https://wizard.openzeppelin.com/) - Integrated in code editor, for more information please visit [our docs](https://docs.openzeppelin.com/defender/remix-plugin). ## Getting Started @@ -16,7 +19,7 @@ pnpm install pnpm dev ``` -The interface is ugly, but don't worry! it's not meant to be used directly, it's used embedded in a Remix iframe instead, and adopts its styles. +NOTE: This project is meant to be embedded in other UIs, just running the project won't be enough to see and debug it. You must embed the UI on an external iframe. ## Testing in Remix @@ -31,4 +34,38 @@ Url: http://localhost:5173 # or live version https://defeder-remix-deploy.netlif Type of connection: Iframe Location in Remix: Side Panel ``` -5. You should see the plugin added to the sidebar (new icon with ? symbol). \ No newline at end of file +5. You should see the plugin added to the sidebar (new icon with ? symbol). + +## Testing in Contracts Wizard + +For testing in Contracts Wizard, you must also run the Contracts Wizard UI locally to point to your local plugin. + +1. Run Contracts Wizard locally. + - a. Go to [https://github.com/OpenZeppelin/contracts-wizard](Contracts Wizard Repo). + - b. Clone the latest `master` branch and follow steps to setup the project. + - c. Move to `pacakges/ui` and run it with `yarn dev`. +2. In another terminal, run this project using `pnpm dev`, make sure the app is served in `http://localhost:5173`. +3. Open Contracts Wizard local UI, generally in `http://localhost:8080`. +4. Click on "Deploy with Defender" button, you should be able to see embedded the local plugin. + +## Development + +Many parts of codebase are shared across plugins (server side code, state definition, ethereum interactions, etc.), but UI components have a separated implementation to make them more flexible and prevent side-effects. + +We have some bootstrap logic to expose one UI or another depending on the parent iframe domain. + +### Remix +The entrypoint for Remix plugin is `src/routes/remix.svelte`. Its components mainly use [bootstrap](https://getbootstrap.com/) for styling, Remix UI injects bootstrap dependency as a html tag when embedded. + +### Wizard +The entrypoint for Contracts Wizard plugin is `src/routes/wizard.svelte`. Its components mainly use [tailwind CSS](https://tailwindcss.com/) for styling, this is mainly for convenience, since Contracts Wizard was made using this CSS framework. + +## Release + +The repo has a CI/CD connected to our netlify account, when we merge `main` to some of the release branches, a new version of the plugin is released to live. Branches: + +- Remix IDE Plugin - `release-remix` +- Contracts Wizard Plugin - `release-wizard` + +> [!WARNING] +> We use `main` branch as the single source of truth and it's the only branch allowed to be merged to release branches. It should be tested carefully before triggering a new release. \ No newline at end of file diff --git a/package.json b/package.json index ed54db7..dbe9cb2 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,11 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", "svelte": "^5.0.0", "svelte-check": "^4.0.0", + "tailwindcss": "^3.4.16", "typescript": "^5.0.0", "vite": "^5.0.3" }, @@ -26,6 +29,7 @@ "@remixproject/plugin-utils": "^0.3.38", "@sveltejs/adapter-netlify": "^4.3.6", "bootstrap": "^5.3.3", - "ethers": "^6.13.4" + "ethers": "^6.13.4", + "solc": "^0.8.28" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fbd3b7e..dabf56c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: ethers: specifier: ^6.13.4 version: 6.13.4 + solc: + specifier: ^0.8.28 + version: 0.8.28 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.0.0 @@ -42,12 +45,21 @@ importers: '@sveltejs/vite-plugin-svelte': specifier: ^4.0.0 version: 4.0.0(svelte@5.1.6)(vite@5.4.10(@types/node@22.9.0)) + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.49) + postcss: + specifier: ^8.4.49 + version: 8.4.49 svelte: specifier: ^5.0.0 version: 5.1.6 svelte-check: specifier: ^4.0.0 version: 4.0.5(svelte@5.1.6)(typescript@5.6.3) + tailwindcss: + specifier: ^3.4.16 + version: 3.4.16 typescript: specifier: ^5.0.0 version: 5.6.3 @@ -63,6 +75,10 @@ packages: '@adraffy/ens-normalize@1.11.0': resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -330,6 +346,18 @@ packages: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@openzeppelin/defender-sdk-account-client@1.15.2': resolution: {integrity: sha512-lhYf1rBtac1MBbKP/ALgkjUhVulqo45RtaemTP9xI6BwUCCb4nq2SSKM82UN5sOE2I+VXSbPXf8w91bao5Mmmg==} @@ -380,6 +408,10 @@ packages: '@openzeppelin/defender-sdk@1.15.2': resolution: {integrity: sha512-Pt7MR+kzhsBfEQvW/cAOgLGb498x3Oq91G15GQ+g+cl978IpQgqx8rneZPv3aoQE5ipIk6EtWJlOl+tIAARKVg==} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} @@ -591,6 +623,16 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -601,6 +643,13 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -621,6 +670,10 @@ packages: bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} @@ -635,9 +688,18 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer@4.9.2: resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} @@ -645,6 +707,17 @@ packages: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + caniuse-lite@1.0.30001686: + resolution: {integrity: sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chokidar@4.0.1: resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} engines: {node: '>= 14.16.0'} @@ -660,6 +733,17 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} @@ -679,6 +763,11 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -703,6 +792,12 @@ packages: devalue@5.1.1: resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} @@ -710,6 +805,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + electron-to-chromium@1.5.68: + resolution: {integrity: sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==} + elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} @@ -732,6 +830,10 @@ packages: engines: {node: '>=12'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + esm-env@1.1.4: resolution: {integrity: sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg==} @@ -755,6 +857,13 @@ packages: fast-base64-decode@1.0.0: resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fdir@6.4.2: resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} peerDependencies: @@ -763,6 +872,10 @@ packages: picomatch: optional: true + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -783,6 +896,9 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} @@ -799,6 +915,18 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@11.0.0: resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} engines: {node: 20 || >=22} @@ -857,10 +985,22 @@ packages: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -869,6 +1009,14 @@ packages: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} @@ -890,10 +1038,17 @@ packages: peerDependencies: ws: '*' + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jackspeak@4.0.2: resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} engines: {node: 20 || >=22} + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + js-cookie@2.2.1: resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} @@ -913,12 +1068,22 @@ packages: lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.0.2: resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} engines: {node: 20 || >=22} @@ -926,6 +1091,18 @@ packages: magic-string@0.30.12: resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -944,6 +1121,10 @@ packages: resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} engines: {node: 20 || >=22} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -959,6 +1140,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -973,6 +1157,29 @@ packages: encoding: optional: true + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -983,6 +1190,13 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.0: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} @@ -990,12 +1204,61 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} process-nextick-args@2.0.1: @@ -1004,22 +1267,43 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + readdirp@4.0.2: resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} engines: {node: '>= 14.16.0'} + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rollup@4.24.3: resolution: {integrity: sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -1027,6 +1311,10 @@ packages: safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + set-cookie-parser@2.7.1: resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} @@ -1053,6 +1341,11 @@ packages: resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} engines: {node: '>=18'} + solc@0.8.28: + resolution: {integrity: sha512-AFCiJ+b4RosyyNhnfdVH4ZR1+TxiL91iluPjw0EJslIu4LXGM9NYqi2z5y8TqochC4tcH9QsHfwWhOIC9jPDKA==} + engines: {node: '>=10.0.0'} + hasBin: true + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1076,6 +1369,15 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + svelte-check@4.0.5: resolution: {integrity: sha512-icBTBZ3ibBaywbXUat3cK6hB5Du+Kq9Z8CRuyLmm64XIe2/r+lQcbuBx/IQgsbrC+kT2jQ0weVpZSSRIPwB6jQ==} engines: {node: '>= 18.0.0'} @@ -1088,9 +1390,29 @@ packages: resolution: {integrity: sha512-bYS/DpkqXk0j5UZgiNXrEjZYPRZ4Ncd87w4KUSbcZGyojA0+i/Ls9OGUjETHmdLe8RcQ0G8SX/T0PypPpAA/ew==} engines: {node: '>=18'} + tailwindcss@3.4.16: + resolution: {integrity: sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -1098,6 +1420,9 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} @@ -1125,6 +1450,12 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1305,6 +1636,11 @@ packages: utf-8-validate: optional: true + yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} + engines: {node: '>= 14'} + hasBin: true + zimmerframe@1.1.2: resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} @@ -1317,6 +1653,8 @@ snapshots: '@adraffy/ens-normalize@1.11.0': {} + '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -1609,6 +1947,18 @@ snapshots: '@noble/hashes@1.4.0': {} + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + '@openzeppelin/defender-sdk-account-client@1.15.2': dependencies: '@openzeppelin/defender-sdk-base-client': 1.15.2 @@ -1781,6 +2131,9 @@ snapshots: - web3-core - web3-utils + '@pkgjs/parseargs@0.11.0': + optional: true + '@polka/url@1.0.0-next.28': {} '@popperjs/core@2.11.8': {} @@ -1978,6 +2331,15 @@ snapshots: ansi-styles@6.2.1: {} + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + aria-query@5.3.2: {} async-retry@1.3.3: @@ -1986,6 +2348,16 @@ snapshots: asynckit@0.4.0: {} + autoprefixer@10.4.20(postcss@8.4.49): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001686 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -2006,6 +2378,8 @@ snapshots: bech32@1.1.4: {} + binary-extensions@2.3.0: {} + bn.js@4.12.0: {} bn.js@5.2.1: {} @@ -2018,8 +2392,19 @@ snapshots: dependencies: balanced-match: 1.0.2 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + brorand@1.1.0: {} + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001686 + electron-to-chromium: 1.5.68 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + buffer@4.9.2: dependencies: base64-js: 1.5.1 @@ -2034,6 +2419,22 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.2 + camelcase-css@2.0.1: {} + + caniuse-lite@1.0.30001686: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chokidar@4.0.1: dependencies: readdirp: 4.0.2 @@ -2048,6 +2449,12 @@ snapshots: dependencies: delayed-stream: 1.0.0 + command-exists@1.2.9: {} + + commander@4.1.1: {} + + commander@8.3.0: {} + cookie@0.6.0: {} core-util-is@1.0.3: {} @@ -2066,6 +2473,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cssesc@3.0.0: {} + debug@4.3.7: dependencies: ms: 2.1.3 @@ -2082,10 +2491,16 @@ snapshots: devalue@5.1.1: {} + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + dotenv@16.4.5: {} eastasianwidth@0.2.0: {} + electron-to-chromium@1.5.68: {} + elliptic@6.5.4: dependencies: bn.js: 4.12.0 @@ -2132,6 +2547,8 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + escalade@3.2.0: {} + esm-env@1.1.4: {} esrap@1.2.2: @@ -2165,8 +2582,24 @@ snapshots: fast-base64-decode@1.0.0: {} + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + fdir@6.4.2: {} + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + follow-redirects@1.15.9: {} for-each@0.3.3: @@ -2184,6 +2617,8 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + fraction.js@4.3.7: {} + fs-extra@11.2.0: dependencies: graceful-fs: 4.2.11 @@ -2203,6 +2638,23 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@11.0.0: dependencies: foreground-child: 3.3.0 @@ -2262,14 +2714,30 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-callable@1.2.7: {} + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + is-reference@3.0.2: dependencies: '@types/estree': 1.0.6 @@ -2293,10 +2761,18 @@ snapshots: dependencies: ws: 8.18.0 + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jackspeak@4.0.2: dependencies: '@isaacs/cliui': 8.0.2 + jiti@1.21.6: {} + js-cookie@2.2.1: {} js-sha3@0.8.0: {} @@ -2320,16 +2796,31 @@ snapshots: dependencies: immediate: 3.0.6 + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + locate-character@3.0.0: {} lodash@4.17.21: {} + lru-cache@10.4.3: {} + lru-cache@11.0.2: {} magic-string@0.30.12: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + memorystream@0.3.1: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + mime-db@1.52.0: {} mime-types@2.1.35: @@ -2344,6 +2835,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + minipass@7.1.2: {} mri@1.2.0: {} @@ -2352,18 +2847,43 @@ snapshots: ms@2.1.3: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.7: {} node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 + node-releases@2.0.18: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + os-tmpdir@1.0.2: {} + package-json-from-dist@1.0.1: {} pako@1.0.11: {} path-key@3.1.1: {} + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-scurry@2.0.0: dependencies: lru-cache: 11.0.2 @@ -2371,9 +2891,46 @@ snapshots: picocolors@1.1.1: {} + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + possible-typed-array-names@1.0.0: {} - postcss@8.4.47: + postcss-import@15.1.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.49): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.49 + + postcss-load-config@4.0.2(postcss@8.4.49): + dependencies: + lilconfig: 3.1.3 + yaml: 2.6.1 + optionalDependencies: + postcss: 8.4.49 + + postcss-nested@6.2.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.49: dependencies: nanoid: 3.3.7 picocolors: 1.1.1 @@ -2383,6 +2940,12 @@ snapshots: proxy-from-env@1.1.0: {} + queue-microtask@1.2.3: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -2393,10 +2956,22 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + readdirp@4.0.2: {} + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + retry@0.13.1: {} + reusify@1.0.4: {} + rollup@4.24.3: dependencies: '@types/estree': 1.0.6 @@ -2421,12 +2996,18 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.24.3 fsevents: 2.3.3 + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + sade@1.8.1: dependencies: mri: 1.2.0 safe-buffer@5.1.2: {} + semver@5.7.2: {} + set-cookie-parser@2.7.1: {} set-function-length@1.2.2: @@ -2454,6 +3035,18 @@ snapshots: mrmime: 2.0.0 totalist: 3.0.1 + solc@0.8.28: + dependencies: + command-exists: 1.2.9 + commander: 8.3.0 + follow-redirects: 1.15.9 + js-sha3: 0.8.0 + memorystream: 0.3.1 + semver: 5.7.2 + tmp: 0.0.33 + transitivePeerDependencies: + - debug + source-map-js@1.2.1: {} string-width@4.2.3: @@ -2480,6 +3073,18 @@ snapshots: dependencies: ansi-regex: 6.1.0 + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-preserve-symlinks-flag@1.0.0: {} + svelte-check@4.0.5(svelte@5.1.6)(typescript@5.6.3): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -2508,15 +3113,60 @@ snapshots: magic-string: 0.30.12 zimmerframe: 1.1.2 + tailwindcss@3.4.16: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-import: 15.1.0(postcss@8.4.49) + postcss-js: 4.0.1(postcss@8.4.49) + postcss-load-config: 4.0.2(postcss@8.4.49) + postcss-nested: 6.2.0(postcss@8.4.49) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + tiny-glob@0.2.9: dependencies: globalyzer: 0.1.0 globrex: 0.1.2 + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + totalist@3.0.1: {} tr46@0.0.3: {} + ts-interface-checker@0.1.13: {} + tslib@1.14.1: {} tslib@2.0.1: {} @@ -2533,6 +3183,12 @@ snapshots: universalify@2.0.1: {} + update-browserslist-db@1.1.1(browserslist@4.24.2): + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + util-deprecate@1.0.2: {} util@0.12.5: @@ -2546,7 +3202,7 @@ snapshots: vite@5.4.10(@types/node@22.9.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 + postcss: 8.4.49 rollup: 4.24.3 optionalDependencies: '@types/node': 22.9.0 @@ -2818,6 +3474,8 @@ snapshots: ws@8.18.0: {} + yaml@2.6.1: {} + zimmerframe@1.1.2: {} zod@3.23.8: {} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/src/app.d.ts b/src/app.d.ts index ad92508..e2c24df 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -13,3 +13,8 @@ declare global { declare interface Window { ethereum?: import('ethers').Eip1193Provider & import('ethers').BrowserProvider; } + +// solc does not have a type definition file. +declare module 'solc' { + export function compile(input: string, opts?: any): any; +} diff --git a/src/lib/api.ts b/src/lib/api.ts index 38a29c4..26180f0 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -1,6 +1,7 @@ import type { CreateApprovalProcessRequest } from "./models/approval-process"; import type { Credentials } from "./models/auth"; import type { DeployContractRequest, UpdateDeploymentRequest } from "./models/deploy"; +import type { CompilerInput } from "./models/solc"; class ApiClient { credentials: Credentials | null = null; @@ -72,6 +73,16 @@ class ApiClient { return response.json(); } + + async compile(input: CompilerInput) { + const response = await fetch("/compiler", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ input }), + }); + + return response.json(); + } } export const API = new ApiClient(); diff --git a/src/lib/models/deploy.ts b/src/lib/models/deploy.ts index 70e956e..e3867c5 100644 --- a/src/lib/models/deploy.ts +++ b/src/lib/models/deploy.ts @@ -70,4 +70,21 @@ export interface UpdateDeploymentRequest { deploymentId: string; address: string; hash: string; -} \ No newline at end of file +} + +export interface DeploymentResult { + deploymentId?: string; + address: string; + hash: string; + sender?: string; +} + +export type ABITypeParameter = 'uint' | 'uint[]' | 'int' | 'int[]' | 'address' | 'address[]' | 'bool' | 'bool[]' | 'fixed' | 'fixed[]' | 'ufixed' | 'ufixed[]' | 'bytes' | 'bytes[]' | 'function' | 'function[]' | 'tuple' | 'tuple[]' | string; +export interface ABIParameter { + /** The name of the parameter */ + name: string; + /** The canonical type of the parameter */ + type: ABITypeParameter; + /** Used for tuple types */ + components?: ABIParameter[]; +} diff --git a/src/lib/models/solc.ts b/src/lib/models/solc.ts new file mode 100644 index 0000000..995e23c --- /dev/null +++ b/src/lib/models/solc.ts @@ -0,0 +1,43 @@ +export type CompilerInput = { + /** + * The language, currently only Solidity is supported. + */ + language: string; + /** + * Name of the file and the content of the file. + * e.g. { 'test.sol': { content: 'contract C { function f() public { L.f(); } }' } } + */ + sources: ContractSources; + /** + * Settings for the compiler. + * e.g. { outputSelection: { '*': { '*': ['*'] } }" + */ + settings: { + outputSelection: Record>; + optimizer?: { + enabled: boolean, + runs: number, + }, + }; +}; + +export type ContractSources = { + [source: string]: { content: string }; +}; + +export function buildCompilerInput(sources: ContractSources): CompilerInput { + return { + sources, + language: 'Solidity', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + outputSelection: { + '*': { '*': ['*'] } + } + } + }; +} + diff --git a/src/lib/components/ApprovalProcess.svelte b/src/lib/remix/components/ApprovalProcess.svelte similarity index 100% rename from src/lib/components/ApprovalProcess.svelte rename to src/lib/remix/components/ApprovalProcess.svelte diff --git a/src/lib/components/Deploy.svelte b/src/lib/remix/components/Deploy.svelte similarity index 99% rename from src/lib/components/Deploy.svelte rename to src/lib/remix/components/Deploy.svelte index 105c405..ea2a4b4 100644 --- a/src/lib/components/Deploy.svelte +++ b/src/lib/remix/components/Deploy.svelte @@ -81,7 +81,7 @@ contractBytecode = getContractBytecode( contractInfo.path, contractInfo.name, - globalState.contract.data + globalState.contract.data.contracts ); } }); @@ -293,7 +293,7 @@ verifySourceCode: true, artifactPayload, constructorBytecode, - salt, + salt: isDeterministic || enforceDeterministic ? salt : undefined, }; const [newDeploymentId, deployError] = await attempt(async () => createDefenderDeployment(deployRequest)); if (deployError) { diff --git a/src/lib/components/Network.svelte b/src/lib/remix/components/Network.svelte similarity index 100% rename from src/lib/components/Network.svelte rename to src/lib/remix/components/Network.svelte diff --git a/src/lib/components/Setup.svelte b/src/lib/remix/components/Setup.svelte similarity index 100% rename from src/lib/components/Setup.svelte rename to src/lib/remix/components/Setup.svelte diff --git a/src/lib/components/shared/Button.svelte b/src/lib/remix/components/shared/Button.svelte similarity index 100% rename from src/lib/components/shared/Button.svelte rename to src/lib/remix/components/shared/Button.svelte diff --git a/src/lib/components/shared/Dropdown.svelte b/src/lib/remix/components/shared/Dropdown.svelte similarity index 100% rename from src/lib/components/shared/Dropdown.svelte rename to src/lib/remix/components/shared/Dropdown.svelte diff --git a/src/lib/remix/index.ts b/src/lib/remix/index.ts index b97f542..f4ca0aa 100644 --- a/src/lib/remix/index.ts +++ b/src/lib/remix/index.ts @@ -4,7 +4,7 @@ import { listenOnThemeChanged } from "./theme"; import { listenOnCompilerResults } from "./compiler"; import { initLogger } from "./logger"; -export const initPlugin = () => { +export const initRemixPlugin = () => { const plugin = new PluginClient({ allowOrigins: ['https://remix.ethereum.org'] }); const client = createClient(plugin); diff --git a/src/lib/state/state.svelte.ts b/src/lib/state/state.svelte.ts index 6d4a1ae..76f1a2a 100644 --- a/src/lib/state/state.svelte.ts +++ b/src/lib/state/state.svelte.ts @@ -1,5 +1,6 @@ import type { ApprovalProcess } from "$lib/models/approval-process"; import type { GlobalState } from "$lib/models/ui"; +import { isDeploymentEnvironment, isSameNetwork } from "$lib/utils/helpers"; /** * Global application state @@ -83,3 +84,13 @@ export const addAPToDropdown = (approvalProcess: ApprovalProcess) => { export function setDeploymentCompleted(completed: boolean) { globalState.form.completed = completed; } + +export function findDeploymentEnvironment(via?: string, network?: string) { + if (!via || !network) return undefined; + return globalState.approvalProcesses.find((ap) => + ap.network && + isDeploymentEnvironment(ap) && + isSameNetwork(ap.network, network) && + ap.via?.toLocaleLowerCase() === via.toLocaleLowerCase() + ); +} \ No newline at end of file diff --git a/src/lib/utils/contracts.ts b/src/lib/utils/contracts.ts index 7882d88..78b0a9c 100644 --- a/src/lib/utils/contracts.ts +++ b/src/lib/utils/contracts.ts @@ -1,6 +1,7 @@ import type { ABIDescription, ABIParameter, CompilationResult } from "@remixproject/plugin-api"; import { AbiCoder } from "ethers"; import { attempt } from "./attempt"; +import type { Artifact } from "$lib/models/deploy"; export function getContractFeatures( path: string, @@ -28,6 +29,23 @@ export function getConstructorInputs( return constructor.inputs as ABIParameter[]; } +export function getConstructorInputsWizard( + path: string | undefined, + contracts: Artifact['output']['contracts'], +): ABIParameter[] { + // if no compiled contracts found, then return empty inputs. + if (!contracts || !path) return []; + + const contractName = + Object.keys(contracts[path]).length > 0 + ? Object.keys(contracts[path])[0] + : ""; + const abi: Array = contracts[path][contractName].abi; + const constructor = abi.find((fragment) => fragment.type === "constructor"); + if (!constructor || !constructor.inputs) return []; + return constructor.inputs as ABIParameter[]; +} + export async function encodeConstructorArgs( inputs: ABIParameter[], inputsWithValue: Record @@ -67,7 +85,7 @@ export function createArtifactPayload( export function getContractBytecode( path: string, contractName: string, - compilation: CompilationResult + contractSources: Record ): string { - return compilation.contracts[path][contractName].evm.bytecode.object; + return contractSources[path][contractName].evm.bytecode.object; } diff --git a/src/lib/utils/helpers.ts b/src/lib/utils/helpers.ts index d32442a..558b4b1 100644 --- a/src/lib/utils/helpers.ts +++ b/src/lib/utils/helpers.ts @@ -1,5 +1,6 @@ import type { ApprovalProcess } from "$lib/models/approval-process"; import { getNetworkLiteral, type TenantNetworkResponse } from "$lib/models/network"; +import type { ContractSources } from "$lib/models/solc"; export const abbreviateAddress = (address: string, size = 6) => { return `${address.slice(0, size)}...${address.slice(-size)}`; @@ -14,3 +15,14 @@ export const isSameNetwork = (a: string | TenantNetworkResponse, b: string | Ten export const isDeploymentEnvironment = (approvalProcess: ApprovalProcess) => { return approvalProcess.component?.includes('deploy'); } + +export const isMultisig = (viaType?: ApprovalProcess['viaType']) => { + if (!viaType) return false; + const multisigTypes = ['Safe', 'Multisig', 'Gnosis Safe', 'Gnosis Multisig']; + return multisigTypes.includes(viaType); +} + +export const isUpgradeable = (sources?: ContractSources) => { + if (!sources) return false; + return Object.keys(sources).some((path) => path.includes('@openzeppelin/contracts-upgradeable')); +} diff --git a/src/lib/wizard/components/ApprovalProcess.svelte b/src/lib/wizard/components/ApprovalProcess.svelte new file mode 100644 index 0000000..b93e049 --- /dev/null +++ b/src/lib/wizard/components/ApprovalProcess.svelte @@ -0,0 +1,207 @@ + + +
+
+ onRadioChange(e)} + checked + /> +
+
+ {#key globalState.form.approvalProcessSelected} + onSelectApprovalProcess(e.detail)} + disabled={radioSelected !== "existing"} + defaultItem={globalState.form.approvalProcessSelected + ? { + label: toDisplayName(globalState.form.approvalProcessSelected), + value: globalState.form.approvalProcessSelected, + } + : undefined} + emptyLabel="No Approval Processes Available" + /> + {/key} +
+
+
+ + +
+
+ onSelectApprovalProcessType(e.detail)} + disabled={radioSelected !== "new" || disableCreation} + defaultItem={{ + label: approvalProcessType, + value: approvalProcessType, + }} + /> + + {#if approvalProcessType === "EOA" || approvalProcessType === "Safe"} +
+ +
+ {:else if approvalProcessType === "Relayer"} + {#if disableRelayers} +
+ +
+ {:else} + onSelectRelayer(e.detail)} + disabled={radioSelected !== "new" || disableCreation} + /> + {/if} + {/if} +
+
+ onRadioChange(e)} + title={disableCreation ? "Deploy Environment already exists" : undefined} + disabled={disableCreation} + /> + +
diff --git a/src/lib/wizard/components/Configuration.svelte b/src/lib/wizard/components/Configuration.svelte new file mode 100644 index 0000000..986c018 --- /dev/null +++ b/src/lib/wizard/components/Configuration.svelte @@ -0,0 +1,102 @@ + + +
+
+
+ + +
+ +
+ + + + +
diff --git a/src/lib/wizard/components/Deploy.svelte b/src/lib/wizard/components/Deploy.svelte new file mode 100644 index 0000000..8328a13 --- /dev/null +++ b/src/lib/wizard/components/Deploy.svelte @@ -0,0 +1,364 @@ + + +
+ {#if displayUpgradeableWarning} + + {/if} + + {#if inputs.length > 0} +
Constructor Arguments
+ {#each inputs as input} + + {/each} + {:else} + + {/if} + +
+ (isDeterministic = !isDeterministic)} + disabled={enforceDeterministic} + > + +
+ + {#if isDeterministic || enforceDeterministic} + + {/if} + + {#if compilationError} + + {/if} + +
\ No newline at end of file diff --git a/src/lib/wizard/components/Network.svelte b/src/lib/wizard/components/Network.svelte new file mode 100644 index 0000000..845eb78 --- /dev/null +++ b/src/lib/wizard/components/Network.svelte @@ -0,0 +1,54 @@ + + + onNetworkSelect(e.detail)} + defaultItem={globalState.form.network ? networkToDropdownItem(globalState.form.network) : undefined} +/> diff --git a/src/lib/wizard/components/shared/Button.svelte b/src/lib/wizard/components/shared/Button.svelte new file mode 100644 index 0000000..93d6ac2 --- /dev/null +++ b/src/lib/wizard/components/shared/Button.svelte @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/src/lib/wizard/components/shared/Dropdown.svelte b/src/lib/wizard/components/shared/Dropdown.svelte new file mode 100644 index 0000000..37a429c --- /dev/null +++ b/src/lib/wizard/components/shared/Dropdown.svelte @@ -0,0 +1,104 @@ + + +
+ + + {#if isOpen} +
+ {#each Object.entries(groupedItems) as [group, items]} + {#if group !== 'default'} +
{group}
+ {/if} + {#each items.sort((a, b) => a.label.localeCompare(b.label)) as item} + + {/each} + {/each} + {#if items.length === 0} +
+ {emptyLabel ?? "No items available"} +
+ {/if} +
+ {/if} +
\ No newline at end of file diff --git a/src/lib/wizard/components/shared/Input.svelte b/src/lib/wizard/components/shared/Input.svelte new file mode 100644 index 0000000..3710bab --- /dev/null +++ b/src/lib/wizard/components/shared/Input.svelte @@ -0,0 +1,28 @@ + + +{#if label} + +{/if} + diff --git a/src/lib/wizard/components/shared/Message.svelte b/src/lib/wizard/components/shared/Message.svelte new file mode 100644 index 0000000..521e6b5 --- /dev/null +++ b/src/lib/wizard/components/shared/Message.svelte @@ -0,0 +1,31 @@ + + +{#if type === 'success'} +
+ +
{@html message}
+
+{:else if type === 'error'} +
+ +
{@html message}
+
+{:else if type === 'warn'} +
+ +
{@html message}
+
+{:else if type === 'info'} +
+ +
{@html message}
+
+{/if} + diff --git a/src/lib/wizard/index.ts b/src/lib/wizard/index.ts new file mode 100644 index 0000000..890be70 --- /dev/null +++ b/src/lib/wizard/index.ts @@ -0,0 +1,31 @@ +import type { ContractSources } from "../models/solc"; +import { globalState } from "$lib/state/state.svelte"; + +export interface DefenderDeployMessage { + kind: 'oz-wizard-defender-deploy'; + sources: ContractSources; +} + +export const initWizardPlugin = () => { + // when users configure a contract, the plugin gets the results. + listenToContracts(); +} + +function listenToContracts() { + window.addEventListener('message', function (e: MessageEvent) { + if (e.data.kind === 'oz-wizard-defender-deploy') { + globalState.contract = { + source: { + sources: e.data.sources, + }, + target: getMainContractName(e.data.sources) + }; + } + }); +} + +function getMainContractName(sources?: ContractSources) { + if (!sources) return ''; + // The first name that is not a dependency + return Object.keys(sources).find(name => !name.startsWith('@')); +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index bbc36c8..3775497 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,150 +1,49 @@
-

- To get started with Deploy With Defender, you need to - have an - OpenZeppelin Defender Account - (It's free) and setup an - - API Key and Secret. -

+ {#if parent === 'none'} +

⚠️ This page is meant to be embedded in an iframe! ⚠️

+ {/if} - {#if globalState.error} -
-

{globalState.error ?? ""}

-
+ {#if parent === 'wizard'} + {/if} -
- {#each [0, 1, 2, 3] as index} -
- - - {#if currentTab === index} -
-
- {#if index === 0} wait(1000).then(() => toggle(1))}/>{/if} - {#if index === 1} wait(1000).then(() => toggle(2))}/>{/if} - {#if index === 2}{/if} - {#if index === 3}{/if} -
-
- {/if} -
- {/each} -
+ {#if parent === 'remix'} + + {/if}
- diff --git a/src/routes/compiler/+server.ts b/src/routes/compiler/+server.ts new file mode 100644 index 0000000..fcb0260 --- /dev/null +++ b/src/routes/compiler/+server.ts @@ -0,0 +1,19 @@ +import type { CompilerInput } from "$lib/models/solc"; +import { json } from '@sveltejs/kit'; +import { SolidityCompiler } from "./compiler"; +import { attempt } from "$lib/utils/attempt"; + + +export async function POST({ request }: { request: Request }) { + const { input }: { input: CompilerInput } = await request.json(); + + const compiler = new SolidityCompiler(); + + const [output, error] = await attempt(() => JSON.parse(compiler.compile(input))); + + if (error) { + return json({ success: false, error: error.msg }); + } + + return json({ success: true, data: { output } }); +} diff --git a/src/routes/compiler/compiler.ts b/src/routes/compiler/compiler.ts new file mode 100644 index 0000000..5582bf6 --- /dev/null +++ b/src/routes/compiler/compiler.ts @@ -0,0 +1,20 @@ +import solc from 'solc'; + +import type { ContractSources } from "$lib/models/solc"; +import type { CompilerInput } from "$lib/models/solc"; + +export class SolidityCompiler { + getContent(path: string, contents: ContractSources) { + if (contents[path]) { + return contents[path]; + } + return { error: 'File not found' }; + } + + compile(input: CompilerInput, contents?: ContractSources) { + const shouldFindImports = contents !== undefined; + const findImports = (path: string) => shouldFindImports ? this.getContent(path, contents) : undefined; + const output = solc.compile(JSON.stringify(input), shouldFindImports ? { import: findImports } : undefined); + return output; + } +} diff --git a/src/routes/deploy/+server.ts b/src/routes/deploy/+server.ts index 28029c7..0f4b36c 100644 --- a/src/routes/deploy/+server.ts +++ b/src/routes/deploy/+server.ts @@ -10,7 +10,8 @@ export async function POST({ request }: { request: Request }) { const [deploymentResult, error] = await attempt(() => deployContract(credentials, deployment)); if (error) { - return json({ success: false, error: error.msg }); + const internalError = error.errorObject?.response?.data?.message; + return json({ success: false, error: internalError || error.msg }); } return json({ success: true, data: { deployment: deploymentResult } }); diff --git a/src/routes/remix.svelte b/src/routes/remix.svelte new file mode 100644 index 0000000..25aad36 --- /dev/null +++ b/src/routes/remix.svelte @@ -0,0 +1,147 @@ + + +

+ To get started with Deploy With Defender, you need to + have an + OpenZeppelin Defender Account + (It's free) and setup an + + API Key and Secret. +

+ +{#if globalState.error} +
+

{globalState.error ?? ""}

+
+{/if} + +
+ {#each [0, 1, 2, 3] as index} +
+ + + {#if currentTab === index} +
+
+ {#if index === 0} wait(1000).then(() => toggle(1))}/>{/if} + {#if index === 1} wait(1000).then(() => toggle(2))}/>{/if} + {#if index === 2}{/if} + {#if index === 3}{/if} +
+
+ {/if} +
+ {/each} +
+ + diff --git a/src/routes/wizard.svelte b/src/routes/wizard.svelte new file mode 100644 index 0000000..1ba981c --- /dev/null +++ b/src/routes/wizard.svelte @@ -0,0 +1,88 @@ + + + +
+
+ +
+
+ +
+
+ +
+
+ {}} /> +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ \ No newline at end of file diff --git a/src/wizard-app.css b/src/wizard-app.css new file mode 100644 index 0000000..bd6213e --- /dev/null +++ b/src/wizard-app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..13207cc --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{html,js,svelte,ts}'], + theme: { + extend: {}, + }, + plugins: [], +} +