├── .github └── ISSUE_TEMPLATE │ └── add-my-project.md ├── .gitignore ├── LICENSE.md ├── README.md ├── coming-soon └── index.html ├── landing ├── backers.js ├── building.html ├── favicon.ico ├── index.html ├── og-preview.jpg ├── projects.js ├── projects │ ├── aboutlo_ether-swr.png │ ├── alphawallet_.jpg │ ├── austintgriffith_scaffold-eth.png │ ├── bokkypoobah_BestBastardGANPunks.png │ ├── compound-finance_compound-js.svg │ ├── ensdomains_ens-app.svg │ ├── ethereum-optimism_optimism.svg │ ├── forta-protocol_forta-agent-sdk.jpg │ ├── holdberg.jpg │ ├── mdtanrikulu_use-metamask.svg │ ├── mycryptohq_mycrypto.png │ ├── nachomazzara_web3playground.jpg │ ├── nanexcool_daistats.png │ ├── rkalis_allbastards-com.png │ ├── rkalis_revoke-cash.png │ ├── scopelift_umbra-protocol.png │ ├── statechannels_statechannels.svg │ ├── tallycash_extension.jpg │ ├── unknown_whalestats.svg │ ├── unlock-protocol_unlock.png │ ├── wallet3_wallet3.png │ ├── wighawag_mandalas.png │ └── wmitsuda_otterscan.png ├── sponsoring.html ├── sponsors │ ├── ankr.png │ ├── ankr.svg │ ├── tally-link │ ├── tally-readme.svg │ ├── tally.jpg │ └── test.html └── static │ ├── docs.svg │ ├── icon-discord.svg │ ├── icon-docs.svg │ ├── icon-github.svg │ ├── icon-playground.svg │ ├── icon-toolbox.svg │ ├── icon-twitter.svg │ ├── icon-wallet.svg │ ├── logo.png │ ├── script.js │ ├── st-alchemy.svg │ ├── st-ankr.png │ ├── st-ankr.svg │ ├── st-ethereum.png │ ├── st-etherscan.svg │ ├── st-gitcoin.png │ ├── st-infura.svg │ ├── st-pokt.svg │ └── style.css └── playground ├── app.js ├── docs.js ├── favicon.ico ├── help.js ├── index.html ├── inspect.js ├── og-preview.jpg ├── sandbox.js ├── sources ├── caret.svg ├── checkmark.svg ├── dark-mode-moon.svg ├── dark-mode-stars.svg ├── dark-mode-sun.svg ├── generate.mjs ├── icon-library.svg ├── icon-settings.svg ├── logo.svg ├── options-open.svg └── style.css ├── style.css └── v5 ├── help.js ├── index.html ├── inspect.js ├── sandbox.js └── static ├── caret.svg ├── checkmark.svg ├── dark-mode-moon.svg ├── dark-mode-stars.svg ├── dark-mode-sun.svg ├── help.js ├── icon-library.svg ├── icon-settings.svg ├── logo.svg ├── options-open.svg ├── script.js ├── style.css └── types.js /.github/ISSUE_TEMPLATE/add-my-project.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Add My Project 3 | about: 'Request to add your project ' 4 | title: 'Add my project, please: [PROJECT NAME]' 5 | labels: add-my-project, landing-page 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thanks for using ethers and we look forward to including a link to your project on ethers. 11 | 12 | Please include the following details: 13 | 14 | - Link to GitHub repository (currently only GitHub is supported, and the project must be public) 15 | - A 256x256 px image (JPG or PNG) for a logo to include (attach it to this issue or include a link) 16 | - A public e-mail address or Twitter account with DMs enabled (this is used to resolve dead links or other concerns with the project) 17 | 18 | Notes: 19 | - All projects are previewed and vetted before inclusion, and monitored for changes and regularly reviewed 20 | - Project license should be compatible with Open Source Initiatives 21 | - Images will be hosted by ethers to protect privacy; contact me to update a logo 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | obsolete/ 2 | .DS_Store 3 | .tmp/ 4 | **/*.swp 5 | *~ 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Richard Moore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ethers Websites 2 | =============== 3 | 4 | - [Landing](https://ethers.org) -- The main landing page for ethers 5 | - [Playground](https://playground.ethers.org/) -- A simple REPL to play around with ethers 6 | - Toolbox (coming soon) -- A simple UI to perform common Ethereum operations 7 | - Wallet (coming soon) -- A simple wallet built on top of ethers 8 | 9 | Other Links 10 | ----------- 11 | 12 | - [Documentation](https://docs.ethers.io/) 13 | 14 | License 15 | ------- 16 | 17 | MIT License. 18 | -------------------------------------------------------------------------------- /coming-soon/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Coming soon... :) 4 | 5 | 6 | -------------------------------------------------------------------------------- /landing/building.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | building - ethers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
GitHub
17 |
Twitter
18 |
Discord
19 |
20 |
21 | 22 |
ethers
23 | 26 |
27 |
28 |
29 |
BUILDING PROJECTS
30 |
31 | 32 | Heya! I thought it might be a good idea to keep a collection 33 | of Open Source projects built using ethers and help share 34 | them with the community at large. So, here are a few ground rules. :) 35 | 36 |
37 |
38 | What do I need to submit? 39 |
    40 |
  • A link to your GitHub project (currently, only GitHub projects are supported)
  • 41 |
  • A 256px × 256px logo as a PNG or JPEG
  • 42 |
  • An e-mail address or Twitter account you can be reached at; in case a link becomes dead, to verify updating logos, other concerns, etc.
  • 43 |
  • Please submit a request to add your project
  • 44 |
45 |
46 |
47 |
48 |
NOTES
49 |
50 |
    51 |
  • 52 | Scam-like endeavours and criminal activity are not welcome and are deemed at 53 | my discretion. 54 |
  • 55 |
  • 56 | All links are manually verified before inclusion. 57 |
  • 58 |
  • 59 | Links are regularly monitored by to prevent scams. 60 |
  • 61 |
  • 62 | All images are hosted by ethers to protect visitor privacy. 63 | Contact me to update your logo. 64 |
  • 65 |
  • 66 | Forwarding referrer headers are disabled, no cookies are used and 67 | personal data is never stored for any visitor. 68 |
  • 69 |
  • 70 | Inclusion does not represent endorsement. 71 |
  • 72 |
  • 73 | Project licenses should be compatible with Open Source inititives. 74 |
  • 75 |
  • 76 | This is more of an experiment at this time; lets see how it goes. 77 |
  • 78 |
79 |
80 |
81 |
82 |
83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /landing/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/favicon.ico -------------------------------------------------------------------------------- /landing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | ethers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 25 | 26 | 27 | 31 | 38 |
39 | 40 |
ethers
41 |
a simple, compact and complete JavaScript
library for all your Ethereum needs

:)
42 |
43 |
44 |
45 |
DOCS & TOOLS
46 | 66 |
67 | 99 | 107 | 131 | 132 |
133 | 134 | 138 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /landing/og-preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/og-preview.jpg -------------------------------------------------------------------------------- /landing/projects.js: -------------------------------------------------------------------------------- 1 | const Projects = [{ 2 | /* Wait for a GitHub project? 3 | image: "holdberg.jpg", 4 | name: "Holdbeg Financial", 5 | url: "https://github.com/hodlberg", 6 | score: 1 7 | },{ 8 | image: "unknown_whalestats.svg", 9 | name: "Whalestats", 10 | url: "", 11 | score: 0 12 | },{ 13 | image: "", 14 | name: "", 15 | url: "", 16 | score: 17 | }, { 18 | */ 19 | image: "mdtanrikulu_use-metamask.svg", 20 | name: "useMetamask", 21 | url: "https://github.com/mdtanrikulu/use-metamask", 22 | score: 47 23 | },{ 24 | image: "rkalis_allbastards-com.png", 25 | name: "AllBastards", 26 | url: "https://github.com/rkalis/allbastards.com", 27 | score: 7 28 | },{ 29 | image: "alphawallet_.jpg", 30 | name: "AlphaWallet", 31 | url: "https://github.com/AlphaWallet/", 32 | score: 204 33 | },{ 34 | image: "bokkypoobah_BestBastardGANPunks.png", 35 | name: "BestBastardGANPunks", 36 | url: "https://github.com/bokkypoobah/BestBastardGANPunks", 37 | score: 1 38 | },{ 39 | image: "compound-finance_compound-js.svg", 40 | name: "Compound.js", 41 | url: "https://github.com/compound-finance/compound-js", 42 | score: 91 43 | },{ 44 | image: "ensdomains_ens-app.svg", 45 | name: "ENS App", 46 | url: "https://github.com/ensdomains/ens-app", 47 | score: 79 48 | },{ 49 | image: "aboutlo_ether-swr.png", 50 | name: "Ether-SWR", 51 | url: "https://github.com/aboutlo/ether-swr", 52 | score: 84 53 | },{ 54 | image: "ethereum-optimism_optimism.svg", 55 | name: "Optimism", 56 | url: "https://github.com/ethereum-optimism/optimism", 57 | score: 507 58 | },{ 59 | image: "forta-protocol_forta-agent-sdk.jpg", 60 | name: "Forta", 61 | url: "https://github.com/forta-protocol/forta-agent-sdk", 62 | score: 25 63 | },{ 64 | image: "mycryptohq_mycrypto.png", 65 | name: "MyCrypto", 66 | url: "https://github.com/MyCryptoHQ/MyCrypto", 67 | score: 968 68 | },{ 69 | image: "nachomazzara_web3playground.jpg", 70 | name: "Web3 Playground", 71 | url: "https://github.com/nachomazzara/web3playground", 72 | score: 20 73 | },{ 74 | image: "nanexcool_daistats.png", 75 | name: "Daistats", 76 | url: "https://github.com/nanexcool/daistats", 77 | score: 57 78 | },{ 79 | image: "rkalis_revoke-cash.png", 80 | name: "Revoke", 81 | url: "https://github.com/rkalis/revoke.cash", 82 | score: 73 83 | },{ 84 | image: "austintgriffith_scaffold-eth.png", 85 | name: "Scaffold-ETH", 86 | url: "https://github.com/austintgriffith/scaffold-eth", 87 | score: 2200 88 | },{ 89 | image: "statechannels_statechannels.svg", 90 | name: "State Channels", 91 | url: "https://github.com/statechannels/statechannels", 92 | score: 101 93 | },{ 94 | image: "wallet3_wallet3.png", 95 | name: "Wallet3", 96 | url: "https://github.com/Wallet3/Wallet3", 97 | score: 0 98 | },{ 99 | image: "scopelift_umbra-protocol.png", 100 | name: "Umbra", 101 | url: "https://github.com/ScopeLift/umbra-protocol", 102 | score: 87 103 | },{ 104 | image: "tallycash_extension.jpg", 105 | name: "Tally.cash", 106 | url: "https://github.com/tallycash/extension", 107 | score: 315 108 | },{ 109 | image: "unlock-protocol_unlock.png", 110 | name: "Unlock", 111 | url: "https://github.com/unlock-protocol/unlock/", 112 | score: 434 113 | },{ 114 | image: "wighawag_mandalas.png", 115 | name: "Mandalas", 116 | url: "https://github.com/wighawag/mandalas", 117 | score: 2 118 | },{ 119 | image: "wmitsuda_otterscan.png", 120 | name: "Otterscan", 121 | url: "https://github.com/wmitsuda/otterscan", 122 | score: 118 123 | }].sort((a, b) => (b.score - a.score)).map((p) => { 124 | p.image = "projects/" + p.image; 125 | return p; 126 | }); 127 | -------------------------------------------------------------------------------- /landing/projects/aboutlo_ether-swr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/aboutlo_ether-swr.png -------------------------------------------------------------------------------- /landing/projects/alphawallet_.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/alphawallet_.jpg -------------------------------------------------------------------------------- /landing/projects/austintgriffith_scaffold-eth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/austintgriffith_scaffold-eth.png -------------------------------------------------------------------------------- /landing/projects/bokkypoobah_BestBastardGANPunks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/bokkypoobah_BestBastardGANPunks.png -------------------------------------------------------------------------------- /landing/projects/compound-finance_compound-js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /landing/projects/ensdomains_ens-app.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /landing/projects/ethereum-optimism_optimism.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /landing/projects/forta-protocol_forta-agent-sdk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/forta-protocol_forta-agent-sdk.jpg -------------------------------------------------------------------------------- /landing/projects/holdberg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/holdberg.jpg -------------------------------------------------------------------------------- /landing/projects/mdtanrikulu_use-metamask.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 20 | Created with Sketch. 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 39 | 40 | 41 | 47 | 48 | 49 | 50 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /landing/projects/mycryptohq_mycrypto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/mycryptohq_mycrypto.png -------------------------------------------------------------------------------- /landing/projects/nachomazzara_web3playground.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/nachomazzara_web3playground.jpg -------------------------------------------------------------------------------- /landing/projects/nanexcool_daistats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/nanexcool_daistats.png -------------------------------------------------------------------------------- /landing/projects/rkalis_allbastards-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/rkalis_allbastards-com.png -------------------------------------------------------------------------------- /landing/projects/rkalis_revoke-cash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/rkalis_revoke-cash.png -------------------------------------------------------------------------------- /landing/projects/scopelift_umbra-protocol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/scopelift_umbra-protocol.png -------------------------------------------------------------------------------- /landing/projects/statechannels_statechannels.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 26 | 27 | -------------------------------------------------------------------------------- /landing/projects/tallycash_extension.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/tallycash_extension.jpg -------------------------------------------------------------------------------- /landing/projects/unknown_whalestats.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /landing/projects/unlock-protocol_unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/unlock-protocol_unlock.png -------------------------------------------------------------------------------- /landing/projects/wallet3_wallet3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/wallet3_wallet3.png -------------------------------------------------------------------------------- /landing/projects/wighawag_mandalas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/wighawag_mandalas.png -------------------------------------------------------------------------------- /landing/projects/wmitsuda_otterscan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/projects/wmitsuda_otterscan.png -------------------------------------------------------------------------------- /landing/sponsoring.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | sponsorship - ethers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
GitHub
17 |
Twitter
18 |
Discord
19 |
20 |
21 | 22 |
ethers
23 | 26 |
27 |
28 |
29 |
SPONSORSHIP
30 |
31 | Ahoy! I thought I would try something new and test the waters 32 | as to whether there is any interest in sponsors, so here are 33 | some rough ideas I have put together. 34 |
35 |
36 |
37 |
SPONSORSHIP TIERS
38 |
39 | Backer — anyone who has donated via GitCoin or BuyMeACoffee 40 |
    41 |
  • 42 | You get your logo+link to your public profile on ethers under the Backers section 43 |
  • 44 |
  • 45 | By default your GitCoin profile avatar is used; contact me to update it 46 |
  • 47 |
  • 48 | All backers are shown probablistically, based on all-time contributions 49 |
  • 50 |
51 |
52 |
53 | Bronze — $1,000 / month 54 |
    55 |
  • 56 | Include logo+link to an approved public website (e.g. GitHub 57 | project, npm package, twitter profile, etc) on ethers 58 | under the Bronze Sponsors section 59 |
  • 60 |
61 |
62 |
63 | Silver — $5,000 / month 64 |
    65 |
  • 66 | Include a logo+link to your project website on ethers 67 | under the Silver Sponsors section 68 |
  • 69 |
70 |
71 |
72 | Gold — $10,000 / month 73 |
    74 |
  • 75 | Include a logo+link to your project website on 76 | ethers under the Gold Sponsors section 77 |
  • 78 |
  • 79 | Also, include a logo+link to your project website in the 80 | README (and therefore on 81 | NPM) 82 |
  • 83 |
84 |
85 |
86 | Unobtainium — $25,000 / month 87 |
    88 |
  • 89 | Everything from the Gold Tier 90 |
  • 91 |
  • 92 | Also, each month I will purchase a coffee from a local coffee shop 93 | (possibly Starbucks) with your company name on the side and 94 | tweet a photo of me enjoying your wonderful gift. 95 |
  • 96 |
97 |
98 |
99 |
100 |
NOTES
101 |
102 |
    103 |
  • 104 | Scam-like endeavours and criminal activity are not welcome and are deemed at 105 | my discretion. 106 |
  • 107 |
  • 108 | All links are manually verified before inclusion, especially on 109 | the README and NPM page. 110 |
  • 111 |
  • 112 | Links are regularly monitored by scripts to prevent scams. 113 |
  • 114 |
  • 115 | All images are hosted by ethers to protect visitor privacy. 116 | Contact me to update your logo. 117 |
  • 118 |
  • 119 | Forwarding referrer headers are disabled, no cookies are used and 120 | personal data is never stored for any visitor. 121 |
  • 122 |
  • 123 | Sponsorship does not represent endorsement. 124 |
  • 125 |
  • 126 | Sponsorship levels are in USD. 127 |
  • 128 |
  • 129 | This is my first attempt at Sponsorship; tiers may be 130 | adjusted over time. 131 |
  • 132 |
  • 133 | Changes to tier benefits will be conveyed with significant 134 | lead-time, during which grandfathered benefits will apply, 135 | if desired. 136 |
  • 137 |
  • 138 | Logos should be provided in an aspect ratio of as close to 1:1 139 | (e.g. square or circle) as possible for best appearance. SVG, 140 | PNG and JPG supported; if providing a raster format, please make 141 | sure it is at least 256x256 so it looks great on retina displays. 142 |
  • 143 |
144 |
145 |
146 |
147 |
148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /landing/sponsors/ankr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/sponsors/ankr.png -------------------------------------------------------------------------------- /landing/sponsors/ankr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /landing/sponsors/tally-link: -------------------------------------------------------------------------------- 1 | https://tally.cash 2 | -------------------------------------------------------------------------------- /landing/sponsors/tally-readme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tally.cash 5 | 6 | -------------------------------------------------------------------------------- /landing/sponsors/tally.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/sponsors/tally.jpg -------------------------------------------------------------------------------- /landing/sponsors/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /landing/static/docs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /landing/static/icon-discord.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /landing/static/icon-docs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /landing/static/icon-github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 17 | 18 | -------------------------------------------------------------------------------- /landing/static/icon-playground.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /landing/static/icon-toolbox.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 14 | 20 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /landing/static/icon-twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /landing/static/icon-wallet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 13 | 15 | 17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /landing/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/static/logo.png -------------------------------------------------------------------------------- /landing/static/script.js: -------------------------------------------------------------------------------- 1 | 2 | // Creates a timer that doesn't tick while the screen is not visible. 3 | // If sync, the event synchronizes with the most recent timer with the 4 | // same duration. 5 | const foregroundTimers = { }; 6 | function setForegroundTimeout(callback, duration, sync) { 7 | if (duration == null) { duration = 0; } 8 | 9 | // Browser doesn't support visibility API 10 | if (typeof(document.hidden) !== "boolean") { 11 | setTimeout(callback, duration); 12 | return; 13 | } 14 | 15 | // If synchronized, reuse the same callback bucket 16 | let timers = [ callback ]; 17 | if (sync) { 18 | if (foregroundTimers[duration] == null) { 19 | foregroundTimers[duration] = timers; 20 | } else { 21 | timers = foregroundTimers[duration]; 22 | timers.push(callback); 23 | return; 24 | } 25 | } 26 | 27 | const TICK = 250; 28 | 29 | // Short timeouts can just behave as normal 30 | if (duration < TICK) { return setTimeout(callback, duration); } 31 | 32 | let elapsed = 0; 33 | const timer = setInterval(() => { 34 | // Document is not visible (browser in the background, different tab, etc.) 35 | if (document.hidden) { return; } 36 | 37 | // Move 1 tick forward (break if it's time) 38 | elapsed += TICK; 39 | if (elapsed < duration) { return; } 40 | 41 | // Stop coalescing timers into this bucket 42 | delete foregroundTimers[duration]; 43 | 44 | // Done with this timer 45 | clearInterval(timer); 46 | 47 | // Execure each callback (in the next event loop) 48 | timers.forEach((c) => { setTimeout(() => { c(); }, 0); }); 49 | }, TICK); 50 | 51 | return; // { _fgTimer: true, timer }; 52 | } 53 | 54 | 55 | // Returns an array of random backers, weigted by total donations 56 | const getBackers = (function() { 57 | 58 | // Load backer data 59 | const backers = Backers.split(",").map((backer) => { 60 | const comps = backer.split("="); 61 | return [ comps[0], parseInt(comps[1]) ]; 62 | }); 63 | const total = backers.reduce((accum, [ name, amount ]) => accum + amount, 0); 64 | 65 | return function (count) { 66 | 67 | // Asking for too many results 68 | if (count >= backers.length) { return backers.map(([ name, amount ]) => name); } 69 | 70 | // The total range to draw from 71 | let remaining = total; 72 | 73 | const result = [ ]; 74 | for (let c = 0; c < count; c++) { 75 | 76 | // Random weighted index to pick 77 | let v = parseInt(Math.random() * remaining); 78 | 79 | // Find that backer 80 | for (let i = 0; i < backers.length; i++) { 81 | const [ name, amount ] = backers[i]; 82 | if (v < amount) { 83 | result.push(name); 84 | backers.splice(i, 1); 85 | v = amount; 86 | break; 87 | } 88 | v -= amount; 89 | } 90 | 91 | // Adjust the randge to draw from 92 | remaining -= v; 93 | } 94 | 95 | return result; 96 | }; 97 | })(); 98 | 99 | // container: div.backers 100 | // items: Array<{ name, image, url? }> 101 | const runZipper = function(container, items, count) { 102 | if (count == null) { count = 6; } 103 | 104 | let nextId = 1; 105 | 106 | const template = document.getElementById("template-zipper-item"); 107 | 108 | function add(item, animated) { 109 | const bucket = template.cloneNode(true); 110 | bucket.id = `zipper-item-${ nextId++ }`; 111 | 112 | let x = 0; 113 | if (container.children.length) { 114 | //console.log(container.lastChild, container.lastChild.style.transform); 115 | x = parseInt(container.lastChild.getAttribute("data-x")) + 100; 116 | } 117 | 118 | bucket.style.transform = `TranslateX(${ x }%)`; 119 | bucket.setAttribute("data-x", x); 120 | 121 | if (item.url) { bucket.setAttribute("href", item.url); } 122 | 123 | const image = bucket.querySelector(".image"); 124 | image.style.background = `url(${ item.image }) center no-repeat`; 125 | image.style.backgroundSize = "contain"; 126 | 127 | if (animated) { 128 | bucket.style.opacity = "0"; 129 | bucket.style.transition = "opacity 0.2s linear 0.5s, transform 0.2s ease-out 0.5s"; 130 | } 131 | 132 | bucket.querySelector(".title").textContent = item.name; 133 | 134 | container.appendChild(bucket); 135 | 136 | if (animated) { 137 | setTimeout(() => { 138 | Array.prototype.forEach.call(container.children, (child, index) => { 139 | const target = (index - 1) * 100; 140 | if (index === 0) { 141 | child.style.transition = "opacity 0.2s linear, transform 0.2s ease-in"; 142 | } else if (child === bucket) { 143 | child.style.transition = "opacity 0.2s linear 0.5s, transform 0.2s ease-out 0.5s"; 144 | } else { 145 | child.style.transition = "opacity 0.3s linear 0.1s, transform 0.5s linear 0.1s"; 146 | } 147 | child.style.opacity = (index === 0) ? "0": "1"; 148 | child.style.transform = `TranslateX(${ target }%)`; 149 | child.setAttribute("data-x", target); 150 | }); 151 | }, 100); 152 | } 153 | 154 | return bucket; 155 | } 156 | 157 | let nextIndex = 0; 158 | let prefetchImage = null; 159 | function nextItem(prefetch) { 160 | const item = items[nextIndex]; 161 | 162 | // Compute the next index 163 | nextIndex = (nextIndex + 1) % items.length; 164 | 165 | // Prefetch the next image 166 | if (prefetch) { 167 | const nextItem = items[nextIndex]; 168 | prefetchImage = new Image(); 169 | prefetchImage.src = nextItem.image; 170 | prefetchImage.onload = function(e) { 171 | //console.log(`Prefetched: ${ nextItem.name }`); 172 | }; 173 | } 174 | 175 | return item; 176 | } 177 | 178 | for (let i = 0; i < count; i++) { add(nextItem(i === (count - 1)), false); } 179 | 180 | function runOnce() { 181 | // Remove the first backer 182 | const bucket = container.firstChild; 183 | setTimeout(() => { bucket.remove(); }, 2000); 184 | 185 | // Add the next backer 186 | const el = add(nextItem(true), true); 187 | setTimeout(() => { 188 | setForegroundTimeout(runOnce, 4000, true); 189 | }, 0); 190 | } 191 | setForegroundTimeout(runOnce, 4000, true); 192 | } 193 | 194 | runZipper(document.getElementById("backers"), getBackers(120).map((name) => ({ 195 | name, 196 | image: `https:/\/gitcoin.co/dynamic/avatar/${ name }`, 197 | url: `https://gitcoin.co/${ name }` 198 | }))); 199 | 200 | runZipper(document.getElementById("projects"), Projects); 201 | -------------------------------------------------------------------------------- /landing/static/st-alchemy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | -------------------------------------------------------------------------------- /landing/static/st-ankr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/static/st-ankr.png -------------------------------------------------------------------------------- /landing/static/st-ankr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /landing/static/st-ethereum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/static/st-ethereum.png -------------------------------------------------------------------------------- /landing/static/st-etherscan.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 17 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /landing/static/st-gitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/landing/static/st-gitcoin.png -------------------------------------------------------------------------------- /landing/static/st-infura.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /landing/static/st-pokt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 18 | 19 | -------------------------------------------------------------------------------- /landing/static/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | color: #1d4c7c; 3 | font-family: sans-serif; 4 | margin: 0; 5 | } 6 | body { 7 | margin: 0; 8 | } 9 | a { 10 | box-sizing: border-box; 11 | } 12 | div { 13 | box-sizing: border-box; 14 | } 15 | 16 | a.link { 17 | color: #3c9cff; 18 | border-bottom: 1px solid #c4e1ff; 19 | text-decoration: none; 20 | } 21 | 22 | a.link:hover { 23 | color: #102b46; 24 | border-bottom: 1px solid #3c9cff; 25 | } 26 | 27 | .social { 28 | display: flex; 29 | flex-flow: row nowrap; 30 | justify-content: space-between; 31 | text-align: right; 32 | top: 20px; 33 | right: 30px; 34 | position: absolute; 35 | width: 170px; 36 | } 37 | 38 | .social a { 39 | display: block; 40 | height: 40px; 41 | opacity: 0.3; 42 | position: relative; 43 | transition: opacity 0.3s linear; 44 | width: 40px; 45 | } 46 | 47 | .social a:hover { 48 | opacity: 1; 49 | transition: opacity 0.1s linear; 50 | } 51 | 52 | .social a .title { 53 | bottom: -20px; 54 | color: #aaa; 55 | font-size: 14px; 56 | font-weight: bold; 57 | left: -30px; 58 | line-height: 30px; 59 | position: absolute; 60 | pointer-events: none; 61 | opacity: 0; 62 | transition: opacity 0.1s linear, transform 0.3s linear; 63 | text-align: center; 64 | width: 100px; 65 | } 66 | 67 | .social a:hover .title { 68 | opacity: 1; 69 | transform: translateY(10px); 70 | } 71 | 72 | .header { 73 | padding: 80px 0 20px; 74 | text-align: center; 75 | } 76 | .header .logo { 77 | background: url(./logo.png) center no-repeat; 78 | background-size: contain; 79 | height: 150px; 80 | text-align: center; 81 | } 82 | 83 | .header .logo a { 84 | line-height: 150px; 85 | display: inline-block; 86 | height: 150px; 87 | text-decoration: none; 88 | width: 250px; 89 | } 90 | 91 | .header .title { 92 | color: #1d4c7c; 93 | font-size: 30px; 94 | } 95 | .header .description { 96 | color: #668; 97 | font-size: 18px; 98 | font-family: sans-serif; 99 | font-style: italic; 100 | letter-spacing: 0.2ex; 101 | padding: 50px 0 10px; 102 | } 103 | 104 | /*.header .description */ 105 | .smile { 106 | font-color: #446; 107 | font-family: monospace; 108 | font-weight: bold; 109 | letter-spacing: 0ex; 110 | } 111 | 112 | .content { 113 | padding: 0 100px; 114 | overflow-x: hidden; 115 | } 116 | 117 | .section { 118 | padding: 30px 0 60px; 119 | } 120 | 121 | .section > .title { 122 | border-top: 1px solid #999; 123 | color: #777; 124 | font-size: 17px; 125 | font-weight: bold; 126 | margin: 0 10% 40px; 127 | padding: 40px 0 20px; 128 | text-align: center; 129 | } 130 | 131 | .about { 132 | color: #aaa; 133 | font-style: italic; 134 | font-size: 20px; 135 | text-align: center; 136 | margin-bottom: 30px; 137 | width: 100%; 138 | } 139 | 140 | .blurb { 141 | font-size: 19px; 142 | line-height: 30px; 143 | margin: 0 0 40px 50%; 144 | transform: translateX(-50%); 145 | width: 600px; 146 | } 147 | 148 | .blurb li { 149 | margin: 10px 0; 150 | } 151 | 152 | .separator { 153 | border-bottom: 1px dashed #bbb; 154 | height: 0; 155 | margin-left: 50%; 156 | margin-bottom: 40px; 157 | transform: translateX(-50%); 158 | width: 400px; 159 | } 160 | 161 | 162 | .buckets { 163 | display: flex; 164 | flex-flow: row nowrap; 165 | justify-content: space-between; 166 | margin-left: 50%; 167 | transform: translateX(-50%); 168 | min-width: 850px; 169 | max-width: 1000px; 170 | width: 100%; 171 | } 172 | 173 | .bucket { 174 | border: 6px solid #ddd; 175 | border-radius: 25px; 176 | color: inherit; 177 | display: block; 178 | font-weight: bold; 179 | height: 175px; 180 | padding: 20px; 181 | position: relative; 182 | text-align: center; 183 | text-decoration: none; 184 | transition: box-shadow 0.2s linear; 185 | width: 175px; 186 | overflow: hidden; 187 | } 188 | 189 | .bucket.inactive { 190 | border: 6px solid #eee; 191 | pointer-events: none; 192 | } 193 | .bucket.inactive div.icon { 194 | opacity: 0.7; 195 | } 196 | .bucket.inactive div.title { 197 | opacity: 0.7; 198 | } 199 | 200 | .bucket:hover { 201 | box-shadow: 0px 0px 20px #ddd; 202 | transition: box-shadow 0.05s linear; 203 | } 204 | 205 | .bucket .icon { 206 | height: 100px; 207 | } 208 | 209 | .bucket .banner { 210 | background: #d55; 211 | border: 2px solid #800; 212 | color: #fff; 213 | box-shadow: 0px 0px 5px #800; 214 | font-size: 16px; 215 | font-weight: bold; 216 | right: 0; 217 | top: 0; 218 | padding: 5px 0; 219 | position: absolute; 220 | transform: translate(25%, 50%) rotate(45deg); 221 | width: 200px; 222 | } 223 | 224 | .bucket-icons { 225 | display: flex; 226 | flex-flow: row wrap; 227 | justify-content: space-between; 228 | margin-left: 50%; 229 | padding-bottom: 20px; 230 | transform: translateX(-50%); 231 | min-width: 400px; 232 | max-width: 1200px; 233 | width: 100%; 234 | } 235 | 236 | .bucket-icons a { 237 | display: block; 238 | flex-grow: 1; 239 | height: 70px; 240 | min-width: 10%; 241 | margin: 0 30px 20px; 242 | position: relative; 243 | width: 50px; 244 | } 245 | 246 | .bucket-icons a .title { 247 | color: #555; 248 | font-size: 14px; 249 | font-weight: bold; 250 | line-height: 20px; 251 | position: absolute; 252 | pointer-events: none; 253 | opacity: 0; 254 | text-align: center; 255 | top: 70px; 256 | transform: translateY(-3px); 257 | transition: opacity 0.1s linear, transform 0.3s linear; 258 | width: 100%; 259 | } 260 | 261 | .bucket-icons a:hover .title { 262 | opacity: 1; 263 | transform: translateY(8px); 264 | } 265 | 266 | /* Sponsors */ 267 | .tier-container { 268 | dddborder: 10px solid black; 269 | display: flex; 270 | flex-flow: row nowrap; 271 | justify-content: space-between; 272 | margin-bottom: 60px; 273 | margin-left: 50%; 274 | min-width: 300px; 275 | max-width: 1000px; 276 | transform: translateX(-50%); 277 | width: 100%; 278 | } 279 | 280 | .tiers { 281 | border-radius: 25px; 282 | display: flex; 283 | flex-flow: row nowrap; 284 | justify-content: space-between; 285 | margin: 0 30px; 286 | padding-left: 50px; 287 | dddmargin-left: 50%; 288 | dddtransform: translateX(-50%); 289 | dddmargin-top: -20px; 290 | dddmargin-bottom: 40px; 291 | dddmin-width: 850px; 292 | dddmax-width: 1000px; 293 | position: relative; 294 | min-width: 300px; 295 | max-width: 1000px; 296 | width: 50%; 297 | } 298 | 299 | .tiers.gold { 300 | background: #fcfce6; 301 | ddbackground: #fcfcd2; 302 | border: 1px solid #898900; 303 | } 304 | 305 | .tiers.silver { 306 | background: #f1f5f5; 307 | ddborder: 1px solid #a8abab; 308 | border: 1px solid #8f9191; 309 | } 310 | 311 | .tiers .label { 312 | font-weight: bold; 313 | height: 175px; 314 | left: 20px; 315 | position: absolute; 316 | text-align: center; 317 | transform: rotate(-90deg); 318 | width: 175px; 319 | } 320 | 321 | .tiers.gold .label { 322 | color: #898900; 323 | } 324 | 325 | .tiers.silver .label { 326 | color: #8f9191; 327 | } 328 | 329 | .sponsor { 330 | ddd-border: 1px solid #000; 331 | ddd-border-radius: 25px; 332 | color: inherit; 333 | display: block; 334 | font-weight: bold; 335 | height: 175px; 336 | padding: 25px 20px 15px 20px; 337 | position: relative; 338 | text-align: center; 339 | text-decoration: none; 340 | transition: box-shadow 0.2s linear; 341 | width: 175px; 342 | overflow: hidden; 343 | } 344 | 345 | .sponsor .icon { 346 | border: 1px solid #898900; 347 | border-radius: 4px; 348 | height: 100px; 349 | margin-left: calc(87px - 50%); 350 | width: 100px; 351 | } 352 | 353 | .sponsor.no-border .icon { 354 | border: none; 355 | } 356 | 357 | .icon-sponsor-tally { 358 | background: url(/sponsors/tally.jpg) center no-repeat; 359 | background-size: contain; 360 | } 361 | .icon-sponsor-ankr { 362 | background: url(/sponsors/ankr.png) center no-repeat; 363 | background-size: contain; 364 | } 365 | 366 | .sponsor .title { 367 | padding-top: 10px; 368 | } 369 | 370 | .sponsor-about { 371 | font-style: italic; 372 | font-size: 20px; 373 | height: 175px; 374 | line-height: 175px; 375 | text-align: center; 376 | width: 50%; 377 | } 378 | 379 | /* Zipper */ 380 | 381 | .zipper { 382 | height: 110px; 383 | margin-left: 50%; 384 | padding-bottom: 20px; 385 | position: relative; 386 | transform: translateX(-50%); 387 | min-width: 600px; 388 | max-width: 1200px; 389 | width: 100%; 390 | } 391 | 392 | .zipper > a { 393 | display: block; 394 | height: 70px; 395 | margin: 0 0px 20px; 396 | position: absolute; 397 | transition: opacity 0.3s linear, transform 0.2s ease-in; 398 | width: 16.6%; 399 | } 400 | 401 | .zipper .image { 402 | box-sizing: border-box; 403 | height: 70px; 404 | margin-left: 50%; 405 | transform: translateX(-50%); 406 | width: 70px; 407 | } 408 | 409 | .zipper .title { 410 | color: #777; 411 | font-size: 14px; 412 | font-weight: bold; 413 | left: 50%; 414 | line-height: 20px; 415 | opacity: 0; 416 | pointer-events: none; 417 | position: absolute; 418 | text-align: center; 419 | transform: translate(-50%, -2px); 420 | transition: opacity 0.1s linear, transform 0.3s linear; 421 | width: 200px; 422 | } 423 | 424 | .zipper a:hover .title { 425 | opacity: 1; 426 | transform: translate(-50%, 8px); 427 | } 428 | 429 | 430 | /* Section-specific Zipper Config */ 431 | 432 | #backers .image { 433 | border: 2px solid #555; 434 | border-radius: 35px; 435 | } 436 | 437 | #projects .image { 438 | border-radius: 5px; 439 | } 440 | 441 | 442 | /* Copyright */ 443 | 444 | .copyright { 445 | border-top: 1px solid #999; 446 | font-size: 12px; 447 | margin: 0 10% 20px; 448 | padding: 40px 0 30px; 449 | text-align: center; 450 | } 451 | 452 | 453 | /* Icons */ 454 | 455 | .icon-discord { 456 | background: url(./icon-discord.svg) center no-repeat; 457 | background-size: contain; 458 | } 459 | .icon-github { 460 | background: url(./icon-github.svg) center no-repeat; 461 | background-size: contain; 462 | } 463 | .icon-twitter { 464 | background: url(./icon-twitter.svg) center no-repeat; 465 | background-size: contain; 466 | } 467 | 468 | .icon-docs { 469 | background: url(./icon-docs.svg) center no-repeat; 470 | background-size: contain; 471 | } 472 | .icon-toolbox { 473 | background: url(./icon-toolbox.svg) center no-repeat; 474 | background-size: contain; 475 | } 476 | .icon-playground { 477 | background: url(./icon-playground.svg) center no-repeat; 478 | background-size: contain; 479 | } 480 | .icon-wallet { 481 | background: url(./icon-wallet.svg) center no-repeat; 482 | background-size: contain; 483 | } 484 | 485 | .icon-st-ethereum { 486 | background: url(./st-ethereum.png) center no-repeat; 487 | background-size: contain; 488 | } 489 | .icon-st-gitcoin { 490 | background: url(./st-gitcoin.png) center no-repeat; 491 | background-size: contain; 492 | } 493 | 494 | .icon-st-etherscan { 495 | background: url(./st-etherscan.svg) center no-repeat; 496 | background-size: contain; 497 | } 498 | .icon-st-infura { 499 | background: url(./st-infura.svg) center no-repeat; 500 | background-size: contain; 501 | } 502 | .icon-st-alchemy { 503 | background: url(./st-alchemy.svg) center no-repeat; 504 | background-size: contain; 505 | } 506 | .icon-st-pokt { 507 | background: url(./st-pokt.svg) center no-repeat; 508 | background-size: contain; 509 | } 510 | .icon-st-ankr { 511 | background: url(./st-ankr.png) center no-repeat; 512 | background-size: contain; 513 | } 514 | 515 | -------------------------------------------------------------------------------- /playground/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/playground/favicon.ico -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | ethers playground 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
29 |
30 |
31 | 32 |
Sizer Content
33 |
34 |
35 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /playground/inspect.js: -------------------------------------------------------------------------------- 1 | const inspect = (function(global) { 2 | 3 | var hasMap = typeof Map === 'function' && Map.prototype; 4 | var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null; 5 | var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null; 6 | var mapForEach = hasMap && Map.prototype.forEach; 7 | var hasSet = typeof Set === 'function' && Set.prototype; 8 | var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null; 9 | var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null; 10 | var setForEach = hasSet && Set.prototype.forEach; 11 | var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype; 12 | var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null; 13 | var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype; 14 | var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null; 15 | var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype; 16 | var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null; 17 | var booleanValueOf = Boolean.prototype.valueOf; 18 | var objectToString = Object.prototype.toString; 19 | var functionToString = Function.prototype.toString; 20 | var match = String.prototype.match; 21 | var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null; 22 | var gOPS = Object.getOwnPropertySymbols; 23 | var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null; 24 | var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object'; 25 | var isEnumerable = Object.prototype.propertyIsEnumerable; 26 | 27 | var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || ( 28 | [].__proto__ === Array.prototype // eslint-disable-line no-proto 29 | ? function (O) { 30 | return O.__proto__; // eslint-disable-line no-proto 31 | } 32 | : null 33 | ); 34 | 35 | var inspectCustom = Symbol.for("nodejs.util.inspect.custom"); //require('./util.inspect').custom; 36 | var inspectSymbol = inspectCustom && isSymbol(inspectCustom) ? inspectCustom : null; 37 | var toStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag !== 'undefined' ? Symbol.toStringTag : null; 38 | 39 | global.exports = function inspect_(obj, options, depth, seen) { 40 | var opts = options || {}; 41 | 42 | if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) { 43 | throw new TypeError('option "quoteStyle" must be "single" or "double"'); 44 | } 45 | if ( 46 | has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number' 47 | ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity 48 | : opts.maxStringLength !== null 49 | ) 50 | ) { 51 | throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`'); 52 | } 53 | var customInspect = has(opts, 'customInspect') ? opts.customInspect : true; 54 | if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') { 55 | throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`'); 56 | } 57 | 58 | if ( 59 | has(opts, 'indent') 60 | && opts.indent !== null 61 | && opts.indent !== '\t' 62 | && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0) 63 | ) { 64 | throw new TypeError('options "indent" must be "\\t", an integer > 0, or `null`'); 65 | } 66 | 67 | if (typeof obj === 'undefined') { 68 | return 'undefined'; 69 | } 70 | if (obj === null) { 71 | return 'null'; 72 | } 73 | if (typeof obj === 'boolean') { 74 | return obj ? 'true' : 'false'; 75 | } 76 | 77 | if (typeof obj === 'string') { 78 | return inspectString(obj, opts); 79 | } 80 | if (typeof obj === 'number') { 81 | if (obj === 0) { 82 | return Infinity / obj > 0 ? '0' : '-0'; 83 | } 84 | return String(obj); 85 | } 86 | if (typeof obj === 'bigint') { 87 | return String(obj) + 'n'; 88 | } 89 | 90 | var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth; 91 | if (typeof depth === 'undefined') { depth = 0; } 92 | if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') { 93 | return isArray(obj) ? '[Array]' : '[Object]'; 94 | } 95 | 96 | var indent = getIndent(opts, depth); 97 | 98 | if (typeof seen === 'undefined') { 99 | seen = []; 100 | } else if (indexOf(seen, obj) >= 0) { 101 | return '[Circular]'; 102 | } 103 | 104 | function inspect(value, from, noIndent) { 105 | if (from) { 106 | seen = seen.slice(); 107 | seen.push(from); 108 | } 109 | if (noIndent) { 110 | var newOpts = { 111 | depth: opts.depth 112 | }; 113 | if (has(opts, 'quoteStyle')) { 114 | newOpts.quoteStyle = opts.quoteStyle; 115 | } 116 | return inspect_(value, newOpts, depth + 1, seen); 117 | } 118 | return inspect_(value, opts, depth + 1, seen); 119 | } 120 | 121 | if (typeof obj === 'function') { 122 | var name = nameOf(obj); 123 | var keys = arrObjKeys(obj, inspect); 124 | return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + keys.join(', ') + ' }' : ''); 125 | } 126 | if (isSymbol(obj)) { 127 | var symString = hasShammedSymbols ? String(obj).replace(/^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj); 128 | return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString; 129 | } 130 | if (isElement(obj)) { 131 | var s = '<' + String(obj.nodeName).toLowerCase(); 132 | var attrs = obj.attributes || []; 133 | for (var i = 0; i < attrs.length; i++) { 134 | s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts); 135 | } 136 | s += '>'; 137 | if (obj.childNodes && obj.childNodes.length) { s += '...'; } 138 | s += ''; 139 | return s; 140 | } 141 | if (isArray(obj)) { 142 | if (obj.length === 0) { return '[]'; } 143 | var xs = arrObjKeys(obj, inspect); 144 | if (indent && !singleLineValues(xs)) { 145 | return '[' + indentedJoin(xs, indent) + ']'; 146 | } 147 | return '[ ' + xs.join(', ') + ' ]'; 148 | } 149 | if (isError(obj)) { 150 | var parts = arrObjKeys(obj, inspect); 151 | if (parts.length === 0) { return '[' + String(obj) + ']'; } 152 | return '{ [' + String(obj) + '] ' + parts.join(', ') + ' }'; 153 | } 154 | if (typeof obj === 'object' && customInspect) { 155 | if (inspectSymbol && typeof obj[inspectSymbol] === 'function') { 156 | var result = obj[inspectSymbol](); 157 | if (result && typeof(result) === "object" && result.name && result.values) { 158 | var ys = arrObjKeys(result.values, inspect); 159 | if (ys.length === 0) { return result.name + ' {}'; } 160 | if (indent) { 161 | return result.name + ' {' + indentedJoin(ys, indent) + '}'; 162 | } 163 | return result.name + ' { ' + ys.join(', ') + ' }'; 164 | } 165 | return result; 166 | } else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') { 167 | return obj.inspect(); 168 | } 169 | } 170 | if (isMap(obj)) { 171 | var mapParts = []; 172 | mapForEach.call(obj, function (value, key) { 173 | mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj)); 174 | }); 175 | return collectionOf('Map', mapSize.call(obj), mapParts, indent); 176 | } 177 | if (isSet(obj)) { 178 | var setParts = []; 179 | setForEach.call(obj, function (value) { 180 | setParts.push(inspect(value, obj)); 181 | }); 182 | return collectionOf('Set', setSize.call(obj), setParts, indent); 183 | } 184 | if (isWeakMap(obj)) { 185 | return weakCollectionOf('WeakMap'); 186 | } 187 | if (isWeakSet(obj)) { 188 | return weakCollectionOf('WeakSet'); 189 | } 190 | if (isWeakRef(obj)) { 191 | return weakCollectionOf('WeakRef'); 192 | } 193 | if (isNumber(obj)) { 194 | return markBoxed(inspect(Number(obj))); 195 | } 196 | if (isBigInt(obj)) { 197 | return markBoxed(inspect(bigIntValueOf.call(obj))); 198 | } 199 | if (isBoolean(obj)) { 200 | return markBoxed(booleanValueOf.call(obj)); 201 | } 202 | if (isString(obj)) { 203 | return markBoxed(inspect(String(obj))); 204 | } 205 | if (!isDate(obj) && !isRegExp(obj)) { 206 | var ys = arrObjKeys(obj, inspect); 207 | var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object; 208 | var protoTag = obj instanceof Object ? '' : 'null prototype'; 209 | var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? toStr(obj).slice(8, -1) : protoTag ? 'Object' : ''; 210 | var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : ''; 211 | var tag = constructorTag + (stringTag || protoTag ? '[' + [].concat(stringTag || [], protoTag || []).join(': ') + '] ' : ''); 212 | if (ys.length === 0) { return tag + '{}'; } 213 | if (indent) { 214 | return tag + '{' + indentedJoin(ys, indent) + '}'; 215 | } 216 | return tag + '{ ' + ys.join(', ') + ' }'; 217 | } 218 | return String(obj); 219 | }; 220 | 221 | function wrapQuotes(s, defaultStyle, opts) { 222 | var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '"' : "'"; 223 | return quoteChar + s + quoteChar; 224 | } 225 | 226 | function quote(s) { 227 | return String(s).replace(/"/g, '"'); 228 | } 229 | 230 | function isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 231 | function isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 232 | function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 233 | function isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 234 | function isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 235 | function isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 236 | function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); } 237 | 238 | // Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives 239 | function isSymbol(obj) { 240 | if (hasShammedSymbols) { 241 | return obj && typeof obj === 'object' && obj instanceof Symbol; 242 | } 243 | if (typeof obj === 'symbol') { 244 | return true; 245 | } 246 | if (!obj || typeof obj !== 'object' || !symToString) { 247 | return false; 248 | } 249 | try { 250 | symToString.call(obj); 251 | return true; 252 | } catch (e) {} 253 | return false; 254 | } 255 | 256 | function isBigInt(obj) { 257 | if (!obj || typeof obj !== 'object' || !bigIntValueOf) { 258 | return false; 259 | } 260 | try { 261 | bigIntValueOf.call(obj); 262 | return true; 263 | } catch (e) {} 264 | return false; 265 | } 266 | 267 | var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; }; 268 | function has(obj, key) { 269 | return hasOwn.call(obj, key); 270 | } 271 | 272 | function toStr(obj) { 273 | return objectToString.call(obj); 274 | } 275 | 276 | function nameOf(f) { 277 | if (f.name) { return f.name; } 278 | var m = match.call(functionToString.call(f), /^function\s*([\w$]+)/); 279 | if (m) { return m[1]; } 280 | return null; 281 | } 282 | 283 | function indexOf(xs, x) { 284 | if (xs.indexOf) { return xs.indexOf(x); } 285 | for (var i = 0, l = xs.length; i < l; i++) { 286 | if (xs[i] === x) { return i; } 287 | } 288 | return -1; 289 | } 290 | 291 | function isMap(x) { 292 | if (!mapSize || !x || typeof x !== 'object') { 293 | return false; 294 | } 295 | try { 296 | mapSize.call(x); 297 | try { 298 | setSize.call(x); 299 | } catch (s) { 300 | return true; 301 | } 302 | return x instanceof Map; // core-js workaround, pre-v2.5.0 303 | } catch (e) {} 304 | return false; 305 | } 306 | 307 | function isWeakMap(x) { 308 | if (!weakMapHas || !x || typeof x !== 'object') { 309 | return false; 310 | } 311 | try { 312 | weakMapHas.call(x, weakMapHas); 313 | try { 314 | weakSetHas.call(x, weakSetHas); 315 | } catch (s) { 316 | return true; 317 | } 318 | return x instanceof WeakMap; // core-js workaround, pre-v2.5.0 319 | } catch (e) {} 320 | return false; 321 | } 322 | 323 | function isWeakRef(x) { 324 | if (!weakRefDeref || !x || typeof x !== 'object') { 325 | return false; 326 | } 327 | try { 328 | weakRefDeref.call(x); 329 | return true; 330 | } catch (e) {} 331 | return false; 332 | } 333 | 334 | function isSet(x) { 335 | if (!setSize || !x || typeof x !== 'object') { 336 | return false; 337 | } 338 | try { 339 | setSize.call(x); 340 | try { 341 | mapSize.call(x); 342 | } catch (m) { 343 | return true; 344 | } 345 | return x instanceof Set; // core-js workaround, pre-v2.5.0 346 | } catch (e) {} 347 | return false; 348 | } 349 | 350 | function isWeakSet(x) { 351 | if (!weakSetHas || !x || typeof x !== 'object') { 352 | return false; 353 | } 354 | try { 355 | weakSetHas.call(x, weakSetHas); 356 | try { 357 | weakMapHas.call(x, weakMapHas); 358 | } catch (s) { 359 | return true; 360 | } 361 | return x instanceof WeakSet; // core-js workaround, pre-v2.5.0 362 | } catch (e) {} 363 | return false; 364 | } 365 | 366 | function isElement(x) { 367 | if (!x || typeof x !== 'object') { return false; } 368 | if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) { 369 | return true; 370 | } 371 | return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function'; 372 | } 373 | 374 | function inspectString(str, opts) { 375 | if (str.length > opts.maxStringLength) { 376 | var remaining = str.length - opts.maxStringLength; 377 | var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : ''); 378 | return inspectString(str.slice(0, opts.maxStringLength), opts) + trailer; 379 | } 380 | // eslint-disable-next-line no-control-regex 381 | var s = str.replace(/(['\\])/g, '\\$1').replace(/[\x00-\x1f]/g, lowbyte); 382 | return wrapQuotes(s, 'single', opts); 383 | } 384 | 385 | function lowbyte(c) { 386 | var n = c.charCodeAt(0); 387 | var x = { 388 | 8: 'b', 389 | 9: 't', 390 | 10: 'n', 391 | 12: 'f', 392 | 13: 'r' 393 | }[n]; 394 | if (x) { return '\\' + x; } 395 | return '\\x' + (n < 0x10 ? '0' : '') + n.toString(16).toUpperCase(); 396 | } 397 | 398 | function markBoxed(str) { 399 | return 'Object(' + str + ')'; 400 | } 401 | 402 | function weakCollectionOf(type) { 403 | return type + ' { ? }'; 404 | } 405 | 406 | function collectionOf(type, size, entries, indent) { 407 | var joinedEntries = indent ? indentedJoin(entries, indent) : entries.join(', '); 408 | return type + ' (' + size + ') {' + joinedEntries + '}'; 409 | } 410 | 411 | function singleLineValues(xs) { 412 | for (var i = 0; i < xs.length; i++) { 413 | if (indexOf(xs[i], '\n') >= 0) { 414 | return false; 415 | } 416 | } 417 | return true; 418 | } 419 | 420 | function getIndent(opts, depth) { 421 | var baseIndent; 422 | if (opts.indent === '\t') { 423 | baseIndent = '\t'; 424 | } else if (typeof opts.indent === 'number' && opts.indent > 0) { 425 | baseIndent = Array(opts.indent + 1).join(' '); 426 | } else { 427 | return null; 428 | } 429 | return { 430 | base: baseIndent, 431 | prev: Array(depth + 1).join(baseIndent) 432 | }; 433 | } 434 | 435 | function indentedJoin(xs, indent) { 436 | if (xs.length === 0) { return ''; } 437 | var lineJoiner = '\n' + indent.prev + indent.base; 438 | return lineJoiner + xs.join(',' + lineJoiner) + '\n' + indent.prev; 439 | } 440 | 441 | function arrObjKeys(obj, inspect) { 442 | var isArr = isArray(obj); 443 | var xs = []; 444 | if (isArr) { 445 | xs.length = obj.length; 446 | for (var i = 0; i < obj.length; i++) { 447 | xs[i] = has(obj, i) ? inspect(obj[i], obj) : ''; 448 | } 449 | } 450 | var syms = typeof gOPS === 'function' ? gOPS(obj) : []; 451 | var symMap; 452 | if (hasShammedSymbols) { 453 | symMap = {}; 454 | for (var k = 0; k < syms.length; k++) { 455 | symMap['$' + syms[k]] = syms[k]; 456 | } 457 | } 458 | 459 | for (var key in obj) { // eslint-disable-line no-restricted-syntax 460 | if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue 461 | if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue 462 | if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) { 463 | // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section 464 | continue; // eslint-disable-line no-restricted-syntax, no-continue 465 | } else if ((/[^\w$]/).test(key)) { 466 | xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj)); 467 | } else { 468 | xs.push(key + ': ' + inspect(obj[key], obj)); 469 | } 470 | } 471 | if (typeof gOPS === 'function') { 472 | for (var j = 0; j < syms.length; j++) { 473 | if (isEnumerable.call(obj, syms[j])) { 474 | xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj)); 475 | } 476 | } 477 | } 478 | return xs; 479 | } 480 | 481 | function NamedObject(name, values) { 482 | this.name = name; 483 | this.values = values; 484 | } 485 | 486 | const sandboxInspect = function(obj) { 487 | return exports(obj, { 488 | quoteStyle: "double", 489 | indent: 2 490 | }); 491 | }; 492 | 493 | Object.defineProperty(sandboxInspect, "custom", { 494 | configurable: false, 495 | enumerable: true, 496 | writable: false, 497 | value: inspectCustom 498 | }); 499 | 500 | Object.defineProperty(sandboxInspect, "NamedObject", { 501 | configurable: false, 502 | enumerable: true, 503 | writable: false, 504 | value: NamedObject 505 | }); 506 | 507 | return sandboxInspect; 508 | 509 | })(self); 510 | -------------------------------------------------------------------------------- /playground/og-preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethers-io/website/c3e460cbb2e79be7369201ed47d2bc097a7dc3bd/playground/og-preview.jpg -------------------------------------------------------------------------------- /playground/sandbox.js: -------------------------------------------------------------------------------- 1 | importScripts("https:\/\/cdnjs.cloudflare.com/ajax/libs/ethers/6.13.2/ethers.umd.min.js"); 2 | importScripts("./inspect.js"); 3 | importScripts("./help.js"); 4 | 5 | /** 6 | * Communication Packets for two-way communication 7 | * 8 | * Action; sends a request which expects a Response 9 | * - { action: string, id: number, params: object } 10 | * Notce; sends a one-way notification 11 | * - { notice: string, params: object } 12 | * Response; the response to an earlier Action 13 | * - { id: number, result: any } 14 | */ 15 | 16 | let _ = undefined; 17 | let _p = undefined; 18 | 19 | // Debug 20 | //self.w = ethers.Wallet.createRandom(); 21 | 22 | const { _onMessage, ethereum } = (function({ Basic, Globals, Help, Returns }, evalFunc) { 23 | 24 | class Eip1193PassThrough { 25 | constructor() { } 26 | 27 | async request(params) { 28 | const resp = await send("provider", params); 29 | if (resp.error) { 30 | throw new Error(resp.error); 31 | } 32 | return resp.result; 33 | } 34 | 35 | on() { 36 | throw new Error("not implemented yet; coming soon"); 37 | } 38 | } 39 | 40 | const lookupClass = new Map(); 41 | Help.forEach((info) => { 42 | if (info.cls) { lookupClass.set(info.cls, info); } 43 | if (info.func) { lookupClass.set(info.func, info); } 44 | }); 45 | 46 | class Follower { 47 | 48 | // descr: 49 | // - name 50 | // - returns: Returns; used to determine follow 51 | // - display? 52 | // - params?: Array 53 | 54 | constructor(descr) { 55 | if (typeof(descr) === "string") { 56 | descr = { name }; 57 | } else { 58 | descr = Object.assign({ }, descr); 59 | } 60 | 61 | descr.display = descr.insert = descr.name; 62 | 63 | // It's a function, dress it up 64 | if (descr.params) { 65 | descr.display += "()"; 66 | descr.insert = descr.name + "(" + descr.params.reduce((accum, p) => { 67 | if (p[0] !== "%") { 68 | accum.push(`%${ p }`); 69 | } else if (p.indexOf("=") >= 0) { 70 | accum.push(p.substring(p.indexOf("=") + 1).trim()); 71 | } 72 | return accum; 73 | }, [ ]).join(", ") + ")"; 74 | } 75 | 76 | // Unknown return type 77 | if (!descr.returns) { descr.returns = new Returns("_"); } 78 | 79 | this._descr = descr; 80 | } 81 | 82 | descr(options) { return this._descr; } 83 | 84 | keys() { return [ ]; } 85 | 86 | follow() { return null; } 87 | 88 | toString() { 89 | return `<${ this.constructor.name } descr="${ JSON.stringify(this.descr) }" keys=(${ this.keys().join(", ") })>`; 90 | } 91 | 92 | // This will always returns a DotFollower or CallFollower? 93 | static from(name, value) { 94 | 95 | if (value == null) { return null; } 96 | 97 | if (value.returns && value.returns instanceof Returns) { 98 | //if (value.returns.type === "class") { 99 | // return new ClassFollower(); 100 | //} 101 | let follower = new PropsFollower(Object.assign({ name }, value), value.returns.props()); 102 | if (value.params) { 103 | return new CallFollower(follower); 104 | } 105 | return new DotFollower(follower); 106 | } 107 | 108 | let match = lookupClass.get(value); 109 | if (match) { 110 | // In case they use hexx = hexlify, allow the new thing to know 111 | const renamed = Object.assign({ }, match, { name }); 112 | 113 | // A class we provide 114 | if (match.cls) { return new ClassFollower(renamed); } 115 | 116 | // A function we provide 117 | if (match.func) { return Follower.from(name, renamed); } 118 | 119 | throw new Error("hmm..."); 120 | } 121 | 122 | // An instance of a class we provide 123 | match = lookupClass.get(value.constructor); 124 | if (match && match.cls) { 125 | const properties = Object.assign({ }, match.properties); 126 | for (const key in value) { 127 | if (!(key in properties)) { 128 | properties[key] = { returns: Returns.from("_") }; 129 | } 130 | } 131 | return new DotFollower(new PropsFollower({ 132 | name: name, 133 | returns: Returns.from(match.name) 134 | }, properties)); 135 | } 136 | 137 | // Something basic 138 | const returns = Returns.fromBasic(value); 139 | if (returns) { 140 | return new DotFollower(new PropsFollower({ 141 | name, returns 142 | }, returns.props())); 143 | } 144 | 145 | // Something else 146 | return new DotFollower(new ObjectFollower(name, value)); 147 | } 148 | } 149 | 150 | class StateFollower extends Follower { 151 | constructor(descr, followers) { 152 | super(descr); 153 | this.followers = followers; 154 | } 155 | 156 | follow(key) { 157 | return this.followers[key] || null; 158 | } 159 | 160 | toString() { 161 | const followers = Object.keys(this.followers).map((key) => { 162 | return `${ JSON.stringify(key) }=${ this.followers[key].toString() }`; 163 | }); 164 | return `<${ this.constructor.name } ${ followers.join("\n ") })>`; 165 | } 166 | } 167 | 168 | class DotFollower extends StateFollower { 169 | constructor(follower) { super(follower.descr(), { ".": follower }); } 170 | } 171 | 172 | class CallFollower extends StateFollower { 173 | constructor(follower) { 174 | super(follower.descr(), { "()": new DotFollower(follower) }); 175 | } 176 | } 177 | 178 | class ClassFollower extends StateFollower { 179 | constructor(help) { 180 | const name = help.name; 181 | 182 | const dotFollower = new PropsFollower({ 183 | name, returns: Returns.from(help.cls) 184 | }, help.staticProperties); 185 | 186 | const callFollower = new DotFollower(new PropsFollower({ 187 | name, params: help.params, returns: Returns.from(help.name) 188 | }, help.properties)); 189 | 190 | super(dotFollower.descr(), { 191 | ".": dotFollower, 192 | "()": callFollower 193 | }); 194 | 195 | this.help = help; 196 | } 197 | 198 | descr(options) { 199 | if (options && options.newing) { 200 | return this.follow("()").descr(); 201 | } 202 | return super.descr(options); 203 | } 204 | } 205 | 206 | /* 207 | class ContractFollower extends Follower { 208 | constructor(contract) { 209 | super({ returns: Returns.from("Contract") }); 210 | } 211 | 212 | keys() { 213 | const keys = [ "address" ]; 214 | // populateTransaction, staticCall, estimateGas 215 | } 216 | 217 | follow(key) { 218 | } 219 | } 220 | */ 221 | 222 | class PropsFollower extends Follower { 223 | constructor(descr, props) { 224 | super(descr); 225 | this._props = props; 226 | } 227 | 228 | keys() { return Object.keys(this._props); } 229 | 230 | follow(key) { 231 | return Follower.from(key, Object.assign({ name: key }, this._props[key])); 232 | } 233 | } 234 | 235 | class ObjectFollower extends Follower { 236 | constructor(name, object) { 237 | super({ name, returns: Returns.from("_") }); 238 | this.object = Object.assign({ }, object); 239 | } 240 | 241 | add(object) { 242 | Object.keys(object).forEach((key) => { 243 | this.object[key] = object[key]; 244 | }); 245 | } 246 | 247 | keys() { return Object.keys(this.object); } 248 | 249 | follow(key) { 250 | if (!(key in this.object)) { return null; } 251 | return Follower.from(key, this.object[key]); 252 | } 253 | } 254 | 255 | function findMatches(tokens) { 256 | //console.log("FIND"); /// DEBUG 257 | 258 | let follower = new Follower(); 259 | let allowed = [ "ROOT" ]; 260 | 261 | let descrOptions = { }; 262 | 263 | while(follower && tokens.length) { 264 | const token = tokens.pop(); 265 | //console.log("TOKEN", token.token, token.text, follower.toString()); ///DEBUG 266 | 267 | if (token.token === "CURSOR") { 268 | //console.internal(token); 269 | const prefix = token.text; 270 | 271 | const matches = follower.keys().reduce((accum, key) => { 272 | if (key.substring(0, prefix.length) === prefix) { 273 | const next = follower.follow(key); 274 | if (next) { accum.push(next.descr(descrOptions)); } 275 | } 276 | return accum; 277 | }, [ ]); 278 | 279 | return { offset: token.offset, width: (token.width + token.precog.length), precog: token.precog, matches}; 280 | } 281 | 282 | if (allowed.indexOf(token.token) === -1) { 283 | //console.internal("Expected:", allowed, "Got:", token); 284 | follower = null; 285 | break; 286 | } 287 | 288 | switch (token.token) { 289 | case "ROOT": 290 | allowed = [ "IDENTIFIER", "NEW", "AWAIT" ]; 291 | follower = new ObjectFollower("self", self); 292 | follower.add(Globals); 293 | break; 294 | 295 | case "DOT": 296 | follower = follower.follow("."); 297 | allowed = [ "IDENTIFIER" ]; 298 | break; 299 | 300 | case "NEW": 301 | allowed = [ "IDENTIFIER" ]; 302 | descrOptions.newing = true 303 | break; 304 | 305 | case "AWAIT": 306 | allowed = [ "IDENTIFIER" ]; 307 | descrOptions.awaiting = true 308 | break; 309 | 310 | case "IDENTIFIER": 311 | allowed = [ "DOT", "PAREN", "BRACKET" ]; 312 | follower = follower.follow(token.text); 313 | break; 314 | 315 | case "PAREN": 316 | allowed = [ "DOT" ]; 317 | follower = follower.follow("()"); 318 | descrOptions.newing = false; 319 | descrOptions.awaiting = false; 320 | break; 321 | 322 | case "BRACKET": 323 | allowed = [ "DOT" ]; 324 | break; 325 | } 326 | } 327 | 328 | return null; 329 | } 330 | 331 | /* 332 | function getInspect(value) { 333 | if (value == null) { return null }; 334 | 335 | for (const name in ethers.providers) { 336 | const klass = ethers.providers[name]; 337 | if (klass === value) { 338 | return { type: "Class", name }; 339 | } 340 | } 341 | 342 | for (const name in ethers.providers) { 343 | const klass = ethers.providers[name]; 344 | if (klass && klass === value.constructor) { return { type: name }; } 345 | } 346 | 347 | if (ethers.BigNumber.isBigNumber(value)) { 348 | return { type: "BigNumber" }; 349 | } 350 | 351 | if (Array.isArray(value)) { 352 | return { type: "array", length: value.length }; 353 | } 354 | 355 | if (typeof(value) === "object") { 356 | return { type: "object", keys: Object.keys(value) }; 357 | } 358 | 359 | return typeof(value); 360 | } 361 | */ 362 | 363 | function _getSigners() { 364 | return [ ]; 365 | } 366 | 367 | function S(v) { return JSON.stringify(v); } 368 | function post(v) { postMessage(S(v)); } 369 | 370 | let nextId = 1; 371 | const resolveMap = { }; 372 | function send(action, params) { 373 | const id = nextId++; 374 | post({ action, id, params }); 375 | return new Promise((resolve) => { 376 | resolveMap[String(id)] = resolve; 377 | }); 378 | } 379 | 380 | async function handleAction(action, params) { 381 | 382 | if (action === "eval") { 383 | 384 | let result = null; 385 | try { 386 | result = evalFunc(params.code); 387 | } catch (error) { 388 | if (error instanceof SyntaxError && params.asyncExpr) { 389 | return { sync: "sync", type: "error", value: JSON.stringify(error.message), note: "NB: only expressions are allowed if using `await` (no statements)", error: inspect(error) }; 390 | } 391 | return { sync: "sync", type: "error", value: JSON.stringify(error.message), error: inspect(error) }; 392 | } 393 | 394 | _ = result; 395 | _p = undefined; 396 | 397 | if (result instanceof Promise) { 398 | post({ notice: "async-running", id: id }); 399 | return await result.then((result) => { 400 | if (params.asyncExpr) { _ = result; } 401 | _p = result; 402 | return { sync: "async", type: "result", value: inspect(result) }; 403 | }, (error) => { 404 | _p = error; 405 | return { sync: "async", type: "error", value: JSON.stringify(error.message), error: inspect(error) }; 406 | }); 407 | 408 | } else { 409 | return { sync: "sync", type: "result", value: inspect(result) }; 410 | } 411 | 412 | } else if (action === "inspect") { 413 | return findMatches(params.tokens); 414 | } 415 | } 416 | 417 | function handleNotice(notice, params) { 418 | } 419 | 420 | function _onMessage(e) { 421 | const data = JSON.parse(e.data); 422 | const id = data.id; 423 | 424 | if (data.result) { 425 | const resolve = resolveMap[String(id)]; 426 | 427 | if (resolve) { 428 | delete resolveMap[String(id)]; 429 | resolve(data.result); 430 | } else { 431 | console.log(`result for ${ id } with no resolver`); 432 | } 433 | 434 | } else if (data.notice) { 435 | handleNotice(data.notice, data.params || { }); 436 | 437 | } else if (data.action) { 438 | handleAction(data.action, data.params || { }).then((result) => {; 439 | post({ id, result }); 440 | }, (error) => { 441 | console.internal(error); 442 | console.internal(error.stack); 443 | }); 444 | } 445 | } 446 | 447 | const ethereum = new Eip1193PassThrough(); 448 | 449 | // Set up the console 450 | ["log", "warn", "error"].forEach((logger) => { 451 | const log = console[logger].bind(console); 452 | console[logger] = function(...args) { 453 | log(...args); 454 | post({ notice: "log", params: { logger, args: args.map(inspect) } }); 455 | }; 456 | }); 457 | 458 | Object.defineProperty(console, "internal", { 459 | configurable: false, 460 | enumerable: true, 461 | value: (function (...args) { 462 | post({ notice: "internal", params: { args: args.map(inspect) }}); 463 | }) 464 | }); 465 | 466 | // Expose all Ethers function, classes and constants 467 | for (const key in ethers) { 468 | self[key] = ethers[key]; 469 | } 470 | 471 | // Some convenient things to expose 472 | abiCoder = ethers.AbiCoder.defaultAbiCoder(); 473 | provider = ethers.getDefaultProvider(); 474 | 475 | 476 | // Pretty Format some common ethers classes 477 | 478 | Help.forEach((help) => { 479 | if (!help.cls || !help.inspect) { return; } 480 | help.cls.prototype[inspect.custom] = function() { 481 | return inspect(help.inspect.call(this)); 482 | } 483 | }); 484 | 485 | Uint8Array.prototype[inspect.custom] = function() { 486 | return `Uint8Array { ${ Array.prototype.map.call(this, (i) => String(i)).join(", ") } }`; 487 | }; 488 | 489 | /* 490 | ethers.providers.AlchemyProvider.prototype[inspect.custom] = function() { 491 | return new inspect.NamedObject(this.constructor.name, { 492 | network: this._network.name, 493 | url: this.connection.url, 494 | apiKey: (this.isCommunityResource() ? "default": this.apiKey) 495 | }); 496 | }; 497 | 498 | ethers.providers.CloudflareProvider.prototype[inspect.custom] = function() { 499 | return new inspect.NamedObject(this.constructor.name, { 500 | network: this._network.name, 501 | url: this.connection.url 502 | }); 503 | }; 504 | 505 | ethers.providers.EtherscanProvider.prototype[inspect.custom] = function() { 506 | return new inspect.NamedObject(this.constructor.name, { 507 | network: this._network.name, 508 | baseUrl: this.baseUrl, 509 | apiKey: this.isCommunityResource() ? "default": this.apiKey 510 | }); 511 | }; 512 | 513 | ethers.providers.FallbackProvider.prototype[inspect.custom] = function() { 514 | return new inspect.NamedObject(this.constructor.name, { 515 | network: this._network.name, 516 | anyNetwork: this.anyNetwork, 517 | providerConfigs: this.providerConfigs, 518 | quorum: this.quorum 519 | }); 520 | }; 521 | 522 | ethers.providers.InfuraProvider.prototype[inspect.custom] = function() { 523 | return new inspect.NamedObject(this.constructor.name, { 524 | network: this._network.name, 525 | url: this.connection.url, 526 | projectId: (this.isCommunityResource() ? "default": this.projectId), 527 | projectSecret: this.projectSecret 528 | }); 529 | }; 530 | 531 | ethers.providers.PocketProvider.prototype[inspect.custom] = function() { 532 | return new inspect.NamedObject(this.constructor.name, { 533 | network: this._network.name, 534 | url: this.connection.url, 535 | applicationId: (this.isCommunityResource() ? "default": this.projectId), 536 | applicationSecretKey: this.applicationSecretKey, 537 | loadBalancer: this.loadBalancer 538 | }); 539 | }; 540 | */ 541 | 542 | // Set up an alias to self as window 543 | Object.defineProperty(self, "signers", { 544 | configurable: false, 545 | enumerable: true, 546 | get: _getSigners 547 | }); 548 | 549 | return { 550 | _onMessage, ethereum 551 | }; 552 | 553 | 554 | })(Help(ethers), (_code) => eval(_code)); 555 | delete Help; 556 | // The above helps us isolate a few extra variables from the 557 | // eval; only the _code should be visible, all other variables 558 | // are hidden 559 | 560 | // Set the message handler (read-only) 561 | onmessage = _onMessage 562 | Object.defineProperty(self, "onmessage", { 563 | configurable: false, 564 | enumerable: true, 565 | writable: false, 566 | value: _onMessage 567 | }); 568 | 569 | // Set up an alias to self as window (read-only) 570 | Object.defineProperty(self, "window", { 571 | configurable: false, 572 | enumerable: true, 573 | writable: false, 574 | value: self 575 | }); 576 | 577 | // Set up an alias to self as window 578 | Object.defineProperty(self, "self", { 579 | configurable: false, 580 | enumerable: true, 581 | writable: false, 582 | value: self 583 | }); 584 | 585 | // Set up self.ethereum (also window.ethereum; read-only) 586 | Object.defineProperty(self, "ethereum", { 587 | configurable: false, 588 | enumerable: true, 589 | writable: false, 590 | value: ethereum 591 | }); 592 | 593 | // Notify our container we are ready to party on! 594 | postMessage(JSON.stringify("ready")); 595 | -------------------------------------------------------------------------------- /playground/sources/caret.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /playground/sources/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/sources/dark-mode-moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /playground/sources/dark-mode-stars.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /playground/sources/dark-mode-sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /playground/sources/generate.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync } from "fs"; 2 | 3 | const css = readFileSync("./style.css").toString(); 4 | 5 | const output = css.replace(/url\((.*)\)/g, (all, url) => { 6 | const base64 = readFileSync(url).toString("base64"); 7 | return `url(data:image/svg+xml;base64,${ base64 })`; 8 | }); 9 | 10 | console.log(output); 11 | -------------------------------------------------------------------------------- /playground/sources/icon-library.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /playground/sources/icon-settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 24 | 38 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /playground/sources/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /playground/sources/options-open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 14 | 18 | 20 | 24 | 26 | 27 | -------------------------------------------------------------------------------- /playground/sources/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | margin: 0; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | transition: background-color 0.2s linear; 8 | } 9 | body.darkMode { 10 | background: #111; 11 | color: #fff; 12 | } 13 | 14 | /* We initialize all animations off until JavaScript 15 | has had a chance to set thigns up */ 16 | 17 | body.disableAnimations { transition: none !important; } 18 | body.disableAnimations * { transition: none !important; } 19 | 20 | div { box-sizing: border-box; } 21 | 22 | /* Animated classes for showing the sidebar */ 23 | 24 | .left { 25 | transition: width 0.3s ease-out; 26 | width: 100%; 27 | } 28 | 29 | .right { 30 | bottom: 0; 31 | position: fixed; 32 | right: -400px; 33 | top: 0; 34 | transition: transform 0.3s ease-out; 35 | width: 400px; 36 | } 37 | 38 | body.showSidebar .left { 39 | width: calc(100% - 400px); 40 | } 41 | 42 | body.showSidebar .right { 43 | transform: TranslateX(-400px); 44 | } 45 | 46 | #banner-background { 47 | background-color: #2535a0; 48 | border-bottom: 2px solid #121a4d; 49 | height: 70px; 50 | left: 0; 51 | position: fixed; 52 | right: 0; 53 | top: 0; 54 | } 55 | 56 | body.darkMode #banner-background { 57 | background-color: #182268; 58 | border-bottom: 1px solid #2c40c0; 59 | } 60 | 61 | #banner { 62 | color: #fff; 63 | height: 70px; 64 | overflow: hidden; 65 | position: fixed; 66 | transition: background-color 0.2s linear, color 0.2s linear, width 0.3s ease-out; 67 | left: 0; 68 | top: 0; 69 | } 70 | 71 | body.darkMode #banner { 72 | ddd-color: #3b54ff; 73 | } 74 | 75 | #banner .logo { 76 | background: url(./logo.svg) no-repeat center; 77 | display: block; 78 | height: 70px; 79 | left: 20px; 80 | opacity: 0.7; 81 | position: absolute; 82 | top: 0px; 83 | width: 70px; 84 | } 85 | #banner .title { 86 | font-family: monospace; 87 | font-size: 30px; 88 | line-height: 70px; 89 | opacity: 0.7; 90 | padding: 0 100px; 91 | text-align: center; 92 | } 93 | 94 | #button-sidebar { 95 | cursor: pointer; 96 | height: 30px; 97 | right: 30px; 98 | opacity: 0.7; 99 | position: absolute; 100 | top: 20px; 101 | width: 30px; 102 | } 103 | 104 | #button-sidebar .open { 105 | background: url(./options-open.svg) no-repeat center; 106 | background-size: contain; 107 | height: 100%; 108 | width: 100%; 109 | } 110 | 111 | #banner #button-darkmode { 112 | cursor: pointer; 113 | opacity: 0.7; 114 | position: absolute; 115 | right: 90px; 116 | top: 20px; 117 | width: 30px; 118 | height: 30px; 119 | } 120 | 121 | #banner #button-darkmode .stars { 122 | background: url(./dark-mode-stars.svg); 123 | background-size: contain; 124 | height: 100%; 125 | position: absolute; 126 | width: 100%; 127 | 128 | opacity: 0; 129 | transition: opacity 0.1s linear 0.15s; 130 | } 131 | 132 | #banner #button-darkmode .light { 133 | background: url(./dark-mode-sun.svg); 134 | background-size: contain; 135 | height: 100%; 136 | position: absolute; 137 | width: 100%; 138 | 139 | transform: translateY(0); 140 | transition: transform 0.3s ease-out 0.3s; 141 | } 142 | 143 | #banner #button-darkmode .dark { 144 | background: url(./dark-mode-moon.svg); 145 | background-size: contain; 146 | height: 100%; 147 | position: absolute; 148 | width: 100%; 149 | 150 | transform: translateY(70px); 151 | transition: transform 0.3s ease-in; 152 | } 153 | 154 | body.darkMode #banner #button-darkmode .stars { 155 | opacity: 1; 156 | transition: opacity 0.3s linear 0.5s; 157 | } 158 | 159 | body.darkMode #banner #button-darkmode .light { 160 | transform: translateY(70px); 161 | transition: transform 0.3s ease-in; 162 | } 163 | 164 | body.darkMode #banner #button-darkmode .dark { 165 | transform: translateY(0); 166 | transition: transform 0.3s ease-out 0.3s; 167 | } 168 | 169 | #output { 170 | margin: 0; 171 | padding: 90px 30px 0 0; 172 | min-height: 100%; 173 | overflow: auto; 174 | } 175 | #output div.output { 176 | font-size: 24px; 177 | font-family: monospace; 178 | padding: 4px 30px 4px; 179 | white-space: pre; 180 | width: 100%; 181 | } 182 | #output div.output.log-warn { 183 | color: #880; 184 | } 185 | body.darMode #output div.output.log-warn { 186 | color: #aa6; 187 | } 188 | #output div.output.log-error { 189 | color: 800; 190 | } 191 | body.darkMode #output div.output.log-error { 192 | color: a66; 193 | } 194 | #output div.output.log-log { 195 | color: #008; 196 | } 197 | body.darkMode #output div.output.log-log { 198 | color: #66a; 199 | } 200 | #output div.output.log-note { 201 | color: #880; 202 | font-size: 16px; 203 | font-style: italic; 204 | } 205 | body.darkMode #output div.output.log-note { 206 | color: #aa5; 207 | } 208 | #output div.output.log-provider { 209 | color: #880; 210 | font-size: 16px; 211 | } 212 | body.darkMode #output div.output.log-provider { 213 | color: #aa5; 214 | } 215 | #output div.output.entry { 216 | background: url(./caret.svg) no-repeat 8px 12px; 217 | background-size: 17px 17px; 218 | color: #888; 219 | } 220 | body.darkMode #output div.output.entry { 221 | color: #aaa; 222 | } 223 | #output div.output.result { 224 | color: #00f; 225 | } 226 | #output div.output.result-bold { 227 | color: #00f; 228 | font-weight: bold; 229 | } 230 | body.darkMode #output div.output.result { 231 | color: #88f; 232 | } 233 | body.darkMode #output div.output.result-bold { 234 | color: #88f; 235 | font-weight: bold; 236 | } 237 | #output div.output.pending { 238 | color: #aaa; 239 | font-style: italic; 240 | } 241 | #output div.output.error { 242 | color: #f00; 243 | } 244 | body.darkMode #output div.output.error { 245 | color: #f88; 246 | } 247 | 248 | #input-box { 249 | position: relative; 250 | } 251 | 252 | textarea { 253 | background: url(./caret.svg) no-repeat 8px 12px; 254 | background-size: 17px 17px; 255 | outline: none; 256 | resize: none; 257 | } 258 | 259 | #sizer-container { 260 | border: 1px solid green; 261 | opacity: 0; 262 | position: absolute; 263 | pointer-events: none; 264 | top: -20px; 265 | white-space: pre-wrap; 266 | } 267 | 268 | .input-style { 269 | border: none; 270 | font-size: 24px; 271 | font-family: monospace; 272 | overflow: hidden; 273 | padding: 4px 30px 4px; 274 | width: 100%; 275 | } 276 | 277 | /* off-screen box to approximate width of monospace font used in the textarea */ 278 | #sizer { 279 | position: absolute; 280 | font-size: 24px; 281 | font-family: monospace; 282 | left: 0; 283 | transform: translateX(-200%); 284 | } 285 | 286 | 287 | body.darkMode textarea { 288 | color: #eee; 289 | } 290 | 291 | #suggestions { 292 | background: #fff; 293 | border: 1px solid #66f; 294 | box-shadow: 0 0 15px rgba(0, 0, 0, 0.5); 295 | color: #008; 296 | font-family: monospace; 297 | font-size: 20px; 298 | opacity: 0.9; 299 | position: absolute; 300 | top: 0px; 301 | transform: translateY(-100%); 302 | ddd-transition: opacity 0.3s linear; 303 | width: 270px; 304 | } 305 | 306 | body.darkMode #suggestions { 307 | background: #222; 308 | border: 1px solid #888; 309 | box-shadow: 0 0 15px #000; 310 | color: #888; 311 | } 312 | 313 | body.hideSuggestions #suggestions { 314 | opacity: 0; 315 | pointer-events: none; 316 | } 317 | 318 | #suggestions > div { 319 | border-bottom: 1px solid #66f; 320 | padding: 4px 10px; 321 | } 322 | 323 | body.darkMode #suggestions > div { 324 | border-bottom: 1px solid #888; 325 | } 326 | 327 | #suggestions > div.selected { 328 | background: #66f; 329 | color: #fff; 330 | } 331 | 332 | body.darkMode #suggestions > div.selected { 333 | background: #555; 334 | color: #fff; 335 | } 336 | 337 | #suggestions > div:last-child { 338 | border-bottom: none; 339 | } 340 | 341 | #sidebar { 342 | background: #333; 343 | color: #fff; 344 | font-family: monospace; 345 | font-size: 18px; 346 | } 347 | 348 | #sidebar .shadow-clip { 349 | top: 0px; 350 | left: 0; 351 | height: 100%; /*calc(100% - 70px); */ 352 | overflow: hidden; 353 | position: absolute; 354 | width: 50px; 355 | } 356 | 357 | #sidebar .shadow { 358 | box-shadow: -10px 0px 18px 18px #000; 359 | position: absolute; 360 | height: 100%; 361 | width: 0; 362 | } 363 | #sidebar .header { 364 | background: #111; 365 | display: flex; 366 | flex-flow: row nowrap; 367 | height: 70px; 368 | line-height: 70px; 369 | } 370 | 371 | #sidebar .header .tab { 372 | flex-grow: 1; 373 | text-align: center; 374 | } 375 | 376 | #sidebar .header .tab.selected { 377 | background: #333; 378 | } 379 | 380 | #sidebar .header .icon { 381 | display: inline-block; 382 | height: 70px; 383 | opacity: 0.3; 384 | cursor: pointer; 385 | transform: scale(0.7); 386 | transition: opacity 0.3s linear, transform 0.3s ease; 387 | width: 50px; 388 | } 389 | 390 | #sidebar .header .tab.selected .icon { 391 | opacity: 0.7; 392 | transform: scale(1); 393 | } 394 | 395 | .icon-library { 396 | background: url(./icon-library.svg) no-repeat center; 397 | } 398 | 399 | .icon-settings { 400 | background: url(./icon-settings.svg) no-repeat center; 401 | } 402 | 403 | #sidebar .header .tab .icon:hover { 404 | opacity: 0.5; 405 | } 406 | 407 | #sidebar .panel { 408 | display: none; 409 | } 410 | 411 | #sidebar .panel.selected { 412 | display: block; 413 | } 414 | 415 | #sidebar .banner { 416 | color: #aaa; 417 | line-height: 30px; 418 | padding: 15px 0 0px; 419 | text-align: center; 420 | } 421 | 422 | #sidebar .search { 423 | border-bottom: 1px solid #222; 424 | padding: 15px 20px 30px; 425 | position: relative; 426 | } 427 | #sidebar .search input { 428 | border-radius: 10px; 429 | font-size: 20px; 430 | height: 30px; 431 | outline: none; 432 | line-height: 30px; 433 | text-align: center; 434 | width: 100%; 435 | } 436 | #sidebar-items { 437 | height: calc(100% - 190px); 438 | overflow: auto; 439 | padding: 0px 0 30px; 440 | position: relative; 441 | } 442 | #sidebar-items > div { 443 | padding: 4px 20px; 444 | transition: background-color 0.3s linear, opacity 0.3s linear; 445 | } 446 | 447 | #sidebar-items > div .group { 448 | color: #888; 449 | font-size: 14px; 450 | white-space: nowrap; 451 | padding: 10px 0px 0px 12px; 452 | } 453 | 454 | /* Highlight only the selected options item; if any */ 455 | /* 456 | #sidebar-items.selected > div .title { 457 | opacity: 0.5; 458 | } 459 | #sidebar-items.selected > div.selected .title { 460 | opacity: 1; 461 | } 462 | */ 463 | #sidebar-items > div.selected { 464 | background: rgba(0, 0, 0, 0.8); 465 | } 466 | 467 | /* Add expanded arrows to the options items */ 468 | #sidebar-items div .title:before { 469 | content: "\00a0\00a0\25b6\00a0"; 470 | } 471 | #sidebar-items > div.selected .title:before { 472 | content: "\00a0\00a0\25bc\00a0"; 473 | } 474 | 475 | /* Options item title */ 476 | #sidebar-items div .title { 477 | color: #ddd; 478 | cursor: pointer; 479 | white-space: nowrap; 480 | } 481 | #sidebar-items div .title .prefix { 482 | color: #888; 483 | cursor: pointer; 484 | font-size: 14px; 485 | white-space: nowrap; 486 | } 487 | #sidebar-items div.selected .title { 488 | font-weight: bold; 489 | } 490 | #sidebar-items div .item { 491 | position: relative; 492 | } 493 | #sidebar-items div .item.experimental { 494 | pointer-events: none; 495 | opacity: 0.2; 496 | } 497 | #sidebar-items div .item .use { 498 | color: #88f; 499 | font-size: 16px; 500 | position: absolute; 501 | cursor: pointer; 502 | right: 0px; 503 | } 504 | #sidebar-items div .item .use:hover { 505 | color: #8f8; 506 | } 507 | 508 | /* Info Blob */ 509 | #sidebar-items div .info .usage { 510 | display: none; /* Maybe don't need this?? */ 511 | } 512 | #sidebar-items div .info { 513 | color: #ddd; 514 | overflow: auto; 515 | padding-left: 23px; 516 | max-height: 0; 517 | transition: max-height 0.3s ease-out; 518 | } 519 | #sidebar-items div.selected .info { 520 | color: #ddd; 521 | padding-right: 7px; 522 | } 523 | /* 524 | #sidebar-items div .info .usage { 525 | margin-bottom: 5px; 526 | white-space: nowrap; 527 | } 528 | */ 529 | #sidebar-items div .info > .description { 530 | color: #aaa; 531 | font-size: 16px; 532 | padding-top: 4px; 533 | } 534 | #sidebar-items div .info .no-params { 535 | margin-bottom: 5px; 536 | line-height: 20px; 537 | font-style: italic; 538 | color: #aaa; 539 | font-family: sans-serif; 540 | font-size: 16px; 541 | padding: 15px 30px 15px 0; 542 | text-align: center; 543 | } 544 | #sidebar-items div .info > .returns:before { 545 | content: "\21aa\00a0"; 546 | } 547 | #sidebar-items div .info > .returns { 548 | color: #4a4; 549 | font-size: 16px; 550 | padding-top: 4px; 551 | } 552 | #sidebar-items div .info .param { 553 | margin: 5px 0; 554 | } 555 | #sidebar-items div .info .param .name { 556 | font-weight: bold; 557 | } 558 | #sidebar-items div .info .param .name i { 559 | color: #aaa; 560 | font-size: 12px; 561 | font-weight: normal; 562 | position: relative; 563 | top: -4px; 564 | } 565 | #sidebar-items div .info .param .description { 566 | color: #aaa; 567 | font-family: sans-serif; 568 | font-size: 16px; 569 | padding-left: 20px; 570 | } 571 | 572 | #sidebar-items div.item .option { 573 | padding-left: 23px; 574 | } 575 | 576 | #sidebar-items div.item .option .checkbox { 577 | border: 2px solid #ddd; 578 | border-radius: 4px; 579 | display: inline-block; 580 | height: 17px; 581 | position: absolute; 582 | cursor: pointer; 583 | right: 0px; 584 | width: 17px; 585 | } 586 | 587 | #sidebar-items div.item .option .checkbox .checkmark { 588 | background: url(./checkmark.svg) no-repeat center; 589 | height: 23px; 590 | left: 1px; 591 | opacity: 0; 592 | position: absolute; 593 | transform: translate(-7px, 3px) scale(0.3); 594 | transition: opacity 0.2s linear, transform 0.2s ease-out; 595 | top: -5px; 596 | width: 23px; 597 | } 598 | 599 | #sidebar-items div.item .option .checkbox.selected .checkmark { 600 | opacity: 1; 601 | transform: translate(0, 0) scale(1.0); 602 | transition: opacity 0.2s linear, transform 0.2s cubic-bezier(0.2, 0.4, 0.6, 1.8); 603 | } 604 | 605 | #sidebar-items .option-info { 606 | color: #aaa; 607 | font-size: 16px; 608 | font-style: italic; 609 | padding: 4px 13px 5px 23px; 610 | } 611 | 612 | #sidebar-items .option-info code { 613 | color: #666; 614 | font-style: normal; 615 | } 616 | 617 | #sidebar-items .button { 618 | border: 1px solid #ddd; 619 | color: #ddd; 620 | cursor: pointer; 621 | font-size: 16px; 622 | font-weight: bold; 623 | line-height: 35px; 624 | margin: 5px 23px; 625 | text-align: center; 626 | transition: background-color 0.1s linear, color 0.1s linear; 627 | } 628 | 629 | #sidebar-items .button:hover { 630 | background: #ddd; 631 | border: 1px solid #111; 632 | color: #111; 633 | transition: background-color 0.2s linear, color 0.2s linear; 634 | } 635 | -------------------------------------------------------------------------------- /playground/v5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | ethers playground 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
29 |
30 |
31 | 32 |
Sizer Content
33 |
34 |
35 | 80 | 81 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /playground/v5/static/caret.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /playground/v5/static/checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/v5/static/dark-mode-moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /playground/v5/static/dark-mode-stars.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /playground/v5/static/dark-mode-sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /playground/v5/static/icon-library.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /playground/v5/static/icon-settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 24 | 38 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /playground/v5/static/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /playground/v5/static/options-open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 14 | 18 | 20 | 24 | 26 | 27 | -------------------------------------------------------------------------------- /playground/v5/static/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | margin: 0; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | transition: background-color 0.2s linear; 8 | } 9 | body.darkMode { 10 | background: #111; 11 | color: #fff; 12 | } 13 | 14 | /* We initialize all animations off until JavaScript 15 | has had a chance to set thigns up */ 16 | 17 | body.disableAnimations { transition: none !important; } 18 | body.disableAnimations * { transition: none !important; } 19 | 20 | div { box-sizing: border-box; } 21 | 22 | /* Animated classes for showing the sidebar */ 23 | 24 | .left { 25 | transition: width 0.3s ease-out; 26 | width: 100%; 27 | } 28 | 29 | .right { 30 | bottom: 0; 31 | position: fixed; 32 | right: -400px; 33 | top: 0; 34 | transition: transform 0.3s ease-out; 35 | width: 400px; 36 | } 37 | 38 | body.showSidebar .left { 39 | width: calc(100% - 400px); 40 | } 41 | 42 | body.showSidebar .right { 43 | transform: TranslateX(-400px); 44 | } 45 | 46 | #banner-background { 47 | background-color: #2535a0; 48 | border-bottom: 2px solid #121a4d; 49 | height: 70px; 50 | left: 0; 51 | position: fixed; 52 | right: 0; 53 | top: 0; 54 | } 55 | 56 | body.darkMode #banner-background { 57 | background-color: #182268; 58 | border-bottom: 1px solid #2c40c0; 59 | } 60 | 61 | #banner { 62 | color: #fff; 63 | height: 70px; 64 | overflow: hidden; 65 | position: fixed; 66 | transition: background-color 0.2s linear, color 0.2s linear, width 0.3s ease-out; 67 | left: 0; 68 | top: 0; 69 | } 70 | 71 | body.darkMode #banner { 72 | ddd-color: #3b54ff; 73 | } 74 | 75 | #banner .logo { 76 | background: url(./logo.svg) no-repeat center; 77 | display: block; 78 | height: 70px; 79 | left: 20px; 80 | opacity: 0.7; 81 | position: absolute; 82 | top: 0px; 83 | width: 70px; 84 | } 85 | #banner .title { 86 | font-family: monospace; 87 | font-size: 30px; 88 | line-height: 70px; 89 | opacity: 0.7; 90 | padding: 0 100px; 91 | text-align: center; 92 | } 93 | /* 94 | #banner #button-sidebar { 95 | background: url(./logo.svg) no-repeat center; 96 | height: 70px; 97 | margin-right: 30px; 98 | opacity: 0.7; 99 | position: absolute; 100 | right: 0px; 101 | top: 0; 102 | width: 70px; 103 | } 104 | */ 105 | 106 | #button-sidebar { 107 | height: 30px; 108 | right: 30px; 109 | opacity: 0.7; 110 | position: absolute; 111 | top: 20px; 112 | width: 30px; 113 | } 114 | 115 | #button-sidebar .open { 116 | background: url(./options-open.svg) no-repeat center; 117 | background-size: contain; 118 | height: 100%; 119 | width: 100%; 120 | } 121 | 122 | #banner #button-darkmode { 123 | opacity: 0.7; 124 | position: absolute; 125 | right: 90px; 126 | top: 20px; 127 | width: 30px; 128 | height: 30px; 129 | } 130 | 131 | #banner #button-darkmode .stars { 132 | background: url(./dark-mode-stars.svg); 133 | background-size: contain; 134 | height: 100%; 135 | position: absolute; 136 | width: 100%; 137 | 138 | opacity: 0; 139 | transition: opacity 0.1s linear 0.15s; 140 | } 141 | 142 | #banner #button-darkmode .light { 143 | background: url(./dark-mode-sun.svg); 144 | background-size: contain; 145 | height: 100%; 146 | position: absolute; 147 | width: 100%; 148 | 149 | transform: translateY(0); 150 | transition: transform 0.3s ease-out 0.3s; 151 | } 152 | 153 | #banner #button-darkmode .dark { 154 | background: url(./dark-mode-moon.svg); 155 | background-size: contain; 156 | height: 100%; 157 | position: absolute; 158 | width: 100%; 159 | 160 | transform: translateY(70px); 161 | transition: transform 0.3s ease-in; 162 | } 163 | 164 | body.darkMode #banner #button-darkmode .stars { 165 | opacity: 1; 166 | transition: opacity 0.3s linear 0.5s; 167 | } 168 | 169 | body.darkMode #banner #button-darkmode .light { 170 | transform: translateY(70px); 171 | transition: transform 0.3s ease-in; 172 | } 173 | 174 | body.darkMode #banner #button-darkmode .dark { 175 | transform: translateY(0); 176 | transition: transform 0.3s ease-out 0.3s; 177 | } 178 | 179 | #output { 180 | margin: 0; 181 | padding: 90px 30px 0 0; 182 | min-height: 100%; 183 | overflow: auto; 184 | } 185 | #output div.output { 186 | font-size: 24px; 187 | font-family: monospace; 188 | padding: 4px 30px 4px; 189 | white-space: pre; 190 | width: 100%; 191 | } 192 | #output div.output.log-warn { 193 | color: #880; 194 | } 195 | body.darMode #output div.output.log-warn { 196 | color: #aa6; 197 | } 198 | #output div.output.log-error { 199 | color: 800; 200 | } 201 | body.darkMode #output div.output.log-error { 202 | color: a66; 203 | } 204 | #output div.output.log-log { 205 | color: #008; 206 | } 207 | body.darkMode #output div.output.log-log { 208 | color: #66a; 209 | } 210 | #output div.output.log-note { 211 | color: #880; 212 | font-size: 16px; 213 | font-style: italic; 214 | } 215 | body.darkMode #output div.output.log-note { 216 | color: #aa5; 217 | } 218 | #output div.output.log-provider { 219 | color: #880; 220 | font-size: 16px; 221 | } 222 | body.darkMode #output div.output.log-provider { 223 | color: #aa5; 224 | } 225 | #output div.output.entry { 226 | background: url(./caret.svg) no-repeat 8px 12px; 227 | background-size: 17px 17px; 228 | color: #888; 229 | } 230 | body.darkMode #output div.output.entry { 231 | color: #aaa; 232 | } 233 | #output div.output.result { 234 | color: #00f; 235 | } 236 | #output div.output.result-bold { 237 | color: #00f; 238 | font-weight: bold; 239 | } 240 | body.darkMode #output div.output.result { 241 | color: #88f; 242 | } 243 | body.darkMode #output div.output.result-bold { 244 | color: #88f; 245 | font-weight: bold; 246 | } 247 | #output div.output.pending { 248 | color: #aaa; 249 | font-style: italic; 250 | } 251 | #output div.output.error { 252 | color: #f00; 253 | } 254 | body.darkMode #output div.output.error { 255 | color: #f88; 256 | } 257 | 258 | #input-box { 259 | position: relative; 260 | } 261 | 262 | textarea { 263 | background: url(./caret.svg) no-repeat 8px 12px; 264 | background-size: 17px 17px; 265 | outline: none; 266 | resize: none; 267 | } 268 | 269 | #sizer-container { 270 | border: 1px solid green; 271 | opacity: 0; 272 | position: absolute; 273 | pointer-events: none; 274 | top: -20px; 275 | white-space: pre-wrap; 276 | } 277 | 278 | .input-style { 279 | border: none; 280 | font-size: 24px; 281 | font-family: monospace; 282 | overflow: hidden; 283 | padding: 4px 30px 4px; 284 | width: 100%; 285 | } 286 | 287 | /* off-screen box to approximate width of monospace font used in the textarea */ 288 | #sizer { 289 | position: absolute; 290 | font-size: 24px; 291 | font-family: monospace; 292 | left: 0; 293 | transform: translateX(-200%); 294 | } 295 | 296 | 297 | body.darkMode textarea { 298 | color: #eee; 299 | } 300 | 301 | #suggestions { 302 | background: #fff; 303 | border: 1px solid #66f; 304 | box-shadow: 0 0 15px rgba(0, 0, 0, 0.5); 305 | color: #008; 306 | font-family: monospace; 307 | font-size: 20px; 308 | opacity: 0.9; 309 | position: absolute; 310 | top: 0px; 311 | transform: translateY(-100%); 312 | ddd-transition: opacity 0.3s linear; 313 | width: 270px; 314 | } 315 | 316 | body.darkMode #suggestions { 317 | background: #222; 318 | border: 1px solid #888; 319 | box-shadow: 0 0 15px #000; 320 | color: #888; 321 | } 322 | 323 | body.hideSuggestions #suggestions { 324 | opacity: 0; 325 | pointer-events: none; 326 | } 327 | 328 | #suggestions > div { 329 | border-bottom: 1px solid #66f; 330 | padding: 4px 10px; 331 | } 332 | 333 | body.darkMode #suggestions > div { 334 | border-bottom: 1px solid #888; 335 | } 336 | 337 | #suggestions > div.selected { 338 | background: #66f; 339 | color: #fff; 340 | } 341 | 342 | body.darkMode #suggestions > div.selected { 343 | background: #555; 344 | color: #fff; 345 | } 346 | 347 | #suggestions > div:last-child { 348 | border-bottom: none; 349 | } 350 | 351 | #sidebar { 352 | background: #333; 353 | color: #fff; 354 | font-family: monospace; 355 | font-size: 18px; 356 | } 357 | 358 | #sidebar .shadow-clip { 359 | top: 0px; 360 | left: 0; 361 | height: 100%; /*calc(100% - 70px); */ 362 | overflow: hidden; 363 | position: absolute; 364 | width: 50px; 365 | } 366 | 367 | #sidebar .shadow { 368 | box-shadow: -10px 0px 18px 18px #000; 369 | position: absolute; 370 | height: 100%; 371 | width: 0; 372 | } 373 | #sidebar .header { 374 | background: #111; 375 | display: flex; 376 | flex-flow: row nowrap; 377 | height: 70px; 378 | line-height: 70px; 379 | } 380 | 381 | #sidebar .header .tab { 382 | flex-grow: 1; 383 | text-align: center; 384 | } 385 | 386 | #sidebar .header .tab.selected { 387 | background: #333; 388 | } 389 | 390 | #sidebar .header .icon { 391 | display: inline-block; 392 | height: 70px; 393 | opacity: 0.3; 394 | cursor: pointer; 395 | transform: scale(0.7); 396 | transition: opacity 0.3s linear, transform 0.3s ease; 397 | width: 50px; 398 | } 399 | 400 | #sidebar .header .tab.selected .icon { 401 | opacity: 0.7; 402 | transform: scale(1); 403 | } 404 | 405 | .icon-library { 406 | background: url(./icon-library.svg) no-repeat center; 407 | } 408 | 409 | .icon-settings { 410 | background: url(./icon-settings.svg) no-repeat center; 411 | } 412 | 413 | #sidebar .header .tab .icon:hover { 414 | opacity: 0.5; 415 | } 416 | 417 | #sidebar .panel { 418 | display: none; 419 | } 420 | 421 | #sidebar .panel.selected { 422 | display: block; 423 | } 424 | 425 | #sidebar .banner { 426 | color: #aaa; 427 | line-height: 30px; 428 | padding: 15px 0 0px; 429 | text-align: center; 430 | } 431 | 432 | #sidebar .search { 433 | border-bottom: 1px solid #222; 434 | padding: 15px 20px 30px; 435 | position: relative; 436 | } 437 | #sidebar .search input { 438 | border-radius: 10px; 439 | font-size: 20px; 440 | height: 30px; 441 | outline: none; 442 | line-height: 30px; 443 | text-align: center; 444 | width: 100%; 445 | } 446 | #sidebar-items { 447 | height: calc(100% - 190px); 448 | overflow: auto; 449 | padding: 0px 0 30px; 450 | position: relative; 451 | } 452 | #sidebar-items > div { 453 | padding: 4px 20px; 454 | transition: background-color 0.3s linear, opacity 0.3s linear; 455 | } 456 | 457 | #sidebar-items > div .group { 458 | color: #888; 459 | font-size: 14px; 460 | white-space: nowrap; 461 | padding: 10px 0px 0px 12px; 462 | } 463 | 464 | /* Highlight only the selected options item; if any */ 465 | /* 466 | #sidebar-items.selected > div .title { 467 | opacity: 0.5; 468 | } 469 | #sidebar-items.selected > div.selected .title { 470 | opacity: 1; 471 | } 472 | */ 473 | #sidebar-items > div.selected { 474 | background: rgba(0, 0, 0, 0.8); 475 | } 476 | 477 | /* Add expanded arrows to the options items */ 478 | #sidebar-items div .title:before { 479 | content: "\00a0\00a0\25b6\00a0"; 480 | } 481 | #sidebar-items > div.selected .title:before { 482 | content: "\00a0\00a0\25bc\00a0"; 483 | } 484 | 485 | /* Options item title */ 486 | #sidebar-items div .title { 487 | color: #ddd; 488 | cursor: pointer; 489 | white-space: nowrap; 490 | } 491 | #sidebar-items div .title .prefix { 492 | color: #888; 493 | cursor: pointer; 494 | font-size: 14px; 495 | white-space: nowrap; 496 | } 497 | #sidebar-items div.selected .title { 498 | font-weight: bold; 499 | } 500 | #sidebar-items div .item { 501 | position: relative; 502 | } 503 | #sidebar-items div .item.experimental { 504 | pointer-events: none; 505 | opacity: 0.2; 506 | } 507 | #sidebar-items div .item .use { 508 | color: #88f; 509 | font-size: 16px; 510 | position: absolute; 511 | cursor: pointer; 512 | right: 0px; 513 | } 514 | #sidebar-items div .item .use:hover { 515 | color: #8f8; 516 | } 517 | 518 | /* Info Blob */ 519 | #sidebar-items div .info .usage { 520 | display: none; /* Maybe don't need this?? */ 521 | } 522 | #sidebar-items div .info { 523 | color: #ddd; 524 | overflow: auto; 525 | padding-left: 23px; 526 | max-height: 0; 527 | transition: max-height 0.3s ease-out; 528 | } 529 | #sidebar-items div.selected .info { 530 | color: #ddd; 531 | padding-right: 7px; 532 | } 533 | /* 534 | #sidebar-items div .info .usage { 535 | margin-bottom: 5px; 536 | white-space: nowrap; 537 | } 538 | */ 539 | #sidebar-items div .info > .description { 540 | color: #aaa; 541 | font-size: 16px; 542 | padding-top: 4px; 543 | } 544 | #sidebar-items div .info .no-params { 545 | margin-bottom: 5px; 546 | line-height: 20px; 547 | font-style: italic; 548 | color: #aaa; 549 | font-family: sans-serif; 550 | font-size: 16px; 551 | padding: 15px 30px 15px 0; 552 | text-align: center; 553 | } 554 | #sidebar-items div .info > .returns:before { 555 | content: "\21aa\00a0"; 556 | } 557 | #sidebar-items div .info > .returns { 558 | color: #4a4; 559 | font-size: 16px; 560 | padding-top: 4px; 561 | } 562 | #sidebar-items div .info .param { 563 | margin: 5px 0; 564 | } 565 | #sidebar-items div .info .param .name { 566 | font-weight: bold; 567 | } 568 | #sidebar-items div .info .param .name i { 569 | color: #aaa; 570 | font-size: 12px; 571 | font-weight: normal; 572 | position: relative; 573 | top: -4px; 574 | } 575 | #sidebar-items div .info .param .description { 576 | color: #aaa; 577 | font-family: sans-serif; 578 | font-size: 16px; 579 | padding-left: 20px; 580 | } 581 | 582 | #sidebar-items div.item .option { 583 | padding-left: 23px; 584 | } 585 | 586 | #sidebar-items div.item .option .checkbox { 587 | border: 2px solid #ddd; 588 | border-radius: 4px; 589 | display: inline-block; 590 | height: 17px; 591 | position: absolute; 592 | cursor: pointer; 593 | right: 0px; 594 | width: 17px; 595 | } 596 | 597 | #sidebar-items div.item .option .checkbox .checkmark { 598 | background: url(./checkmark.svg) no-repeat center; 599 | height: 23px; 600 | left: 1px; 601 | opacity: 0; 602 | position: absolute; 603 | transform: translate(-7px, 3px) scale(0.3); 604 | transition: opacity 0.2s linear, transform 0.2s ease-out; 605 | top: -5px; 606 | width: 23px; 607 | } 608 | 609 | #sidebar-items div.item .option .checkbox.selected .checkmark { 610 | opacity: 1; 611 | transform: translate(0, 0) scale(1.0); 612 | transition: opacity 0.2s linear, transform 0.2s cubic-bezier(0.2, 0.4, 0.6, 1.8); 613 | } 614 | 615 | #sidebar-items .option-info { 616 | color: #aaa; 617 | font-size: 16px; 618 | font-style: italic; 619 | padding: 4px 13px 5px 23px; 620 | } 621 | 622 | #sidebar-items .option-info code { 623 | color: #666; 624 | font-style: normal; 625 | } 626 | 627 | #sidebar-items .button { 628 | border: 1px solid #ddd; 629 | color: #ddd; 630 | cursor: pointer; 631 | font-size: 16px; 632 | font-weight: bold; 633 | line-height: 35px; 634 | margin: 5px 23px; 635 | text-align: center; 636 | transition: background-color 0.1s linear, color 0.1s linear; 637 | } 638 | 639 | #sidebar-items .button:hover { 640 | background: #ddd; 641 | border: 1px solid #111; 642 | color: #111; 643 | transition: background-color 0.2s linear, color 0.2s linear; 644 | } 645 | -------------------------------------------------------------------------------- /playground/v5/static/types.js: -------------------------------------------------------------------------------- 1 | const Types = { 2 | ethers: { 3 | type: "object", 4 | values: { 5 | constants: ethers.constants, 6 | getDefaultProvider: find("getDefaultProvider"), 7 | providers: { 8 | AlchemyProvider: find("AlchemyProvider", [ 9 | 10 | ]); 11 | } 12 | } 13 | } 14 | }; 15 | --------------------------------------------------------------------------------