chore: custom connect button
This commit is contained in:
parent
8fe1ec0dda
commit
10321e6006
17
README.md
17
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...
|
||||
|
@ -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';
|
||||
|
@ -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 <img src={avatar} className="w-full" />;
|
||||
export const CustomAvatar = ({ size }) => {
|
||||
const { avatar } = usePrimaryName();
|
||||
|
||||
return <img src={avatar || defaultAvatar} width={size} height={size} />;
|
||||
};
|
||||
|
||||
CustomAvatar.propTypes = {
|
||||
size: PropTypes.number,
|
||||
};
|
||||
|
53
src/abi.js
53
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',
|
||||
},
|
||||
];
|
||||
|
@ -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 }) => (
|
||||
<button
|
||||
className={cn(
|
||||
'px-3 py-2 rounded-full justify-center flex',
|
||||
'text-white text-sm font-semibold leading-none w-24 text-center',
|
||||
loading ? 'bg-blue-400' : 'bg-blue-600'
|
||||
'text-white text-sm font-semibold leading-none min-w-24 text-center',
|
||||
loading ? 'bg-blue-400' : 'bg-blue-600',
|
||||
className
|
||||
)}
|
||||
onClick={onClick}
|
||||
disabled={loading}
|
||||
@ -24,4 +25,5 @@ Button.propTypes = {
|
||||
children: PropTypes.node,
|
||||
onClick: PropTypes.func,
|
||||
loading: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
};
|
66
src/components/button/ConnectButton.jsx
Normal file
66
src/components/button/ConnectButton.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { ConnectButton as RainbowBtn } from '@rainbow-me/rainbowkit';
|
||||
import { Button } from './Button';
|
||||
import defaultAvatar from '../../assets/avatar.svg';
|
||||
import { usePrimaryName } from '../../hooks/usePrimaryName';
|
||||
|
||||
const Custom = ({
|
||||
account,
|
||||
chain,
|
||||
openAccountModal,
|
||||
openChainModal,
|
||||
openConnectModal,
|
||||
}) => {
|
||||
const { name, avatar } = usePrimaryName();
|
||||
const connected = account && chain;
|
||||
|
||||
if (!connected) {
|
||||
return <Button onClick={openConnectModal}>Connect Wallet</Button>;
|
||||
}
|
||||
|
||||
if (chain.unsupported) {
|
||||
return (
|
||||
<Button
|
||||
onClick={openChainModal}
|
||||
type="button"
|
||||
className="bg-red-600 whitespace-nowrap"
|
||||
>
|
||||
Wrong network
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className="p-1 bg-white rounded-lg shadow justify-start items-center inline-flex gap-1 cursor-pointer hover:scale-105 transition duration-200"
|
||||
onClick={openAccountModal}
|
||||
>
|
||||
<div className="text-sky-950 font-semibold hidden md:block pl-1">
|
||||
{account.displayBalance}
|
||||
</div>
|
||||
<div className="px-1.5 py-1 bg-neutral-100 rounded-lg justify-end items-center gap-1.5 flex">
|
||||
<img
|
||||
alt={name}
|
||||
src={avatar || account.ensAvatar || defaultAvatar}
|
||||
className="w-6 h-6 rounded-full overflow-hidden"
|
||||
/>
|
||||
|
||||
<div className="text-neutral-900 font-semibold">
|
||||
{name || account.ensName || account.displayName}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
Custom.propTypes = {
|
||||
account: PropTypes.object,
|
||||
chain: PropTypes.object,
|
||||
openAccountModal: PropTypes.func,
|
||||
openChainModal: PropTypes.func,
|
||||
openConnectModal: PropTypes.func,
|
||||
};
|
||||
|
||||
export const ConnectButton = () => {
|
||||
return <RainbowBtn.Custom>{Custom}</RainbowBtn.Custom>;
|
||||
};
|
@ -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';
|
||||
|
@ -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();
|
||||
|
@ -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';
|
||||
|
29
src/hooks/usePrimaryName.js
Normal file
29
src/hooks/usePrimaryName.js
Normal file
@ -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 };
|
||||
};
|
Loading…
Reference in New Issue
Block a user