Merge branch 'wallets'
This commit is contained in:
commit
bff24051d5
@ -2,7 +2,7 @@
|
||||
"name": "react-wallet-v2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3100",
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
@ -11,18 +11,22 @@
|
||||
"@walletconnect/client": "2.0.0-beta.22",
|
||||
"@walletconnect/utils": "2.0.0-beta.22",
|
||||
"@walletconnect/jsonrpc-utils": "1.0.0",
|
||||
"@nextui-org/react": "1.0.2-beta.3",
|
||||
"@nextui-org/react": "1.0.2-beta.4",
|
||||
"next": "12.0.10",
|
||||
"next-themes": "0.0.15",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-qr-reader-es6": "2.2.1-2",
|
||||
"framer-motion": "6.2.6",
|
||||
"ethers": "5.5.4",
|
||||
"keyvaluestorage": "0.7.1"
|
||||
"valtio": "1.3.0",
|
||||
"@json-rpc-tools/utils": "1.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@walletconnect/types": "2.0.0-beta.22",
|
||||
"@types/node": "17.0.14",
|
||||
"@types/react": "17.0.38",
|
||||
"eslint": "8.8.0",
|
||||
"@types/node": "17.0.17",
|
||||
"@types/react": "17.0.39",
|
||||
"eslint": "8.9.0",
|
||||
"eslint-config-next": "12.0.10",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"prettier": "2.5.1",
|
||||
|
24
wallets/react-wallet-v2/public/accounts-icon.svg
Normal file
24
wallets/react-wallet-v2/public/accounts-icon.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M160 368H448M160 144H448H160ZM160 256H448H160Z" stroke="url(#paint0_linear_46_13)" stroke-width="48" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M80 160C88.8366 160 96 152.837 96 144C96 135.163 88.8366 128 80 128C71.1634 128 64 135.163 64 144C64 152.837 71.1634 160 80 160Z" stroke="url(#paint1_linear_46_13)" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M80 272C88.8366 272 96 264.837 96 256C96 247.163 88.8366 240 80 240C71.1634 240 64 247.163 64 256C64 264.837 71.1634 272 80 272Z" stroke="url(#paint2_linear_46_13)" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M80 384C88.8366 384 96 376.837 96 368C96 359.163 88.8366 352 80 352C71.1634 352 64 359.163 64 368C64 376.837 71.1634 384 80 384Z" stroke="url(#paint3_linear_46_13)" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_46_13" x1="160" y1="144.018" x2="380.191" y2="421.745" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A562D5"/>
|
||||
<stop offset="1" stop-color="#306FEB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_46_13" x1="64" y1="128.003" x2="96.3014" y2="159.69" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A562D5"/>
|
||||
<stop offset="1" stop-color="#306FEB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_46_13" x1="64" y1="240.003" x2="96.3014" y2="271.69" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A562D5"/>
|
||||
<stop offset="1" stop-color="#306FEB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_46_13" x1="64" y1="352.003" x2="96.3014" y2="383.69" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A562D5"/>
|
||||
<stop offset="1" stop-color="#306FEB"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
46
wallets/react-wallet-v2/public/main.css
Normal file
46
wallets/react-wallet-v2/public/main.css
Normal file
@ -0,0 +1,46 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.routeTransition {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.qrVideoMask {
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
overflow: hidden !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.qrPlaceholder {
|
||||
border: 2px rgba(139, 139, 139, 0.4) dashed;
|
||||
width: 100%;
|
||||
border-radius: 15px;
|
||||
padding: 50px;
|
||||
}
|
||||
|
||||
.qrIcon {
|
||||
opacity: 0.3;
|
||||
}
|
13
wallets/react-wallet-v2/public/qr-icon.svg
Normal file
13
wallets/react-wallet-v2/public/qr-icon.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M408 336H344C339.582 336 336 339.582 336 344V408C336 412.418 339.582 416 344 416H408C412.418 416 416 412.418 416 408V344C416 339.582 412.418 336 408 336Z" fill="#8B8B8B"/>
|
||||
<path d="M328 272H280C275.582 272 272 275.582 272 280V328C272 332.418 275.582 336 280 336H328C332.418 336 336 332.418 336 328V280C336 275.582 332.418 272 328 272Z" fill="#8B8B8B"/>
|
||||
<path d="M472 416H424C419.582 416 416 419.582 416 424V472C416 476.418 419.582 480 424 480H472C476.418 480 480 476.418 480 472V424C480 419.582 476.418 416 472 416Z" fill="#8B8B8B"/>
|
||||
<path d="M472 272H440C435.582 272 432 275.582 432 280V312C432 316.418 435.582 320 440 320H472C476.418 320 480 316.418 480 312V280C480 275.582 476.418 272 472 272Z" fill="#8B8B8B"/>
|
||||
<path d="M312 432H280C275.582 432 272 435.582 272 440V472C272 476.418 275.582 480 280 480H312C316.418 480 320 476.418 320 472V440C320 435.582 316.418 432 312 432Z" fill="#8B8B8B"/>
|
||||
<path d="M408 96H344C339.582 96 336 99.5817 336 104V168C336 172.418 339.582 176 344 176H408C412.418 176 416 172.418 416 168V104C416 99.5817 412.418 96 408 96Z" fill="#8B8B8B"/>
|
||||
<path d="M448 48H304C295.163 48 288 55.1634 288 64V208C288 216.837 295.163 224 304 224H448C456.837 224 464 216.837 464 208V64C464 55.1634 456.837 48 448 48Z" stroke="#8B8B8B" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M168 96H104C99.5817 96 96 99.5817 96 104V168C96 172.418 99.5817 176 104 176H168C172.418 176 176 172.418 176 168V104C176 99.5817 172.418 96 168 96Z" fill="#8B8B8B"/>
|
||||
<path d="M208 48H64C55.1634 48 48 55.1634 48 64V208C48 216.837 55.1634 224 64 224H208C216.837 224 224 216.837 224 208V64C224 55.1634 216.837 48 208 48Z" stroke="#8B8B8B" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M168 336H104C99.5817 336 96 339.582 96 344V408C96 412.418 99.5817 416 104 416H168C172.418 416 176 412.418 176 408V344C176 339.582 172.418 336 168 336Z" fill="#8B8B8B"/>
|
||||
<path d="M208 288H64C55.1634 288 48 295.163 48 304V448C48 456.837 55.1634 464 64 464H208C216.837 464 224 456.837 224 448V304C224 295.163 216.837 288 208 288Z" stroke="#8B8B8B" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
9
wallets/react-wallet-v2/public/settings-icon.svg
Normal file
9
wallets/react-wallet-v2/public/settings-icon.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.8 KiB |
3
wallets/react-wallet-v2/public/wallet-connect-logo.svg
Normal file
3
wallets/react-wallet-v2/public/wallet-connect-logo.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="388" height="238" viewBox="0 0 388 238" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M79.4993 46.539C142.716 -15.355 245.209 -15.355 308.426 46.539L316.034 53.988C319.195 57.0827 319.195 62.1002 316.034 65.1949L290.008 90.6766C288.427 92.2239 285.865 92.2239 284.285 90.6766L273.815 80.4258C229.714 37.247 158.211 37.247 114.11 80.4258L102.898 91.4035C101.317 92.9509 98.7551 92.9509 97.1747 91.4035L71.1486 65.9219C67.9878 62.8272 67.9878 57.8096 71.1486 54.715L79.4993 46.539ZM362.25 99.2378L385.413 121.917C388.574 125.011 388.574 130.029 385.413 133.123L280.969 235.385C277.808 238.48 272.683 238.48 269.522 235.385C269.522 235.385 269.522 235.385 269.522 235.385L195.394 162.807C194.604 162.033 193.322 162.033 192.532 162.807C192.532 162.807 192.532 162.807 192.532 162.807L118.405 235.385C115.244 238.48 110.12 238.48 106.959 235.385C106.959 235.385 106.959 235.385 106.959 235.385L2.51129 133.122C-0.649517 130.027 -0.649517 125.01 2.51129 121.915L25.6746 99.2365C28.8354 96.1418 33.9601 96.1418 37.1209 99.2365L111.25 171.816C112.041 172.589 113.322 172.589 114.112 171.816C114.112 171.816 114.112 171.815 114.112 171.815L188.238 99.2365C191.399 96.1417 196.523 96.1416 199.684 99.2362C199.684 99.2362 199.684 99.2363 199.684 99.2363L273.814 171.815C274.604 172.589 275.885 172.589 276.675 171.815L350.804 99.2378C353.964 96.1431 359.089 96.1431 362.25 99.2378Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
48
wallets/react-wallet-v2/src/components/AccountCard.tsx
Normal file
48
wallets/react-wallet-v2/src/components/AccountCard.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { truncate } from '@/utils/HelperUtil'
|
||||
import { Avatar, Card, Text } from '@nextui-org/react'
|
||||
import Link from 'next/link'
|
||||
|
||||
interface Props {
|
||||
name: string
|
||||
logo: string
|
||||
rgb: string
|
||||
address: string
|
||||
}
|
||||
|
||||
export default function AccountCard({ name, logo, rgb, address }: Props) {
|
||||
return (
|
||||
<Link href={`/sessions?address=${address}`} passHref>
|
||||
<Card
|
||||
bordered
|
||||
clickable
|
||||
borderWeight="light"
|
||||
css={{
|
||||
borderColor: `rgba(${rgb}, 0.4)`,
|
||||
boxShadow: `0 0 10px 0 rgba(${rgb}, 0.15)`,
|
||||
backgroundColor: `rgba(${rgb}, 0.25)`,
|
||||
marginBottom: '$6',
|
||||
minHeight: '70px'
|
||||
}}
|
||||
>
|
||||
<Card.Body
|
||||
css={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
>
|
||||
<Avatar src={logo} />
|
||||
<div style={{ flex: 1 }}>
|
||||
<Text h5 css={{ marginLeft: '$9' }}>
|
||||
{name}
|
||||
</Text>
|
||||
<Text weight="light" size={13} css={{ marginLeft: '$9' }}>
|
||||
{truncate(address, 19)}
|
||||
</Text>
|
||||
</div>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Link>
|
||||
)
|
||||
}
|
@ -1,32 +1,81 @@
|
||||
import { Card, Container, Divider } from '@nextui-org/react'
|
||||
import { ReactNode } from 'react'
|
||||
import Navigation from '@/components/Navigation'
|
||||
import RouteTransition from '@/components/RouteTransition'
|
||||
import { Card, Container, Loading } from '@nextui-org/react'
|
||||
import { Fragment, ReactNode } from 'react'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface Props {
|
||||
initialized: boolean
|
||||
children: ReactNode | ReactNode[]
|
||||
}
|
||||
|
||||
export default function Layout({ children }: Props) {
|
||||
/**
|
||||
* Container
|
||||
*/
|
||||
export default function Layout({ children, initialized }: Props) {
|
||||
return (
|
||||
<Container
|
||||
display="flex"
|
||||
justify="center"
|
||||
alignItems="center"
|
||||
css={{ width: '100vw', height: '100vh' }}
|
||||
css={{
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
bordered
|
||||
borderWeight="light"
|
||||
css={{ height: '92vh', maxWidth: '600px', width: '100%' }}
|
||||
bordered={{ '@initial': false, '@xs': true }}
|
||||
borderWeight={{ '@initial': 'light', '@xs': 'light' }}
|
||||
css={{
|
||||
height: '100vh',
|
||||
width: '100%',
|
||||
justifyContent: initialized ? 'normal' : 'center',
|
||||
alignItems: initialized ? 'normal' : 'center',
|
||||
borderRadius: 0,
|
||||
outline: 'none',
|
||||
paddingBottom: 5,
|
||||
'@xs': {
|
||||
borderRadius: '$lg',
|
||||
height: '95vh',
|
||||
maxWidth: '450px'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Card.Header>Header</Card.Header>
|
||||
{initialized ? (
|
||||
<Fragment>
|
||||
<RouteTransition>
|
||||
<Card.Body
|
||||
css={{
|
||||
paddingLeft: 2,
|
||||
paddingRight: 2,
|
||||
'@xs': {
|
||||
padding: '20px'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Card.Body>
|
||||
</RouteTransition>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card.Body css={{ overflow: 'scroll' }}>{children}</Card.Body>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card.Footer>Footer</Card.Footer>
|
||||
<Card.Footer
|
||||
css={{
|
||||
height: '50px',
|
||||
minHeight: '50px',
|
||||
position: 'sticky',
|
||||
bottom: 0,
|
||||
left: 0
|
||||
}}
|
||||
>
|
||||
<Navigation />
|
||||
</Card.Footer>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Loading />
|
||||
)}
|
||||
</Card>
|
||||
</Container>
|
||||
)
|
||||
|
16
wallets/react-wallet-v2/src/components/Modal.tsx
Normal file
16
wallets/react-wallet-v2/src/components/Modal.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import SessionProposalModal from '@/views/SessionProposalModal'
|
||||
import SessionRequestModal from '@/views/SessionSignModal'
|
||||
import { Modal as NextModal } from '@nextui-org/react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
|
||||
export default function Modal() {
|
||||
const { open, view } = useSnapshot(ModalStore.state)
|
||||
|
||||
return (
|
||||
<NextModal blur open={open} style={{ border: '1px solid rgba(139, 139, 139, 0.4)' }}>
|
||||
{view === 'SessionProposalModal' && <SessionProposalModal />}
|
||||
{view === 'SessionSignModal' && <SessionRequestModal />}
|
||||
</NextModal>
|
||||
)
|
||||
}
|
39
wallets/react-wallet-v2/src/components/Navigation.tsx
Normal file
39
wallets/react-wallet-v2/src/components/Navigation.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import { Avatar, Row } from '@nextui-org/react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function Navigation() {
|
||||
return (
|
||||
<Row justify="space-between" align="center" css={{ width: '80%', margin: '0 auto' }}>
|
||||
<Link href="/" passHref>
|
||||
<a>
|
||||
<Image alt="accounts icon" src="/accounts-icon.svg" width={30} height={30} />
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link href="/walletconnect" passHref>
|
||||
<a>
|
||||
<Avatar
|
||||
size="lg"
|
||||
css={{ cursor: 'pointer' }}
|
||||
color="gradient"
|
||||
icon={
|
||||
<Image
|
||||
alt="wallet connect icon"
|
||||
src="/wallet-connect-logo.svg"
|
||||
width={30}
|
||||
height={30}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<Link href="/settings" passHref>
|
||||
<a>
|
||||
<Image alt="settings icon" src="/settings-icon.svg" width={35} height={35} />
|
||||
</a>
|
||||
</Link>
|
||||
</Row>
|
||||
)
|
||||
}
|
@ -1,19 +1,30 @@
|
||||
import { Text } from '@nextui-org/react'
|
||||
import { Divider, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface Props {
|
||||
children: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default function PageHeader({ children }: Props) {
|
||||
return (
|
||||
<Text
|
||||
h3
|
||||
css={{
|
||||
textGradient: '45deg, $cyan300 -30%, $green600 100%'
|
||||
}}
|
||||
weight="bold"
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
<Fragment>
|
||||
<Text
|
||||
h3
|
||||
weight="bold"
|
||||
css={{
|
||||
textGradient: '90deg, $secondary, $primary 30%',
|
||||
marginBottom: '$5'
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
<Divider css={{ marginBottom: '$10' }} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
77
wallets/react-wallet-v2/src/components/QrReader.tsx
Normal file
77
wallets/react-wallet-v2/src/components/QrReader.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import { Button, Loading } from '@nextui-org/react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Image from 'next/image'
|
||||
import { Fragment, useState } from 'react'
|
||||
|
||||
/**
|
||||
* You can use normal import if you are not within next / ssr environment
|
||||
* @info https://nextjs.org/docs/advanced-features/dynamic-import
|
||||
*/
|
||||
const ReactQrReader = dynamic(() => import('react-qr-reader-es6'), { ssr: false })
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface IProps {
|
||||
onConnect: (uri: string) => Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default function QrReader({ onConnect }: IProps) {
|
||||
const [show, setShow] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
function onError() {
|
||||
setShow(false)
|
||||
}
|
||||
|
||||
async function onScan(data: string | null) {
|
||||
if (data) {
|
||||
await onConnect(data)
|
||||
setShow(false)
|
||||
}
|
||||
}
|
||||
|
||||
function onShowScanner() {
|
||||
setLoading(true)
|
||||
setShow(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
{show ? (
|
||||
<Fragment>
|
||||
{loading && <Loading css={{ position: 'absolute' }} />}
|
||||
<div className="qrVideoMask">
|
||||
<ReactQrReader
|
||||
onLoad={() => setLoading(false)}
|
||||
showViewFinder={false}
|
||||
onError={onError}
|
||||
onScan={onScan}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) : (
|
||||
<div className="container qrPlaceholder">
|
||||
<Image
|
||||
src="/qr-icon.svg"
|
||||
width={100}
|
||||
height={100}
|
||||
alt="qr code icon"
|
||||
className="qrIcon"
|
||||
/>
|
||||
<Button
|
||||
color="gradient"
|
||||
css={{ marginTop: '$10', width: '100%' }}
|
||||
onClick={onShowScanner}
|
||||
>
|
||||
Scan QR code
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
32
wallets/react-wallet-v2/src/components/RouteTransition.tsx
Normal file
32
wallets/react-wallet-v2/src/components/RouteTransition.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { useRouter } from 'next/router'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface IProps {
|
||||
children: ReactNode | ReactNode[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
export default function RouteTransition({ children }: IProps) {
|
||||
const { pathname } = useRouter()
|
||||
|
||||
return (
|
||||
<AnimatePresence exitBeforeEnter>
|
||||
<motion.div
|
||||
className="routeTransition"
|
||||
key={pathname}
|
||||
initial={{ opacity: 0, translateY: 7 }}
|
||||
animate={{ opacity: 1, translateY: 0 }}
|
||||
exit={{ opacity: 0, translateY: 7 }}
|
||||
transition={{ duration: 0.18 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
)
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import { createContext, ReactNode, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface State {}
|
||||
|
||||
interface Props {
|
||||
children: ReactNode | ReactNode[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Context
|
||||
*/
|
||||
export const WalletContext = createContext<State>({})
|
||||
|
||||
/**
|
||||
* Provider
|
||||
*/
|
||||
export function WalletContextProvider({ children }: Props) {
|
||||
const [state, setState] = useState<State>({})
|
||||
|
||||
const actions = {
|
||||
async initialise() {}
|
||||
}
|
||||
|
||||
return <WalletContext.Provider value={{ state, actions }}>{children}</WalletContext.Provider>
|
||||
}
|
57
wallets/react-wallet-v2/src/data/EIP155Data.ts
Normal file
57
wallets/react-wallet-v2/src/data/EIP155Data.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @desc Refference list of eip155 chains
|
||||
* @url https://chainlist.org
|
||||
*/
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
const LOGO_BASE_URL = 'https://blockchain-api.xyz/logos/'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
export type TEIP155Chain = keyof typeof EIP155_CHAINS
|
||||
|
||||
/**
|
||||
* Chains
|
||||
*/
|
||||
export const EIP155_CHAINS = {
|
||||
'eip155:1': {
|
||||
chainId: 1,
|
||||
name: 'Ethereum',
|
||||
logo: LOGO_BASE_URL + 'eip155:1.png',
|
||||
rgb: '99, 125, 234'
|
||||
},
|
||||
'eip155:10': {
|
||||
chainId: 10,
|
||||
name: 'Optimism',
|
||||
logo: LOGO_BASE_URL + 'eip155:10.png',
|
||||
rgb: '233, 1, 1'
|
||||
},
|
||||
'eip155:137': {
|
||||
chainId: 137,
|
||||
name: 'Polygon',
|
||||
logo: LOGO_BASE_URL + 'eip155:137.png',
|
||||
rgb: '130, 71, 229'
|
||||
},
|
||||
'eip155:42161': {
|
||||
chainId: 42161,
|
||||
name: 'Arbitrum',
|
||||
logo: LOGO_BASE_URL + 'eip155:42161.png',
|
||||
rgb: '44, 55, 75'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
export const EIP155_SIGNING_METHODS = {
|
||||
PERSONAL_SIGN: 'personal_sign',
|
||||
ETH_SIGN: 'eth_sign',
|
||||
ETH_SIGN_TRANSACTION: 'eth_signTransaction',
|
||||
ETH_SIGN_TYPED_DATA: 'eth_signTypedData',
|
||||
ETH_SIGN_TYPED_DATA_V4: 'eth_signTypedData_v4',
|
||||
ETH_SIGN_RAW_TRANSACTION: 'eth_sendRawTransaction',
|
||||
ETH_SEND_TRANSACTION: 'eth_sendTransaction'
|
||||
}
|
25
wallets/react-wallet-v2/src/hooks/useInitialization.ts
Normal file
25
wallets/react-wallet-v2/src/hooks/useInitialization.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { createWalletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { createOrRestoreWallet } from '@/utils/WalletUtil'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
export default function useInitialization() {
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
|
||||
const onInitialize = useCallback(async () => {
|
||||
try {
|
||||
createOrRestoreWallet()
|
||||
await createWalletConnectClient()
|
||||
setInitialized(true)
|
||||
} catch (err: unknown) {
|
||||
alert(err)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
onInitialize()
|
||||
}
|
||||
}, [initialized, onInitialize])
|
||||
|
||||
return initialized
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { CLIENT_EVENTS } from '@walletconnect/client'
|
||||
import { SessionTypes } from '@walletconnect/types'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
|
||||
export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
// 1. Open session proposal modal for confirmation / rejection
|
||||
const onSessionProposal = useCallback((proposal: SessionTypes.Proposal) => {
|
||||
ModalStore.open('SessionProposalModal', { proposal })
|
||||
}, [])
|
||||
|
||||
// 2. Open session created modal to show success feedback
|
||||
const onSessionCreated = useCallback((created: SessionTypes.Created) => {}, [])
|
||||
|
||||
// 3. Open request handling modal based on method that was used
|
||||
const onSessionRequest = useCallback(async (requestEvent: SessionTypes.RequestEvent) => {
|
||||
const { topic, request } = requestEvent
|
||||
const { method } = request
|
||||
const requestSession = await walletConnectClient.session.get(topic)
|
||||
|
||||
if ([EIP155_SIGNING_METHODS.ETH_SIGN, EIP155_SIGNING_METHODS.PERSONAL_SIGN].includes(method)) {
|
||||
ModalStore.open('SessionSignModal', { requestEvent, requestSession })
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (initialized) {
|
||||
walletConnectClient.on(CLIENT_EVENTS.session.proposal, onSessionProposal)
|
||||
|
||||
walletConnectClient.on(CLIENT_EVENTS.session.created, onSessionCreated)
|
||||
|
||||
walletConnectClient.on(CLIENT_EVENTS.session.request, onSessionRequest)
|
||||
}
|
||||
}, [initialized, onSessionProposal, onSessionCreated, onSessionRequest])
|
||||
}
|
@ -1,17 +1,36 @@
|
||||
import Layout from '@/components/Layout'
|
||||
import { WalletContextProvider } from '@/contexts/WalletContext'
|
||||
import { theme } from '@/utils/ThemeUtil'
|
||||
import Modal from '@/components/Modal'
|
||||
import useInitialization from '@/hooks/useInitialization'
|
||||
import useWalletConnectEventsManager from '@/hooks/useWalletConnectEventsManager'
|
||||
import { darkTheme, lightTheme } from '@/utils/ThemeUtil'
|
||||
import { NextUIProvider } from '@nextui-org/react'
|
||||
import { ThemeProvider } from 'next-themes'
|
||||
import { AppProps } from 'next/app'
|
||||
import '../../public/main.css'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
// Step 1 - Initialize wallets and wallet connect client
|
||||
const initialized = useInitialization()
|
||||
|
||||
// Step 2 - Once initialized, set up wallet connect event manager
|
||||
useWalletConnectEventsManager(initialized)
|
||||
|
||||
return (
|
||||
<NextUIProvider theme={theme}>
|
||||
<WalletContextProvider>
|
||||
<Layout>
|
||||
<ThemeProvider
|
||||
defaultTheme="system"
|
||||
attribute="class"
|
||||
value={{
|
||||
light: lightTheme.className,
|
||||
dark: darkTheme.className
|
||||
}}
|
||||
>
|
||||
<NextUIProvider>
|
||||
<Layout initialized={initialized}>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</WalletContextProvider>
|
||||
</NextUIProvider>
|
||||
|
||||
<Modal />
|
||||
</NextUIProvider>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,16 @@
|
||||
import AccountCard from '@/components/AccountCard'
|
||||
import PageHeader from '@/components/PageHeader'
|
||||
import { EIP155_CHAINS } from '@/data/EIP155Data'
|
||||
import { wallet } from '@/utils/WalletUtil'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function HomePage() {
|
||||
return <PageHeader>Accounts</PageHeader>
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader>Accounts</PageHeader>
|
||||
{Object.values(EIP155_CHAINS).map(({ name, logo, rgb }) => (
|
||||
<AccountCard key={name} name={name} logo={logo} rgb={rgb} address={wallet.address} />
|
||||
))}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
20
wallets/react-wallet-v2/src/pages/sessions.tsx
Normal file
20
wallets/react-wallet-v2/src/pages/sessions.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import PageHeader from '@/components/PageHeader'
|
||||
import { truncate } from '@/utils/HelperUtil'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Fragment, useEffect } from 'react'
|
||||
|
||||
export default function SessionsPage() {
|
||||
const { query } = useRouter()
|
||||
const address = (query?.address as string) ?? 'Unknown'
|
||||
|
||||
useEffect(() => {
|
||||
console.log(walletConnectClient.session.values)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader>{truncate(address, 15)}</PageHeader>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
46
wallets/react-wallet-v2/src/pages/settings.tsx
Normal file
46
wallets/react-wallet-v2/src/pages/settings.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import PageHeader from '@/components/PageHeader'
|
||||
import { wallet } from '@/utils/WalletUtil'
|
||||
import { Card, Divider, Row, Switch, Text, useTheme } from '@nextui-org/react'
|
||||
import { useTheme as useNextTheme } from 'next-themes'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { setTheme } = useNextTheme()
|
||||
const { isDark, type } = useTheme()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader>Settings</PageHeader>
|
||||
<Text h4 css={{ marginBottom: '$5' }}>
|
||||
Mnemonic
|
||||
</Text>
|
||||
<Card bordered borderWeight="light">
|
||||
<Text css={{ fontFamily: '$mono' }}>{wallet.mnemonic.phrase}</Text>
|
||||
</Card>
|
||||
|
||||
<Text css={{ color: '$yellow500', marginTop: '$5', textAlign: 'center' }}>
|
||||
Warning: mnemonic is provided for development purposes only and should not be used
|
||||
elsewhere!
|
||||
</Text>
|
||||
|
||||
<Divider y={3} />
|
||||
|
||||
<Text h4 css={{ marginBottom: '$5' }}>
|
||||
Testnets
|
||||
</Text>
|
||||
<Row justify="space-between" align="center">
|
||||
<Switch /> <Text>Dissabled</Text>
|
||||
</Row>
|
||||
|
||||
<Divider y={3} />
|
||||
|
||||
<Text h4 css={{ marginBottom: '$5' }}>
|
||||
Theme
|
||||
</Text>
|
||||
<Row justify="space-between" align="center">
|
||||
<Switch checked={isDark} onChange={e => setTheme(e.target.checked ? 'dark' : 'light')} />{' '}
|
||||
<Text>{type}</Text>
|
||||
</Row>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
52
wallets/react-wallet-v2/src/pages/walletconnect.tsx
Normal file
52
wallets/react-wallet-v2/src/pages/walletconnect.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import PageHeader from '@/components/PageHeader'
|
||||
import QrReader from '@/components/QrReader'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { Button, Input, Loading, Text } from '@nextui-org/react'
|
||||
import { Fragment, useState } from 'react'
|
||||
|
||||
export default function WalletConnectPage() {
|
||||
const [uri, setUri] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
async function onConnect(uri: string) {
|
||||
try {
|
||||
setLoading(true)
|
||||
await walletConnectClient.pair({ uri })
|
||||
} catch (err: unknown) {
|
||||
alert(err)
|
||||
} finally {
|
||||
setUri('')
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageHeader>WalletConnect</PageHeader>
|
||||
|
||||
<QrReader onConnect={onConnect} />
|
||||
|
||||
<Text size={13} css={{ textAlign: 'center', marginTop: '$10', marginBottom: '$10' }}>
|
||||
or use walletconnect uri
|
||||
</Text>
|
||||
|
||||
<Input
|
||||
bordered
|
||||
placeholder="e.g. wc:a281567bb3e4..."
|
||||
onChange={e => setUri(e.target.value)}
|
||||
value={uri}
|
||||
contentRight={
|
||||
<Button
|
||||
size="xs"
|
||||
disabled={!uri}
|
||||
css={{ marginLeft: -60 }}
|
||||
onClick={() => onConnect(uri)}
|
||||
color="gradient"
|
||||
>
|
||||
{loading ? <Loading size="sm" /> : 'Connect'}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
44
wallets/react-wallet-v2/src/store/ModalStore.ts
Normal file
44
wallets/react-wallet-v2/src/store/ModalStore.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { SessionTypes } from '@walletconnect/types'
|
||||
import { proxy } from 'valtio'
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
interface ModalData {
|
||||
proposal?: SessionTypes.Proposal
|
||||
created?: SessionTypes.Created
|
||||
requestEvent?: SessionTypes.RequestEvent
|
||||
requestSession?: SessionTypes.Settled
|
||||
}
|
||||
|
||||
interface State {
|
||||
open: boolean
|
||||
view?: 'SessionProposalModal' | 'SessionSignModal'
|
||||
data?: ModalData
|
||||
}
|
||||
|
||||
/**
|
||||
* State
|
||||
*/
|
||||
const state = proxy<State>({
|
||||
open: false
|
||||
})
|
||||
|
||||
/**
|
||||
* Store / Actions
|
||||
*/
|
||||
const ModalStore = {
|
||||
state,
|
||||
|
||||
open(view: State['view'], data: State['data']) {
|
||||
state.view = view
|
||||
state.data = data
|
||||
state.open = true
|
||||
},
|
||||
|
||||
close() {
|
||||
state.open = false
|
||||
}
|
||||
}
|
||||
|
||||
export default ModalStore
|
28
wallets/react-wallet-v2/src/utils/HelperUtil.ts
Normal file
28
wallets/react-wallet-v2/src/utils/HelperUtil.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { utils } from 'ethers'
|
||||
|
||||
/**
|
||||
* Truncates string (in the middle) via given lenght value
|
||||
*/
|
||||
export function truncate(value: string, length: number) {
|
||||
if (value.length <= length) {
|
||||
return value
|
||||
}
|
||||
|
||||
const separator = '...'
|
||||
const stringLength = length - separator.length
|
||||
const frontLength = Math.ceil(stringLength / 2)
|
||||
const backLength = Math.floor(stringLength / 2)
|
||||
|
||||
return value.substring(0, frontLength) + separator + value.substring(value.length - backLength)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts hex to utf8 string if it is valid bytes
|
||||
*/
|
||||
export function convertHexToUtf8(value: string) {
|
||||
if (utils.isHexString(value)) {
|
||||
return utils.toUtf8String(value)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
29
wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
Normal file
29
wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
|
||||
import { convertHexToUtf8 } from '@/utils/HelperUtil'
|
||||
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
|
||||
import { RequestEvent } from '@walletconnect/types'
|
||||
import { ERROR } from '@walletconnect/utils'
|
||||
import { Wallet } from 'ethers'
|
||||
|
||||
export async function approveEIP155Request(request: RequestEvent['request'], wallet: Wallet) {
|
||||
const { method, params, id } = request
|
||||
|
||||
switch (method) {
|
||||
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
||||
const personalSignResult = await wallet.signMessage(convertHexToUtf8(params[0]))
|
||||
return formatJsonRpcResult(id, personalSignResult)
|
||||
|
||||
case EIP155_SIGNING_METHODS.ETH_SIGN:
|
||||
const ethSignResult = await wallet.signMessage(convertHexToUtf8(params[1]))
|
||||
return formatJsonRpcResult(id, ethSignResult)
|
||||
|
||||
default:
|
||||
throw new Error(ERROR.UNKNOWN_JSONRPC_METHOD.format().message)
|
||||
}
|
||||
}
|
||||
|
||||
export function rejectEIP155Request(request: RequestEvent['request']) {
|
||||
const { id } = request
|
||||
|
||||
return formatJsonRpcError(id, ERROR.JSONRPC_REQUEST_METHOD_REJECTED.format().message)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { createTheme } from '@nextui-org/react'
|
||||
|
||||
export const theme = createTheme({
|
||||
type: 'dark'
|
||||
})
|
||||
export const darkTheme = createTheme({ type: 'dark' })
|
||||
|
||||
export const lightTheme = createTheme({ type: 'light' })
|
||||
|
17
wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts
Normal file
17
wallets/react-wallet-v2/src/utils/WalletConnectUtil.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import WalletConnectClient from '@walletconnect/client'
|
||||
|
||||
export let walletConnectClient: WalletConnectClient
|
||||
|
||||
export async function createWalletConnectClient() {
|
||||
walletConnectClient = await WalletConnectClient.init({
|
||||
controller: true,
|
||||
projectId: '8f331b9812e0e5b8f2da2c7203624869',
|
||||
relayUrl: 'wss://relay.walletconnect.com',
|
||||
metadata: {
|
||||
name: 'React Wallet',
|
||||
description: 'React Wallet for WalletConnect',
|
||||
url: 'https://walletconnect.com/',
|
||||
icons: ['https://avatars.githubusercontent.com/u/37784886']
|
||||
}
|
||||
})
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { Wallet } from 'ethers'
|
||||
|
||||
const STORAGE_KEY = 'WALLET_MNEMONIC'
|
||||
|
||||
export let wallet: Wallet
|
||||
|
||||
export function createOrRestoreWallet() {
|
||||
const mnemonic = localStorage.getItem(STORAGE_KEY)
|
||||
|
||||
if (mnemonic) {
|
||||
wallet = Wallet.fromMnemonic(mnemonic)
|
||||
} else {
|
||||
wallet = Wallet.createRandom()
|
||||
// Don't store mnemonic in local storage in a production project!
|
||||
localStorage.setItem(STORAGE_KEY, wallet.mnemonic.phrase)
|
||||
}
|
||||
}
|
106
wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
Normal file
106
wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
Normal file
@ -0,0 +1,106 @@
|
||||
import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { wallet } from '@/utils/WalletUtil'
|
||||
import { Avatar, Button, Col, Container, Divider, Link, Modal, Row, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SessionProposalModal() {
|
||||
// Get proposal data and wallet address from store
|
||||
const proposal = ModalStore.state.data?.proposal
|
||||
|
||||
// Ensure proposal is defined
|
||||
if (!proposal) {
|
||||
return <Text>Missing proposal data</Text>
|
||||
}
|
||||
|
||||
// Get required proposal data
|
||||
const { proposer, permissions, relay } = proposal
|
||||
const { icons, name, url } = proposer.metadata
|
||||
const { chains } = permissions.blockchain
|
||||
const { methods } = permissions.jsonrpc
|
||||
const { protocol } = relay
|
||||
|
||||
// Hanlde approve action
|
||||
async function onApprove() {
|
||||
if (proposal) {
|
||||
const response = {
|
||||
state: {
|
||||
accounts: chains.map(chain => `${chain}:${wallet.address}`)
|
||||
}
|
||||
}
|
||||
await walletConnectClient.approve({ proposal, response })
|
||||
}
|
||||
ModalStore.close()
|
||||
}
|
||||
|
||||
// Hanlde reject action
|
||||
async function onReject() {
|
||||
if (proposal) {
|
||||
await walletConnectClient.reject({ proposal })
|
||||
}
|
||||
ModalStore.close()
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Modal.Header>
|
||||
<Text h3>Session Proposal</Text>
|
||||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
<Container css={{ padding: 0 }}>
|
||||
<Row align="center">
|
||||
<Col span={3}>
|
||||
<Avatar src={icons[0]} />
|
||||
</Col>
|
||||
<Col span={14}>
|
||||
<Text h5>{name}</Text>
|
||||
<Link href={url}>{url}</Link>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Blockchains</Text>
|
||||
<Text color="$gray400">
|
||||
{chains
|
||||
.map(chain => EIP155_CHAINS[chain as TEIP155Chain]?.name ?? chain)
|
||||
.join(', ')}
|
||||
</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Methods</Text>
|
||||
<Text color="$gray400">{methods.map(method => method).join(', ')}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Relay Protocol</Text>
|
||||
<Text color="$gray400">{protocol}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button auto flat color="error" onClick={onReject}>
|
||||
Reject
|
||||
</Button>
|
||||
<Button auto flat color="success" onClick={onApprove}>
|
||||
Approve
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
122
wallets/react-wallet-v2/src/views/SessionSignModal.tsx
Normal file
122
wallets/react-wallet-v2/src/views/SessionSignModal.tsx
Normal file
@ -0,0 +1,122 @@
|
||||
import { EIP155_CHAINS, EIP155_SIGNING_METHODS, TEIP155Chain } from '@/data/EIP155Data'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { convertHexToUtf8 } from '@/utils/HelperUtil'
|
||||
import { approveEIP155Request, rejectEIP155Request } from '@/utils/RequestHandlerUtil'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { wallet } from '@/utils/WalletUtil'
|
||||
import { Avatar, Button, Col, Container, Divider, Link, Modal, Row, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SessionSignModal() {
|
||||
// Get request and wallet data from store
|
||||
const requestEvent = ModalStore.state.data?.requestEvent
|
||||
const requestSession = ModalStore.state.data?.requestSession
|
||||
|
||||
// Ensure request and wallet are defined
|
||||
if (!requestEvent || !requestSession) {
|
||||
return <Text>Missing request data</Text>
|
||||
}
|
||||
|
||||
// Get required request data
|
||||
const { chainId } = requestEvent
|
||||
const { method, params } = requestEvent.request
|
||||
const { protocol } = requestSession.relay
|
||||
const { name, icons, url } = requestSession.peer.metadata
|
||||
|
||||
// Get message, convert it to UTF8 string if it is valid hex
|
||||
let message = method === EIP155_SIGNING_METHODS.PERSONAL_SIGN ? params[0] : params[1]
|
||||
message = convertHexToUtf8(message)
|
||||
|
||||
// Handle approve action (logic varies based on request method)
|
||||
async function onApprove() {
|
||||
if (requestEvent) {
|
||||
const response = await approveEIP155Request(requestEvent.request, wallet)
|
||||
await walletConnectClient.respond({
|
||||
topic: requestEvent.topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reject action
|
||||
async function onReject() {
|
||||
if (requestEvent) {
|
||||
const response = rejectEIP155Request(requestEvent.request)
|
||||
await walletConnectClient.respond({
|
||||
topic: requestEvent.topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Modal.Header>
|
||||
<Text h3>Request</Text>
|
||||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
<Container css={{ padding: 0 }}>
|
||||
<Row align="center">
|
||||
<Col span={3}>
|
||||
<Avatar src={icons[0]} />
|
||||
</Col>
|
||||
<Col span={14}>
|
||||
<Text h5>{name}</Text>
|
||||
<Link href={url}>{url}</Link>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Blockchain</Text>
|
||||
<Text color="$gray400">
|
||||
{EIP155_CHAINS[chainId as TEIP155Chain]?.name ?? chainId}
|
||||
</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Message</Text>
|
||||
<Text color="$gray400">{message}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Method</Text>
|
||||
<Text color="$gray400">{method}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<Row>
|
||||
<Col>
|
||||
<Text h5>Relay Protocol</Text>
|
||||
<Text color="$gray400">{protocol}</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</Modal.Body>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button auto flat color="error" onClick={onReject}>
|
||||
Reject
|
||||
</Button>
|
||||
<Button auto flat color="success" onClick={onApprove}>
|
||||
Approve
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
|
@ -24,14 +24,33 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@eslint/eslintrc@^1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318"
|
||||
integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==
|
||||
"@babel/runtime@^7.6.2":
|
||||
version "7.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
|
||||
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@emotion/is-prop-valid@^0.8.2":
|
||||
version "0.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
||||
dependencies:
|
||||
"@emotion/memoize" "0.7.4"
|
||||
|
||||
"@emotion/memoize@0.7.4":
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
||||
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
||||
|
||||
"@eslint/eslintrc@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3"
|
||||
integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^9.2.0"
|
||||
espree "^9.3.1"
|
||||
globals "^13.9.0"
|
||||
ignore "^4.0.6"
|
||||
import-fresh "^3.2.1"
|
||||
@ -398,6 +417,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@json-rpc-tools/types@^1.7.6":
|
||||
version "1.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.6.tgz#5abd5fde01364a130c46093b501715bcce5bdc0e"
|
||||
integrity sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ==
|
||||
dependencies:
|
||||
keyvaluestorage-interface "^1.0.0"
|
||||
|
||||
"@json-rpc-tools/utils@1.7.6":
|
||||
version "1.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.7.6.tgz#67f04987dbaa2e7adb6adff1575367b75a9a9ba1"
|
||||
integrity sha512-HjA8x/U/Q78HRRe19yh8HVKoZ+Iaoo3YZjakJYxR+rw52NHo6jM+VE9b8+7ygkCFXl/EHID5wh/MkXaE/jGyYw==
|
||||
dependencies:
|
||||
"@json-rpc-tools/types" "^1.7.6"
|
||||
"@pedrouid/environment" "^1.0.1"
|
||||
|
||||
"@next/env@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.10.tgz#561640fd62279218ccd2798ae907bae8d94a7730"
|
||||
@ -465,12 +499,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz#5c0ba98b695c4be44d8793aff42971a0dac65c2d"
|
||||
integrity sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==
|
||||
|
||||
"@nextui-org/react@1.0.2-beta.3":
|
||||
version "1.0.2-beta.3"
|
||||
resolved "https://registry.yarnpkg.com/@nextui-org/react/-/react-1.0.2-beta.3.tgz#d224654aa54a9b316922fdfacdd79d8ffa1d9797"
|
||||
integrity sha512-YkAXBc4f3Qfzf409BFZi9MAKj0lWArTb1L2ZASAKoBQKsxtRbVTko18Losjsjun/WwK4X8RiR9e8XlzYPm2RZA==
|
||||
"@nextui-org/react@1.0.2-beta.4":
|
||||
version "1.0.2-beta.4"
|
||||
resolved "https://registry.yarnpkg.com/@nextui-org/react/-/react-1.0.2-beta.4.tgz#fe88e4ed2335e0bf10dfb065474a5d1f66ba6766"
|
||||
integrity sha512-14QFPOJwVn6c6WWmLyud/458DoVolWDBhq1wpMCe3o0dWdtNoOr/YwxiuZjSNwtypeDrroMbXcEIY4AoGzLV1w==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.9.6"
|
||||
"@react-aria/focus" "3.5.0"
|
||||
"@react-aria/label" "3.2.1"
|
||||
"@react-aria/ssr" "3.1.0"
|
||||
"@react-aria/utils" "3.11.0"
|
||||
"@stitches/react" "1.2.6"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
@ -494,6 +532,78 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@pedrouid/environment@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec"
|
||||
integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug==
|
||||
|
||||
"@react-aria/focus@3.5.0":
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.5.0.tgz#02b85f97d6114af1eccc0902ce40723b626cb7f9"
|
||||
integrity sha512-Eib75Q6QgQdn8VVVByg5Vipaaj/C//8Bs++sQY7nkomRx4sdArOnXbDppul3YHP6mRfU9VRLvAigEUlReQF/Xw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
"@react-aria/interactions" "^3.6.0"
|
||||
"@react-aria/utils" "^3.9.0"
|
||||
"@react-types/shared" "^3.9.0"
|
||||
clsx "^1.1.1"
|
||||
|
||||
"@react-aria/interactions@^3.6.0":
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.7.0.tgz#eb19c1068b557a6b6df1e1c4abef07de719e9f25"
|
||||
integrity sha512-Xomchjb9bqvh3ocil+QCEYFSxsTy8PHEz43mNP6z2yuu3UqTpl2FsWfyKgF/Yy0WKVkyV2dO2uz758KJTCLZhw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
"@react-aria/utils" "^3.10.0"
|
||||
"@react-types/shared" "^3.10.0"
|
||||
|
||||
"@react-aria/label@3.2.1":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@react-aria/label/-/label-3.2.1.tgz#e6562259e6b17e3856c4c3e0060903cf705d094b"
|
||||
integrity sha512-QZ5/dpJKRjB1JtFZfOVd5GUiCpA2yMgmNA6ky6jT5XNAo7H14QqGRFUGDTLAQYGd+Bc3s+NayOT3NKUYur/3Xw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
"@react-aria/utils" "^3.10.0"
|
||||
"@react-types/label" "^3.5.0"
|
||||
"@react-types/shared" "^3.10.0"
|
||||
|
||||
"@react-aria/ssr@3.1.0", "@react-aria/ssr@^3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.1.0.tgz#b7163e6224725c30121932a8d1422ef91d1fab22"
|
||||
integrity sha512-RxqQKmE8sO7TGdrcSlHTcVzMP450hqowtBSd2bBS9oPlcokVkaGq28c3Rwa8ty5ctw4EBCjXqjP7xdcKMGDzug==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
|
||||
"@react-aria/utils@3.11.0", "@react-aria/utils@^3.10.0", "@react-aria/utils@^3.9.0":
|
||||
version "3.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.11.0.tgz#215ea23a5435672a822cd713bdb8217972c5c80b"
|
||||
integrity sha512-4yFA8E9xqDCUlolYSsoyp/qxrkiQrnEqx1BQOrKDuicpW7MBJ39pJC23YFMpyK2a6xEptc6xJEeIEFJXp57jJw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
"@react-aria/ssr" "^3.1.0"
|
||||
"@react-stately/utils" "^3.3.0"
|
||||
"@react-types/shared" "^3.10.1"
|
||||
clsx "^1.1.1"
|
||||
|
||||
"@react-stately/utils@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-stately/utils/-/utils-3.3.0.tgz#99866c5788539268a06035acd5925b25bb4cedde"
|
||||
integrity sha512-f//Y8q0+FFcS04xvCNvbba7WWRLHzj2AegLgdgwTxsnk9Gb+AyuasdRrRY7bGQhdHuEJ7OIiQZ9EQWndDbrTcg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.2"
|
||||
|
||||
"@react-types/label@^3.5.0":
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-types/label/-/label-3.5.0.tgz#c7093871f42c62e1b5523f61a0856a2f58d4cf2a"
|
||||
integrity sha512-a9lpQUyV4XwsZv0gV1jPjPWicSSa+DRliuXLTwORirxNLF0kMk89DLYf0a9CZhiEniJYqoqR3laJDvLAFW1x/Q==
|
||||
dependencies:
|
||||
"@react-types/shared" "^3.9.0"
|
||||
|
||||
"@react-types/shared@^3.10.0", "@react-types/shared@^3.10.1", "@react-types/shared@^3.9.0":
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@react-types/shared/-/shared-3.10.1.tgz#16cd3038361dee63f351fa4d0fd25d90480a149b"
|
||||
integrity sha512-U3dLJtstvOiZ8XLrWdNv9WXuruoDyfIfSXguTs9N0naDdO+M0MIbt/1Hg7Toe43ueAe56GM14IFL+S0/jhv8ow==
|
||||
|
||||
"@rushstack/eslint-patch@^1.0.8":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
|
||||
@ -555,20 +665,20 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/node@17.0.14":
|
||||
version "17.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.14.tgz#33b9b94f789a8fedd30a68efdbca4dbb06b61f20"
|
||||
integrity sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==
|
||||
"@types/node@17.0.17":
|
||||
version "17.0.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c"
|
||||
integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
|
||||
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
|
||||
|
||||
"@types/react@17.0.38":
|
||||
version "17.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd"
|
||||
integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ==
|
||||
"@types/react@17.0.39":
|
||||
version "17.0.39"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce"
|
||||
integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
@ -1032,6 +1142,11 @@ chownr@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
clsx@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
|
||||
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
|
||||
|
||||
code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
@ -1370,10 +1485,10 @@ eslint-plugin-react@^7.27.0:
|
||||
semver "^6.3.0"
|
||||
string.prototype.matchall "^4.0.6"
|
||||
|
||||
eslint-scope@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153"
|
||||
integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==
|
||||
eslint-scope@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
||||
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
@ -1390,17 +1505,22 @@ eslint-visitor-keys@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
|
||||
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
|
||||
|
||||
eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0:
|
||||
eslint-visitor-keys@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1"
|
||||
integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==
|
||||
|
||||
eslint@8.8.0:
|
||||
version "8.8.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.8.0.tgz#9762b49abad0cb4952539ffdb0a046392e571a2d"
|
||||
integrity sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==
|
||||
eslint-visitor-keys@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
|
||||
eslint@8.9.0:
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb"
|
||||
integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^1.0.5"
|
||||
"@eslint/eslintrc" "^1.1.0"
|
||||
"@humanwhocodes/config-array" "^0.9.2"
|
||||
ajv "^6.10.0"
|
||||
chalk "^4.0.0"
|
||||
@ -1408,10 +1528,10 @@ eslint@8.8.0:
|
||||
debug "^4.3.2"
|
||||
doctrine "^3.0.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^7.1.0"
|
||||
eslint-scope "^7.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
eslint-visitor-keys "^3.2.0"
|
||||
espree "^9.3.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
espree "^9.3.1"
|
||||
esquery "^1.4.0"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
@ -1436,14 +1556,14 @@ eslint@8.8.0:
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
espree@^9.2.0, espree@^9.3.0:
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8"
|
||||
integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==
|
||||
espree@^9.3.1:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
|
||||
integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
|
||||
dependencies:
|
||||
acorn "^8.7.0"
|
||||
acorn-jsx "^5.3.1"
|
||||
eslint-visitor-keys "^3.1.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
esquery@^1.4.0:
|
||||
version "1.4.0"
|
||||
@ -1602,6 +1722,26 @@ flatted@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
|
||||
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
|
||||
|
||||
framer-motion@6.2.6:
|
||||
version "6.2.6"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.2.6.tgz#75277b4944a1234beaf7453da19028bbf4f75cce"
|
||||
integrity sha512-7eGav5MxEEzDHozQTDY6+psTIOw2i2kM1QVoJOC3bCp9VOKoo+mKR5n7aT5JPh7ksEKFYJYz0GJDils/9S+oLA==
|
||||
dependencies:
|
||||
framesync "6.0.1"
|
||||
hey-listen "^1.0.8"
|
||||
popmotion "11.0.3"
|
||||
style-value-types "5.0.0"
|
||||
tslib "^2.1.0"
|
||||
optionalDependencies:
|
||||
"@emotion/is-prop-valid" "^0.8.2"
|
||||
|
||||
framesync@6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20"
|
||||
integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
fs-constants@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
@ -1762,6 +1902,11 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7:
|
||||
inherits "^2.0.3"
|
||||
minimalistic-assert "^1.0.1"
|
||||
|
||||
hey-listen@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
|
||||
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
|
||||
|
||||
hmac-drbg@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||
@ -1994,6 +2139,11 @@ json5@^1.0.1:
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
jsqr-es6@^1.4.0-1:
|
||||
version "1.4.0-1"
|
||||
resolved "https://registry.yarnpkg.com/jsqr-es6/-/jsqr-es6-1.4.0-1.tgz#e72d94a0ed794c6f19d87682ac89fab2a0f8496b"
|
||||
integrity sha512-LPWZJLI+3LLOy9k3/s/MeXlkfNOs3bYBX5O+fp4N0XuxbgO8H7Uc/nYZeNwo13nSZXRW9xWFKmZdy9591+PyAg==
|
||||
|
||||
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b"
|
||||
@ -2007,7 +2157,7 @@ keyvaluestorage-interface@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff"
|
||||
integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==
|
||||
|
||||
keyvaluestorage@0.7.1, keyvaluestorage@^0.7.1:
|
||||
keyvaluestorage@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/keyvaluestorage/-/keyvaluestorage-0.7.1.tgz#be2f9f742d759d5442cdf9d49af6bdacc964c1eb"
|
||||
integrity sha512-7AHq8bZE4WRWy+BltiuPwQo5aKuj7CguhwGdW7NUUOEImY2Tq/lJaBjHdOf0MYzeu+Y4oxQWhkZEZcrDc9KnxA==
|
||||
@ -2159,6 +2309,11 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
next-themes@0.0.15:
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.15.tgz#ab0cee69cd763b77d41211f631e108beab39bf7d"
|
||||
integrity sha512-LTmtqYi03c4gMTJmWwVK9XkHL7h0/+XrtR970Ujvtu3s0kZNeJN24aJsi4rkZOI8i19+qq6f8j+8Duwy5jqcrQ==
|
||||
|
||||
next@12.0.10:
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.0.10.tgz#fcc4584177418bd777ce157f3165b7ba5e7708f7"
|
||||
@ -2380,6 +2535,16 @@ pino@^6.7.0:
|
||||
quick-format-unescaped "^4.0.3"
|
||||
sonic-boom "^1.0.2"
|
||||
|
||||
popmotion@11.0.3:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9"
|
||||
integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==
|
||||
dependencies:
|
||||
framesync "6.0.1"
|
||||
hey-listen "^1.0.8"
|
||||
style-value-types "5.0.0"
|
||||
tslib "^2.1.0"
|
||||
|
||||
postcss@8.4.5:
|
||||
version "8.4.5"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
|
||||
@ -2437,6 +2602,11 @@ prop-types@^15.7.2:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
proxy-compare@2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.0.2.tgz#343e624d0ec399dfbe575f1d365d4fa042c9fc69"
|
||||
integrity sha512-3qUXJBariEj3eO90M3Rgqq3+/P5Efl0t/dl9g/1uVzIQmO3M+ql4hvNH3mYdu8H+1zcKv07YvL55tsY74jmH1A==
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
@ -2501,6 +2671,14 @@ react-is@^16.13.1:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-qr-reader-es6@2.2.1-2:
|
||||
version "2.2.1-2"
|
||||
resolved "https://registry.yarnpkg.com/react-qr-reader-es6/-/react-qr-reader-es6-2.2.1-2.tgz#d1e23881db4775e57ea82a8a7719d5e9d34879fe"
|
||||
integrity sha512-pDNH8FoR3fOBBCgh4ImKHlX+pv/D3P8JmE+vjjcw3+YTEUgBqUAZbIkD/WUE3HzhVhN2zx7ZLBhO9vJngnjJxw==
|
||||
dependencies:
|
||||
jsqr-es6 "^1.4.0-1"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
@ -2806,6 +2984,14 @@ strip-json-comments@~2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
|
||||
style-value-types@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad"
|
||||
integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==
|
||||
dependencies:
|
||||
hey-listen "^1.0.8"
|
||||
tslib "^2.1.0"
|
||||
|
||||
styled-jsx@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77"
|
||||
@ -2878,6 +3064,11 @@ tslib@^1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.1.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||
@ -2950,6 +3141,13 @@ v8-compile-cache@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
||||
|
||||
valtio@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.3.0.tgz#b83cfcca8455940119738659946565d5c0389af8"
|
||||
integrity sha512-wsE6EDIkt+CNZPNHOxNVzoi026Fyt6ZRT750etZCAvrndcdT3N7Z+SSV4kJQdCwl5gNxsnU4BhP1wFS7cu21oA==
|
||||
dependencies:
|
||||
proxy-compare "2.0.2"
|
||||
|
||||
which-boxed-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||
|
Loading…
Reference in New Issue
Block a user