Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: update react-opendax, Account inside boilerplate #13

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions assets/images/Metamask.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { FC } from 'react'
import { SVGICON } from '../../helpers/svgicon';

export const Metamask: FC<{}> = () => (
<SVGICON>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.9126 2L13.3184 8.35914L14.9165 4.61149L21.9126 2Z" fill="#E17726" stroke="#E17726" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M2.08789 2L10.6056 8.41849L9.08401 4.61149L2.08789 2Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M18.817 16.7438L16.5303 20.2371L21.4267 21.5852L22.8293 16.8201L18.817 16.7438Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M1.17871 16.8201L2.57282 21.5852L7.46077 20.2371L5.18255 16.7438L1.17871 16.8201Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.19701 10.8449L5.83691 12.8968L10.6823 13.1173L10.5208 7.90277L7.19701 10.8449Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M16.8026 10.8426L13.4279 7.84113L13.3174 13.115L18.1628 12.8945L16.8026 10.8426Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.46094 20.2363L10.3937 18.8204L7.86899 16.8533L7.46094 20.2363Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.6064 18.8204L16.5307 20.2363L16.1311 16.8533L13.6064 18.8204Z" fill="#E27625" stroke="#E27625" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M16.5307 20.2395L13.6064 18.8235L13.8444 20.7228L13.8189 21.5283L16.5307 20.2395Z" fill="#D5BFB2" stroke="#D5BFB2" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.46094 20.2395L10.1812 21.5283L10.1642 20.7228L10.3937 18.8235L7.46094 20.2395Z" fill="#D5BFB2" stroke="#D5BFB2" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M10.232 15.6003L7.80078 14.8881L9.51792 14.0996L10.232 15.6003Z" fill="#233447" stroke="#233447" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.7676 15.6003L14.4817 14.0996L16.2073 14.8881L13.7676 15.6003Z" fill="#233447" stroke="#233447" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.45982 20.2371L7.88488 16.7438L5.18164 16.8201L7.45982 20.2371Z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M16.1143 16.7438L16.5308 20.2371L18.8175 16.8201L16.1143 16.7438Z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M18.1628 12.8941L13.3174 13.1146L13.7679 15.5989L14.482 14.0981L16.2076 14.8867L18.1628 12.8941Z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.80058 14.8867L9.51772 14.0981L10.2318 15.5989L10.6823 13.1146L5.83691 12.8941L7.80058 14.8867Z" fill="#CC6228" stroke="#CC6228" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M5.83691 12.8941L7.8686 16.8538L7.80055 14.8867L5.83691 12.8941Z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M16.2083 14.8867L16.1318 16.8538L18.1635 12.8941L16.2083 14.8867Z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M10.683 13.116L10.2324 15.6003L10.802 18.534L10.9295 14.6676L10.683 13.116Z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.3172 13.116L13.0791 14.6592L13.1981 18.534L13.7677 15.6003L13.3172 13.116Z" fill="#E27525" stroke="#E27525" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.7678 15.6002L13.1982 18.5338L13.6063 18.8221L16.131 16.855L16.2075 14.8879L13.7678 15.6002Z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.80078 14.8879L7.86883 16.855L10.3935 18.8221L10.8016 18.5338L10.232 15.6002L7.80078 14.8879Z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.8195 21.5284L13.8449 20.7229L13.624 20.5364H10.3767L10.1642 20.7229L10.1812 21.5284L7.46094 20.2396L8.41301 21.0197L10.3427 22.3509H13.6494L15.5876 21.0197L16.5312 20.2396L13.8195 21.5284Z" fill="#C0AC9D" stroke="#C0AC9D" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.6068 18.8217L13.1988 18.5335H10.8016L10.3936 18.8217L10.1641 20.7211L10.3766 20.5345H13.6239L13.8449 20.7211L13.6068 18.8217Z" fill="#161616" stroke="#161616" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M22.2771 8.77459L22.9997 5.26436L21.9116 2L13.6064 8.1472L16.8027 10.8434L21.3166 12.1577L22.3112 10.9961L21.8777 10.6823L22.5662 10.0549L22.0391 9.64795L22.7277 9.12224L22.2771 8.77459Z" fill="#763E1A" stroke="#763E1A" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M1 5.26436L1.73106 8.77459L1.26353 9.12224L1.96058 9.64795L1.43354 10.0549L2.12209 10.6823L1.68856 10.9961L2.68314 12.1577L7.19706 10.8434L10.3933 8.1472L2.08809 2L1 5.26436Z" fill="#763E1A" stroke="#763E1A" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M21.3173 12.1573L16.8034 10.8431L18.1635 12.895L16.1318 16.8546L18.8181 16.8207H22.8304L21.3173 12.1573Z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M7.19719 10.8431L2.68334 12.1573L1.17871 16.8207H5.18255L7.86875 16.8546L5.83711 12.895L7.19719 10.8431Z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M13.3173 13.1153L13.6064 8.14668L14.9155 4.61102H9.08398L10.3931 8.14668L10.6821 13.1153L10.7926 14.6754L10.8011 18.5333H13.1983L13.2068 14.6754L13.3173 13.1153Z" fill="#F5841F" stroke="#F5841F" strokeWidth="0.25" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</SVGICON>
);
10 changes: 10 additions & 0 deletions assets/images/WalletConnect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { FC } from 'react'
import { SVGICON } from '../../helpers/svgicon';

export const WalletConnect: FC<{}> = () => (
<SVGICON>
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.91499 3.52042C8.82789 -0.293592 15.1719 -0.293592 19.0848 3.52042L19.5558 3.97945C19.7514 4.17015 19.7514 4.47933 19.5558 4.67003L17.9448 6.24026C17.847 6.33561 17.6884 6.33561 17.5906 6.24026L16.9425 5.60859C14.2128 2.94784 9.78703 2.94784 7.05729 5.60859L6.36329 6.28506C6.26547 6.38041 6.10687 6.38041 6.00904 6.28506L4.39811 4.71483C4.20246 4.52413 4.20246 4.21494 4.39811 4.02424L4.91499 3.52042ZM22.4164 6.76782L23.8501 8.16532C24.0458 8.35602 24.0458 8.66521 23.8502 8.85591L17.3853 15.1575C17.1897 15.3482 16.8725 15.3482 16.6768 15.1575C16.6768 15.1575 16.6768 15.1575 16.6768 15.1575L12.0885 10.6851C12.0396 10.6374 11.9603 10.6374 11.9114 10.6851C11.9114 10.6851 11.9114 10.6851 11.9114 10.6851L7.32315 15.1575C7.12751 15.3482 6.81031 15.3482 6.61466 15.1575C6.61466 15.1575 6.61466 15.1575 6.61466 15.1575L0.149663 8.85583C-0.0459815 8.66513 -0.0459815 8.35594 0.149663 8.16524L1.5834 6.76774C1.77905 6.57703 2.09625 6.57703 2.29189 6.76774L6.88029 11.2402C6.9292 11.2879 7.0085 11.2879 7.05742 11.2402C7.05742 11.2402 7.05742 11.2402 7.05742 11.2402L11.6456 6.76774C11.8412 6.57703 12.1584 6.57702 12.3541 6.76772C12.3541 6.76772 12.3541 6.76772 12.3541 6.76773L16.9425 11.2402C16.9914 11.2879 17.0707 11.2879 17.1196 11.2402L21.7079 6.76782C21.9036 6.57712 22.2208 6.57712 22.4164 6.76782Z" fill="#3B99FC"/>
</svg>
</SVGICON>
);
7 changes: 7 additions & 0 deletions assets/images/WalletIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const WalletIcon = ({classNames= '', stroke= 'rgb(55, 65, 81)'}: {classNames?: string, stroke?: string}): JSX.Element => (
<svg className={classNames} fill="none" viewBox="0 0 512 512" stroke={stroke} aria-hidden="true">
<rect width="416" height="288" x="48" y="144" fill="none" strokeLinejoin="round" strokeWidth="32" rx="48" ry="48"></rect>
<path fill="none" strokeLinejoin="round" strokeWidth="32" d="M411.36 144v-30A50 50 0 00352 64.9L88.64 109.85A50 50 0 0048 159v49"></path>
<path strokeWidth="32" d="M368 320a32 32 0 1132-32 32 32 0 01-32 32z"></path>
</svg>
);
92 changes: 92 additions & 0 deletions components/Account/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import classNames from 'classnames'
import React, { FC, useState } from 'react'
import {
useDApp,
useEagerConnect,
useENSName,
useWallet,
} from '../../hooks'
import { shortenHex } from '../../helpers'
import { AccountModal, Balance, Connector } from '../'
import { Metamask } from '../../assets/images/Metamask'
import { WalletIcon } from '../../assets/images/WalletIcon'

export type AccountProps = {
contentClassNames?: string;
label?: string;
buttonClassNames?: string;
collapseLeftBar?: boolean;
}

export const Account: FC<AccountProps> = ({
contentClassNames,
label,
buttonClassNames,
collapseLeftBar,
}: AccountProps) => {
const [showModal, setModal] = useState(false)
const triedToEagerConnect = useEagerConnect()
const { active, account, chain } = useWallet()
const { disconnect } = useDApp()
const ENSName = useENSName(account)
if (!triedToEagerConnect) {
return null
}

if (!active) {
return (
<Connector
Label={() => (
<>
{collapseLeftBar ?
<span>
<WalletIcon classNames="h-5 w-5" stroke="white" />
</span> :
<span className={buttonClassNames}>
{label}
</span>}
</>
)}
/>
)
}

return (
<>
<a
role="button"
className="flex justify-center lg:justify-start p-2 group block rounded-md hover:bg-gray-50"
onClick={() => setModal(true)}
>
<div className="flex items-center">
<div className="flex h-8 w-8 items-center justify-center bg-indigo-50 rounded-full">
<div className="flex w-5">
<Metamask />
</div>
</div>
{!collapseLeftBar && <div className={classNames('ml-2 truncate', contentClassNames)}>
<p className="flex text-base font-bold text-gray-700 group-hover:text-gray-900">
{chain && <Balance symbol={chain.nativeCurrency.symbol} precision={6} />}
</p>
<p className="text-xs font-medium truncate text-gray-500 group-hover:text-gray-700">
{ENSName || `${shortenHex(account, 4)}`}
</p>
</div>}
</div>
</a>
{account && chain && (
<AccountModal
open={showModal}
setOpen={setModal}
address={account}
chain={chain}
handleLogout={() => disconnect()}
/>
)}
</>
)
}

Account.defaultProps = {
label: 'Connect your wallet',
} as AccountProps
113 changes: 113 additions & 0 deletions components/AccountModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Dialog, Transition } from '@headlessui/react';
import { XIcon } from '@heroicons/react/solid'
import React, { FC } from 'react';
import { Fragment, useRef } from 'react'
import type { Chain } from '../../configs/chains'
import { ExplorerLink } from '../ExplorerLink'

type AccountModalProps = {
open: boolean
setOpen: (open: boolean) => void
address: string
chain: Chain
handleLogout: () => void
}

export const AccountModal: FC<AccountModalProps> = ({
open,
setOpen,
address,
chain,
handleLogout,
}: AccountModalProps) => {
const ctaButtonRef = useRef(null)
return (
<Transition.Root show={open} as={Fragment}>
<Dialog
as="div"
static
className="fixed z-20 inset-0 overflow-y-auto"
initialFocus={ctaButtonRef}
open={open}
onClose={setOpen}
>
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>

{/* This element is to trick the browser into centering the modal contents. */}
<span
className="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true"
>
&#8203;
</span>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
<div>
<div>
<Dialog.Title as="div" className="flex">
<h3 className="flex-1 text-lg leading-6 font-medium text-gray-900">
Your Wallet
</h3>
<button
className="bg-white rounded-md inline-flex text-gray-400 hover:text-gray-500"
onClick={() => setOpen(false)}
>
<span className="sr-only">Close</span>
<XIcon className="h-5 w-5" aria-hidden="true" />
</button>
</Dialog.Title>
<div className="mt-5 flex flex-col">
<div className="bg-gray-50 sm:rounded-lg p-2 sm:p-3 truncate">
{address}
</div>
<div className="mt-2 pl-3">
<ExplorerLink
chain={chain}
type={'address'}
value={address}
Label={({ name }) => (
<>
View on <span className="capitalize">{name}</span>
</>
)}
/>
</div>
<div className="flex justify-center mt-4">
<button
ref={ctaButtonRef}
type="button"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-primary-cta-color-main hover:bg-primary-cta-color-hover"
onClick={() => handleLogout()}
>
Logout
</button>
</div>
</div>
</div>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>
)
}
24 changes: 24 additions & 0 deletions components/Balance/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ethers } from 'ethers'
import React, { FC } from 'react'
import { useWallet } from '../../hooks/useWallet'

type BalanceProps = {
symbol: string
precision?: number
}

export const Balance: FC<BalanceProps> = ({ symbol, precision }: BalanceProps) => {
const { balance } = useWallet()

return (
<>
{balance ?
precision ?
ethers.utils.commify((+ethers.utils.formatEther(balance)).toFixed(precision)) :
ethers.utils.commify(ethers.utils.formatEther(balance))
: ''
}{' '}
{symbol}
</>
)
}
41 changes: 41 additions & 0 deletions components/Connector/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { FC } from 'react'
import { useCallback, useState } from 'react'
import type { ProviderWhitelist } from '../../hooks/useDApp'
import { useDApp } from '../../hooks'
import { WalletModal } from '../WalletModal'

type ConnectorProps = {
Label?: () => JSX.Element
}

export const Connector: FC<ConnectorProps> = ({
Label = () => <span>Connect your wallet</span>,
}: ConnectorProps) => {
const [showModal, setModal] = useState(false)
const { connectWithProvider } = useDApp()

const handleConnectWallet = useCallback(
(provider: ProviderWhitelist) => {
connectWithProvider(provider).catch(console.error)
setModal(false)
},
[connectWithProvider],
)

return (
<>
<button
type="button"
className="inline-flex justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-primary-cta-color-main hover:bg-primary-cta-color-hover"
onClick={() => setModal(true)}
>
<Label />
</button>
<WalletModal
open={showModal}
setOpen={setModal}
handleTriggerConnect={handleConnectWallet}
/>
</>
)
}
55 changes: 55 additions & 0 deletions components/ExplorerLink/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Link from 'next/link'
import React, { FC } from 'react'
import type { Chain } from '../../configs/chains'

type Explorer = {
name: string
url: string
standard: string
}

type ExploreType = 'address' | 'tx' | 'block'

function explorerLink(
explorer: Explorer,
type: ExploreType,
value: string | number,
) {
return `${explorer.url}/${type}/${value}`
}

function explorerName(explorer: Explorer) {
return explorer.name
}

type ExplorerLinkProps = {
chain: Chain
type: ExploreType
value: string | number
Label?: (params: { explorer: Explorer; name: string }) => JSX.Element
}

export const ExplorerLink: FC<ExplorerLinkProps> = ({
chain,
type,
value,
Label = ({ name }) => <span className="capitalize">{name}</span>,
}: ExplorerLinkProps) => {
const [explorer] = chain.explorers ?? []

return (
<>
{explorer && (
<Link href={explorerLink(explorer, type, value)}>
<a
target="_blank"
rel="noopener noreferrer"
className="text-sm font-medium text-indigo-600 hover:text-indigo-700 truncate"
>
<Label explorer={explorer} name={explorerName(explorer)} />
</a>
</Link>
)}
</>
)
}
Loading