Save progress

This commit is contained in:
Ilja 2022-02-10 16:13:01 +02:00
parent f970b91d7d
commit 008fb6cbe2
7 changed files with 150 additions and 21 deletions

View File

@ -1,15 +1,16 @@
import ModalStore from '@/store/ModalStore' import ModalStore from '@/store/ModalStore'
import SessionProposalModal from '@/views/SessionProposalModal'
import { Modal as NextModal } from '@nextui-org/react' import { Modal as NextModal } from '@nextui-org/react'
import { useSnapshot } from 'valtio' import { useSnapshot } from 'valtio'
export default function Modal() { export default function Modal() {
const { open } = useSnapshot(ModalStore.state) const { open, view } = useSnapshot(ModalStore.state)
console.log(open)
return ( return (
<NextModal open={open} onClose={ModalStore.close}> <NextModal blur open={open} style={{ border: '1px solid rgba(139, 139, 139, 0.4)' }}>
<NextModal.Header></NextModal.Header> {view === 'SessionProposalModal' && <SessionProposalModal />}
<NextModal.Body></NextModal.Body>
<NextModal.Footer></NextModal.Footer>
</NextModal> </NextModal>
) )
} }

View File

@ -1,16 +1,26 @@
import ModalStore from '@/store/ModalStore'
import { client } from '@/utils/WalletConnectUtil' import { client } from '@/utils/WalletConnectUtil'
import { CLIENT_EVENTS } from '@walletconnect/client' import { CLIENT_EVENTS } from '@walletconnect/client'
import { SessionTypes } from '@walletconnect/types' import { SessionTypes } from '@walletconnect/types'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
export default function useWalletConnectEventsManager(initialized: boolean) { export default function useWalletConnectEventsManager(initialized: boolean) {
const onPairingProposal = useCallback((proposal: SessionTypes.Proposal) => { const onSessionProposal = useCallback((proposal: SessionTypes.Proposal) => {
console.log(proposal) console.log(proposal)
ModalStore.open('SessionProposalModal', { proposal })
}, [])
const onSessionCreated = useCallback((created: SessionTypes.Created) => {
// ModalStore.open('SessionCreatedModal', { created })
}, []) }, [])
useEffect(() => { useEffect(() => {
if (initialized) { if (initialized && client) {
client?.on(CLIENT_EVENTS.pairing.proposal, onPairingProposal) // 1. Open session proposal modal for confirmation / rejection
client.on(CLIENT_EVENTS.session.proposal, onSessionProposal)
// 2. Open session created modal to show success feedback
client.on(CLIENT_EVENTS.session.created, onSessionCreated)
} }
}, [initialized, onPairingProposal]) }, [initialized, onSessionProposal, onSessionCreated])
} }

View File

@ -15,6 +15,7 @@ export default function WalletConnectPage() {
} catch (err: unknown) { } catch (err: unknown) {
alert(err) alert(err)
} finally { } finally {
setUri('')
setLoading(false) setLoading(false)
} }
} }

View File

@ -1,17 +1,27 @@
import { SessionTypes } from '@walletconnect/types'
import { proxy } from 'valtio' import { proxy } from 'valtio'
/** /**
* Types * Types
*/ */
interface ModalData {
proposal?: SessionTypes.Proposal
created?: SessionTypes.Created
}
interface State { interface State {
open: boolean open: boolean
view?: 'SessionProposalModal' | 'SessionCreatedModal'
data?: ModalData
} }
/** /**
* State * State
*/ */
const state = proxy<State>({ const state = proxy<State>({
open: false view: undefined,
open: false,
data: undefined
}) })
/** /**
@ -20,7 +30,9 @@ const state = proxy<State>({
const ModalStore = { const ModalStore = {
state, state,
open() { open(view: State['view'], data: State['data']) {
state.view = view
state.data = data
state.open = true state.open = true
}, },

View File

@ -3,30 +3,31 @@
* @url https://chainlist.org * @url https://chainlist.org
*/ */
export type CHAIN = keyof typeof MAINNET_CHAINS
export const LOGO_BASE_URL = 'https://blockchain-api.xyz/logos/' export const LOGO_BASE_URL = 'https://blockchain-api.xyz/logos/'
export const MAINNET_CHAINS = { export const MAINNET_CHAINS = {
'1': { 'eip155:1': {
chainId: 1,
name: 'Ethereum', name: 'Ethereum',
logo: LOGO_BASE_URL + 'eip155:1.png', logo: LOGO_BASE_URL + 'eip155:1.png',
rgb: '99, 125, 234' rgb: '99, 125, 234'
}, },
'10': { 'eip155:10': {
chainId: 10,
name: 'Optimism', name: 'Optimism',
logo: LOGO_BASE_URL + 'eip155:10.png', logo: LOGO_BASE_URL + 'eip155:10.png',
rgb: '233, 1, 1' rgb: '233, 1, 1'
}, },
'100': { 'eip155:137': {
name: 'Gnosis', chainId: 137,
logo: LOGO_BASE_URL + 'eip155:100.png',
rgb: '73, 169, 166'
},
'137': {
name: 'Polygon', name: 'Polygon',
logo: LOGO_BASE_URL + 'eip155:137.png', logo: LOGO_BASE_URL + 'eip155:137.png',
rgb: '130, 71, 229' rgb: '130, 71, 229'
}, },
'42161': { 'eip155:42161': {
chainId: 42161,
name: 'Arbitrum', name: 'Arbitrum',
logo: LOGO_BASE_URL + 'eip155:42161.png', logo: LOGO_BASE_URL + 'eip155:42161.png',
rgb: '44, 55, 75' rgb: '44, 55, 75'

View File

@ -5,7 +5,6 @@ export let client: WalletConnectClient | undefined = undefined
export async function createClient() { export async function createClient() {
client = await WalletConnectClient.init({ client = await WalletConnectClient.init({
controller: true, controller: true,
logger: 'debug',
projectId: '8f331b9812e0e5b8f2da2c7203624869', projectId: '8f331b9812e0e5b8f2da2c7203624869',
relayUrl: 'wss://relay.walletconnect.com', relayUrl: 'wss://relay.walletconnect.com',
metadata: { metadata: {

View File

@ -0,0 +1,105 @@
import ModalStore from '@/store/ModalStore'
import WalletStore from '@/store/WalletStore'
import { CHAIN, MAINNET_CHAINS } from '@/utils/EIP155ChainsUtil'
import { client } from '@/utils/WalletConnectUtil'
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
const address = WalletStore.state.wallet?.address
// Ensure proposal and client are defined
if (!proposal || !client) {
return <Text>Missing proposal data</Text>
}
// Get data to display
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 (client && proposal && address) {
const response = {
state: {
accounts: chains.map(chain => `${chain}:${address}`)
}
}
await client.approve({ proposal, response })
}
ModalStore.close()
}
// Hanlde reject action
async function onReject() {
if (client && proposal) {
await client.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 => MAINNET_CHAINS[chain as CHAIN]?.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>
)
}