From 10321e6006ac142703fb9d098a55d58405b0d186 Mon Sep 17 00:00:00 2001 From: Fernando Falci Date: Tue, 23 Apr 2024 14:55:24 +0200 Subject: [PATCH] chore: custom connect button --- README.md | 17 ++++- src/App.jsx | 2 +- src/CustomAvatar.jsx | 14 +++- src/abi.js | 53 +++++++++++++++ src/components/{ => button}/Button.jsx | 10 +-- src/components/button/ConnectButton.jsx | 66 +++++++++++++++++++ .../{ => button}/RegisterButton.jsx | 4 +- src/components/search/SearchCTA.jsx | 4 +- src/constants.js | 4 ++ src/hooks/usePrimaryName.js | 29 ++++++++ 10 files changed, 190 insertions(+), 13 deletions(-) rename src/components/{ => button}/Button.jsx (60%) create mode 100644 src/components/button/ConnectButton.jsx rename src/components/{ => button}/RegisterButton.jsx (88%) create mode 100644 src/hooks/usePrimaryName.js diff --git a/README.md b/README.md index 532685e..874ea75 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The contracts addresses are also in the [constants.js](/src/constants.js#L17-L23 This project can be deployed as static website. All the data needed comes from smart contracts. -Handling the communication with the contracts can be done with 2 React hooks: +Handling the communication with the contracts can be done with a few [React hooks](https://react.dev/reference/react/hooks): ### useDomainStatus() @@ -49,6 +49,21 @@ const register = useRegister({ `register` is an async function that will invoke Metamask (or any other wallet the user choose) and will be resolved once the user signs the transaction. +Tip: you can connect both hooks: + +```jsx +const { data } = useDomainStatus({ label: 'my-sld' }); +const register = useRegister(data); +``` + +### usePrimaryName() + +```jsx +const { name, avatar } = usePrimaryName(); +``` + +Both can be empty/null if the user hasn't defined a primary name a name yet. + ## Running locally It uses yarn, so... diff --git a/src/App.jsx b/src/App.jsx index 0218676..6fcdb3c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,4 @@ -import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { ConnectButton } from './components/button/ConnectButton'; import brandLogo from './assets/brand.png'; import hnsLogo from './assets/hns.id.png'; import { Search } from './components/search/Search'; diff --git a/src/CustomAvatar.jsx b/src/CustomAvatar.jsx index cf56af1..9ed802c 100644 --- a/src/CustomAvatar.jsx +++ b/src/CustomAvatar.jsx @@ -1,5 +1,13 @@ -import avatar from './assets/avatar.svg'; +import PropTypes from 'prop-types'; +import defaultAvatar from './assets/avatar.svg'; +import { usePrimaryName } from './hooks/usePrimaryName'; -export const CustomAvatar = () => { - return ; +export const CustomAvatar = ({ size }) => { + const { avatar } = usePrimaryName(); + + return ; +}; + +CustomAvatar.propTypes = { + size: PropTypes.number, }; diff --git a/src/abi.js b/src/abi.js index 32a968d..34db46e 100644 --- a/src/abi.js +++ b/src/abi.js @@ -95,4 +95,57 @@ export const abi = [ name: 'registerWithSignature', outputs: [], }, + { + inputs: [ + { + internalType: 'address', + name: '_addr', + type: 'address', + }, + { + internalType: 'uint256', + name: '_coinType', + type: 'uint256', + }, + ], + name: 'getName', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_addr', + type: 'address', + }, + { + internalType: 'string', + name: '_key', + type: 'string', + }, + { + internalType: 'uint256', + name: '_coinType', + type: 'uint256', + }, + ], + name: 'getText', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, ]; diff --git a/src/components/Button.jsx b/src/components/button/Button.jsx similarity index 60% rename from src/components/Button.jsx rename to src/components/button/Button.jsx index b57bd52..4a6db6a 100644 --- a/src/components/Button.jsx +++ b/src/components/button/Button.jsx @@ -1,13 +1,14 @@ import cn from 'classnames'; import PropTypes from 'prop-types'; -import icon from '../assets/loading.png'; +import icon from '../../assets/loading.png'; -export const Button = ({ children, onClick, loading }) => ( +export const Button = ({ children, onClick, loading, className }) => ( ; + } + + if (chain.unsupported) { + return ( + + ); + } + + return ( + + ); +}; + +Custom.propTypes = { + account: PropTypes.object, + chain: PropTypes.object, + openAccountModal: PropTypes.func, + openChainModal: PropTypes.func, + openConnectModal: PropTypes.func, +}; + +export const ConnectButton = () => { + return {Custom}; +}; diff --git a/src/components/RegisterButton.jsx b/src/components/button/RegisterButton.jsx similarity index 88% rename from src/components/RegisterButton.jsx rename to src/components/button/RegisterButton.jsx index 41da596..40a19e0 100644 --- a/src/components/RegisterButton.jsx +++ b/src/components/button/RegisterButton.jsx @@ -1,7 +1,7 @@ import { useQueryClient } from '@tanstack/react-query'; import { toast } from 'react-toastify'; -import { useRegister } from '../hooks/useRegister'; -import { domainDetails } from '../types'; +import { useRegister } from '../../hooks/useRegister'; +import { domainDetails } from '../../types'; import { Button } from './Button'; import { useState } from 'react'; diff --git a/src/components/search/SearchCTA.jsx b/src/components/search/SearchCTA.jsx index ce243f1..307d213 100644 --- a/src/components/search/SearchCTA.jsx +++ b/src/components/search/SearchCTA.jsx @@ -1,9 +1,9 @@ -import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { ConnectButton } from '../button/ConnectButton'; import Skeleton from 'react-loading-skeleton'; import { useAccount } from 'wagmi'; import { TLD } from '../../constants'; import { domainDetails } from '../../types'; -import { RegisterButton } from '../RegisterButton'; +import { RegisterButton } from '../button/RegisterButton'; export const SearchCTA = ({ details }) => { const { address, isConnected } = useAccount(); diff --git a/src/constants.js b/src/constants.js index 094e246..9bf2837 100644 --- a/src/constants.js +++ b/src/constants.js @@ -21,3 +21,7 @@ export const STATUS_CONTRACT_ADDR = DEV_MODE export const REGISTER_CONTRACT_ADDR = DEV_MODE ? '0x529B2b5B576c27769Ae0aB811F1655012f756C00' : '0xfda87CC032cD641ac192027353e5B25261dfe6b3'; + +export const PRIMARY_NAME_CONTRACT_ADDR = DEV_MODE + ? '0x342d6524829bedfF5Ce9f56cd56d5baAcf3dbC58' + : '0xDDa56f06D80f3D8E3E35159701A63753f39c3BCB'; diff --git a/src/hooks/usePrimaryName.js b/src/hooks/usePrimaryName.js new file mode 100644 index 0000000..f2a6c42 --- /dev/null +++ b/src/hooks/usePrimaryName.js @@ -0,0 +1,29 @@ +import { useAccount, useReadContracts } from 'wagmi'; +import { abi } from '../abi'; +import { PRIMARY_NAME_CONTRACT_ADDR } from '../constants'; + +export const usePrimaryName = () => { + const { address } = useAccount(); + + const res = useReadContracts({ + contracts: [ + { + address: PRIMARY_NAME_CONTRACT_ADDR, + abi: abi, + functionName: 'getName', + args: [address, 614n], + }, + { + address: PRIMARY_NAME_CONTRACT_ADDR, + abi: abi, + functionName: 'getText', + args: [address, 'avatar', 614n], + }, + ], + }); + + const name = res.data?.[0]?.result; + const avatar = res.data?.[1]?.result; + + return { name, avatar, ...res }; +};