wallet-connect-web-examples/wallets/react-web3wallet/src/views/SessionProposalModal.tsx
Gancho Radkov 2810f0178f
chore: updates @walletconnect deps (#157)
* chore: updates `@walletconnect` deps

* fix: cosmos provider

* fix: updates web3wallet example

* fix: eip155 legacy session request type

---------

Co-authored-by: Gancho Radkov <ganchoradkov@gmail.com>
2023-05-09 16:51:32 +03:00

194 lines
5.7 KiB
TypeScript

import ProjectInfoCard from '@/components/ProjectInfoCard'
import ProposalSelectSection from '@/components/ProposalSelectSection'
import RequestModalContainer from '@/components/RequestModalContainer'
import SessionProposalChainCard from '@/components/SessionProposalChainCard'
import ModalStore from '@/store/ModalStore'
import { cosmosAddresses } from '@/utils/CosmosWalletUtil'
import { eip155Addresses } from '@/utils/EIP155WalletUtil'
import { polkadotAddresses } from '@/utils/PolkadotWalletUtil'
import { elrondAddresses } from '@/utils/ElrondWalletUtil'
import {
isCosmosChain,
isEIP155Chain,
isSolanaChain,
isPolkadotChain,
isNearChain,
isElrondChain
} from '@/utils/HelperUtil'
import { solanaAddresses } from '@/utils/SolanaWalletUtil'
import { web3wallet } from '@/utils/WalletConnectUtil'
import { Button, Divider, Modal, Text } from '@nextui-org/react'
import { SessionTypes } from '@walletconnect/types'
import { getSdkError } from '@walletconnect/utils'
import { Fragment, useState } from 'react'
import { nearAddresses } from '@/utils/NearWalletUtil'
export default function SessionProposalModal() {
const [selectedAccounts, setSelectedAccounts] = useState<Record<string, string[]>>({})
const hasSelected = Object.keys(selectedAccounts).length
// 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 { id, params } = proposal
const { proposer, requiredNamespaces, relays } = params
// Add / remove address from EIP155 selection
function onSelectAccount(chain: string, account: string) {
if (selectedAccounts[chain]?.includes(account)) {
const newSelectedAccounts = selectedAccounts[chain]?.filter(a => a !== account)
setSelectedAccounts(prev => ({
...prev,
[chain]: newSelectedAccounts
}))
} else {
const prevChainAddresses = selectedAccounts[chain] ?? []
setSelectedAccounts(prev => ({
...prev,
[chain]: [...prevChainAddresses, account]
}))
}
}
// Hanlde approve action, construct session namespace
async function onApprove() {
if (proposal) {
const namespaces: SessionTypes.Namespaces = {}
Object.keys(requiredNamespaces).forEach(key => {
const accounts: string[] = []
requiredNamespaces[key].chains?.map(chain => {
selectedAccounts[key].map(acc => accounts.push(`${chain}:${acc}`))
})
namespaces[key] = {
accounts,
methods: requiredNamespaces[key].methods,
events: requiredNamespaces[key].events
}
})
await web3wallet.approveSession({
id,
relayProtocol: relays[0].protocol,
namespaces
})
}
ModalStore.close()
}
// Hanlde reject action
async function onReject() {
if (proposal) {
await web3wallet.rejectSession({
id,
reason: getSdkError('USER_REJECTED_METHODS')
})
}
ModalStore.close()
}
// Render account selection checkboxes based on chain
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}
/>
)
} else if (isPolkadotChain(chain)) {
return (
<ProposalSelectSection
addresses={polkadotAddresses}
selectedAddresses={selectedAccounts[chain]}
onSelect={onSelectAccount}
chain={chain}
/>
)
} else if (isNearChain(chain)) {
return (
<ProposalSelectSection
addresses={nearAddresses}
selectedAddresses={selectedAccounts[chain]}
onSelect={onSelectAccount}
chain={chain}
/>
)
} else if (isElrondChain(chain)) {
return (
<ProposalSelectSection
addresses={elrondAddresses}
selectedAddresses={selectedAccounts[chain]}
onSelect={onSelectAccount}
chain={chain}
/>
)
}
}
return (
<Fragment>
<RequestModalContainer title="Session Proposal">
<ProjectInfoCard metadata={proposer.metadata} />
{/* TODO(ilja) Relays selection */}
<Divider y={2} />
{Object.keys(requiredNamespaces).map(chain => {
return (
<Fragment key={chain}>
<Text h4 css={{ marginBottom: '$5' }}>{`Review ${chain} permissions`}</Text>
<SessionProposalChainCard requiredNamespace={requiredNamespaces[chain]} />
{renderAccountSelection(chain)}
<Divider y={2} />
</Fragment>
)
})}
</RequestModalContainer>
<Modal.Footer>
<Button auto flat color="error" onClick={onReject}>
Reject
</Button>
<Button
auto
flat
color="success"
onClick={onApprove}
disabled={!hasSelected}
css={{ opacity: hasSelected ? 1 : 0.4 }}
>
Approve
</Button>
</Modal.Footer>
</Fragment>
)
}