feat: loading indicators (#402)

* feat: adds loading indicators on all modals

* feat: implements modal loader for session propose

* feat: implements loaders for each separate button

* feat: adds loaders on disconnect & when proposing session on known pairing topic

* refactor: restructure modal properties to avoid conditional hooks

---------

Co-authored-by: Gancho Radkov <ganchoradkov@gmail.com>
This commit is contained in:
Gancho Radkov 2024-01-11 16:03:35 +02:00 committed by GitHub
parent 426b068868
commit 7c36326bff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 492 additions and 314 deletions

View File

@ -200,17 +200,11 @@ export function ClientContextProvider({
throw new Error("Session is not connected");
}
try {
await client.disconnect({
topic: session.topic,
reason: getSdkError("USER_DISCONNECTED"),
});
} catch (error) {
toast.error((error as Error).message, {
position: "bottom-left",
});
return;
}
await client.disconnect({
topic: session.topic,
reason: getSdkError("USER_DISCONNECTED"),
});
// Reset app state after disconnect.
reset();
}, [client, session]);

View File

@ -0,0 +1,29 @@
import * as React from "react";
import Loader from "../components/Loader";
import { SContainer } from "../components/shared";
import { SModalContainer, SModalParagraph, SModalTitle } from "./shared";
interface LoaderModal {
title: string;
text?: string;
}
const LoaderModal = (props: LoaderModal) => {
const { title, text } = props;
return (
<>
<SModalContainer>
<SModalTitle>{title}</SModalTitle>
<SContainer>
<Loader />
<br />
<SModalParagraph>{text}</SModalParagraph>
</SContainer>
</SModalContainer>
</>
);
};
export default LoaderModal;

View File

@ -7,6 +7,8 @@ import Pairing from "../components/Pairing";
import { STable } from "../components/shared";
import { SModalContainer, SModalTitle } from "./shared";
import LoaderModal from "./LoaderModal";
import toast from "react-hot-toast";
interface PairingModalProps {
pairings: PairingTypes.Struct[];
@ -15,7 +17,28 @@ interface PairingModalProps {
const PairingModal = (props: PairingModalProps) => {
const { pairings, connect } = props;
return (
const [pairing, setPairing] = React.useState<PairingTypes.Struct>();
const onConnect = React.useCallback(
async (pairing: PairingTypes.Struct) => {
try {
setPairing(pairing);
await connect({ topic: pairing.topic });
} catch (error) {
toast.error((error as Error).message, {
position: "bottom-left",
});
setPairing(undefined);
}
},
[connect]
);
return pairing ? (
<LoaderModal
title={`Connecting to ${pairing?.peerMetadata?.name}`}
text="Open your wallet to approve the connection request"
/>
) : (
<SModalContainer>
<SModalTitle>{"Select available pairing or create new one"}</SModalTitle>
<STable>
@ -23,7 +46,7 @@ const PairingModal = (props: PairingModalProps) => {
<Pairing
key={pairing.topic}
pairing={pairing}
onClick={() => connect({ topic: pairing.topic })}
onClick={() => onConnect(pairing)}
/>
))}
</STable>

View File

@ -1,5 +1,6 @@
import type { NextPage } from "next";
import React, { useEffect, useRef, useState } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import Banner from "../components/Banner";
import Blockchain from "../components/Blockchain";
@ -42,6 +43,7 @@ import { useJsonRpc } from "../contexts/JsonRpcContext";
import { useChainData } from "../contexts/ChainDataContext";
import Icon from "../components/Icon";
import OriginSimulationDropdown from "../components/OriginSimulationDropdown";
import LoaderModal from "../modals/LoaderModal";
// Normal import does not work here
const { version } = require("@walletconnect/sign-client/package.json");
@ -53,6 +55,7 @@ const Home: NextPage = () => {
const openPairingModal = () => setModal("pairing");
const openPingModal = () => setModal("ping");
const openRequestModal = () => setModal("request");
const openDisconnectModal = () => setModal("disconnect");
// Initialize the WalletConnect client.
const {
@ -117,6 +120,18 @@ const Home: NextPage = () => {
await ping();
};
const onDisconnect = useCallback(async () => {
openDisconnectModal();
try {
await disconnect();
} catch (error) {
toast.error((error as Error).message, {
position: "bottom-left",
});
}
closeModal();
}, [disconnect]);
async function emit() {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
@ -443,6 +458,8 @@ const Home: NextPage = () => {
);
case "ping":
return <PingModal pending={isRpcRequestPending} result={rpcResult} />;
case "disconnect":
return <LoaderModal title={"Disconnecting..."} />;
default:
return null;
}
@ -522,7 +539,7 @@ const Home: NextPage = () => {
<Column maxWidth={1000} spanHeight>
<Header
ping={onPing}
disconnect={disconnect}
disconnect={onDisconnect}
session={session}
emit={emit}
/>

View File

@ -14,7 +14,7 @@ import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
import SessionUnsuportedMethodModal from '@/views/SessionUnsuportedMethodModal'
import { Modal as NextModal } from '@nextui-org/react'
import { useSnapshot } from 'valtio'
import { useCallback } from 'react'
import { useCallback, useMemo } from 'react'
import AuthRequestModal from '@/views/AuthRequestModal'
export default function Modal() {
@ -26,6 +26,41 @@ export default function Modal() {
}
}, [open])
const componentView = useMemo(() => {
switch (view) {
case 'SessionProposalModal':
return <SessionProposalModal />
case 'SessionSignModal':
return <SessionRequestModal />
case 'SessionSignTypedDataModal':
return <SessionSignTypedDataModal />
case 'SessionSendTransactionModal':
return <SessionSendTransactionModal />
case 'SessionUnsuportedMethodModal':
return <SessionUnsuportedMethodModal />
case 'SessionSignCosmosModal':
return <SessionSignCosmosModal />
case 'SessionSignSolanaModal':
return <SessionSignSolanaModal />
case 'SessionSignPolkadotModal':
return <SessionSignPolkadotModal />
case 'SessionSignNearModal':
return <SessionSignNearModal />
case 'SessionSignMultiversxModal':
return <SessionSignMultiversxModal />
case 'SessionSignTronModal':
return <SessionSignTronModal />
case 'SessionSignTezosModal':
return <SessionSignTezosModal />
case 'SessionSignKadenaModal':
return <SessionSignKadenaModal />
case 'AuthRequestModal':
return <AuthRequestModal />
default:
return null
}
}, [view])
return (
<NextModal
blur
@ -33,20 +68,7 @@ export default function Modal() {
open={open}
style={{ border: '1px solid rgba(139, 139, 139, 0.4)' }}
>
{view === 'SessionProposalModal' && <SessionProposalModal />}
{view === 'SessionSignModal' && <SessionRequestModal />}
{view === 'SessionSignTypedDataModal' && <SessionSignTypedDataModal />}
{view === 'SessionSendTransactionModal' && <SessionSendTransactionModal />}
{view === 'SessionUnsuportedMethodModal' && <SessionUnsuportedMethodModal />}
{view === 'SessionSignCosmosModal' && <SessionSignCosmosModal />}
{view === 'SessionSignSolanaModal' && <SessionSignSolanaModal />}
{view === 'SessionSignPolkadotModal' && <SessionSignPolkadotModal />}
{view === 'SessionSignNearModal' && <SessionSignNearModal />}
{view === 'SessionSignMultiversxModal' && <SessionSignMultiversxModal />}
{view === 'SessionSignTronModal' && <SessionSignTronModal />}
{view === 'SessionSignTezosModal' && <SessionSignTezosModal />}
{view === 'SessionSignKadenaModal' && <SessionSignKadenaModal />}
{view === 'AuthRequestModal' && <AuthRequestModal />}
{componentView}
</NextModal>
)
}

View File

@ -1,19 +1,26 @@
import SettingsStore from '@/store/SettingsStore'
import { Button, Modal, Row } from '@nextui-org/react'
import { Button, Modal, Row, Loading } from '@nextui-org/react'
import { useMemo } from 'react'
import { useSnapshot } from 'valtio'
export interface LoaderProps {
color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'white'
active?: boolean
}
interface Props {
onApprove: () => void
onReject: () => void
infoBoxCondition?: boolean
infoBoxText?: string
disabledApprove?: boolean
approveLoader?: LoaderProps
rejectLoader?: LoaderProps
}
export default function ModalFooter({
onApprove,
approveLoader,
onReject,
rejectLoader,
infoBoxCondition,
infoBoxText,
disabledApprove
@ -47,7 +54,11 @@ export default function ModalFooter({
onPress={onReject}
data-testid="session-reject-button"
>
Reject
{rejectLoader && rejectLoader.active ? (
<Loading size="md" type="points" color={rejectLoader.color || 'white'} />
) : (
'Reject'
)}
</Button>
<Button
auto
@ -57,7 +68,11 @@ export default function ModalFooter({
onPress={onApprove}
data-testid="session-approve-button"
>
Approve
{approveLoader && approveLoader.active ? (
<Loading size="md" type="points" color={approveLoader.color || approveButtonColor} />
) : (
'Approve'
)}
</Button>
</Row>
</Modal.Footer>

View File

@ -44,7 +44,9 @@ export default function SessionChainCard({ namespace }: IProps) {
namespace.accounts.forEach(account => {
const [type, chain] = account.split(':')
const chainId = `${type}:${chain}`
chains.push(chainId)
if (!chains.includes(chainId)) {
chains.push(chainId)
}
})
return (

View File

@ -1,13 +1,13 @@
/* eslint-disable react-hooks/rules-of-hooks */
import PageHeader from '@/components/PageHeader'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import SessionChainCard from '@/components/SessionChainCard'
import SettingsStore from '@/store/SettingsStore'
import { styledToast } from '@/utils/HelperUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import { Button, Divider, Loading, Row, Text } from '@nextui-org/react'
import { getSdkError } from '@walletconnect/utils'
import { useRouter } from 'next/router'
import { Fragment, useEffect, useState } from 'react'
import { useSnapshot } from 'valtio'
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'
/**
* Component
@ -16,9 +16,10 @@ export default function SessionPage() {
const [topic, setTopic] = useState('')
const [updated, setUpdated] = useState(new Date())
const { query, replace } = useRouter()
const [loading, setLoading] = useState(false)
const { activeChainId } = useSnapshot(SettingsStore.state)
const [updateLoading, setUpdateLoading] = useState(false)
const [pingLoading, setPingLoading] = useState(false)
const [emitLoading, setEmitLoading] = useState(false)
const [deleteLoading, setDeleteLoading] = useState(false)
useEffect(() => {
if (query?.topic) {
@ -26,96 +27,81 @@ export default function SessionPage() {
}
}, [query])
const session = web3wallet.engine.signClient.session.values.find(s => s.topic === topic)
if (!session) {
return null
}
const session = useMemo(
() => web3wallet.engine.signClient.session.values.find(s => s.topic === topic),
[topic]
)
const namespaces = useMemo(() => session?.namespaces, [session])
// Get necessary data from session
const expiryDate = new Date(session.expiry * 1000)
const { namespaces } = session
const expiryDate = useMemo(() => new Date(session?.expiry! * 1000), [session])
// Handle deletion of a session
async function onDeleteSession() {
setLoading(true)
await web3wallet.disconnectSession({ topic, reason: getSdkError('USER_DISCONNECTED') })
replace('/sessions')
setLoading(false)
}
const onDeleteSession = useCallback(async () => {
setDeleteLoading(true)
try {
await web3wallet.disconnectSession({ topic, reason: getSdkError('USER_DISCONNECTED') })
replace('/sessions')
} catch (e) {
styledToast((e as Error).message, 'error')
}
setDeleteLoading(false)
}, [topic, replace])
async function onSessionPing() {
setLoading(true)
const onSessionPing = useCallback(async () => {
setPingLoading(true)
await web3wallet.engine.signClient.ping({ topic })
setLoading(false)
}
setPingLoading(false)
}, [topic])
async function onSessionEmit() {
setLoading(true)
await web3wallet.emitSessionEvent({
topic,
event: { name: 'chainChanged', data: 'Hello World' },
chainId: activeChainId.toString() // chainId: 'eip155:1'
})
setLoading(false)
}
const onSessionEmit = useCallback(async () => {
setEmitLoading(true)
try {
const namespace = Object.keys(session?.namespaces!)[0]
const chainId = session?.namespaces[namespace].chains?.[0]
await web3wallet.emitSessionEvent({
topic,
event: { name: 'chainChanged', data: 'Hello World' },
chainId: chainId! // chainId: 'eip155:1'
})
} catch (e) {
styledToast((e as Error).message, 'error')
}
setEmitLoading(false)
}, [session?.namespaces, topic])
async function onSessionUpdate() {
setLoading(true)
const session = web3wallet.engine.signClient.session.get(topic)
const baseAddress = '0x70012948c348CBF00806A3C79E3c5DAdFaAa347'
const namespaceKeyToUpdate = Object.keys(session?.namespaces)[0]
const namespaceToUpdate = session?.namespaces[namespaceKeyToUpdate]
await web3wallet.updateSession({
topic,
namespaces: {
...session?.namespaces,
[namespaceKeyToUpdate]: {
...session?.namespaces[namespaceKeyToUpdate],
accounts: namespaceToUpdate.accounts.concat(
`${namespaceToUpdate.chains?.[0]}:${baseAddress}${Math.floor(
Math.random() * (9 - 1 + 1) + 0
)}`
) // generates random number between 0 and 9
const onSessionUpdate = useCallback(async () => {
setUpdateLoading(true)
try {
const session = web3wallet.engine.signClient.session.get(topic)
const baseAddress = '0x70012948c348CBF00806A3C79E3c5DAdFaAa347'
const namespaceKeyToUpdate = Object.keys(session?.namespaces)[0]
const namespaceToUpdate = session?.namespaces[namespaceKeyToUpdate]
await web3wallet.updateSession({
topic,
namespaces: {
...session?.namespaces,
[namespaceKeyToUpdate]: {
...session?.namespaces[namespaceKeyToUpdate],
accounts: namespaceToUpdate.accounts.concat(
`${namespaceToUpdate.chains?.[0]}:${baseAddress}${Math.floor(
Math.random() * (9 - 1 + 1) + 0
)}`
) // generates random number between 0 and 9
}
}
}
})
setUpdated(new Date())
setLoading(false)
}
})
setUpdated(new Date())
} catch (e) {
styledToast((e as Error).message, 'error')
}
setUpdateLoading(false)
}, [topic])
// function renderAccountSelection(chain: string) {
// if (isEIP155Chain(chain)) {
// return (
// <ProposalSelectSection
// addresses={eip155Addresses}
// selectedAddresses={selectedAccounts[chain]}
// onSelect={onSelectAccount}
// chain={chain}
// />
// )
// } else if (isCosmosChain(chain)) {
// return (
// <ProposalSelectSection
// addresses={cosmosAddresses}
// selectedAddresses={selectedAccounts[chain]}
// onSelect={onSelectAccount}
// chain={chain}
// />
// )
// } else if (isSolanaChain(chain)) {
// return (
// <ProposalSelectSection
// addresses={solanaAddresses}
// selectedAddresses={selectedAccounts[chain]}
// onSelect={onSelectAccount}
// chain={chain}
// />
// )
// }
// }
return (
console.log('session', session)
return !session ? (
<></>
) : (
<Fragment>
<PageHeader title="Session Details" />
@ -123,18 +109,19 @@ export default function SessionPage() {
<Divider y={2} />
{Object.keys(namespaces).map(chain => {
return (
<Fragment key={chain}>
<Text h4 css={{ marginBottom: '$5' }}>{`Review ${chain} permissions`}</Text>
<SessionChainCard
namespace={namespaces[chain]}
data-testid={'session-card' + namespaces[chain]}
/>
<Divider y={2} />
</Fragment>
)
})}
{namespaces &&
Object.keys(namespaces).map(chain => {
return (
<Fragment key={chain}>
<Text h4 css={{ marginBottom: '$5' }}>{`Review ${chain} permissions`}</Text>
<SessionChainCard
namespace={namespaces[chain]}
data-testid={'session-card' + namespaces[chain]}
/>
<Divider y={2} />
</Fragment>
)
})}
<Row justify="space-between">
<Text h5>Expiry</Text>
@ -158,7 +145,7 @@ export default function SessionPage() {
onClick={onDeleteSession}
data-testid="session-delete-button"
>
{loading ? <Loading size="sm" color="error" /> : 'Delete'}
{deleteLoading ? <Loading size="sm" color="error" type="points" /> : 'Delete'}
</Button>
</Row>
@ -170,7 +157,7 @@ export default function SessionPage() {
onClick={onSessionPing}
data-testid="session-ping-button"
>
{loading ? <Loading size="sm" color="primary" /> : 'Ping'}
{pingLoading ? <Loading size="sm" color="primary" type="points" /> : 'Ping'}
</Button>
</Row>
@ -182,7 +169,7 @@ export default function SessionPage() {
onClick={onSessionEmit}
data-testid="session-emit-button"
>
{loading ? <Loading size="sm" color="secondary" /> : 'Emit'}
{emitLoading ? <Loading size="sm" color="secondary" type="points" /> : 'Emit'}
</Button>
</Row>
@ -194,7 +181,7 @@ export default function SessionPage() {
onClick={onSessionUpdate}
data-testid="session-update-button"
>
{loading ? <Loading size="sm" color="warning" /> : 'Update'}
{updateLoading ? <Loading size="sm" color="warning" type="points" /> : 'Update'}
</Button>
</Row>
</Fragment>

View File

@ -5,20 +5,36 @@ import { web3wallet } from '@/utils/WalletConnectUtil'
import { Button, Input, Loading, Text } from '@nextui-org/react'
import { Fragment, useState } from 'react'
import { styledToast } from '@/utils/HelperUtil'
import ModalStore from '@/store/ModalStore'
export default function WalletConnectPage() {
const [uri, setUri] = useState('')
const [loading, setLoading] = useState(false)
async function onConnect(uri: string) {
const { topic: pairingTopic } = parseUri(uri)
// if for some reason, the proposal is not received, we need to close the modal when the pairing expires (5mins)
const pairingExpiredListener = ({ topic }: { topic: string }) => {
if (pairingTopic === topic) {
styledToast('Pairing expired. Please try again with new Connection URI', 'error')
ModalStore.close()
web3wallet.core.pairing.events.removeListener('pairing_expire', pairingExpiredListener)
}
}
web3wallet.once('session_proposal', () => {
web3wallet.core.pairing.events.removeListener('pairing_expire', pairingExpiredListener)
})
try {
setLoading(true)
ModalStore.open('SessionProposalModal', {})
web3wallet.core.pairing.events.on('pairing_expire', pairingExpiredListener)
await web3wallet.pair({ uri })
} catch (error) {
styledToast((error as Error).message, 'error')
ModalStore.close()
} finally {
setUri('')
setLoading(false)
setUri('')
}
}
@ -49,7 +65,7 @@ export default function WalletConnectPage() {
color="gradient"
data-testid="uri-connect-button"
>
{loading ? <Loading size="sm" /> : 'Connect'}
{loading ? <Loading size="md" type="points" color={'white'} /> : 'Connect'}
</Button>
}
/>

View File

@ -1,12 +1,9 @@
import { Fragment } from 'react'
/* eslint-disable react-hooks/rules-of-hooks */
import { useCallback, useState } from 'react'
import { useSnapshot } from 'valtio'
import { Col, Divider, Row, Text, Code } from '@nextui-org/react'
import { Col, Row, Text, Code } from '@nextui-org/react'
import { getSdkError } from '@walletconnect/utils'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import SettingsStore from '@/store/SettingsStore'
import { eip155Addresses, eip155Wallets } from '@/utils/EIP155WalletUtil'
@ -15,6 +12,8 @@ import RequestModal from './RequestModal'
export default function AuthRequestModal() {
const { account } = useSnapshot(SettingsStore.state)
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
console.log('modal data', ModalStore.state.data, account)
// Get request and wallet data from store
const request = ModalStore.state.data?.request
@ -32,8 +31,9 @@ export default function AuthRequestModal() {
const message = web3wallet.formatMessage(params.cacaoPayload, iss)
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (request) {
setIsLoadingApprove(true)
const signature = await eip155Wallets[address].signMessage(message)
await web3wallet.respondAuthRequest(
{
@ -45,13 +45,15 @@ export default function AuthRequestModal() {
},
iss
)
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [request, address, message, iss])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (request) {
setIsLoadingReject(true)
await web3wallet.respondAuthRequest(
{
id: request.id,
@ -59,15 +61,19 @@ export default function AuthRequestModal() {
},
iss
)
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [request, iss])
return (
<RequestModal
intention="request a signature"
metadata={request.params.requester.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<Row>
<Col>

View File

@ -1,8 +1,8 @@
import { Fragment, ReactNode, useMemo, useState } from 'react'
import { Divider, Text } from '@nextui-org/react'
import { Divider } from '@nextui-org/react'
import { CoreTypes } from '@walletconnect/types'
import ModalFooter from '@/components/ModalFooter'
import ModalFooter, { LoaderProps } from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
@ -19,12 +19,16 @@ interface IProps {
infoBoxCondition?: boolean
infoBoxText?: string
disabledApprove?: boolean
approveLoader?: LoaderProps
rejectLoader?: LoaderProps
}
export default function RequestModal({
children,
metadata,
onApprove,
onReject,
approveLoader,
rejectLoader,
intention,
infoBoxCondition,
infoBoxText,
@ -57,6 +61,8 @@ export default function RequestModal({
<ModalFooter
onApprove={onApprove}
onReject={onReject}
approveLoader={approveLoader}
rejectLoader={rejectLoader}
infoBoxCondition={infoBoxCondition}
infoBoxText={infoBoxText}
disabledApprove={disabledApprove}
@ -64,6 +70,7 @@ export default function RequestModal({
</>
)
}, [
approveLoader,
children,
disabledApprove,
infoBoxCondition,
@ -71,7 +78,8 @@ export default function RequestModal({
intention,
metadata,
onApprove,
onReject
onReject,
rejectLoader
])
return <Fragment>{isScam && !threatAcknowledged ? threatPromptContent : modalContent}</Fragment>
}

View File

@ -1,12 +1,12 @@
import { Col, Divider, Grid, Row, Text, styled } from '@nextui-org/react'
import { Fragment, useCallback, useMemo } from 'react'
/* eslint-disable react-hooks/rules-of-hooks */
import { Col, Grid, Loading, Row, Text, styled } from '@nextui-org/react'
import { useCallback, useMemo, useState } from 'react'
import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils'
import { SignClientTypes } from '@walletconnect/types'
import DoneIcon from '@mui/icons-material/Done'
import CloseIcon from '@mui/icons-material/Close'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import ModalStore from '@/store/ModalStore'
import { cosmosAddresses } from '@/utils/CosmosWalletUtil'
import { eip155Addresses } from '@/utils/EIP155WalletUtil'
@ -31,9 +31,8 @@ import { TRON_CHAINS, TRON_SIGNING_METHODS } from '@/data/TronData'
import ChainDataMini from '@/components/ChainDataMini'
import ChainAddressMini from '@/components/ChainAddressMini'
import { getChainData } from '@/data/chainsUtil'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalFooter from '@/components/ModalFooter'
import RequestModal from './RequestModal'
import { useSnapshot } from 'valtio'
const StyledText = styled(Text, {
fontWeight: 400
@ -45,8 +44,12 @@ const StyledSpan = styled('span', {
export default function SessionProposalModal() {
// Get proposal data and wallet address from store
const proposal = ModalStore.state.data?.proposal
console.log('proposal', proposal)
const data = useSnapshot(ModalStore.state)
const proposal = data?.data?.proposal as SignClientTypes.EventArguments['session_proposal']
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
console.log('proposal', data.data?.proposal)
const supportedNamespaces = useMemo(() => {
// eip155
const eip155Chains = Object.keys(EIP155_CHAINS)
@ -213,30 +216,10 @@ export default function SessionProposalModal() {
}
}, [])
const approveButtonColor: any = useMemo(() => {
switch (proposal?.verifyContext.verified.validation) {
case 'INVALID':
return 'error'
case 'UNKNOWN':
return 'warning'
default:
return 'success'
}
}, [proposal])
// Ensure proposal is defined
if (!proposal) {
return <Text>Missing proposal data</Text>
}
// Get required proposal data
const { id, params } = proposal
const { proposer, relays } = params
// Hanlde approve action, construct session namespace
async function onApprove() {
const onApprove = useCallback(async () => {
if (proposal) {
setIsLoadingApprove(true)
const namespaces = buildApprovedNamespaces({
proposal: proposal.params,
supportedNamespaces
@ -246,39 +229,54 @@ export default function SessionProposalModal() {
try {
await web3wallet.approveSession({
id,
relayProtocol: relays[0].protocol,
id: proposal.id,
namespaces
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
}
setIsLoadingApprove(false)
ModalStore.close()
}
}, [proposal, supportedNamespaces])
// Hanlde reject action
async function onReject() {
// eslint-disable-next-line react-hooks/rules-of-hooks
const onReject = useCallback(async () => {
if (proposal) {
try {
setIsLoadingReject(true)
await new Promise(resolve => setTimeout(resolve, 1000))
await web3wallet.rejectSession({
id,
id: proposal.id,
reason: getSdkError('USER_REJECTED_METHODS')
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
}
setIsLoadingReject(false)
ModalStore.close()
}
}, [proposal])
return (
return !proposal ? (
<>
<br />
<Loading size="lg" color="primary" type="default" />
<Text>Attempting to pair...</Text>
<br />
</>
) : (
<RequestModal
metadata={proposal.params.proposer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
infoBoxCondition={notSupportedChains.length > 0}
infoBoxText={`The following required chains are not supported by your wallet - ${notSupportedChains.toString()}`}
disabledApprove={notSupportedChains.length > 0}

View File

@ -1,13 +1,9 @@
import { Fragment, useState } from 'react'
import { Divider, Modal, Text } from '@nextui-org/react'
import { useCallback, useState } from 'react'
import { Divider, Text } from '@nextui-org/react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { approveEIP155Request, rejectEIP155Request } from '@/utils/EIP155RequestHandlerUtil'
import { styledToast } from '@/utils/HelperUtil'
@ -15,27 +11,23 @@ import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
export default function SessionSendTransactionModal() {
const [loading, setLoading] = useState(false)
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// 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 proposal data
const { topic, params } = requestEvent
const { request, chainId } = params
const transaction = request.params[0]
const topic = requestEvent?.topic
const params = requestEvent?.params
const chainId = params?.chainId
const request = params?.request
const transaction = request?.params[0]
// Handle approve action
async function onApprove() {
if (requestEvent) {
setLoading(true)
const onApprove = useCallback(async () => {
if (requestEvent && topic) {
setIsLoadingApprove(true)
try {
const response = await approveEIP155Request(requestEvent)
await web3wallet.respondSessionRequest({
@ -43,16 +35,19 @@ export default function SessionSendTransactionModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
if (requestEvent) {
const onReject = useCallback(async () => {
if (requestEvent && topic) {
setIsLoadingReject(true)
const response = rejectEIP155Request(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -60,25 +55,31 @@ export default function SessionSendTransactionModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
return request && requestSession ? (
<RequestModal
intention="sign a transaction"
metadata={requestSession.peer.metadata}
metadata={requestSession?.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequestDataCard data={transaction} />
<Divider y={1} />
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession?.relay.protocol} />
<Divider y={1} />
<RequestMethodCard methods={[request.method]} />
</RequestModal>
) : (
<Text>Request not found</Text>
)
}

View File

@ -1,13 +1,10 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useCallback, useState } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { approveCosmosRequest, rejectCosmosRequest } from '@/utils/CosmosRequestHandler'
import { styledToast } from '@/utils/HelperUtil'
@ -18,6 +15,8 @@ export default function SessionSignCosmosModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -29,8 +28,9 @@ export default function SessionSignCosmosModal() {
const { chainId, request } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveCosmosRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -38,16 +38,19 @@ export default function SessionSignCosmosModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectCosmosRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -55,12 +58,14 @@ export default function SessionSignCosmosModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -68,6 +73,8 @@ export default function SessionSignCosmosModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,21 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Col, Divider, Row, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequestDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { convertHexToUtf8, styledToast } from '@/utils/HelperUtil'
import { approveKadenaRequest, rejectKadenaRequest } from '@/utils/KadenaRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignKadenaModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -32,8 +30,9 @@ export default function SessionSignKadenaModal() {
const message = convertHexToUtf8(request.params.message)
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveKadenaRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -41,16 +40,19 @@ export default function SessionSignKadenaModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectKadenaRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -58,12 +60,14 @@ export default function SessionSignKadenaModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -71,6 +75,8 @@ export default function SessionSignKadenaModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequestDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,12 +1,8 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Col, Divider, Row, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useCallback, useState } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { approveEIP155Request, rejectEIP155Request } from '@/utils/EIP155RequestHandlerUtil'
import { getSignParamsMessage, styledToast } from '@/utils/HelperUtil'
@ -16,6 +12,8 @@ export default function SessionSignModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -30,8 +28,9 @@ export default function SessionSignModal() {
const message = getSignParamsMessage(request.params)
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveEIP155Request(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -39,16 +38,19 @@ export default function SessionSignModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectEIP155Request(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -56,12 +58,14 @@ export default function SessionSignModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -69,6 +73,8 @@ export default function SessionSignModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,13 +1,10 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useCallback, useState } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { styledToast } from '@/utils/HelperUtil'
import {
@ -21,6 +18,8 @@ export default function SessionSignMultiversxModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -32,8 +31,9 @@ export default function SessionSignMultiversxModal() {
const { request, chainId } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveMultiversxRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -41,16 +41,19 @@ export default function SessionSignMultiversxModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectMultiversxRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -58,12 +61,14 @@ export default function SessionSignMultiversxModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -71,6 +76,8 @@ export default function SessionSignMultiversxModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,25 +1,24 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { transactions } from 'near-api-js'
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequestDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import ModalStore from '@/store/ModalStore'
import { approveNearRequest, rejectNearRequest } from '@/utils/NearRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import { NEAR_SIGNING_METHODS } from '@/data/NEARData'
import { styledToast } from '@/utils/HelperUtil'
import ModalFooter from '@/components/ModalFooter'
import VerifyInfobox from '@/components/VerifyInfobox'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignNearModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -142,8 +141,9 @@ export default function SessionSignNearModal() {
}
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveNearRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -151,16 +151,19 @@ export default function SessionSignNearModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectNearRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -168,12 +171,14 @@ export default function SessionSignNearModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -181,6 +186,8 @@ export default function SessionSignNearModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequestDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,22 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { styledToast } from '@/utils/HelperUtil'
import { approvePolkadotRequest, rejectPolkadotRequest } from '@/utils/PolkadotRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignPolkadotModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -29,8 +28,9 @@ export default function SessionSignPolkadotModal() {
const { request, chainId } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approvePolkadotRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -38,16 +38,19 @@ export default function SessionSignPolkadotModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectPolkadotRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -55,12 +58,14 @@ export default function SessionSignPolkadotModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -68,6 +73,8 @@ export default function SessionSignPolkadotModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,22 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { styledToast } from '@/utils/HelperUtil'
import { approveSolanaRequest, rejectSolanaRequest } from '@/utils/SolanaRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignSolanaModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -29,8 +28,9 @@ export default function SessionSignSolanaModal() {
const { request, chainId } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveSolanaRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -38,16 +38,19 @@ export default function SessionSignSolanaModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectSolanaRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -55,12 +58,14 @@ export default function SessionSignSolanaModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -68,6 +73,8 @@ export default function SessionSignSolanaModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,22 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { styledToast } from '@/utils/HelperUtil'
import { approveTezosRequest, rejectTezosRequest } from '@/utils/TezosRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignTezosModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -29,8 +28,9 @@ export default function SessionSignTezosModal() {
const { request, chainId } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveTezosRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -38,16 +38,19 @@ export default function SessionSignTezosModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectTezosRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -55,12 +58,14 @@ export default function SessionSignTezosModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -68,6 +73,8 @@ export default function SessionSignTezosModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,22 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { styledToast } from '@/utils/HelperUtil'
import { approveTronRequest, rejectTronRequest } from '@/utils/TronRequestHandlerUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignTronModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -29,8 +28,9 @@ export default function SessionSignTronModal() {
const { request, chainId } = params
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveTronRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -38,16 +38,19 @@ export default function SessionSignTronModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectTronRequest(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -55,12 +58,14 @@ export default function SessionSignTronModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
@ -68,6 +73,8 @@ export default function SessionSignTronModal() {
metadata={requestSession.peer.metadata}
onApprove={onApprove}
onReject={onReject}
approveLoader={{ active: isLoadingApprove }}
rejectLoader={{ active: isLoadingReject }}
>
<RequesDetailsCard chains={[chainId ?? '']} protocol={requestSession.relay.protocol} />
<Divider y={1} />

View File

@ -1,23 +1,22 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Divider, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestDataCard from '@/components/RequestDataCard'
import RequesDetailsCard from '@/components/RequestDetalilsCard'
import RequestMethodCard from '@/components/RequestMethodCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import ModalStore from '@/store/ModalStore'
import { approveEIP155Request, rejectEIP155Request } from '@/utils/EIP155RequestHandlerUtil'
import { getSignTypedDataParamsData, styledToast } from '@/utils/HelperUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import RequestModal from './RequestModal'
import { useCallback, useState } from 'react'
export default function SessionSignTypedDataModal() {
// Get request and wallet data from store
const requestEvent = ModalStore.state.data?.requestEvent
const requestSession = ModalStore.state.data?.requestSession
const [isLoadingApprove, setIsLoadingApprove] = useState(false)
const [isLoadingReject, setIsLoadingReject] = useState(false)
// Ensure request and wallet are defined
if (!requestEvent || !requestSession) {
@ -32,8 +31,9 @@ export default function SessionSignTypedDataModal() {
const data = getSignTypedDataParamsData(request.params)
// Handle approve action (logic varies based on request method)
async function onApprove() {
const onApprove = useCallback(async () => {
if (requestEvent) {
setIsLoadingApprove(true)
const response = await approveEIP155Request(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -41,16 +41,19 @@ export default function SessionSignTypedDataModal() {
response
})
} catch (e) {
setIsLoadingApprove(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingApprove(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
// Handle reject action
async function onReject() {
const onReject = useCallback(async () => {
if (requestEvent) {
setIsLoadingReject(true)
const response = rejectEIP155Request(requestEvent)
try {
await web3wallet.respondSessionRequest({
@ -58,12 +61,14 @@ export default function SessionSignTypedDataModal() {
response
})
} catch (e) {
setIsLoadingReject(false)
styledToast((e as Error).message, 'error')
return
}
setIsLoadingReject(false)
ModalStore.close()
}
}
}, [requestEvent, topic])
return (
<RequestModal
intention="sign a message"

View File

@ -1,14 +1,8 @@
import { Fragment, ReactNode, useMemo } from 'react'
import { Col, Divider, Link, Row, Text, styled } from '@nextui-org/react'
import { CoreTypes } from '@walletconnect/types'
import NewReleasesIcon from '@mui/icons-material/NewReleases'
import ModalFooter from '@/components/ModalFooter'
import ProjectInfoCard from '@/components/ProjectInfoCard'
import RequestModalContainer from '@/components/RequestModalContainer'
import VerifyInfobox from '@/components/VerifyInfobox'
import { useSnapshot } from 'valtio'
import SettingsStore from '@/store/SettingsStore'
interface IProps {
metadata: CoreTypes.Metadata