From a450bc3552132d9ebeb51924c7729b2613cc81bf Mon Sep 17 00:00:00 2001 From: dankelleher Date: Fri, 20 Oct 2023 09:25:03 +0200 Subject: [PATCH 1/2] Replace cardinal twitter profile with civic.me, as cardinal has shut down and their API is no longer working. --- components/App.tsx | 17 +++++----- components/ConnectWalletButton.tsx | 31 ++++++------------ components/DelegateCard.tsx | 18 +++++------ components/Members/MemberOverview.tsx | 7 ++--- components/Members/MembersTabs.tsx | 17 +++------- components/Profile/ProfileImage.tsx | 30 +++++++++++++----- components/Profile/ProfileName.tsx | 40 ++++++++++++++++++++++++ components/Profile/ShortAddress.tsx | 16 ++++++++++ components/Profile/index.ts | 1 + components/Profile/useProfile.ts | 21 +++++++++---- components/SelectPrimaryDelegators.tsx | 12 +++---- components/VotingRules.tsx | 4 +-- package.json | 3 +- pages/dao/[symbol]/token-stats/index.tsx | 18 +++-------- utils/address.ts | 3 ++ yarn.lock | 10 ++++++ 16 files changed, 154 insertions(+), 94 deletions(-) create mode 100644 components/Profile/ProfileName.tsx create mode 100644 components/Profile/ShortAddress.tsx create mode 100644 utils/address.ts diff --git a/components/App.tsx b/components/App.tsx index 43c00fd053..6a74061f91 100644 --- a/components/App.tsx +++ b/components/App.tsx @@ -1,5 +1,4 @@ import { ThemeProvider } from 'next-themes' -import { WalletIdentityProvider } from '@cardinal/namespaces-components' import dynamic from 'next/dynamic' import React, { useEffect, useMemo } from 'react' import Head from 'next/head' @@ -274,15 +273,13 @@ export function AppContents(props: Props) { - - - - - - - {props.children} - - + + + + + + {props.children} + diff --git a/components/ConnectWalletButton.tsx b/components/ConnectWalletButton.tsx index cb5d30a55a..b26ce69fbc 100644 --- a/components/ConnectWalletButton.tsx +++ b/components/ConnectWalletButton.tsx @@ -1,8 +1,6 @@ import { useRouter } from 'next/router' -import { AddressImage, DisplayAddress } from '@cardinal/namespaces-components' import styled from '@emotion/styled' import { Menu } from '@headlessui/react' -import { UserCircleIcon } from '@heroicons/react/outline' import { BackspaceIcon, CheckCircleIcon, @@ -12,7 +10,7 @@ import { abbreviateAddress } from '@utils/formatting' import { useCallback, useEffect, useState } from 'react' import Switch from './Switch' import { notify } from '@utils/notifications' -import { Profile } from '@components/Profile' +import {Profile, ProfileImage} from '@components/Profile' import Loading from './Loading' import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base' import { useWallet } from '@solana/wallet-adapter-react' @@ -20,6 +18,7 @@ import { ExternalLinkIcon } from '@heroicons/react/outline' import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { DEFAULT_PROVIDER } from '../utils/wallet-adapters' import useViewAsWallet from '@hooks/useViewAsWallet' +import { ProfileName } from "@components/Profile/ProfileName"; const StyledWalletProviderLabel = styled.p` font-size: 0.65rem; @@ -112,18 +111,7 @@ const ConnectWalletButton = (props) => { ) : null} {connected && publicKey ? (
- - -
- } - />{' '} + ) : (
@@ -134,13 +122,12 @@ const ConnectWalletButton = (props) => { {connected && publicKey ? ( <> {connected && publicKey ? ( - + ) : null} {walletAddressFormatted} diff --git a/components/DelegateCard.tsx b/components/DelegateCard.tsx index 77dc2365e3..026cb0dbb8 100644 --- a/components/DelegateCard.tsx +++ b/components/DelegateCard.tsx @@ -12,7 +12,6 @@ import { CashIcon, CreditCardIcon } from '@heroicons/react/solid' import Button from './Button' import Checkbox from '@components/inputs/Checkbox' import Divider from './Divider' -import { DisplayAddress } from '@cardinal/namespaces-components' import { tryParseKey } from 'tools/validators/pubkey' import { XCircleIcon } from '@heroicons/react/outline' import Tooltip from './Tooltip' @@ -24,6 +23,7 @@ import { import { useRealmQuery } from '@hooks/queries/realm' import { useConnection } from '@solana/wallet-adapter-react' import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { ProfileName } from "@components/Profile"; const DelegateCard = () => { const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result @@ -161,12 +161,11 @@ const DelegateCard = () => {
{ownCouncilTokenRecord?.account.governanceDelegate && (
- { {ownTokenRecord?.account.governanceDelegate && (
- = ({ member, @@ -401,9 +401,8 @@ const MemberOverview = ({ <>

- { return ( - ( - } - /> + ), // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO please fix, it can cause difficult bugs. You might wanna check out https://bobbyhadz.com/blog/react-hooks-exhaustive-deps for info. -@asktree [walletAddress] diff --git a/components/Profile/ProfileImage.tsx b/components/Profile/ProfileImage.tsx index edfe21f66c..0c96e872cc 100644 --- a/components/Profile/ProfileImage.tsx +++ b/components/Profile/ProfileImage.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { useProfile } from '@components/Profile' +import { useProfile } from '@components/Profile/useProfile' import ImgWithLoader from '@components/ImgWithLoader' import { PublicKey } from '@solana/web3.js' import { LoadingDots } from '@components/Loading' @@ -25,14 +25,30 @@ export const ProfileImage: FC = ({ publicKey, expanded, className }) => { if (!profile && loading) return // No civic profile - show placeholder - if (!profile || !profile.image) return + if (!profile || !profile.image) { + return + + + } // Show civic profile image with loader as image loads return ( - + + + ) } diff --git a/components/Profile/ProfileName.tsx b/components/Profile/ProfileName.tsx new file mode 100644 index 0000000000..75c5be6f9e --- /dev/null +++ b/components/Profile/ProfileName.tsx @@ -0,0 +1,40 @@ +import React, { FC } from 'react' +import { useProfile } from '@components/Profile/useProfile'; +import { PublicKey } from '@solana/web3.js'; +import ContentLoader from "react-content-loader"; +import {ShortAddress} from "@components/Profile/ShortAddress"; + +type Props = { publicKey?: PublicKey, height?: string; + width?: string; + dark?: boolean; + style?: React.CSSProperties; } +export const ProfileName: FC = ({ publicKey, height = "13", + width = "300", + dark = false, + style, }) => { + const { profile, loading } = useProfile(publicKey) + + + if (!publicKey) return <>; + return loading ? ( +
+ + + +
+ ) : ( +
+ {profile?.name?.value || } +
+ ); +} diff --git a/components/Profile/ShortAddress.tsx b/components/Profile/ShortAddress.tsx new file mode 100644 index 0000000000..4a4d4ec5ec --- /dev/null +++ b/components/Profile/ShortAddress.tsx @@ -0,0 +1,16 @@ +import {PublicKey} from "@solana/web3.js"; +import React, {FC} from "react"; +import {shortenAddress} from "@utils/address"; + +export const ShortAddress:FC<{address: PublicKey | undefined }> = ({address}) => { + if (!address) return <>; + return ( + + {shortenAddress(address.toString())} + + ); +}; \ No newline at end of file diff --git a/components/Profile/index.ts b/components/Profile/index.ts index 5bd5bc1ddb..906312443d 100644 --- a/components/Profile/index.ts +++ b/components/Profile/index.ts @@ -1,4 +1,5 @@ export { Profile } from './Profile' export { ProfilePopup } from './ProfilePopup' export { ProfileImage } from './ProfileImage' +export { ProfileName } from './ProfileName' export { useProfile } from './useProfile' diff --git a/components/Profile/useProfile.ts b/components/Profile/useProfile.ts index 43ca33897a..eff4025801 100644 --- a/components/Profile/useProfile.ts +++ b/components/Profile/useProfile.ts @@ -8,15 +8,24 @@ type Profile = BaseProfile & { exists: boolean } +const profiles = new Map>() + const getProfile = async ( publicKey: PublicKey, connection?: Connection -): Promise => - CivicProfile.get(publicKey.toBase58(), { - solana: { - connection, - }, - }) +): Promise => { + const cached = profiles.get(publicKey.toBase58()); + if (cached) return cached; + const promise = CivicProfile.get(publicKey.toBase58(), { + solana: { + connection, + }, + }); + + profiles.set(publicKey.toBase58(), promise) + + return promise; +} const profileIsSet = (profile: BaseProfile): boolean => !!profile.name || !!profile.image || !!profile.headline diff --git a/components/SelectPrimaryDelegators.tsx b/components/SelectPrimaryDelegators.tsx index d3af4a2bb5..b44f1a1efa 100644 --- a/components/SelectPrimaryDelegators.tsx +++ b/components/SelectPrimaryDelegators.tsx @@ -1,4 +1,3 @@ -import { DisplayAddress } from '@cardinal/namespaces-components' import Select from '@components/inputs/Select' import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' @@ -9,6 +8,7 @@ import { useRealmQuery } from '@hooks/queries/realm' import { useMemo } from 'react' import { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' import { capitalize } from '@utils/helpers' +import { ProfileName } from './Profile/ProfileName' const YOUR_WALLET_VALUE = 'Your wallet' @@ -118,9 +118,8 @@ function PrimaryDelegatorSelect({ componentLabel={ selectedDelegator ? (
-
- x.toFixed(1).replace(/[.,]0$/, '') @@ -125,7 +125,7 @@ const VotingRules = () => {
{ACCOUNT_NAMES[treasuryAddress.result.toString()] ? ACCOUNT_NAMES[treasuryAddress.result.toString()] - : formatShortAddress(treasuryAddress.result)} + : }
diff --git a/package.json b/package.json index 8bd9c3a4c6..480b2c6273 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "@bonfida/spl-name-service": "0.1.47", "@bundlr-network/client": "0.7.15", "@carbon/icons-react": "11.7.0", - "@cardinal/namespaces-components": "2.5.5", "@civic/profile": "0.1.2", "@civic/solana-gateway-react": "0.15.0", "@coral-xyz/anchor": "0.27.0", @@ -146,11 +145,13 @@ "rc-slider": "9.7.5", "react": "18.2.0", "react-async-hook": "4.0.0", + "react-content-loader": "6.2.1", "react-dom": "18.0.0", "react-dropzone": "14.2.2", "react-easy-sort": "1.5.0", "react-headless-pagination": "0.1.0", "react-hook-form": "7.31.3", + "react-icons": "4.11.0", "react-markdown": "7.0.0", "react-portal": "4.2.2", "react-responsive": "9.0.0-beta.10", diff --git a/pages/dao/[symbol]/token-stats/index.tsx b/pages/dao/[symbol]/token-stats/index.tsx index f7a023eefa..e031a263ad 100644 --- a/pages/dao/[symbol]/token-stats/index.tsx +++ b/pages/dao/[symbol]/token-stats/index.tsx @@ -2,7 +2,7 @@ import Input from '@components/inputs/Input' import { GrantInstruction } from '@components/instructions/programs/voteStakeRegistry' import { MANGO_DAO_TREASURY } from '@components/instructions/tools' import PreviousRouteBtn from '@components/PreviousRouteBtn' -import { SearchIcon, UserCircleIcon } from '@heroicons/react/outline' +import { SearchIcon } from '@heroicons/react/outline' import useRealm from '@hooks/useRealm' import { BN, BorshInstructionCoder } from '@coral-xyz/anchor' import { @@ -22,7 +22,6 @@ import { getTimeLeftFromNowFmt, } from '@utils/dateTools' import InfoBox from 'VoteStakeRegistry/components/LockTokenStats/InfoBox' -import { AddressImage, DisplayAddress } from '@cardinal/namespaces-components' import { LockupType } from 'VoteStakeRegistry/sdk/accounts' import { DepositWithWallet, @@ -47,6 +46,7 @@ import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { useRealmProposalsQuery } from '@hooks/queries/proposal' import { useQuery } from '@tanstack/react-query' import { IDL } from 'VoteStakeRegistry/sdk/voter_stake_registry' +import {ProfileImage, ProfileName} from "@components/Profile"; const VestingVsTime = dynamic( () => import('VoteStakeRegistry/components/LockTokenStats/VestingVsTime'), @@ -437,9 +437,8 @@ const LockTokenStats = () => { : symbol const renderAddressName = (wallet) => { return ( - { ) } const renderAddressImage = (wallet) => ( - } - /> + ) return ( diff --git a/utils/address.ts b/utils/address.ts new file mode 100644 index 0000000000..9b2c27beab --- /dev/null +++ b/utils/address.ts @@ -0,0 +1,3 @@ +export const shortenAddress = (address: string, chars = 5): string => `${address.substring(0, chars)}...${address.substring( + address.length - chars +)}`; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9e2ec0b356..0d4d54c047 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13574,6 +13574,11 @@ react-clientside-effect@^1.2.6: dependencies: "@babel/runtime" "^7.12.13" +react-content-loader@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-6.2.1.tgz#8feb733c2d2495002e1b216f13707f2b5f2a8ead" + integrity sha512-6ONbFX+Hi3SHuP66JB8CPvJn372pj+qwltJV0J8z/8MFrq98I1cbFdZuhDWeQXu3CFxiiDTXJn7DFxx2ZvrO7g== + react-content-loader@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-6.2.0.tgz#cd8fee8160b8fda6610d0c69ce5aee7b8094cba6" @@ -13643,6 +13648,11 @@ react-hook-form@7.31.3: resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.3.tgz#b61bafb9a7435f91695351a7a9f714d8c4df0121" integrity sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ== +react-icons@4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.11.0.tgz#4b0e31c9bfc919608095cc429c4f1846f4d66c65" + integrity sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA== + react-icons@^4.3.1: version "4.7.1" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345" From eb225b150006694cadbf37e19ead6cc71545232f Mon Sep 17 00:00:00 2001 From: dankelleher Date: Fri, 20 Oct 2023 10:41:00 +0200 Subject: [PATCH 2/2] Lint fixes --- components/ConnectWalletButton.tsx | 2 -- components/Members/MembersTabs.tsx | 4 +--- components/SelectPrimaryDelegators.tsx | 2 -- pages/dao/[symbol]/token-stats/index.tsx | 1 - 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/components/ConnectWalletButton.tsx b/components/ConnectWalletButton.tsx index b26ce69fbc..cc23d0ea2f 100644 --- a/components/ConnectWalletButton.tsx +++ b/components/ConnectWalletButton.tsx @@ -15,7 +15,6 @@ import Loading from './Loading' import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base' import { useWallet } from '@solana/wallet-adapter-react' import { ExternalLinkIcon } from '@heroicons/react/outline' -import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { DEFAULT_PROVIDER } from '../utils/wallet-adapters' import useViewAsWallet from '@hooks/useViewAsWallet' import { ProfileName } from "@components/Profile/ProfileName"; @@ -39,7 +38,6 @@ const ConnectWalletButton = (props) => { publicKey: realPublicKey, connected, } = useWallet() - const connection = useLegacyConnectionContext() const publicKey = debugAdapter?.publicKey ?? realPublicKey diff --git a/components/Members/MembersTabs.tsx b/components/Members/MembersTabs.tsx index 0ec0bc144b..175b97465c 100644 --- a/components/Members/MembersTabs.tsx +++ b/components/Members/MembersTabs.tsx @@ -1,5 +1,5 @@ import { FunctionComponent, useMemo } from 'react' -import { LogoutIcon, UserCircleIcon } from '@heroicons/react/outline' +import { LogoutIcon } from '@heroicons/react/outline' import tokenPriceService from '@utils/services/tokenPrice' import { fmtMintAmount } from '@tools/sdk/units' import { PublicKey } from '@solana/web3.js' @@ -10,7 +10,6 @@ import { useRealmCommunityMintInfoQuery, useRealmCouncilMintInfoQuery, } from '@hooks/queries/mintInfo' -import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { useRealmConfigQuery } from '@hooks/queries/realmConfig' import { NFT_PLUGINS_PKS } from '@constants/plugins' import {ProfileName} from "@components/Profile/ProfileName"; @@ -110,7 +109,6 @@ const MemberItems = ({ councilVotes && !councilVotes.isZero() ? fmtMintAmount(councilMint, councilVotes) : null - const connection = useLegacyConnectionContext() const renderAddressName = useMemo(() => { return ( diff --git a/components/SelectPrimaryDelegators.tsx b/components/SelectPrimaryDelegators.tsx index b44f1a1efa..89e4bbb077 100644 --- a/components/SelectPrimaryDelegators.tsx +++ b/components/SelectPrimaryDelegators.tsx @@ -3,7 +3,6 @@ import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' import { PublicKey } from '@solana/web3.js' -import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' import { useRealmQuery } from '@hooks/queries/realm' import { useMemo } from 'react' import { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' @@ -104,7 +103,6 @@ function PrimaryDelegatorSelect({ kind: 'community' | 'council' tors: ProgramAccount[] }) { - const connection = useLegacyConnectionContext() return (
diff --git a/pages/dao/[symbol]/token-stats/index.tsx b/pages/dao/[symbol]/token-stats/index.tsx index e031a263ad..990cc5c662 100644 --- a/pages/dao/[symbol]/token-stats/index.tsx +++ b/pages/dao/[symbol]/token-stats/index.tsx @@ -141,7 +141,6 @@ const LockTokenStats = () => { const voteStakeRegistryRegistrar = useVotePluginsClientStore( (s) => s.state.voteStakeRegistryRegistrar ) - const connection = useLegacyConnectionContext() const governedTokenAccounts = useGovernanceAssetsStore( (s) => s.governedTokenAccounts )