From a738b4dc35290c6b937c7e4802036bc7da8b747e Mon Sep 17 00:00:00 2001 From: sneg55 Date: Wed, 22 Feb 2023 14:56:55 -0800 Subject: [PATCH 01/27] DexGuru Added [Fixes #9172] --- src/assets/dapps/dexguru.png | Bin 0 -> 40416 bytes src/intl/en/page-dapps.json | 2 ++ src/pages-conditional/dapps.tsx | 13 +++++++++++++ 3 files changed, 15 insertions(+) create mode 100644 src/assets/dapps/dexguru.png diff --git a/src/assets/dapps/dexguru.png b/src/assets/dapps/dexguru.png new file mode 100644 index 0000000000000000000000000000000000000000..b1bc761a88513745df5077143f5723e33b22e3a9 GIT binary patch literal 40416 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 literal 0 HcmV?d00001 diff --git a/src/intl/en/page-dapps.json b/src/intl/en/page-dapps.json index 42fefea3494..7eb5d33a096 100644 --- a/src/intl/en/page-dapps.json +++ b/src/intl/en/page-dapps.json @@ -1,5 +1,6 @@ { "page-dapps-1inch-logo-alt": "1inch logo", + "page-dapps-dexguru-logo-alt": "DexGuru logo", "page-dapps-aave-logo-alt": "Aave logo", "page-dapps-add-button": "Suggest dapp", "page-dapps-add-title": "Add dapp", @@ -86,6 +87,7 @@ "page-dapps-dapp-description-token-sets": "Crypto investment strategies that automatically rebalance.", "page-dapps-dapp-description-tornado-cash": "Send anonymous transactions on Ethereum.", "page-dapps-dapp-description-uniswap": "Swap tokens simply or provide tokens for % rewards.", + "page-dapps-dapp-description-dexguru": "Non-custodial trading terminal for DeFi traders", "page-dapps-docklink-dapps": "Intro to dapps", "page-dapps-docklink-smart-contracts": "Smart contracts", "page-dapps-dark-forest-logo-alt": "Dark Forest logo", diff --git a/src/pages-conditional/dapps.tsx b/src/pages-conditional/dapps.tsx index 7bc175834bb..884e459bea2 100644 --- a/src/pages-conditional/dapps.tsx +++ b/src/pages-conditional/dapps.tsx @@ -697,6 +697,16 @@ const DappsPage = ({ image: getImage(data.oneinch), alt: translateMessageId("page-dapps-1inch-logo-alt", intl), }, + { + title: "DexGuru", + description: translateMessageId( + "page-dapps-dapp-description-dexguru", + intl + ), + link: "https://dex.guru", + image: getImage(data.dexguru), + alt: translateMessageId("page-dapps-dexguru-logo-alt", intl), + }, ] const trading = [ @@ -1932,5 +1942,8 @@ export const query = graphql` balancer: file(relativePath: { eq: "dapps/balancer.png" }) { ...dappImage } + dexguru: file(relativePath: { eq: "dapps/dexguru.png" }) { + ...dappImage + } } ` From 7ec1835a45c89b45750314cd2cee47361530b6a2 Mon Sep 17 00:00:00 2001 From: Tarun Samanta Date: Tue, 18 Apr 2023 10:19:11 +0530 Subject: [PATCH 02/27] implemented feature --- src/pages/layer-2.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pages/layer-2.tsx b/src/pages/layer-2.tsx index eed9be64ffe..004fab31082 100644 --- a/src/pages/layer-2.tsx +++ b/src/pages/layer-2.tsx @@ -749,16 +749,22 @@ const Layer2Page = ({ data }: PageProps) => { - +
    +
  • + - +
  • +
  • + +
  • +
From e14d1ad55448b63bf47f34da4e6de4bcd861a1ea Mon Sep 17 00:00:00 2001 From: soheil Date: Thu, 20 Apr 2023 23:58:20 +0330 Subject: [PATCH 03/27] refactor(staking-template): migrate to chakra --- src/templates/staking.tsx | 589 +++++++++++++++++++++----------------- 1 file changed, 320 insertions(+), 269 deletions(-) diff --git a/src/templates/staking.tsx b/src/templates/staking.tsx index f3c8619106d..ca6a4948ac7 100644 --- a/src/templates/staking.tsx +++ b/src/templates/staking.tsx @@ -1,10 +1,24 @@ -import React, { FC } from "react" +import React from "react" import { graphql, PageProps } from "gatsby" import { MDXRenderer } from "gatsby-plugin-mdx" import { GatsbyImage } from "gatsby-plugin-image" import { MDXProvider } from "@mdx-js/react" -import styled from "@emotion/styled" -import { Badge, Box, BoxProps } from "@chakra-ui/react" +import { + Badge, + Box, + BoxProps, + Flex, + Heading, + SimpleGrid, + Text, + useTheme, + chakra, + calc, + Grid, + Image, + UnorderedList, +} from "@chakra-ui/react" + import ButtonLink from "../components/ButtonLink" import ButtonDropdown, { List as ButtonDropdownList, @@ -13,7 +27,9 @@ import Card from "../components/Card" import ExpandableCard from "../components/ExpandableCard" import DocLink from "../components/DocLink" import Contributors from "../components/Contributors" -import SharedInfoBanner from "../components/InfoBanner" +import SharedInfoBanner, { + IProps as ISharedInfoBannerProps, +} from "../components/InfoBanner" import UpgradeStatus from "../components/UpgradeStatus" import Link from "../components/Link" import MarkdownTable from "../components/MarkdownTable" @@ -27,14 +43,7 @@ import TableOfContents, { } from "../components/TableOfContents" import FeedbackCard from "../components/FeedbackCard" import SectionNav from "../components/SectionNav" -import { - Divider, - Paragraph, - Header1, - Header4, - InfoGrid, -} from "../components/SharedStyledComponents" -import Emoji from "../components/OldEmoji" +import Emoji from "../components/Emoji" import YouTube from "../components/YouTube" import Breadcrumbs from "../components/Breadcrumbs" import StakingLaunchpadWidget from "../components/Staking/StakingLaunchpadWidget" @@ -49,268 +58,234 @@ import WithdrawalsTabComparison from "../components/Staking/WithdrawalsTabCompar import Callout from "../components/Callout" import { isLangRightToLeft, TranslationKey } from "../utils/translations" -import { Context } from "../types" import { Lang } from "../utils/languages" import { getImage } from "../utils/image" -const Page = styled.div` - display: flex; - justify-content: space-between; - width: 100%; - margin: 0 auto 4rem; - - @media (min-width: ${(props) => props.theme.breakpoints.l}) { - padding-top: 4rem; - } - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - flex-direction: column; - } -` - -const InfoColumn = styled.aside` - display: flex; - flex-direction: column; - position: sticky; - top: 6.25rem; /* account for navbar */ - height: calc(100vh - 80px); - flex: 0 1 330px; - margin: 0 2rem; - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - display: none; - } -` - -const MobileButton = styled.div` - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - background: ${(props) => props.theme.colors.background}; - box-shadow: 0 -1px 0px ${(props) => props.theme.colors.border}; - width: 100%; - bottom: 0; - position: sticky; - padding: 2rem; - z-index: 99; - margin-bottom: 0rem; - } -` +import { ChildOnlyProp, Context } from "../types" // Apply styles for classes within markdown here -const ContentContainer = styled.article` - flex: 1 1 ${(props) => props.theme.breakpoints.l}; - position: relative; - padding: 2rem; - padding-top: 0rem; - - @media (min-width: ${({ theme }) => theme.breakpoints.l}) { - h2:first-of-type { - margin-top: 0; - } - } - - .featured { - padding-left: 1rem; - margin-left: -1rem; - border-left: 1px dotted ${(props) => props.theme.colors.primary}; - } - - .citation { - p { - color: ${(props) => props.theme.colors.text200}; - } - } -` - -const Pre = styled.pre` - max-width: 100%; - overflow-x: scroll; - background-color: ${(props) => props.theme.colors.preBackground}; - border-radius: 0.25rem; - padding: 1rem; - border: 1px solid ${(props) => props.theme.colors.preBorder}; - white-space: pre-wrap; -` - -const InfoTitle = styled.h2` - font-size: 3rem; - font-weight: 700; - text-align: right; - margin-top: 0rem; - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - text-align: left; - font-size: 2.5rem - display: none; - } -` - -const H2 = styled.h2` - font-size: 2rem; - font-weight: 700; - margin-top: 4rem; - - a { - display: none; - } - - /* Anchor tag styles */ - - a { - position: relative; - display: initial; - opacity: 0; - margin-left: -1.5em; - padding-right: 0.5rem; - font-size: 1rem; - vertical-align: middle; - &:hover { - display: initial; - fill: ${(props) => props.theme.colors.primary}; - opacity: 1; - } - } - - &:hover { - a { - display: initial; - fill: ${(props) => props.theme.colors.primary}; - opacity: 1; - } - } -` - -const H3 = styled.h3` - font-size: 1.5rem; - font-weight: 700; - - a { - display: none; - } - - /* Anchor tag styles */ - - a { - position: relative; - display: initial; - opacity: 0; - margin-left: -1.5em; - padding-right: 0.5rem; - font-size: 1rem; - vertical-align: middle; - &:hover { - display: initial; - fill: ${(props) => props.theme.colors.primary}; - opacity: 1; - } - } +const Divider = (props: ChildOnlyProp) => ( + +) - &:hover { - a { - display: initial; - fill: ${(props) => props.theme.colors.primary}; - opacity: 1; - } - } -` +const Paragraph = (props: ChildOnlyProp) => ( + +) -const CardGrid = styled.div` - display: grid; - grid-template-columns: repeat(3, 1fr); +const Header1 = (props: ChildOnlyProp) => ( + +) - gap: 2rem; - h3 { - margin-top: 0; - } +const Header4 = (props: ChildOnlyProp) => ( + +) - @media (max-width: ${(props) => props.theme.breakpoints.m}) { - grid-template-columns: repeat(1, 1fr); - margin: auto; - } -` +const InfoGrid = (props: ChildOnlyProp) => ( + div": { + h: "fit-content", + m: 0, + "&:hover": { + transition: "0.1s", + transform: "scale(1.01)", + svg: { + transition: "0.1s", + transform: "scale(1.1)", + }, + }, + }, + }} + {...props} + /> +) -const Title = styled.h1` - font-size: 2.5rem; - font-weight: 700; - margin-top: 1rem; -` +const Pre = (props: ChildOnlyProp) => ( + +) -const SummaryPoint = styled.li` - color: ${(props) => props.theme.colors.text300}; -` +const InfoTitle = (props: ChildOnlyProp) => ( + +) -const StyledButtonDropdown = styled(ButtonDropdown)` - margin-bottom: 2rem; - display: flex; - justify-content: flex-end; - text-align: center; - @media (min-width: ${(props) => props.theme.breakpoints.s}) { - align-self: flex-end; - } -` +const H2 = (props: ChildOnlyProp) => ( + +) -const MobileButtonDropdown = styled(StyledButtonDropdown)` - margin-bottom: 0rem; - display: none; - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - display: block; - } -` +const H3 = (props: ChildOnlyProp) => ( + +) -const Container = styled.div` - position: relative; - * { - scroll-margin-top: 5.5rem; - } -` +const CardGrid = (props: ChildOnlyProp) => ( + +) -const HeroContainer = styled.div` - display: flex; - align-items: center; - padding: 2rem; - --height: 500px; - max-height: var(--height); - min-height: var(--height); - background: ${({ theme }) => theme.colors.layer2Gradient}; - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - flex-direction: column; - max-height: 100%; - padding-left: 0; - padding-right: 0; - } -` +const Title = (props: ChildOnlyProp) => ( + +) -const Image = styled(GatsbyImage)` - flex: 1 1 100%; - background-repeat: no-repeat; - right: 0; - bottom: 0; - max-width: 400px; - @media (max-width: ${({ theme }) => theme.breakpoints.l}) { - width: 100%; - height: 100%; - max-height: 340px; - max-width: min(400px, 98%); - overflow: initial; - align-self: center; - margin: 0; - } -` +const SummaryPoint = (props: ChildOnlyProp) => ( + +) -const MobileTableOfContents = styled(TableOfContents)` - position: relative; - z-index: 2; -` +const Container = (props: ChildOnlyProp) => ( + +) -const TitleCard = styled.div` - padding: 2rem; - display: flex; - flex-direction: column; - justify-content: flex-start; - width: 100%; -` +const HeroContainer = (props: ChildOnlyProp) => { + return ( + + ) +} -const InfoBanner = styled(SharedInfoBanner)` - margin: 2rem 0; -` +const InfoBanner = (props: ISharedInfoBannerProps) => ( + +) -const TableContainer: FC = (props) => ( +const TableContainer = (props: BoxProps) => ( - + {mdx.frontmatter.title} -
    + {(summaryPoints || []).map((point, idx) => ( {point} ))} -
- + -
+
{mdx.frontmatter.alt - + - - + + {mdx.frontmatter.title} {tocItems && ( @@ -474,18 +486,57 @@ const StakingPage = ({ maxDepth={mdx.frontmatter.sidebarDepth!} /> )} - - + + {mdx.body} - - - - - +
+ + + + ) } From cc35bf861cd64f03ab88aa675ce1c2ee36959a47 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 21 Apr 2023 15:06:17 -0400 Subject: [PATCH 04/27] refactor(wallet-table): move logic into a hook --- .../index.tsx} | 349 ++---------------- .../FindWallet/WalletTable/useWalletTable.tsx | 337 +++++++++++++++++ src/data/wallets/wallet-data.ts | 2 +- 3 files changed, 374 insertions(+), 314 deletions(-) rename src/components/FindWallet/{WalletTable.tsx => WalletTable/index.tsx} (71%) create mode 100644 src/components/FindWallet/WalletTable/useWalletTable.tsx diff --git a/src/components/FindWallet/WalletTable.tsx b/src/components/FindWallet/WalletTable/index.tsx similarity index 71% rename from src/components/FindWallet/WalletTable.tsx rename to src/components/FindWallet/WalletTable/index.tsx index 574d57b05f5..ae1f1c31907 100644 --- a/src/components/FindWallet/WalletTable.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -1,50 +1,31 @@ // Libraries -import React, { ReactNode, useState } from "react" +import React, { ReactNode } from "react" import { GatsbyImage } from "gatsby-plugin-image" import { keyframes } from "@emotion/react" import styled from "@emotion/styled" import { useTranslation } from "gatsby-plugin-react-i18next" // Components -import ButtonLink from "../ButtonLink" -import Icon from "../Icon" -import Link from "../Link" -import { StyledSelect as Select } from "../SharedStyledComponents" -import Tooltip from "../Tooltip" -import Translation from "../Translation" +import ButtonLink from "../../ButtonLink" +import Icon from "../../Icon" +import Link from "../../Link" +import { StyledSelect as Select } from "../../SharedStyledComponents" +import Tooltip from "../../Tooltip" +import Translation from "../../Translation" // Data -import walletFilterData from "../../data/wallets/wallet-filters" +import walletFilterData from "../../../data/wallets/wallet-filters" // Icons import { GreenCheckProductGlyphIcon, WarningProductGlyphIcon, -} from "../icons/staking" -import { - BuyCryptoIcon, - ConnectDappsIcon, - EIP1559Icon, - ENSSupportIcon, - ERC20SupportIcon, - GasFeeCustomizationIcon, - HardwareSupportIcon, - Layer2Icon, - MultisigIcon, - NFTSupportIcon, - NonCustodialIcon, - OpenSourceWalletIcon, - RPCImportingIcon, - SocialRecoverIcon, - StakingIcon, - SwapIcon, - WalletConnectIcon, - WithdrawCryptoIcon, -} from "../icons/wallets" +} from "../../icons/staking" // Utils -import { trackCustomEvent } from "../../utils/matomo" -import { getImage } from "../../utils/image" +import { trackCustomEvent } from "../../../utils/matomo" +import { getImage } from "../../../utils/image" +import { useWalletTable } from "./useWalletTable" // Styles const Container = styled.table` @@ -470,291 +451,33 @@ export interface DropdownOption { icon: ReactNode } -type ColumnClassName = "firstCol" | "secondCol" | "thirdCol" - // Constants const firstCol = "firstCol" const secondCol = "secondCol" const thirdCol = "thirdCol" -const WalletTable = ({ data, filters, walletData }) => { - const { t } = useTranslation() - const featureDropdownItems: Array = [ - { - label: t("page-find-wallet-open-source"), - value: t("page-find-wallet-open-source"), - filterKey: "open_source", - category: "security", - icon: , - }, - { - label: t("page-find-wallet-self-custody"), - value: t("page-find-wallet-self-custody"), - filterKey: "non_custodial", - category: "security", - icon: , - }, - { - label: t("page-find-wallet-hardware-wallet-support"), - value: t("page-find-wallet-hardware-wallet-support"), - filterKey: "hardware_support", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-walletconnect"), - value: t("page-find-wallet-walletconnect"), - filterKey: "walletconnect", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-rpc-importing"), - value: t("page-find-wallet-rpc-importing"), - filterKey: "rpc_importing", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-nft-support"), - value: t("page-find-wallet-nft-support"), - filterKey: "nft_support", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-connect-to-dapps"), - value: t("page-find-wallet-connect-to-dapps"), - filterKey: "connect_to_dapps", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-staking"), - value: t("page-find-wallet-staking"), - filterKey: "staking", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-swaps"), - value: t("page-find-wallet-swaps"), - filterKey: "swaps", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-layer-2"), - value: t("page-find-wallet-layer-2"), - filterKey: "layer_2", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-gas-fee-customization"), - value: t("page-find-wallet-gas-fee-customization"), - filterKey: "gas_fee_customization", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-ens-support"), - value: t("page-find-wallet-ens-support"), - filterKey: "ens_support", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-token-importing"), - value: t("page-find-wallet-token-importing"), - filterKey: "erc_20_support", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-fee-optimization"), - value: t("page-find-wallet-fee-optimization"), - filterKey: "eip_1559_support", - category: "feature", - icon: , - }, - { - label: t("page-find-wallet-buy-crypto"), - value: t("page-find-wallet-buy-crypto"), - filterKey: "buy_crypto", - category: "trade_and_buy", - icon: , - }, - { - label: t("page-find-wallet-sell-for-fiat"), - value: t("page-find-wallet-sell-for-fiat"), - filterKey: "withdraw_crypto", - category: "trade_and_buy", - icon: , - }, - { - label: t("page-find-wallet-multisig"), - value: t("page-find-wallet-multisig"), - filterKey: "multisig", - category: "smart_contract", - icon: , - }, - { - label: t("page-find-wallet-social-recovery"), - value: t("page-find-wallet-social-recovery"), - filterKey: "social_recovery", - category: "smart_contract", - icon: , - }, - ] - - const [walletCardData, setWalletData] = useState( - walletData.map((wallet) => { - return { ...wallet, moreInfo: false, key: wallet.image_name } - }) - ) - const [firstFeatureSelect, setFirstFeatureSelect] = useState( - featureDropdownItems[14] - ) - const [secondFeatureSelect, setSecondFeatureSelect] = useState( - featureDropdownItems[1] - ) - const [thirdFeatureSelect, setThirdFeatureSelect] = useState( - featureDropdownItems[9] - ) - - const updateMoreInfo = (key) => { - const temp = [...walletCardData] - - for (const [idx, wallet] of temp.entries()) { - if (wallet.key === key) { - temp[idx].moreInfo = !temp[idx].moreInfo - break - } - } - - setWalletData(temp) - } - - const filteredWallets = walletCardData.filter((wallet) => { - let showWallet = true - let mobileCheck = true - let desktopCheck = true - let browserCheck = true - let hardwareCheck = true - - const featureFilterKeys = featureDropdownItems.map((item) => item.filterKey) - const deviceFilters = Object.entries(filters).filter( - (item) => !featureFilterKeys.includes(item[0]) - ) - const mobileFiltersTrue = deviceFilters - .filter((item) => item[0] === "ios" || item[0] === "android") - .filter((item) => item[1]) - .map((item) => item[0]) - const desktopFiltersTrue = deviceFilters - .filter( - (item) => - item[0] === "linux" || item[0] === "windows" || item[0] === "macOS" - ) - .filter((item) => item[1]) - .map((item) => item[0]) - const browserFiltersTrue = deviceFilters - .filter((item) => item[0] === "firefox" || item[0] === "chromium") - .filter((item) => item[1]) - .map((item) => item[0]) - const hardwareFiltersTrue = deviceFilters - .filter((item) => item[0] === "hardware") - .filter((item) => item[1]) - .map((item) => item[0]) - - for (let item of mobileFiltersTrue) { - if (wallet[item]) { - mobileCheck = true - break - } else { - mobileCheck = false - } - } - - for (let item of desktopFiltersTrue) { - if (wallet[item]) { - desktopCheck = true - break - } else { - desktopCheck = false - } - } - - for (let item of browserFiltersTrue) { - if (wallet[item]) { - browserCheck = true - break - } else { - browserCheck = false - } - } - - for (let item of hardwareFiltersTrue) { - if (wallet[item]) { - hardwareCheck = true - break - } else { - hardwareCheck = false - } - } - - featureFilterKeys.forEach((filter) => { - if (filters[filter] && showWallet === true) { - showWallet = filters[filter] === wallet[filter] - } - }) - - return ( - mobileCheck && desktopCheck && browserCheck && hardwareCheck && showWallet - ) - }) - - const filteredFeatureDropdownItems = [...featureDropdownItems].filter( - (item) => { - return ( - item.label !== firstFeatureSelect.label && - item.label !== secondFeatureSelect.label && - item.label !== thirdFeatureSelect.label - ) - } - ) - - /** - * - * @param selectedOption selected dropdown option - * @param stateUpdateMethod method for updating state for dropdown - * @param className className of column - * - * This method gets the elements with the className, adds a fade class to fade icons out, after 0.5s it will then update state for the dropdown with the selectedOption, and then remove the fade class to fade the icons back in. Then it will send a matomo event for updating the dropdown. - */ - const updateDropdown = ( - selectedOption: DropdownOption, - stateUpdateMethod: Function, - className: ColumnClassName - ) => { - const domItems: HTMLCollectionOf = - document.getElementsByClassName(className) - for (let item of domItems) { - item.classList.add("fade") - } - setTimeout(() => { - stateUpdateMethod(selectedOption) - for (let item of domItems) { - item.classList.remove("fade") - } - }, 375) +export interface WalletTableProps { + data: Record + filters: Record + walletData: WalletData[] +} - trackCustomEvent({ - eventCategory: "WalletFeatureCompare", - eventAction: `Select WalletFeatureCompare`, - eventName: `${selectedOption.filterKey} selected`, - }) - } +const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { + const { t } = useTranslation() + const { + featureDropdownItems, + filteredFeatureDropdownItems, + filteredWallets, + setFirstFeatureSelect, + setSecondFeatureSelect, + setThirdFeatureSelect, + updateDropdown, + updateMoreInfo, + firstFeatureSelect, + secondFeatureSelect, + thirdFeatureSelect, + walletCardData, + } = useWalletTable({ filters, t, walletData }) const WalletMoreInfo = ({ wallet, filters, idx }) => { const walletHasFilter = (filterKey) => { @@ -1061,7 +784,7 @@ const WalletTable = ({ data, filters, walletData }) => { eventCategory: "WalletExternalLinkList", eventAction: `Go to wallet`, eventName: `${wallet.name} ${idx}`, - eventValue: filters, + eventValue: JSON.stringify(filters), }} > @@ -1074,7 +797,7 @@ const WalletTable = ({ data, filters, walletData }) => { eventCategory: "WalletExternalLinkList", eventAction: `Go to wallet`, eventName: `${wallet.name} ${idx}`, - eventValue: filters, + eventValue: JSON.stringify(filters), }} > @@ -1088,7 +811,7 @@ const WalletTable = ({ data, filters, walletData }) => { eventCategory: "WalletExternalLinkList", eventAction: `Go to wallet`, eventName: `${wallet.name} ${idx}`, - eventValue: filters, + eventValue: JSON.stringify(filters), }} > diff --git a/src/components/FindWallet/WalletTable/useWalletTable.tsx b/src/components/FindWallet/WalletTable/useWalletTable.tsx new file mode 100644 index 00000000000..5a24ede7496 --- /dev/null +++ b/src/components/FindWallet/WalletTable/useWalletTable.tsx @@ -0,0 +1,337 @@ +import * as React from "react" +import { Icon } from "@chakra-ui/react" +import { useState } from "react" +import { WalletTableProps } from "." +import { trackCustomEvent } from "../../../utils/matomo" +import { + OpenSourceWalletIcon, + NonCustodialIcon, + HardwareSupportIcon, + WalletConnectIcon, + RPCImportingIcon, + NFTSupportIcon, + ConnectDappsIcon, + StakingIcon, + SwapIcon, + Layer2Icon, + GasFeeCustomizationIcon, + ENSSupportIcon, + ERC20SupportIcon, + EIP1559Icon, + BuyCryptoIcon, + WithdrawCryptoIcon, + MultisigIcon, + SocialRecoverIcon, +} from "../../icons/wallets" + +export interface DropdownOption { + label: string + value: string + filterKey: string + category: string + icon: typeof Icon +} + +type ColumnClassName = "firstCol" | "secondCol" | "thirdCol" + +type UseWalletTableProps = Pick & { + t: (x: string) => string +} + +export const useWalletTable = ({ + filters, + t, + walletData, +}: UseWalletTableProps) => { + const featureDropdownItems: Array = [ + { + label: t("page-find-wallet-open-source"), + value: t("page-find-wallet-open-source"), + filterKey: "open_source", + category: "security", + icon: OpenSourceWalletIcon, + }, + { + label: t("page-find-wallet-self-custody"), + value: t("page-find-wallet-self-custody"), + filterKey: "non_custodial", + category: "security", + icon: NonCustodialIcon, + }, + { + label: t("page-find-wallet-hardware-wallet-support"), + value: t("page-find-wallet-hardware-wallet-support"), + filterKey: "hardware_support", + category: "feature", + icon: HardwareSupportIcon, + }, + { + label: t("page-find-wallet-walletconnect"), + value: t("page-find-wallet-walletconnect"), + filterKey: "walletconnect", + category: "feature", + icon: WalletConnectIcon, + }, + { + label: t("page-find-wallet-rpc-importing"), + value: t("page-find-wallet-rpc-importing"), + filterKey: "rpc_importing", + category: "feature", + icon: RPCImportingIcon, + }, + { + label: t("page-find-wallet-nft-support"), + value: t("page-find-wallet-nft-support"), + filterKey: "nft_support", + category: "feature", + icon: NFTSupportIcon, + }, + { + label: t("page-find-wallet-connect-to-dapps"), + value: t("page-find-wallet-connect-to-dapps"), + filterKey: "connect_to_dapps", + category: "feature", + icon: ConnectDappsIcon, + }, + { + label: t("page-find-wallet-staking"), + value: t("page-find-wallet-staking"), + filterKey: "staking", + category: "feature", + icon: StakingIcon, + }, + { + label: t("page-find-wallet-swaps"), + value: t("page-find-wallet-swaps"), + filterKey: "swaps", + category: "feature", + icon: SwapIcon, + }, + { + label: t("page-find-wallet-layer-2"), + value: t("page-find-wallet-layer-2"), + filterKey: "layer_2", + category: "feature", + icon: Layer2Icon, + }, + { + label: t("page-find-wallet-gas-fee-customization"), + value: t("page-find-wallet-gas-fee-customization"), + filterKey: "gas_fee_customization", + category: "feature", + icon: GasFeeCustomizationIcon, + }, + { + label: t("page-find-wallet-ens-support"), + value: t("page-find-wallet-ens-support"), + filterKey: "ens_support", + category: "feature", + icon: ENSSupportIcon, + }, + { + label: t("page-find-wallet-token-importing"), + value: t("page-find-wallet-token-importing"), + filterKey: "erc_20_support", + category: "feature", + icon: ERC20SupportIcon, + }, + { + label: t("page-find-wallet-fee-optimization"), + value: t("page-find-wallet-fee-optimization"), + filterKey: "eip_1559_support", + category: "feature", + icon: EIP1559Icon, + }, + { + label: t("page-find-wallet-buy-crypto"), + value: t("page-find-wallet-buy-crypto"), + filterKey: "buy_crypto", + category: "trade_and_buy", + icon: BuyCryptoIcon, + }, + { + label: t("page-find-wallet-sell-for-fiat"), + value: t("page-find-wallet-sell-for-fiat"), + filterKey: "withdraw_crypto", + category: "trade_and_buy", + icon: WithdrawCryptoIcon, + }, + { + label: t("page-find-wallet-multisig"), + value: t("page-find-wallet-multisig"), + filterKey: "multisig", + category: "smart_contract", + icon: MultisigIcon, + }, + { + label: t("page-find-wallet-social-recovery"), + value: t("page-find-wallet-social-recovery"), + filterKey: "social_recovery", + category: "smart_contract", + icon: SocialRecoverIcon, + }, + ] + + const [walletCardData, setWalletData] = useState( + walletData.map((wallet) => { + return { ...wallet, moreInfo: false, key: wallet.image_name } + }) + ) + const [firstFeatureSelect, setFirstFeatureSelect] = useState( + featureDropdownItems[14] + ) + const [secondFeatureSelect, setSecondFeatureSelect] = useState( + featureDropdownItems[1] + ) + const [thirdFeatureSelect, setThirdFeatureSelect] = useState( + featureDropdownItems[9] + ) + + const updateMoreInfo = (key) => { + const temp = [...walletCardData] + + for (const [idx, wallet] of temp.entries()) { + if (wallet.key === key) { + temp[idx].moreInfo = !temp[idx].moreInfo + break + } + } + + setWalletData(temp) + } + + const filteredWallets = walletCardData.filter((wallet) => { + let showWallet = true + let mobileCheck = true + let desktopCheck = true + let browserCheck = true + let hardwareCheck = true + + const featureFilterKeys = featureDropdownItems.map((item) => item.filterKey) + const deviceFilters = Object.entries(filters).filter( + (item) => !featureFilterKeys.includes(item[0]) + ) + const mobileFiltersTrue = deviceFilters + .filter((item) => item[0] === "ios" || item[0] === "android") + .filter((item) => item[1]) + .map((item) => item[0]) + const desktopFiltersTrue = deviceFilters + .filter( + (item) => + item[0] === "linux" || item[0] === "windows" || item[0] === "macOS" + ) + .filter((item) => item[1]) + .map((item) => item[0]) + const browserFiltersTrue = deviceFilters + .filter((item) => item[0] === "firefox" || item[0] === "chromium") + .filter((item) => item[1]) + .map((item) => item[0]) + const hardwareFiltersTrue = deviceFilters + .filter((item) => item[0] === "hardware") + .filter((item) => item[1]) + .map((item) => item[0]) + + for (let item of mobileFiltersTrue) { + if (wallet[item]) { + mobileCheck = true + break + } else { + mobileCheck = false + } + } + + for (let item of desktopFiltersTrue) { + if (wallet[item]) { + desktopCheck = true + break + } else { + desktopCheck = false + } + } + + for (let item of browserFiltersTrue) { + if (wallet[item]) { + browserCheck = true + break + } else { + browserCheck = false + } + } + + for (let item of hardwareFiltersTrue) { + if (wallet[item]) { + hardwareCheck = true + break + } else { + hardwareCheck = false + } + } + + featureFilterKeys.forEach((filter) => { + if (filters[filter] && showWallet === true) { + showWallet = filters[filter] === wallet[filter] + } + }) + + return ( + mobileCheck && desktopCheck && browserCheck && hardwareCheck && showWallet + ) + }) + + const filteredFeatureDropdownItems = [...featureDropdownItems].filter( + (item) => { + return ( + item.label !== firstFeatureSelect.label && + item.label !== secondFeatureSelect.label && + item.label !== thirdFeatureSelect.label + ) + } + ) + + /** + * + * @param selectedOption selected dropdown option + * @param stateUpdateMethod method for updating state for dropdown + * @param className className of column + * + * This method gets the elements with the className, adds a fade class to fade icons out, after 0.5s it will then update state for the dropdown with the selectedOption, and then remove the fade class to fade the icons back in. Then it will send a matomo event for updating the dropdown. + */ + const updateDropdown = ( + selectedOption: DropdownOption, + stateUpdateMethod: Function, + className: ColumnClassName + ) => { + const domItems: HTMLCollectionOf = + document.getElementsByClassName(className) + for (let item of domItems) { + item.classList.add("fade") + } + setTimeout(() => { + stateUpdateMethod(selectedOption) + for (let item of domItems) { + item.classList.remove("fade") + } + }, 375) + + trackCustomEvent({ + eventCategory: "WalletFeatureCompare", + eventAction: `Select WalletFeatureCompare`, + eventName: `${selectedOption.filterKey} selected`, + }) + } + + return { + featureDropdownItems, + updateMoreInfo, + filteredWallets, + filteredFeatureDropdownItems, + updateDropdown, + setFirstFeatureSelect, + setSecondFeatureSelect, + setThirdFeatureSelect, + walletCardData, + firstFeatureSelect, + secondFeatureSelect, + thirdFeatureSelect, + } +} diff --git a/src/data/wallets/wallet-data.ts b/src/data/wallets/wallet-data.ts index 4b8f8eea89f..f8956a5021a 100644 --- a/src/data/wallets/wallet-data.ts +++ b/src/data/wallets/wallet-data.ts @@ -1,4 +1,4 @@ -interface WalletData { +export interface WalletData { last_updated: string name: string image_name: string From b4234d1fefdc7e6f11d1efc4ce2a6d4f202d4f67 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 21 Apr 2023 15:12:11 -0400 Subject: [PATCH 05/27] refactor(WalletTable): split more info content into separate component files --- .../FindWallet/WalletTable/WalletMoreInfo.tsx | 100 ++++++ .../WalletTable/WalletMoreInfoCategory.tsx | 95 ++++++ .../FindWallet/WalletTable/index.tsx | 310 +----------------- 3 files changed, 203 insertions(+), 302 deletions(-) create mode 100644 src/components/FindWallet/WalletTable/WalletMoreInfo.tsx create mode 100644 src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx diff --git a/src/components/FindWallet/WalletTable/WalletMoreInfo.tsx b/src/components/FindWallet/WalletTable/WalletMoreInfo.tsx new file mode 100644 index 00000000000..0e21cd93fd1 --- /dev/null +++ b/src/components/FindWallet/WalletTable/WalletMoreInfo.tsx @@ -0,0 +1,100 @@ +import * as React from "react" +import { Box, SimpleGrid, VStack, Text } from "@chakra-ui/react" +import { useTranslation } from "gatsby-plugin-react-i18next" + +import ButtonLink from "../../ButtonLink" +import { WalletMoreInfoCategory } from "./WalletMoreInfoCategory" +import { DropdownOption } from "./useWalletTable" + +interface WalletMoreInfoProps { + wallet: Record + filters: Record + idx: number + featureDropdownItems: DropdownOption[] +} + +export const WalletMoreInfo = ({ + wallet, + filters, + idx, + featureDropdownItems, +}: WalletMoreInfoProps) => { + const { t } = useTranslation() + const walletHasFilter = (filterKey) => { + return wallet[filterKey] === true + } + // Cast as Number because TypeScript warned about sorting implicitly by true/false + const orderedFeatureDropdownItems = featureDropdownItems.sort( + (a, b) => + Number(walletHasFilter(b.filterKey)) - + Number(walletHasFilter(a.filterKey)) + ) + + const walletInfoSections = [ + { headingLabel: t("page-find-wallet-features"), sectionName: "feature" }, + { headingLabel: t("page-find-wallet-security"), sectionName: "security" }, + { + headingLabel: + t("page-find-wallet-buy-crypto") + + " / " + + t("page-find-wallet-sell-for-fiat"), + sectionName: "trade_and_buy", + }, + { + headingLabel: t("page-find-wallet-smart-contract"), + sectionName: "smart_contract", + }, + ] + + return ( + + + + + + + {walletInfoSections.map((section, idx) => ( + + ))} + + + {`${t("page-find-wallet-check-out")} ${wallet.name}`} + + + {`${wallet.name} ${t("page-find-wallet-info-updated-on")} ${ + wallet.last_updated + }`} + + + + + + ) +} diff --git a/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx b/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx new file mode 100644 index 00000000000..0b1674b5447 --- /dev/null +++ b/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx @@ -0,0 +1,95 @@ +import * as React from "react" +import { Box, Flex, Heading, HStack, Icon, Text } from "@chakra-ui/react" +import { useTranslation } from "gatsby-plugin-react-i18next" +import { MdInfoOutline } from "react-icons/md" + +import Tooltip from "../../Tooltip" +import { DropdownOption } from "./useWalletTable" + +import walletFilterData from "../../../data/wallets/wallet-filters" + +interface WalletMoreInfoCategoryProps { + wallet: any + orderedFeatureDropdownItems: DropdownOption[] + headingLabel: any + sectionName: string +} + +export const WalletMoreInfoCategory = ({ + wallet, + orderedFeatureDropdownItems, + headingLabel, + sectionName, +}: WalletMoreInfoCategoryProps) => { + const { t } = useTranslation() + + return ( + + + {headingLabel} + + + {orderedFeatureDropdownItems.map((feature) => { + const featureColor = wallet[feature.filterKey!] ? "text" : "secondary" + if (feature.category === sectionName) + return ( + + +

{feature.label}

+ + {t(walletFilterData[feature.filterKey].description)} +
+ } + > + + + + ) + })} + +
+ ) +} diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index ae1f1c31907..8d18b72279d 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -6,15 +6,9 @@ import styled from "@emotion/styled" import { useTranslation } from "gatsby-plugin-react-i18next" // Components -import ButtonLink from "../../ButtonLink" import Icon from "../../Icon" import Link from "../../Link" import { StyledSelect as Select } from "../../SharedStyledComponents" -import Tooltip from "../../Tooltip" -import Translation from "../../Translation" - -// Data -import walletFilterData from "../../../data/wallets/wallet-filters" // Icons import { @@ -26,6 +20,8 @@ import { import { trackCustomEvent } from "../../../utils/matomo" import { getImage } from "../../../utils/image" import { useWalletTable } from "./useWalletTable" +import { WalletData } from "../../../data/wallets/wallet-data" +import { WalletMoreInfo } from "./WalletMoreInfo" // Styles const Container = styled.table` @@ -300,96 +296,6 @@ const WalletMoreInfoArrow = styled(Icon)` fill: ${(props) => props.theme.colors.primary}; ` -const WalletMoreInfoContainer = styled.div` - display: grid; - grid-template-columns: 65px auto; - width: 100%; -` - -const WalletMoreInfoCategory = styled.div` - width: 100%; - margin: 3rem 0 0; - :first-child { - margin: 0.5rem 0 0; - } - - h4 { - color: ${(props) => props.theme.colors.primary}; - margin: 0 0.2rem 0.5rem; - display: block; - font-size: 1rem; - } -` - -const Features = styled.div` - display: flex; - flex-wrap: wrap; - gap: 0.2rem; - - @media (max-width: ${(props) => props.theme.breakpoints.m}) { - flex-wrap: nowrap; - flex-direction: column; - } -` - -const ColoredLine = styled.div<{ color: string }>` - --color: ${(props) => props.color}; - margin: auto; - width: 0.25rem; - height: 100%; - background: linear-gradient( - 180deg, - var(--color) 0%, - rgba(217, 217, 217, 0) 97.4% - ); -` - -const FeatureLabel = styled.div<{ hasFeature: boolean }>` - display: flex; - gap: 0.2rem; - font-size: 0.9rem; - line-height: 1rem; - align-items: center; - padding: 0.2rem; - margin: 0 1rem; - position: relative; - width: 200px; - p { - margin-bottom: 0; - flex: none; - color: ${(props) => - props.hasFeature - ? props.theme.colors.text - : props.theme.colors.secondary}; - text-decoration: ${(props) => (props.hasFeature ? "none" : "line-through")}; - } - span + p { - text-decoration: none; - } - p + div, - div + div { - svg { - width: 1.5rem; - fill: ${(props) => props.theme.colors.secondary}; - padding-right: 0.5rem; - } - } -` - -const FeatureIcon = styled.div<{ hasFeature: boolean }>` - svg { - width: 1.75rem; - height: 1.75rem; - - path { - fill: ${(props) => - props.hasFeature - ? props.theme.colors.text - : props.theme.colors.secondary}; - } - } -` - const SocialsContainer = styled.div` margin-top: 1rem; p { @@ -421,27 +327,6 @@ const Socials = styled.div` } ` -const LastUpdated = styled.p` - color: ${(props) => props.theme.colors.text300}; - margin: 2rem 0; - font-size: 0.875rem; - display: flex; - gap: 1rem; - justify-content: space-between; - flex-wrap: wrap; - flex-direction: column; - align-items: flex-start; -` - -const StyledIcon = styled(Icon)<{ hasFeature: boolean }>` - fill: ${(props) => - props.hasFeature ? props.theme.colors.text : props.theme.colors.secondary}; - &:hover, - &:active, - &:focus { - fill: ${({ theme }) => theme.colors.primary}; - } -` // Types export interface DropdownOption { label: string @@ -479,190 +364,6 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { walletCardData, } = useWalletTable({ filters, t, walletData }) - const WalletMoreInfo = ({ wallet, filters, idx }) => { - const walletHasFilter = (filterKey) => { - return wallet[filterKey] === true - } - // Cast as Number because TypeScript warned about sorting implicitly by true/false - const orderedFeatureDropdownItems = [...featureDropdownItems].sort( - (a, b) => - Number(walletHasFilter(b.filterKey)) - - Number(walletHasFilter(a.filterKey)) - ) - - return ( -
- -
- -
-
- -

- -

- - {orderedFeatureDropdownItems.map((feature) => { - if (feature.category === "feature") - return ( - - - {feature.icon} - -

{feature.label}

- - {t( - walletFilterData[feature.filterKey].description - )} -

- } - > - -
-
- ) - })} -
-
- -

- -

- - {orderedFeatureDropdownItems.map((feature) => { - if (feature.category === "security") - return ( - - - {feature.icon} - -

{feature.label}

- - {t( - walletFilterData[feature.filterKey].description - )} -

- } - > - -
-
- ) - })} -
-
- -

- {`${t("page-find-wallet-buy-crypto")} / ${t( - "page-find-wallet-sell-for-fiat" - )}`} -

- - {orderedFeatureDropdownItems.map((feature) => { - if (feature.category === "trade_and_buy") - return ( - - - {feature.icon} - -

{feature.label}

- - {t( - walletFilterData[feature.filterKey].description - )} -

- } - > - -
-
- ) - })} -
-
- -

- -

- - {orderedFeatureDropdownItems.map((feature) => { - if (feature.category === "smart_contract") - return ( - - - {feature.icon} - -

{feature.label}

- - {t( - walletFilterData[feature.filterKey].description - )} -

- } - > - -
-
- ) - })} -
-
- - - {`${t("page-find-wallet-check-out")} ${wallet.name}`} - - - {`${wallet.name} ${t("page-find-wallet-info-updated-on")} ${ - wallet.last_updated - }`} - - -
-
-
- ) - } - return ( @@ -860,7 +561,12 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { {wallet.moreInfo && ( - + )} ) From d460674b1d809ac9e5709979ee342243af3c4533 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 21 Apr 2023 20:06:56 -0400 Subject: [PATCH 06/27] fix(WalletTable/WalletMoreInfoCategory): add lineheight to tool tips --- .../FindWallet/WalletTable/WalletMoreInfoCategory.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx b/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx index 0b1674b5447..500ab2edb4c 100644 --- a/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx +++ b/src/components/FindWallet/WalletTable/WalletMoreInfoCategory.tsx @@ -79,7 +79,7 @@ export const WalletMoreInfoCategory = ({

{feature.label}

+ {t(walletFilterData[feature.filterKey].description)} } From 2fe0470142450a3a9e968218dd2847ee3e19b5d1 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 21 Apr 2023 20:07:16 -0400 Subject: [PATCH 07/27] refactor(WalletTable): migrate main component to Chakra --- .../FindWallet/WalletTable/index.tsx | 671 +++++++++--------- 1 file changed, 333 insertions(+), 338 deletions(-) diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index 8d18b72279d..601f94745a3 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -1,14 +1,33 @@ // Libraries import React, { ReactNode } from "react" import { GatsbyImage } from "gatsby-plugin-image" -import { keyframes } from "@emotion/react" import styled from "@emotion/styled" import { useTranslation } from "gatsby-plugin-react-i18next" +import Select from "react-select" +import { MdExpandLess, MdExpandMore } from "react-icons/md" +import { FaDiscord, FaGlobe, FaTwitter } from "react-icons/fa" +import { + Box, + chakra, + Flex, + FlexProps, + forwardRef, + Icon, + Img, + keyframes, + SimpleGrid, + SimpleGridProps, + Table, + TableProps, + Td, + Text, + Th, + Tr, +} from "@chakra-ui/react" // Components -import Icon from "../../Icon" -import Link from "../../Link" -import { StyledSelect as Select } from "../../SharedStyledComponents" +import Link, { IProps as LinkProps } from "../../Link" +import { WalletMoreInfo } from "./WalletMoreInfo" // Icons import { @@ -17,223 +36,215 @@ import { } from "../../icons/staking" // Utils +import { useWalletTable } from "./useWalletTable" import { trackCustomEvent } from "../../../utils/matomo" import { getImage } from "../../../utils/image" -import { useWalletTable } from "./useWalletTable" import { WalletData } from "../../../data/wallets/wallet-data" -import { WalletMoreInfo } from "./WalletMoreInfo" - -// Styles -const Container = styled.table` - width: 100%; - th { - font-weight: normal; - p { - font-size: 0.9rem; - } - } -` - -const WalletContainer = styled(Container)` - border-bottom: 1px solid ${(props) => props.theme.colors.lightBorder}; - :hover { - background: ${(props) => props.theme.colors.boxShadow}; - transition: 0.5s all; - } -` - -const Grid = styled.tr` - display: grid; - grid-template-columns: 40% auto auto auto 5%; - width: 100%; - column-gap: 0.5rem; - align-items: center; - - p { - margin: 0; - } - - @media (max-width: ${(props) => props.theme.breakpoints.m}) { - grid-template-columns: 60% auto 0% 0% 5%; - - th:nth-of-type(3) { - display: none; - } - th:nth-of-type(4) { - display: none; - } - - td:nth-of-type(3) { - display: none; - } - td:nth-of-type(4) { - display: none; - } - } -` - -const WalletContentHeader = styled(Grid)` - position: sticky; - top: 0; - padding: 8px; - background: ${(props) => props.theme.colors.background}; - z-index: 1; - border-bottom: 1px solid ${(props) => props.theme.colors.primary}; - - th { - padding: 0; - border-bottom: none; - } - - @media (max-width: ${(props) => props.theme.breakpoints.s}) { - grid-template-columns: auto; - gap: 1rem; - text-align: center; - th:nth-of-type(1) { - text-align: center; - } - th:nth-of-type(2) { - display: flex; - align-items: center; - gap: 1rem; - &:before { - white-space: nowrap; - content: "Compare features"; - } - } - } - - @media (max-width: ${(props) => props.theme.breakpoints.m}) { - top: 50; - } -` - -const Wallet = styled(Grid)` - padding: 25px 4px; - cursor: pointer; - td { - padding: 0; - border-bottom: none; - height: 100%; - } - @media (max-width: ${(props) => props.theme.breakpoints.l}) { - padding: 25px 1rem; - } -` - -// https://react-select.com/styles#using-classnames -// Pass menuIsOpen to component to debug -const StyledSelect = styled(Select)` - .react-select__control { - border: 1px solid ${(props) => props.theme.colors.text}; - cursor: pointer; - font-size: 0.9rem; - padding-right: 0.3rem; - transition: 0.5s all; - svg { - fill: ${(props) => props.theme.colors.text}; - transition: 0.5s all; - } - - .react-select__value-container { - .react-select__single-value { - color: ${(props) => props.theme.colors.text}; - } - } - - .react-select__indicators { - .react-select__indicator-separator { - background: none; - } - .react-select__indicator { - color: ${(props) => props.theme.colors.text}; - padding: 0; - } - } - - &:hover { - background: ${(props) => props.theme.colors.primary}; - cursor: pointer; - border-color: ${(props) => props.theme.colors.primary}; - color: ${(props) => props.theme.colors.background}; - transition: 0.5s all; - svg { - fill: ${(props) => props.theme.colors.background}; - transition: 0.5s all; - } - - .react-select__value-container { - .react-select__single-value { - color: ${(props) => props.theme.colors.background}; - } - } - - .react-select__indicators { - .react-select__indicator-separator { - background: none; - } - .react-select__indicator { - color: ${(props) => props.theme.colors.text}; - } - } - } - } - - .react-select__control--is-focused { - border: 1px solid ${(props) => props.theme.colors.primary}; - background: ${(props) => props.theme.colors.primary}; - svg { - fill: ${(props) => props.theme.colors.background}; - transition: 0.5s all; - } - - .react-select__value-container { - .react-select__single-value { - color: ${(props) => props.theme.colors.background}; - } - } - - .react-select__indicators { - background: ${(props) => props.theme.colors.primary}; - .react-select__value-container { - .react-select__single-value { - color: ${(props) => props.theme.colors.background}; - } - } - - .react-select__indicators { - .react-select__indicator { - color: ${(props) => props.theme.colors.background}; - } - } - } - } - - @media (max-width: ${(props) => props.theme.breakpoints.s}) { - .react-select__control { - padding: 0; - } - } -` - -const FlexInfo = styled.div` - display: flex; - gap: 1rem; - align-items: center; - padding-left: 0.3rem; +import { ChildOnlyProp } from "../../../types" + +const Container = (props: TableProps) => ( + +) + +const WalletContainer = (props: ChildOnlyProp) => ( + +) + +const Grid = forwardRef((props, ref) => ( + +)) + +const WalletContentHeader = (props: ChildOnlyProp) => ( + +) + +const Wallet = forwardRef((props, ref) => ( + +)) + +const ChakraSelect = chakra((props: { className?: string }) => ( + - + - + - + + {filteredWallets.map((wallet, idx) => { const deviceLabels: Array = [] @@ -459,26 +429,41 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { }) }} > - - + - + - + - + + {wallet.moreInfo && ( Date: Fri, 5 May 2023 19:12:31 +0530 Subject: [PATCH 08/27] Made requested changes --- src/pages/layer-2.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/layer-2.tsx b/src/pages/layer-2.tsx index 004fab31082..0ad6d5402b3 100644 --- a/src/pages/layer-2.tsx +++ b/src/pages/layer-2.tsx @@ -749,22 +749,22 @@ const Layer2Page = ({ data }: PageProps) => { -
    -
  • + + -
  • -
  • + + -
  • -
+ + From 057d21b7fb5b8c47a7b921318057faf626af35ba Mon Sep 17 00:00:00 2001 From: "Cassio R. Chagas" <82733130+CassioChagas@users.noreply.github.com> Date: Tue, 9 May 2023 20:06:19 -0300 Subject: [PATCH 09/27] Update community-events.json --- src/data/community-events.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/data/community-events.json b/src/data/community-events.json index 25b19c9f2c7..681a6e6660b 100644 --- a/src/data/community-events.json +++ b/src/data/community-events.json @@ -286,5 +286,14 @@ "description": "The decentralized protocol and infrastructure conference. Protocol Berg is a one-day technical conference for protocol/system/network engineers, decentralized-infrastructure administrators, researchers, and other curious minds from different ecosystems.", "startDate": "2023-09-15", "endDate": "2023-09-15" + }, + { + "title": "EthereumSP 23", + "to": "https://www.ethereumbrasil.com/ethereum-sp23", + "sponsor": null, + "location": "Campus USP, São Paulo, Brazil", + "description": "EthereumSP 2023 is a four-day event to educate and boost the Brazilian Web3 community. Participants will have free access to advanced workshops, bootcamps, and an international Hackathon.", + "startDate": "2023-06-22", + "endDate": "2023-06-25" } ] From f7698453c13e0ce0981bde60f8653271d2341de1 Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Wed, 10 May 2023 17:48:07 -0300 Subject: [PATCH 10/27] reuse components from use-cases template and fix layout for responsive design --- .../TableOfContents/TableOfContentsMobile.tsx | 6 +- src/components/TableOfContents/index.tsx | 5 +- src/templates/staking.tsx | 149 +++++------------- src/templates/use-cases.tsx | 15 +- 4 files changed, 60 insertions(+), 115 deletions(-) diff --git a/src/components/TableOfContents/TableOfContentsMobile.tsx b/src/components/TableOfContents/TableOfContentsMobile.tsx index 93a69034d67..724bf8258bb 100644 --- a/src/components/TableOfContents/TableOfContentsMobile.tsx +++ b/src/components/TableOfContents/TableOfContentsMobile.tsx @@ -7,6 +7,7 @@ import { Icon, List, Show, + useToken, } from "@chakra-ui/react" import React from "react" import { MdExpandMore } from "react-icons/md" @@ -20,6 +21,9 @@ export interface IPropsTableOfContentsMobile { } const Mobile: React.FC = ({ items, maxDepth }) => { + // TODO: Replace with direct token implementation after UI migration is completed + const lgBp = useToken("breakpoints", "lg") + const { getButtonProps, getDisclosureProps, isOpen } = useDisclosure({ defaultIsOpen: false, }) @@ -28,7 +32,7 @@ const Mobile: React.FC = ({ items, maxDepth }) => { } return ( - + {/* TODO: switch `l` to `lg` after UI migration and use `hideBelow` prop */} = ({ ...rest }) => { const { isZenMode, handleZenModeChange } = useContext(ZenModeContext) + // TODO: Replace with direct token implementation after UI migration is completed + const lgBp = useToken("breakpoints", "lg") const titleIds: Array = [] @@ -81,7 +84,7 @@ const TableOfContents: React.FC = ({ return ( // TODO: Switch to `above="lg"` after completion of Chakra Migration - + ( @@ -254,18 +260,6 @@ const SummaryPoint = (props: ChildOnlyProp) => ( ) -const Container = (props: ChildOnlyProp) => ( - -) - const HeroContainer = (props: ChildOnlyProp) => { return ( { ) } -const InfoBanner = (props: ISharedInfoBannerProps) => ( - -) - const TableContainer = (props: BoxProps) => ( ) => { + // TODO: Replace with direct token implementation after UI migration is completed + const lgBp = useToken("breakpoints", "lg") + if (!mdx?.frontmatter) throw new Error( "Staking page template query does not return expected values" @@ -358,7 +351,6 @@ const StakingPage = ({ const isRightToLeft = isLangRightToLeft(mdx.frontmatter.lang as Lang) const tocItems = mdx.tableOfContents?.items as ItemTableOfContents[] const { summaryPoints } = mdx.frontmatter - const theme = useTheme() const dropdownLinks: ButtonDropdownList = { text: "Staking Options", @@ -413,7 +405,7 @@ const StakingPage = ({ } return ( - + @@ -447,97 +439,40 @@ const StakingPage = ({ objectFit="contain" /> - + - - - {mdx.frontmatter.title} + {/* // TODO: Switch to `above="lg"` after completion of Chakra Migration */} + + + + {mdx.frontmatter.title} - {tocItems && ( - - )} - - + {tocItems && ( + + )} + + + {mdx.body} - - - - - - + + {/* // TODO: Switch to `above="lg"` after completion of Chakra Migration */} + + + + + + + ) } diff --git a/src/templates/use-cases.tsx b/src/templates/use-cases.tsx index 83111eb650b..aa86ac7d33f 100644 --- a/src/templates/use-cases.tsx +++ b/src/templates/use-cases.tsx @@ -191,7 +191,7 @@ const HeroImage = chakra(GatsbyImage, { }, }) -const Page = (props: FlexProps) => ( +export const Page = (props: FlexProps) => ( ( mb={16} pt={{ lg: 16 }} width="full" + sx={{ "h2:first-of-type": { mt: { lg: 0 } } }} {...props} /> ) -const InfoColumn = (props: ChildOnlyProp) => ( +export const InfoColumn = (props: ChildOnlyProp) => ( ( type ButtonDropdownProps = Parameters[0] -const StyledButtonDropdown = (props: FlexProps & ButtonDropdownProps) => ( +export const StyledButtonDropdown = ( + props: FlexProps & ButtonDropdownProps +) => ( ( /> ) -const MobileButtonDropdown = (props: ButtonDropdownProps) => ( +export const MobileButtonDropdown = (props: ButtonDropdownProps) => ( ) -const ContentContainer = (props: Pick) => ( +export const ContentContainer = (props: Pick) => ( ) => ( /> ) -const MobileButton = (props: ChildOnlyProp) => { +export const MobileButton = (props: ChildOnlyProp) => { const borderColor = useToken("colors", "border") return ( Date: Fri, 12 May 2023 18:39:27 +0530 Subject: [PATCH 11/27] fix redundant word. Removed duplicate word from sentence. --- .../tutorials/reverse-engineering-a-contract/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/developers/tutorials/reverse-engineering-a-contract/index.md b/src/content/developers/tutorials/reverse-engineering-a-contract/index.md index 6fbd451aec2..071f3e3f7f2 100644 --- a/src/content/developers/tutorials/reverse-engineering-a-contract/index.md +++ b/src/content/developers/tutorials/reverse-engineering-a-contract/index.md @@ -14,7 +14,7 @@ _There are no secrets on the blockchain_, everything that happens is consistent, There are reverse compilers, but they don't always produce [usable results](https://etherscan.io/bytecode-decompiler?a=0x2510c039cc3b061d79e564b38836da87e31b342f). In this article you learn how to manually reverse engineer and understand a contract from [the opcodes](https://github.com/wolflo/evm-opcodes), as well as how to interpret the results of a decompiler. -To be able to understand this article you should already know the basics of the EVM, and be at least somewhat familiar with EVM assembler. [You can read about about these topics here](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e). +To be able to understand this article you should already know the basics of the EVM, and be at least somewhat familiar with EVM assembler. [You can read about these topics here](https://medium.com/mycrypto/the-ethereum-virtual-machine-how-does-it-work-9abac2b7c9e). ## Prepare the Executable Code {#prepare-the-executable-code} From 9a9a0af87f862e4108f3ae8c5ea129a1386c51cb Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 12 May 2023 13:38:25 -0400 Subject: [PATCH 12/27] chore(WalletTable): remove unused import --- src/components/FindWallet/WalletTable/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index 601f94745a3..255b9e47cc9 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -1,7 +1,6 @@ // Libraries import React, { ReactNode } from "react" import { GatsbyImage } from "gatsby-plugin-image" -import styled from "@emotion/styled" import { useTranslation } from "gatsby-plugin-react-i18next" import Select from "react-select" import { MdExpandLess, MdExpandMore } from "react-icons/md" From 1fa00e9591a1f91e1fe7aea8a71db324d18a5162 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 12 May 2023 13:43:58 -0400 Subject: [PATCH 13/27] fix(WalletTable): hide feature dropdowns at a higher breakpoint --- src/components/FindWallet/WalletTable/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index 255b9e47cc9..318046c34cd 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -108,7 +108,7 @@ const WalletContentHeader = (props: ChildOnlyProp) => ( gap: 4, }, "&:nth-of-type(3), &:nth-of-type(4)": { - hideBelow: "sm", + hideBelow: "md", }, }, }} @@ -132,7 +132,7 @@ const Wallet = forwardRef((props, ref) => ( height: "full", }, "td:nth-of-type(3), td:nth-of-type(4)": { - hideBelow: "sm", + hideBelow: "md", }, }} {...props} From fdcd50d4e76449cf9fdc49c84d9f56bc116ddbe6 Mon Sep 17 00:00:00 2001 From: tylerapfledderer Date: Fri, 12 May 2023 13:44:20 -0400 Subject: [PATCH 14/27] fix(WalletTable): apply full width to select --- src/components/FindWallet/WalletTable/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index 318046c34cd..00a6cf2ea03 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -144,6 +144,7 @@ const ChakraSelect = chakra((props: { className?: string }) => ( )) const StyledSelect = (props) => ( Date: Fri, 12 May 2023 15:40:46 -0300 Subject: [PATCH 15/27] refactor the staking page to reuse already existing components from the use-case template --- src/pages/staking/index.tsx | 182 ++++++++++-------------------------- src/templates/staking.tsx | 13 +-- src/templates/use-cases.tsx | 60 ++++++------ 3 files changed, 82 insertions(+), 173 deletions(-) diff --git a/src/pages/staking/index.tsx b/src/pages/staking/index.tsx index 3666a77c402..6dc9ee50d27 100644 --- a/src/pages/staking/index.tsx +++ b/src/pages/staking/index.tsx @@ -1,11 +1,9 @@ import React, { ReactNode } from "react" import { graphql, PageProps } from "gatsby" import { useTranslation } from "gatsby-plugin-react-i18next" -import { Box, Flex, Grid, Heading, useToken } from "@chakra-ui/react" +import { Box, Flex, Grid, Heading, Show, useToken } from "@chakra-ui/react" -import ButtonDropdown, { - List as ButtonDropdownList, -} from "../../components/ButtonDropdown" +import { List as ButtonDropdownList } from "../../components/ButtonDropdown" import ButtonLink from "../../components/ButtonLink" import Card from "../../components/Card" import Link from "../../components/Link" @@ -20,12 +18,19 @@ import StakingCommunityCallout from "../../components/Staking/StakingCommunityCa import UpgradeTableOfContents from "../../components/UpgradeTableOfContents" import { getImage } from "../../utils/image" - +import type { TranslationKey } from "../../utils/translations" import type { ChildOnlyProp, Context } from "../../types" -const Content = (props: ChildOnlyProp) => ( - -) +// TODO: move these components to a new folder under /components +import { + ContentContainer, + InfoColumn, + InfoTitle, + MobileButton, + MobileButtonDropdown, + Page, + StyledButtonDropdown, +} from "../../templates/use-cases" const PageContainer = (props: ChildOnlyProp) => ( @@ -46,105 +51,6 @@ const HeroStatsWrapper = (props: ChildOnlyProp) => ( /> ) -const Page = (props: ChildOnlyProp) => ( - -) - -const InfoTitle = (props: ChildOnlyProp) => ( - -) - -// InfoColumn shows above xl -const InfoColumn = (props: ChildOnlyProp) => ( - -) - -const StyledButtonDropdown = ({ - list, - ...rest -}: { - list: ButtonDropdownList -}) => ( - - - -) - -// ButtonDropdown for mobile only -const MobileButton = ({ list, ...rest }: { list: ButtonDropdownList }) => { - const borderBoxShadowColor = useToken("colors", "border") - - return ( - - - - ) -} - -const ContentContainer = (props: { children: ReactNode; id: string }) => { - const [mdBp, lgBp] = useToken("breakpoints", ["md", "lg"]) - - return ( - div:first-of-type": { - mt: 0, - pt: 0, - }, - }} - {...props} - > - ) -} - const ComparisonGrid = (props: ChildOnlyProp) => { const gridAreas = { base: `"solo-title" @@ -162,7 +68,7 @@ const ComparisonGrid = (props: ChildOnlyProp) => { "pool-risks" "pool-reqs" "pool-cta";`, - lg: `"solo-title saas-title pool-title" + xl: `"solo-title saas-title pool-title" "solo-rewards saas-rewards pool-rewards" "solo-risks saas-risks pool-risks" "solo-reqs saas-reqs pool-reqs" @@ -172,7 +78,7 @@ const ComparisonGrid = (props: ChildOnlyProp) => { ) => { const { t } = useTranslation() + // TODO: Replace with direct token implementation after UI migration is completed + const lgBp = useToken("breakpoints", "lg") const heroContent = { title: t("page-staking-hero-title"), @@ -368,15 +276,18 @@ const StakingPage = ({ - - - - - - - + {/* // TODO: Switch to `above="lg"` after completion of Chakra Migration */} + + + + + + + + + - +

{tocItems.whatIsStaking.title}

@@ -388,8 +299,8 @@ const StakingPage = ({

-
- +
+

{tocItems.whyStakeYourEth.title}

@@ -407,8 +318,8 @@ const StakingPage = ({ ) )} - - +
+

{tocItems.howToStakeYourEth.title}

@@ -418,15 +329,15 @@ const StakingPage = ({

- +
- +

-
+
- +

{tocItems.comparisonOfOptions.title}

@@ -619,10 +530,10 @@ const StakingPage = ({ /> -
+
- +

{tocItems.faq.title}

@@ -663,8 +574,8 @@ const StakingPage = ({

-
- + +

{tocItems.further.title}

  • @@ -738,12 +649,17 @@ const StakingPage = ({
-
- + + - + - + {/* // TODO: Switch to `above="lg"` after completion of Chakra Migration */} + + + + + ) diff --git a/src/templates/staking.tsx b/src/templates/staking.tsx index 6ae8678ae35..3fb686614eb 100644 --- a/src/templates/staking.tsx +++ b/src/templates/staking.tsx @@ -63,6 +63,7 @@ import { ChildOnlyProp, Context } from "../types" import { ContentContainer, InfoColumn, + InfoTitle, MobileButton, MobileButtonDropdown, Page, @@ -155,18 +156,6 @@ const Pre = (props: ChildOnlyProp) => ( /> ) -const InfoTitle = (props: ChildOnlyProp) => ( - -) - const H2 = (props: ChildOnlyProp) => ( ( /> ) -const InfoTitle = (props: ChildOnlyProp) => ( +export const InfoTitle = (props: ChildOnlyProp) => (

( ) -export const ContentContainer = (props: Pick) => ( - -) +export const ContentContainer = (props: Pick) => { + const lgBp = useToken("breakpoints", "lg") + + return ( + + ) +} export const MobileButton = (props: ChildOnlyProp) => { const borderColor = useToken("colors", "border") @@ -288,6 +292,8 @@ const UseCasePage = ({ pageContext, }: PageProps) => { const { t } = useTranslation() + // TODO: Replace with direct token implementation after UI migration is completed + const lgBp = useToken("breakpoints", "lg") if (!siteData || !mdx?.frontmatter) throw new Error( @@ -347,11 +353,9 @@ const UseCasePage = ({ ], } - const lgBreakpoint = useToken("breakpoints", "lg") - return ( - +
@@ -393,7 +397,7 @@ const UseCasePage = ({ }} /> - + - + {mdx.frontmatter.title} @@ -432,7 +436,7 @@ const UseCasePage = ({ - + From c88e283b99c8e0e00d95a32b2ef60a9ddb36404b Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Fri, 12 May 2023 15:53:22 -0300 Subject: [PATCH 16/27] add new text to translations --- src/components/FindWallet/WalletTable/index.tsx | 2 +- src/intl/en/page-wallets-find-wallet.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/FindWallet/WalletTable/index.tsx b/src/components/FindWallet/WalletTable/index.tsx index 00a6cf2ea03..6f0b3f09a97 100644 --- a/src/components/FindWallet/WalletTable/index.tsx +++ b/src/components/FindWallet/WalletTable/index.tsx @@ -352,7 +352,7 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => {

+ {filteredWallets.length === walletCardData.length ? ( -

+ {t("page-find-wallet-showing-all-wallets")} ( {walletCardData.length}) -

+ ) : ( -

+ {t("page-find-wallet-showing")}{" "} {filteredWallets.length} / {walletCardData.length} {" "} {t("page-find-wallet-wallets")} -

+ )} -
+ + + Choose features + { defaultValue={firstFeatureSelect} isSearchable={false} /> - + { defaultValue={secondFeatureSelect} isSearchable={false} /> - + { defaultValue={thirdFeatureSelect} isSearchable={false} /> - + -
- + -
-
-

{wallet.name}

- {deviceLabels.join(" | ")} + + + {wallet.name} + + {deviceLabels.join(" | ")} + {deviceLabels.map((label) => ( - + {label} - + ))} - - - + + { eventValue: JSON.stringify(filters), }} > - - + + {wallet.twitter && ( - { eventValue: JSON.stringify(filters), }} > - - + + )} {wallet.discord && ( - { eventValue: JSON.stringify(filters), }} > - - + + )} - - -
+ + +
-
+ {wallet[firstFeatureSelect.filterKey!] ? ( @@ -531,8 +524,8 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { )} - + {wallet[secondFeatureSelect.filterKey!] ? ( @@ -540,8 +533,8 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { )} - + {wallet[thirdFeatureSelect.filterKey!] ? ( @@ -549,16 +542,18 @@ const WalletTable = ({ data, filters, walletData }: WalletTableProps) => { )} - + -
- + -
+
-
- Choose features + {t("page-find-wallet-choose-features")} Date: Sat, 13 May 2023 12:38:35 +0900 Subject: [PATCH 17/27] Update web3 UX page (more links) adding new community link --- src/content/developers/docs/design-and-ux/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/developers/docs/design-and-ux/index.md b/src/content/developers/docs/design-and-ux/index.md index 7de6e7b8c46..a58dea8c8bc 100644 --- a/src/content/developers/docs/design-and-ux/index.md +++ b/src/content/developers/docs/design-and-ux/index.md @@ -64,7 +64,8 @@ Get involved in professional community-driven organizations or join design group - [Designer-dao.xyz](https://www.designer-dao.xyz/) - [We3.co](https://we3.co/) - [Openux.xyz](https://openux.xyz/about) -- [web3trends.org/](https://web3trends.org/) +- [web3trends.org](https://web3trends.org/) +- [Open Source Web3Design](https://t.me/joinchat/RLu-SuLwRwf7aubu) ## Design Systems {#Design-systems} From 4373a6055246bec57bd6276c26e6c33255567441 Mon Sep 17 00:00:00 2001 From: Jakub <100724231+konopkja@users.noreply.github.com> Date: Sat, 13 May 2023 20:19:31 +0900 Subject: [PATCH 18/27] Update index.md --- src/content/developers/docs/design-and-ux/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/developers/docs/design-and-ux/index.md b/src/content/developers/docs/design-and-ux/index.md index a58dea8c8bc..a814c9a2694 100644 --- a/src/content/developers/docs/design-and-ux/index.md +++ b/src/content/developers/docs/design-and-ux/index.md @@ -65,7 +65,7 @@ Get involved in professional community-driven organizations or join design group - [We3.co](https://we3.co/) - [Openux.xyz](https://openux.xyz/about) - [web3trends.org](https://web3trends.org/) -- [Open Source Web3Design](https://t.me/joinchat/RLu-SuLwRwf7aubu) +- [Open Source Web3Design](https://www.web3designers.org/) ## Design Systems {#Design-systems} From e5d79d13efca357d0fa89e4d43f006507498bb4c Mon Sep 17 00:00:00 2001 From: Hassan Tanveer Date: Sat, 13 May 2023 18:21:48 +0000 Subject: [PATCH 19/27] Added smart contracts link in footer --- src/components/Footer.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 7f16972fd73..58f87c617e1 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -122,6 +122,10 @@ const Footer: React.FC = () => { text: t("web3"), to: "/web3/", }, + { + text: t("smart-contracts"), + to: "/smart-contracts/", + }, { text: t("energy-consumption"), to: "/energy-consumption/", From e086bd56d742ce2fd3877cafc8b03ac6c4fb19fe Mon Sep 17 00:00:00 2001 From: Tarun Samanta Date: Sun, 14 May 2023 20:18:35 +0530 Subject: [PATCH 20/27] Removed the text tags from unorderedlist tag --- src/pages/layer-2.tsx | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/pages/layer-2.tsx b/src/pages/layer-2.tsx index a0335a67507..78fd75ab490 100644 --- a/src/pages/layer-2.tsx +++ b/src/pages/layer-2.tsx @@ -764,19 +764,15 @@ const Layer2Page = ({ data }: PageProps) => { - - - - - - - - - - - - - + + + + + + + + + From e6068172d09a37ce53b3337e5335fb45df2b79af Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 15 May 2023 09:37:41 +0200 Subject: [PATCH 21/27] Update CODEOWNERS remove myself from CODEOWNERS :) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eec84aaa2ba..fa042c6b933 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,4 +8,4 @@ * @samajammin @wackerow @corwintines @pettinarip @minimalsm @jmcook1186 @nhsz # Owners of specific files -/src/data/consensus-bounty-hunters.csv @djrtwo @JustinDrake @asanso @fredriksvantes +/src/data/consensus-bounty-hunters.csv @djrtwo @asanso @fredriksvantes From ea064dab2fbba815b7e520a9ef8d82bb38e14179 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Mon, 15 May 2023 21:18:56 +0900 Subject: [PATCH 22/27] Fix typo in oracles/index.md lenght -> length --- src/content/translations/tr/developers/docs/oracles/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/translations/tr/developers/docs/oracles/index.md b/src/content/translations/tr/developers/docs/oracles/index.md index 1101ea49109..8fc79d22ccc 100644 --- a/src/content/translations/tr/developers/docs/oracles/index.md +++ b/src/content/translations/tr/developers/docs/oracles/index.md @@ -347,8 +347,8 @@ contract Oracle { ) public { - uint lenght = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, "")); - Request storage r = requests[lenght-1]; + uint length = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, "")); + Request storage r = requests[length-1]; // Hardcoded oracles address r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1; From de7d2996e4b42331c23db6cc9a728da3260d35af Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Tue, 16 May 2023 12:51:53 -0300 Subject: [PATCH 23/27] change build event --- .github/workflows/chromatic.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index df583ee1e7b..dddbb427496 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -5,11 +5,7 @@ name: Chromatic Publish and Testing # Event for the workflow on: - pull_request: - types: - - opened - - synchronize - - ready_for_review + push: paths: # Only run on file changes in any of these paths - "src/components/**/*" From 616fd8d3277ef40c51856e5f97583d0502e6e5b2 Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Tue, 16 May 2023 12:54:40 -0600 Subject: [PATCH 24/27] add erc4337.io to further reading on account abstraction page --- src/content/roadmap/account-abstraction/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content/roadmap/account-abstraction/index.md b/src/content/roadmap/account-abstraction/index.md index 5ed0f3dc920..cb9ab99efb7 100644 --- a/src/content/roadmap/account-abstraction/index.md +++ b/src/content/roadmap/account-abstraction/index.md @@ -112,6 +112,7 @@ Smart contract wallets are already available, but more upgrades are required to ## Further reading {#further-reading} +- [erc4337.io](https://www.erc4337.io/) - [Account abstraction panel discussion from Devcon Bogota](https://www.youtube.com/watch?app=desktop&v=WsZBymiyT-8) - ["Why account abstraction is a game changer for dapps" from Devcon Bogota](https://www.youtube.com/watch?v=OwppworJGzs) - ["Account abstraction ELI5" from Devcon Bogota](https://www.youtube.com/watch?v=QuYZWJj65AY) From 44295d508c3ffe103095d5bf2c0684deaed083d6 Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Tue, 16 May 2023 14:20:20 -0600 Subject: [PATCH 25/27] Remove node providers and link out to node-as-a-service page --- .../developers/docs/nodes-and-clients/index.md | 4 ++-- .../docs/nodes-and-clients/run-a-node/index.md | 12 +----------- .../docs/smart-contracts/deploying/index.md | 3 ++- .../index.md | 2 +- .../index.md | 2 +- 5 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/content/developers/docs/nodes-and-clients/index.md b/src/content/developers/docs/nodes-and-clients/index.md index c8ef5b19b32..5e572e032dc 100644 --- a/src/content/developers/docs/nodes-and-clients/index.md +++ b/src/content/developers/docs/nodes-and-clients/index.md @@ -126,9 +126,9 @@ If you're more of a technical user, dive into more details and options on how to ## Alternatives {#alternatives} -Setting up your own node can cost you time and resources but you don’t always need to run your own instance. In this case, you can use a third party API provider like [Infura](https://infura.io), [Alchemy](https://alchemyapi.io), [Chainstack](https://chainstack.com), [QuikNode](https://www.quiknode.io), [Tenderly](https://tenderly.co/web3-gateway), [Blast](https://blastapi.io/), [DRPC](https://drpc.org/), or [GetBlock](https://getblock.io/). For an overview of using these services, check out [nodes as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/). +Setting up your own node can cost you time and resources but you don’t always need to run your own instance. In this case, you can use a third party API provider. For an overview of using these services, check out [nodes as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/). -If somebody runs an Ethereum node with a public API in your community, you can point your light wallets (like MetaMask) to a community node [via Custom RPC](https://metamask.zendesk.com/hc/en-us/articles/360015290012-Using-a-Local-Node) and gain more privacy than with some random trusted third party. +If somebody runs an Ethereum node with a public API in your community, you can point your wallets to a community node via Custom RPC and gain more privacy than with some random trusted third party. On the other hand, if you run a client, you can share it with your friends who might need it. diff --git a/src/content/developers/docs/nodes-and-clients/run-a-node/index.md b/src/content/developers/docs/nodes-and-clients/run-a-node/index.md index e2b9cc35220..734aadb9585 100644 --- a/src/content/developers/docs/nodes-and-clients/run-a-node/index.md +++ b/src/content/developers/docs/nodes-and-clients/run-a-node/index.md @@ -49,17 +49,7 @@ To simplify, let's think about running a node on both a local physical machine a - An option to buy preconfigured machines - You have to physically prepare, maintain, and potentially troubleshoot the machine and networking -Both options have different advantages summed up above. If you are looking for a cloud solution, in addition to many traditional cloud computing providers, there are also services focused on deploying nodes. For example: - -- [QuikNode](https://www.quiknode.io/) -- [Blockdaemon](https://blockdaemon.com) -- [Alchemy](https://www.alchemy.com/) -- [Blast](https://blastapi.io/) -- [Getblock](https://getblock.io/) -- [NodeReal](https://nodereal.io/) -- [NOWNodes](https://nownodes.io/) - -Check out also [nodes as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/) for more options on hosted nodes. +Both options have different advantages summed up above. If you are looking for a cloud solution, in addition to many traditional cloud computing providers, there are also services focused on deploying nodes. Check out [nodes as a service](/developers/docs/nodes-and-clients/nodes-as-a-service/) for more options on hosted nodes. #### Hardware {#hardware} diff --git a/src/content/developers/docs/smart-contracts/deploying/index.md b/src/content/developers/docs/smart-contracts/deploying/index.md index 4af27cdfd9e..2469943db62 100644 --- a/src/content/developers/docs/smart-contracts/deploying/index.md +++ b/src/content/developers/docs/smart-contracts/deploying/index.md @@ -23,7 +23,7 @@ Finally, you'll need to compile your contract before deploying it, so make sure - your contract's bytecode – this is generated through [compilation](/developers/docs/smart-contracts/compiling/) - ETH for gas – you'll set your gas limit like other transactions so be aware that contract deployment needs a lot more gas than a simple ETH transfer - a deployment script or plugin -- access to an [Ethereum node](/developers/docs/nodes-and-clients/), either by running your own, connecting to a public node, or via an API key using a [node service](/developers/docs/nodes-and-clients/nodes-as-a-service/) like [Infura](https://www.infura.io/) or [Alchemy](https://docs.alchemy.com/). +- access to an [Ethereum node](/developers/docs/nodes-and-clients/), either by running your own, connecting to a public node, or via an API key using a [node service](/developers/docs/nodes-and-clients/nodes-as-a-service/) ### Steps to deploy a smart contract {#steps-to-deploy} @@ -75,3 +75,4 @@ _Know of a community resource that helped you? Edit this page and add it!_ - [Development frameworks](/developers/docs/frameworks/) - [Run an Ethereum node](/developers/docs/nodes-and-clients/run-a-node/) +- [Nodes-as-a-service](/developers/docs/nodes-and-clients/nodes-as-a-service) diff --git a/src/content/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md b/src/content/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md index e99ab89a578..8b1a183df07 100644 --- a/src/content/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md +++ b/src/content/developers/tutorials/kickstart-your-dapp-frontend-development-wth-create-eth-app/index.md @@ -52,7 +52,7 @@ While [Web3](https://web3js.readthedocs.io/en/v1.2.7/) is still mostly used, [et [GraphQL](https://graphql.org/) is an alternative way for handling data compared to a [Restful API](https://restfulapi.net/). They have several advantages over Restful Apis, especially for decentralized blockchain data. If you are interested in the reasoning behind this, have a look at [GraphQL Will Power the Decentralized Web](https://medium.com/graphprotocol/graphql-will-power-the-decentralized-web-d7443a69c69a). -Usually you would fetch data from your smart contract directly. Want to read the time of the latest trade? Just call `MyContract.methods.latestTradeTime().call()` which fetches the data from an Ethereum node like Infura into your dapp. But what if you need hundreds of different data points? That would result in hundreds of data fetches to the node, each time requiring an [RTT](https://wikipedia.org/wiki/Round-trip_delay_time) making your dapp slow and inefficient. One workaround might be a fetcher call function inside your contract that returns multiple data at once. This is not always ideal though. +Usually you would fetch data from your smart contract directly. Want to read the time of the latest trade? Just call `MyContract.methods.latestTradeTime().call()` which fetches the data from an Ethereum node into your dapp. But what if you need hundreds of different data points? That would result in hundreds of data fetches to the node, each time requiring an [RTT](https://wikipedia.org/wiki/Round-trip_delay_time) making your dapp slow and inefficient. One workaround might be a fetcher call function inside your contract that returns multiple data at once. This is not always ideal though. And then you might be interested in historical data as well. You want to know not only the last trade time, but the times for all trades that you ever did yourself. Use the _create-eth-app_ subgraph package, read the [documentation](https://thegraph.com/docs/define-a-subgraph) and adapt it to your own contracts. If you are looking for popular smart contracts, there may even already be a subgraph. Check out the [subgraph explorer](https://thegraph.com/explorer/). diff --git a/src/content/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md b/src/content/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md index 8db48e99c61..6b164981944 100644 --- a/src/content/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md +++ b/src/content/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/index.md @@ -37,7 +37,7 @@ Now that we included the library in the project we need to initialize it. Your p const web3 = new Web3("http://localhost:8545") ``` -If you’d like to directly access a hosted node you can use Infura. You can also use the free ones provided by [Cloudflare](https://cloudflare-eth.com/), [Moralis](https://moralis.io), or [Alchemy](https://alchemy.com/ethereum): +If you’d like to directly access a hosted node you can find options on [nodes as a service](/developers/docs/nodes-and-clients/nodes-as-a-service). ```js const web3 = new Web3("https://cloudflare-eth.com") From 8f892ce6f73ede2a8a1521fc80feaa07c2a36f36 Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Tue, 16 May 2023 15:28:50 -0600 Subject: [PATCH 26/27] v7.12.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index deb368341e0..71dcff0cba7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ethereum-org-website", - "version": "7.12.0", + "version": "7.12.1", "description": "Website of ethereum.org", "main": "index.js", "repository": "git@github.com:ethereum/ethereum-org-website.git", From 364bf9aa5745d658f2ca6b4e026a802040dd1b97 Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Tue, 16 May 2023 20:32:40 -0300 Subject: [PATCH 27/27] fix undefined translation function --- src/pages-conditional/dapps.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages-conditional/dapps.tsx b/src/pages-conditional/dapps.tsx index 26c12f8f980..b4dd09f9b54 100644 --- a/src/pages-conditional/dapps.tsx +++ b/src/pages-conditional/dapps.tsx @@ -610,13 +610,10 @@ const DappsPage = ({ }, { title: "DexGuru", - description: translateMessageId( - "page-dapps-dapp-description-dexguru", - intl - ), + description: t("page-dapps-dapp-description-dexguru"), link: "https://dex.guru", image: getImage(data.dexguru), - alt: translateMessageId("page-dapps-dexguru-logo-alt", intl), + alt: t("page-dapps-dexguru-logo-alt"), }, ]