diff --git a/.all-contributorsrc b/.all-contributorsrc index c4dd25c658e..fdd6bd3885a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1713,7 +1713,12 @@ "profile": "https://github.com/ryancreatescopy", "contributions": [ "doc", - "code" + "code", + "design", + "bug", + "ideas", + "review", + "content" ] }, { @@ -3805,6 +3810,60 @@ "contributions": [ "ideas" ] + }, + { + "login": "Karthickmerk", + "name": "Karthickmerk", + "avatar_url": "https://avatars.githubusercontent.com/u/53270101?v=4", + "profile": "https://github.com/Karthickmerk", + "contributions": [ + "ideas" + ] + }, + { + "login": "hueyhe", + "name": "Sihong", + "avatar_url": "https://avatars.githubusercontent.com/u/13460383?v=4", + "profile": "https://github.com/hueyhe", + "contributions": [ + "code" + ] + }, + { + "login": "AmirAliM", + "name": "AmirAliM", + "avatar_url": "https://avatars.githubusercontent.com/u/8203572?v=4", + "profile": "https://github.com/AmirAliM", + "contributions": [ + "content" + ] + }, + { + "login": "Rub3cula", + "name": "Rub3cula", + "avatar_url": "https://avatars.githubusercontent.com/u/63545006?v=4", + "profile": "https://github.com/Rub3cula", + "contributions": [ + "content" + ] + }, + { + "login": "pawurb", + "name": "Paweł Urbanek", + "avatar_url": "https://avatars.githubusercontent.com/u/1131944?v=4", + "profile": "https://pawelurbanek.com", + "contributions": [ + "content" + ] + }, + { + "login": "adi44", + "name": "Aditya Dhir", + "avatar_url": "https://avatars.githubusercontent.com/u/31381639?v=4", + "profile": "https://github.com/adi44", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 4a8fdefdc9c..53b3cc0bb47 100644 --- a/README.md +++ b/README.md @@ -76,13 +76,35 @@ We recommend setting this up when running the project locally, as we use the Git > - [Follow these instructions](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) to create a personal GitHub API token > - When selecting scopes in step 7, leave everything unchecked (the data we fetch doesn't require any [scope](https://docs.github.com/en/developers/apps/scopes-for-oauth-apps#available-scopes)) > - In local repo root directory: Make a copy of `.env.example` and name it `.env` -> - Copy & paste your new GitHub API token in `.env` +> - Copy & paste your new GitHub API token into `.env` ``` // .env Example: GATSBY_GITHUB_TOKEN_READ_ONLY=48f84de812090000demo00000000697cf6e6a059 ``` +5. Add Etherscan API token (free) + +> - [Create an account](https://etherscan.io/) on Etherscan +> - Navigate to your Account Settings page +> - In the sidebar, click on 'API-KEYs' and add a new token +> - Copy & paste your Api-Key Token from Etherscan into `.env` + +``` +// .env Example: +ETHERSCAN_API_KEY=K6NUTARFJZJCIXHF1F1E1YGJZ8RQ29BE4U +``` + +6. Add DeFiPulse API token (free) + +> - [Follow this guide](https://docs.defipulse.com/quick-start-guide) to create an account and get your DeFiPulse API token +> - Copy & paste your Active API Key from DeFiPulse into `.env` + +``` +// .env Example: +DEFI_PULSE_API_KEY=4953aaf7966dad9c129397e197a0630ed0594f66962dd5fb058972b250da +``` + ### Make awesome changes! 1. Create new branch for your changes @@ -675,7 +697,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Shadab Khan

💻 -
ryancreatescopy

📖 💻 +
ryancreatescopy

📖 💻 🎨 🐛 🤔 👀 🖋
Hammad Jutt

🖋
Becaz

🤔
Caos

🖋 @@ -966,6 +988,14 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Ayushman Singh Chauhan

🐛 🖋
Keqi Huang

🐛 🖋
davidplutus

🤔 +
Karthickmerk

🤔 +
Sihong

💻 +
AmirAliM

🖋 + + +
Rub3cula

🖋 +
Paweł Urbanek

🖋 +
Aditya Dhir

🐛 diff --git a/package.json b/package.json index 5b6f2f8a3ce..5affd5bf2ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ethereum-org-website", - "version": "2.29.2", + "version": "2.30.0", "description": "Website of ethereum.org", "main": "index.js", "repository": "git@github.com:ethereum/ethereum-org-website.git", diff --git a/src/assets/wallets/walleth.png b/src/assets/wallets/walleth.png new file mode 100644 index 00000000000..41fd5e4e25e Binary files /dev/null and b/src/assets/wallets/walleth.png differ diff --git a/src/components/FileContributors.js b/src/components/FileContributors.js index e6f52a3ce79..7f7c7e77448 100644 --- a/src/components/FileContributors.js +++ b/src/components/FileContributors.js @@ -1,6 +1,6 @@ -import React, { useState, useEffect } from "react" +import React, { useState } from "react" import { useIntl } from "gatsby-plugin-intl" -import styled from "styled-components" +import styled, { css } from "styled-components" import { useQuery, gql } from "@apollo/client" import ButtonLink from "./ButtonLink" @@ -11,9 +11,27 @@ import Translation from "./Translation" import { ButtonSecondary } from "./SharedStyledComponents" import { getLocaleTimestamp } from "../utils/time" +const loadingStyles = css` + font-size: 0; + background: ${({ theme }) => + `linear-gradient(-90deg, ${theme.colors.lightBorder} 0%, ${theme.colors.searchBackgroundEmpty} 50%, ${theme.colors.lightBorder} 100%)`}; + background-size: 400% 400%; + animation: pulse 1.2s ease-in-out infinite; + + @keyframes pulse { + 0% { + background-position: 0% 0%; + } + 100% { + background-position: -135% 0%; + } + } +` + const Container = styled.div` display: flex; justify-content: space-between; + position: relative; border-radius: 2px; padding: 0.5rem; @@ -29,6 +47,23 @@ const Container = styled.div` } ` +const SkeletonContainer = styled(Container)` + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + opacity: 1; + transition: opacity 0.15s ease-in-out; + + ${({ loading }) => + !loading && + ` + opacity: 0; + pointer-events: none; + `} +` + const LeftContent = styled.div` display: flex; align-items: center; @@ -38,6 +73,13 @@ const LeftContent = styled.div` } ` +const SkeletonLeftContent = styled(LeftContent)` + flex: 1; + @media (max-width: ${(props) => props.theme.breakpoints.m}) { + flex: none; + } +` + const Avatar = styled.img` height: 40px; width: 40px; @@ -45,17 +87,48 @@ const Avatar = styled.img` border-radius: 50%; ` +const SkeletonAvatar = styled.div` + height: 40px; + width: 40px; + margin-right: 0.5rem; + border-radius: 50%; + ${loadingStyles} +` + const Info = styled.div` line-height: 130%; color: ${(props) => props.theme.colors.text200}; ` +const SkeletonInfo = styled(Info)` + ${loadingStyles} + height: 40px; + flex: 1; + border-radius: 3px; +` + const ButtonContainer = styled.div` display: flex; align-items: flex-end; justify-content: space-between; ` +const SkeletonButtonContainer = styled(ButtonContainer)` + ${loadingStyles} + width: 145px; + border-radius: 3px; + @media (max-width: ${(props) => props.theme.breakpoints.l}) { + margin-top: 1rem; + justify-content: center; + width: calc(50% - 2rem); + } + @media (max-width: ${(props) => props.theme.breakpoints.m}) { + height: 40px; + width: 50%; + margin-top: 1rem; + } +` + const ContributorsButton = styled(ButtonSecondary)` background-color: ${(props) => props.theme.colors.background}; margin-top: 0; @@ -70,6 +143,12 @@ const ContributorsButton = styled(ButtonSecondary)` justify-content: center; width: 50%; } + + ${({ loading }) => + loading && + ` + visibility: hidden; + `} ` const GithubButton = styled(ButtonLink)` @@ -151,28 +230,31 @@ const FileContributors = ({ relativePath, className, editPath }) => { variables: { relativePath }, }) - if (loading || error) return null + if (error) return null - const commits = data.repository?.ref?.target?.history?.edges?.map( + const commits = data?.repository?.ref?.target?.history?.edges?.map( (commit) => commit.node ) - const lastCommit = commits[0] - if (typeof lastCommit === "undefined") return null - const lastContributor = lastCommit.author - const uniqueContributors = commits.reduce( - (res, cur) => { - for (const contributor of res) { - const hasAuthorInfo = !!contributor.user && !!cur.author.user - if (hasAuthorInfo && contributor.user.login === cur.author.user.login) { - return res + const lastCommit = commits?.[0] || {} + const lastContributor = lastCommit?.author || {} + const uniqueContributors = + commits?.reduce( + (res, cur) => { + for (const contributor of res) { + const hasAuthorInfo = !!contributor.user && !!cur.author.user + if ( + hasAuthorInfo && + contributor.user.login === cur.author.user.login + ) { + return res + } } - } - res.push(cur.author) - return res - }, - [lastContributor] - ) + res.push(cur.author) + return res + }, + [lastContributor] + ) || [] return (
@@ -196,6 +278,13 @@ const FileContributors = ({ relativePath, className, editPath }) => { + + + + + + + @@ -210,7 +299,10 @@ const FileContributors = ({ relativePath, className, editPath }) => { - setModalOpen(true)}> + setModalOpen(true)} + loading={loading} + > {editPath && ( diff --git a/src/components/Roadmap.js b/src/components/Roadmap.js index 6a073ace01b..1bacb03016b 100644 --- a/src/components/Roadmap.js +++ b/src/components/Roadmap.js @@ -97,7 +97,8 @@ const Roadmap = () => { .filter( (issue) => issue.state === "closed" && - "allcontributors[bot]" !== issue.user.login + "allcontributors[bot]" !== issue.user.login && + !!issue.pull_request ) .slice(0, 6) setIssues({ diff --git a/src/components/StablecoinAccordion.js b/src/components/StablecoinAccordion.js index c2bf8056d86..b048b096986 100644 --- a/src/components/StablecoinAccordion.js +++ b/src/components/StablecoinAccordion.js @@ -20,7 +20,6 @@ import { } from "./SharedStyledComponents" import { translateMessageId } from "../utils/translations" -import { BsTypeH3 } from "react-icons/bs" const Card = styled.div` border-radius: 2px; diff --git a/src/components/StatsBoxGrid.js b/src/components/StatsBoxGrid.js index 4970bade9cd..7f9c578fb98 100644 --- a/src/components/StatsBoxGrid.js +++ b/src/components/StatsBoxGrid.js @@ -197,19 +197,19 @@ const StatsBoxGrid = () => { // Skip APIs when not in production if (process.env.NODE_ENV !== "production") { setEthPrice({ - value: formatPrice(1330), + value: formatPrice(2265), hasError: false, }) setValueLocked({ - value: formatTVL(23456789000), + value: formatTVL(57141111000), hasError: false, }) setTxs({ - value: formatTxs(1234567), + value: formatTxs(1305167), hasError: false, }) setNodes({ - value: formatNodes(8040), + value: formatNodes(5472), hasError: false, }) } else { diff --git a/src/components/WalletCompare.js b/src/components/WalletCompare.js index 8bdad12b635..565ebd49201 100644 --- a/src/components/WalletCompare.js +++ b/src/components/WalletCompare.js @@ -291,6 +291,9 @@ const WalletCompare = ({ location }) => { zengo: file(relativePath: { eq: "wallets/zengo.png" }) { ...walletCardImage } + walleth: file(relativePath: { eq: "wallets/walleth.png" }) { + ...walletCardImage + } tokenpocket: file(relativePath: { eq: "wallets/tokenpocket.png" }) { ...walletCardImage } diff --git a/src/content/community/grants/index.md b/src/content/community/grants/index.md index 20460d10be7..d76004a0f1b 100644 --- a/src/content/community/grants/index.md +++ b/src/content/community/grants/index.md @@ -15,7 +15,7 @@ This list is curated by our community. If there's something missing or incorrect These programs support the broad Ethereum ecosystem by offering grants to a wide scope of projects. These include solutions for scalability, community building, security, privacy and more. These grants are not specific to any one Ethereum platform, and are a good place to start if you're unsure. -- [EF Ecosystem Support Program](https://esp.ethereum.foundation) - _Rollups, community and education, tooling and testing, infrastructure, interoperability, standards and research, wallets, and more_ +- [EF Ecosystem Support Program](https://esp.ethereum.foundation) - _Funding open source projects that benefit Ethereum, with a particular focus on universal tools, infrastructure, research and public goods_ - [EF Rollup Community Grants Wave](https://esp.ethereum.foundation/en/rollup-grants/) - _For everything related to rollups. Proposals are due April 16th 2021_ - [MetaCartel](https://www.metacartel.org/grants/) - _Dapp development, DAO creation_ Grants ranging from $1K - $8K USD. diff --git a/src/content/developers/docs/accounts/index.md b/src/content/developers/docs/accounts/index.md index e70b50cbef4..ed6236a0780 100644 --- a/src/content/developers/docs/accounts/index.md +++ b/src/content/developers/docs/accounts/index.md @@ -33,7 +33,7 @@ Both account types have the ability to: **Contract** -- Creating an account has a cost because you're using network storage +- Creating a contract has a cost because you're using network storage - Can only send transactions in response to receiving a transaction - Transactions from an external account to a contract account can trigger code which can execute many different actions, such as transferring tokens or even creating a new contract @@ -67,7 +67,7 @@ Example: `fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036415f` -The public key is generated from the private key using the [Elliptic Curve Digital Signature Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm). You get a public address for your account by taking the last 20 bytes of the SHA3 hash of the private key and adding `0x` to the beginning. +The public key is generated from the private key using the [Elliptic Curve Digital Signature Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm). You get a public address for your account by taking the last 20 bytes of the Keccak-256 hash of the public key and adding `0x` to the beginning. Here's an example of creating an account in the console using GETH's `personal_newAccount` diff --git a/src/content/developers/docs/dapps/index.md b/src/content/developers/docs/dapps/index.md index fde67e71b87..777ca1e2f75 100644 --- a/src/content/developers/docs/dapps/index.md +++ b/src/content/developers/docs/dapps/index.md @@ -74,7 +74,7 @@ Tokens must be generated in order to prove the value nodes that contribute to th - [rimble.consensys.design](https://rimble.consensys.design) - [GitHub](https://github.com/ConsenSys/rimble-ui) -**One Click Dapp** **_- FOSS tool for generating dapp frontends from an ABI._** +**One Click Dapp** **_- FOSS tool for generating dapp frontends from an [ABI](/developers/docs/apis/javascript/#interact-with-smart-contract-functions)._** - [oneclickdapp.com](https://oneclickdapp.com) - [GitHub](https://github.com/One-Click-Dapp/one-click-dApp) diff --git a/src/content/developers/tutorials/erc20-annotated-code/index.md b/src/content/developers/tutorials/erc20-annotated-code/index.md index 18de870a294..be0aa51b64f 100644 --- a/src/content/developers/tutorials/erc20-annotated-code/index.md +++ b/src/content/developers/tutorials/erc20-annotated-code/index.md @@ -819,7 +819,7 @@ Make sure to update `_totalSupply` when the total number of tokens changes. } ``` -The `_burn` function is almost identical to `_emit`, except it goes in the other direction. +The `_burn` function is almost identical to `_mint`, except it goes in the other direction. #### The \_approve function {#\_approve} diff --git a/src/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/src/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md new file mode 100644 index 00000000000..90dd425d17e --- /dev/null +++ b/src/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md @@ -0,0 +1,198 @@ +--- +title: "Waffle say hello world tutorial with hardhat and ethers" +description: Make your first Waffle project with hardhat and ethers.js +author: "MiZiet" +tags: + ["waffle", "smart contracts", "solidity", "testing", "hardhat", "ethers.js"] +skill: basic +lang: en +sidebar: true +published: 2020-10-16 +--- + +In this [Waffle](https://ethereum-waffle.readthedocs.io) tutorial, we will learn how to set up a simple "Hello world" smart contract project, using [hardhat](https://hardhat.org/) and [ethers.js](https://docs.ethers.io/v5/). Then we will learn how to add a new functionality to our smart contract and how to test it with Waffle. + +Let's start with creating new project: + +```bash +yarn init +``` + +or + +```bash +npm init +``` + +and installing required packages: + +```bash +yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai +``` + +or + +```bash +npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai +``` + +Next step is creating a sample hardhat project by running `npx hardhat`. + +```bash +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Welcome to Hardhat v2.0.3 👷‍ + +? What do you want to do? … +❯ Create a sample project +Create an empty hardhat.config.js +Quit +``` + +Select `Create a sample project` + +Our project's structure should look like this: + +``` +MyWaffleProject +├── contracts +│ └── Greeter.sol +├── node_modules +├── scripts +│ └── sample-script.js +├── test +│ └── sample-test.js +├── .gitattributs +├── .gitignore +├── hardhat.config.js +└── package.json +``` + +### Now let's talk about some of these files: {#now-lets-talk} + +- Greeter.sol - our smart contract writen in solidity; + +```solidity +contract Greeter { +string greeting; + +constructor(string memory _greeting) public { +console.log("Deploying a Greeter with greeting:", _greeting); +greeting = _greeting; +} + +function greet() public view returns (string memory) { +return greeting; +} + +function setGreeting(string memory _greeting) public { +console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); +greeting = _greeting; +} +} +``` + +Our smart contract can be divided into three parts: + +1. constructor - where we declare a string type variable called `greeting`, +2. function greet - a function that will return the `greeting` when called, +3. function setGreeting - a function that allows us to change the `greeting` value. + +- sample-test.js - our tests file + +```js +describe("Greeter", function () { + it("Should return the new greeting once it's changed", async function () { + const Greeter = await ethers.getContractFactory("Greeter") + const greeter = await Greeter.deploy("Hello, world!") + + await greeter.deployed() + expect(await greeter.greet()).to.equal("Hello, world!") + + await greeter.setGreeting("Hola, mundo!") + expect(await greeter.greet()).to.equal("Hola, mundo!") + }) +}) +``` + +### Next step consists of compiling our contract and running tests: {#compiling-and-testing} + +Waffle tests use Mocha (a test framework) with Chai (an assertion library). All you have to do is run `npx hardhat test` and wait for the following message to appear. + +```bash +✓ Should return the new greeting once it's changed +``` + +### Everything looks great so far, let's add some more complexity to our project {#adding-complexity} + +Imagine a situation where someone adds an empty string as a greeting. It wouldn't be a warm greeting, right? +Let's make sure that doesn't happen: + +We want to use solidity's `revert` when someone passes an empty string. A good thing is that we can easily test this functionality with Waffle's chai matcher `to.be.revertedWith()`. + +```js +it("Should revert when passing an empty string", async () => { + const Greeter = await ethers.getContractFactory("Greeter") + const greeter = await Greeter.deploy("Hello, world!") + + await greeter.deployed() + await expect(greeter.setGreeting("")).to.be.revertedWith( + "Greeting should not be empty" + ) +}) +``` + +Looks like our new test didn't pass: + +```bash +Deploying a Greeter with greeting: Hello, world! +Changing greeting from 'Hello, world!' to 'Hola, mundo!' + ✓ Should return the new greeting once it's changed (1514ms) +Deploying a Greeter with greeting: Hello, world! +Changing greeting from 'Hello, world!' to '' + 1) Should revert when passing an empty string + + + 1 passing (2s) + 1 failing +``` + +Let's implement this functionality into our smart contract: + +```solidity +require(bytes(_greeting).length > 0, "Greeting message is empty"); +``` + +Now, our setGreeting function looks like this: + +```solidity +function setGreeting(string memory _greeting) public { +require(bytes(_greeting).length > 0, "Greeting should not be empty"); +console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); +greeting = _greeting; +} +``` + +Let's run tests again: + +```bash +✓ Should return the new greeting once it's changed (1467ms) +✓ Should revert when passing an empty string (276ms) + +2 passing (2s) +``` + +Congrats! You made it :) + +### Conclusion {#conclusion} + +We made a simple project with Waffle, Hardhat and ethers.js. We learned how to set up a project, add a test and implement new functionality. + +For more great chai matchers to test your smart contracts, check [official Waffle's docs](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). \ No newline at end of file diff --git a/src/content/eips/index.md b/src/content/eips/index.md index fd2b8a4c4a1..03ac231f382 100644 --- a/src/content/eips/index.md +++ b/src/content/eips/index.md @@ -30,9 +30,11 @@ EIP editors are tasked with reviewing EIPs for technical soundness, correct spel - Alex Beregszaszi (EWASM/Ethereum Foundation) - Greg Colvin (Community) - Casey Detrio (EWASM/Ethereum Foundation) +- Matt Garnett (Quilt) - Hudson James (Ethereum Foundation) - Nick Johnson (ENS) - Nick Savers (Community) +- Micah Zoltu (Community) ## Learn more {#learn-more} diff --git a/src/content/translations/ro/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/src/content/translations/ro/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md new file mode 100644 index 00000000000..45966a1192f --- /dev/null +++ b/src/content/translations/ro/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md @@ -0,0 +1,198 @@ +--- +title: "Waffle spune „Salut, lume”; tutorial cu Hardhat și eteri" +description: Realizează primul tău proiect Waffle cu hardhat și ethers.js +author: "MiZiet" +tags: + ["waffle", "contracte inteligente", "solidity", "testare", "hardhat", "ethers.js"] +skill: de bază +lang: ro +sidebar: true +published: 2020-10-16 +--- + +În acest tutorial [Waffle](https://ethereum-waffle.readthedocs.io), vei învăța cum să configurezi un proiect simplu de contract inteligent „Salut, lume”, utilizând [hardhat](https://hardhat.org/) și [ethers.js](https://docs.ethers.io/v5/). Apoi vei învăța cum să adaugi o nouă funcționalitate la contractul tău inteligent și cum să-l testezi cu Waffle. + +Să începem cu crearea unui nou proiect: + +```bash +yarn init +``` + +sau + +```bash +npm init +``` + +și instalează pachetele necesare: + +```bash +yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai +``` + +sau + +```bash +npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai +``` + +Următorul pas este crearea unui exemplu de proiect hardhat executând `npx hardhat`. + +```bash +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Bun venit la Hardhat v2.0.3 👷‍ + +? What do you want to do ? (Ce vrei să faci?) … +Create a sample project (Să creez un exemplu de proiect) +Create an empty hardhat.config.js +Quit +``` + +Selectează `Creează un exemplu de proiect` + +Structura proiectelor noastre ar trebui să arate astfel: + +``` +MyWaffleProject +├── contracts +│ └── Greeter.sol +├── node_modules +├── scripts +│ └── sample-script.js +├── test +│ └── sample-test.js +├── .gitattributs +├── .gitignore +├── hardhat.config.js +└── package.json +``` + +### Acum să vorbim despre unele dintre aceste fișiere: {#now-lets-talk} + +- Greeter.sol - contractul nostru inteligent scris în solidity; + +```solidity +contract Greeter { +string greeting; + +constructor(string memory _greeting) public { +console.log("Implementare program Greeter cu salutări:", _greeting); +greeting = _greeting; +} + +function greet() public view returns (string memory) { +return greeting; +} + +function setGreeting(string memory _greeting) public { +console.log("Schimbare salut din '%s' în '%s'", greeting, _greeting); +greeting = _greeting; +} +} +``` + +Contractul nostru inteligent poate fi împărțit în trei părți: + +1. „constructor” - unde declarăm o variabilă de tip string numită `greeting`, +2. funcția „greet” -o funcție care va returna `greeting` atunci când este apelată, +3. funcția „setGreeting” - o funcție care ne permite să schimbăm valoarea `greeting`. + +- sample-test.js - fișierul nostru de teste + +```js +describe("Greeter", function () { + it("Trebuie să returneze noul mesaj de salut odată ce a fost schimbat", async function () { + const Greeter = await ethers.getContractFactory("Greeter") + const greeter = await Greeter.deploy("Hello, world!") + + await greeter.deployed() + expect(await greeter.greet()).to.equal("Hello, world!") + + await greeter.setGreeting("Salut, lume!") + expect(await greeter.greet()).to.equal("Salut, lume!") + }) +}) +``` + +### Pasul următor constă în compilarea contractelor și a testelor de execuție: {#compiling-and-testing} + +Testele Waffle folosesc Mocha (un cadru de testare) cu Chai (o bibliotecă de afirmații). Tot ce trebuie să faci este să rulezi `npx hardhat test` și să aștepți să apară următorul mesaj. + +```bash +✓ Trebuie să returneze noul mesaj de salut odată ce a fost schimbat +``` + +### Totul arată bine până acum, hai să adăugăm ceva mai multă complexitate proiectului nostru {#adding-complexity} + +Imaginează-ți o situație când cineva adaugă un string gol ca salut. Nu ar fi un salut călduros, nu? +Să ne asigurăm că acest lucru nu se întâmplă: + +Vrem să folosim funcția solidity `revert` atunci când cineva transmite un string gol. Un lucru bun este că putem testa cu ușurință această funcționalitate cu validatorul matcher chai `to.bo.revertedWith()` a lui Waffle.. + +```js +it("Trebuie să se schimbe când se transmite un string gol", async () => { + const Greeter = await ethers.getContractFactory("Greeter") + const greeter = await Greeter.deploy("Hello, world!") + + await greeter.deployed() + await expect(greeter.setGreeting("")).to.be.revertedWith( + "Salutul nu trebuie să rămână gol" + ) +}) +``` + +Se pare că noul nostru test nu a trecut: + +```bash +Implementarea unui Greeter cu salut: Hello, world! +Schimbarea salutului din „Hello, world!” în „Salut, lume!” + ✓ Trebuie să returneze noul mesaj de salut odată ce a fost schimbat (1514 ms) +Implementarea unui Greeter cu salut: Salut, lume! +Schimbarea salutului din „Salut, lume!” în „ + 1) Trebuie să se schimbe când se transmite un string gol + + + 1 transmitere (2 s) + 1 nereușită +``` + +Să implementăm această funcționalitate în contractul nostru inteligent: + +```solidity +require(bytes(_greeting).length > 0, "Mesajul de salut este gol"); +``` + +Acum, funcția noastră „setGreeting” arată astfel: + +```solidity +function setGreeting(string memory _greeting) public { +require(bytes(_greeting).length > 0, "Salutul nu trebuie să fie gol"); +console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); +greeting = _greeting; +} +``` + +Să rulăm din nou testele: + +```bash +✓ Trebuie să returneze noul mesaj de salut odată ce a fost schimbat (1467 ms) +✓ Trebuie să se schimbe când se transmite un string gol (276 ms) + +2 transmiteri (2 secunde) +``` + +Felicitări! Ai reușit :) + +### Concluzie {#conclusion} + +Am făcut un proiect simplu cu Waffle, Hardhat și ethers.js. Am învățat cum să configurăm un proiect, să adăugăm un test și să implementăm noi funcționalități. + +Pentru mai mulți validatori matcher chai de mare valoare pentru testarea contractelor inteligente consultă [documentele oficiale Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). \ No newline at end of file diff --git a/src/data/wallets.csv b/src/data/wallets.csv index 6b18841a43b..0cb577a8f0a 100644 --- a/src/data/wallets.csv +++ b/src/data/wallets.csv @@ -29,3 +29,4 @@ unstoppable,Unstoppable,https://unstoppable.money/,#000,TRUE,FALSE,FALSE,FALSE,F guarda,Guarda Wallet,https://guarda.com/,#FFF,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE linen,Linen,https://linen.app/,#FFF,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,FALSE coinomi,Coinomi,https://www.coinomi.com/en/,#11b8ef,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,FALSE,TRUE +walleth,WallETH,https://walleth.org,#FFF,TRUE,FALSE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE diff --git a/src/intl/en/page-assets.json b/src/intl/en/page-assets.json index 70b0951a5ba..4c78f89b6fc 100644 --- a/src/intl/en/page-assets.json +++ b/src/intl/en/page-assets.json @@ -1,6 +1,10 @@ { "page-assets-bazaar": "Ethereum bazaar", + "page-assets-beacon-chain": "Beacon Chain", "page-assets-blocks": "Building blocks", + "page-assets-dao": "DAO", + "page-assets-defi": "DeFi", + "page-assets-merge": "The Merge", "page-assets-doge": "Doge using dapps", "page-assets-download-artist": "Artist:", "page-assets-download-download": "Download", @@ -23,14 +27,21 @@ "page-assets-eth-wordmark-purple": "ETH wordmark (purple)", "page-assets-eth-wordmark-white": "ETH wordmark (white)", "page-assets-ethereum-brand-assets": "Ethereum \"brand\" assets", + "page-assets-finance": "Finance", + "page-assets-future": "Future", "page-assets-h1": "ethereum.org assets", "page-assets-hero": "ethereum.org hero", "page-assets-hero-particles": "ETH particles image", "page-assets-historical-artwork": "Historical artwork", "page-assets-illustrations": "Illustrations", + "page-assets-impact": "Impact", + "page-assets-infrastructure": "Infrastructure", "page-assets-meta-desc": "Explore and download Ethereum and ethereum.org brand assets, illustrations and media.", "page-assets-meta-title": "Ethereum brand assets", + "page-assets-mainnet": "Mainnet", "page-assets-page-assets-solid-background": "Solid background", "page-assets-page-assets-transparent-background": "Transparent background", - "page-assets-robot": "Robot wallet" + "page-assets-robot": "Robot wallet", + "page-assets-sharding": "Sharding", + "page-assets-hackathon": "Hackathon" } diff --git a/src/intl/en/page-wallets-find-wallet.json b/src/intl/en/page-wallets-find-wallet.json index 9d292c5eeec..d35806d2fa7 100644 --- a/src/intl/en/page-wallets-find-wallet.json +++ b/src/intl/en/page-wallets-find-wallet.json @@ -60,6 +60,7 @@ "page-find-wallet-description-trust": "Trust Wallet is a decentralized multi-coin cryptocurrency wallet. Buy crypto, explore dapps, swap assets, and more while keeping control of your keys.", "page-find-wallet-description-unstoppable": "Unstoppable Wallet is an open-source, non-custodial storage solution known for its intuitive design and frictionless user experience. Natively integrates decentralized trading/exchange capabilities.", "page-find-wallet-description-zengo": "ZenGo is the first keyless crypto wallet. With ZenGo, there are no private keys, passwords or seed phrases to manage or lose. Buy, trade, earn and store Ethereum with unprecedented simplicity and safety", + "page-find-wallet-description-walleth": "100% open source (GPLv3) and native Android Ethereum Wallet for your service since 2017. Connect to your favorite Ethereum Applications via WalletConnect and use it directly with hardware wallets like the TREZOR or KeepKey via USB or the KeyCard via NFC.", "page-find-wallet-dharma-logo-alt": "Dharma logo", "page-find-wallet-enjin-logo-alt": "Enjin logo", "page-find-wallet-Ethereum-wallets": "Ethereum Wallets", @@ -121,5 +122,6 @@ "page-find-wallet-withdraw-desc": "You can cash out your ETH straight to your bank account without going through an exchange.", "page-find-wallet-yet": "yet", "page-find-wallet-zengo-logo-alt": "ZenGo logo", + "page-find-wallet-walleth-logo-alt": "WallETH logo", "page-stake-eth": "Stake ETH" } diff --git a/src/pages-conditional/wallets/index.js b/src/pages-conditional/wallets/index.js index af5485ff01e..3a71d8502c3 100644 --- a/src/pages-conditional/wallets/index.js +++ b/src/pages-conditional/wallets/index.js @@ -728,5 +728,8 @@ export const query = graphql` tokenpocket: file(relativePath: { eq: "wallets/tokenpocket.png" }) { ...listImage } + walleth: file(relativePath: { eq: "wallets/walleth.png" }) { + ...listImage + } } ` diff --git a/src/pages/assets.js b/src/pages/assets.js index df8e097de43..6f0ad124dbc 100644 --- a/src/pages/assets.js +++ b/src/pages/assets.js @@ -152,6 +152,47 @@ const AssetsPage = ({ data }) => { /> + + + + + + + + + + + { /> + + + + + + + + + + + + + + +

@@ -500,10 +592,10 @@ export const query = graphql` hero: file(relativePath: { eq: "home/hero.png" }) { ...heroImage } - developers: file(relativePath: { eq: "developers-eth-blocks.png" }) { + doge: file(relativePath: { eq: "doge-computer.png" }) { ...assetItem } - doge: file(relativePath: { eq: "doge-computer.png" }) { + developers: file(relativePath: { eq: "developers-eth-blocks.png" }) { ...assetItem } enterprise: file(relativePath: { eq: "enterprise-eth.png" }) { @@ -512,12 +604,47 @@ export const query = graphql` wallet: file(relativePath: { eq: "wallet.png" }) { ...assetItem } - eth: file(relativePath: { eq: "eth.png" }) { + hackathon: file(relativePath: { eq: "hackathon_transparent.png" }) { + ...assetItem + } + impact: file(relativePath: { eq: "impact_transparent.png" }) { + ...assetItem + } + future: file(relativePath: { eq: "future_transparent.png" }) { + ...assetItem + } + finance: file(relativePath: { eq: "finance_transparent.png" }) { + ...assetItem + } + infrastructure: file( + relativePath: { eq: "infrastructure_transparent.png" } + ) { ...assetItem } whatIsEthereum: file(relativePath: { eq: "what-is-ethereum.png" }) { ...assetItem } + eth: file(relativePath: { eq: "eth.png" }) { + ...assetItem + } + oldShip: file(relativePath: { eq: "eth2/oldship.png" }) { + ...assetItem + } + merge: file(relativePath: { eq: "eth2/merge.png" }) { + ...assetItem + } + beaconChain: file(relativePath: { eq: "eth2/core.png" }) { + ...assetItem + } + newRings: file(relativePath: { eq: "eth2/newrings.png" }) { + ...assetItem + } + defi: file(relativePath: { eq: "use-cases/defi.png" }) { + ...assetItem + } + dao: file(relativePath: { eq: "use-cases/dao-2.png" }) { + ...assetItem + } ethGifCat: file(relativePath: { eq: "eth-gif-cat.png" }) { ...assetItem } diff --git a/src/pages/studio.js b/src/pages/studio.js index f46bcce98bd..23b3265c0c8 100644 --- a/src/pages/studio.js +++ b/src/pages/studio.js @@ -2,7 +2,6 @@ import React from "react" import styled from "styled-components" import Link from "../components/Link" -import Icon from "../components/Icon" import Emoji from "../components/Emoji" import ButtonLink from "../components/ButtonLink" import { Page, Content, Divider } from "../components/SharedStyledComponents" diff --git a/src/pages/wallets/find-wallet.js b/src/pages/wallets/find-wallet.js index 651d33fac92..5d9b213f975 100644 --- a/src/pages/wallets/find-wallet.js +++ b/src/pages/wallets/find-wallet.js @@ -13,7 +13,6 @@ import InfoBanner from "../../components/InfoBanner" import PageMetadata from "../../components/PageMetadata" import WalletCompare from "../../components/WalletCompare" import { Divider, Page } from "../../components/SharedStyledComponents" -import { BsTypeH1 } from "react-icons/bs" const Subtitle = styled.div` font-size: 20px; diff --git a/src/templates/job.js b/src/templates/job.js index 0d8d78aa93a..754bc1dd462 100644 --- a/src/templates/job.js +++ b/src/templates/job.js @@ -6,14 +6,11 @@ import { MDXRenderer } from "gatsby-plugin-mdx" import styled from "styled-components" import Img from "gatsby-image" import ButtonLink from "../components/ButtonLink" -import MarkdownTable from "../components/MarkdownTable" import Link from "../components/Link" import PageMetadata from "../components/PageMetadata" -import Translation from "../components/Translation" import { isLangRightToLeft } from "../utils/translations" import Emoji from "../components/Emoji" import { - Divider, Paragraph, Header1, Header4, diff --git a/src/templates/use-cases.js b/src/templates/use-cases.js index f58c114f97e..aa4d942de04 100644 --- a/src/templates/use-cases.js +++ b/src/templates/use-cases.js @@ -8,7 +8,6 @@ import Img from "gatsby-image" import ButtonLink from "../components/ButtonLink" import ButtonDropdown from "../components/ButtonDropdown" import BannerNotification from "../components/BannerNotification" -import Breadcrumbs from "../components/Breadcrumbs" import Card from "../components/Card" import ExpandableCard from "../components/ExpandableCard" import DocLink from "../components/DocLink" diff --git a/yarn.lock b/yarn.lock index 71a1c2402a9..53e3c576de5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5987,9 +5987,9 @@ dns-equal@^1.0.0: integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-packet@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== dependencies: ip "^1.1.0" safe-buffer "^5.0.1"