Skip to content

Commit

Permalink
Merge pull request #82 from TalismanSociety/refactor/useKownAddresses
Browse files Browse the repository at this point in the history
Refactor: useKownAddresses
  • Loading branch information
UrbanWill authored Oct 15, 2024
2 parents 5a72f52 + a193a74 commit 85324e2
Show file tree
Hide file tree
Showing 20 changed files with 216 additions and 45 deletions.
3 changes: 3 additions & 0 deletions apps/multisig/src/components/AddressInput/AccountDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type Props = {
hideAddress?: boolean
identiconSize?: number
breakLine?: boolean
isNameLoading?: boolean
}

export const AccountDetails: React.FC<Props> = ({
Expand All @@ -33,6 +34,7 @@ export const AccountDetails: React.FC<Props> = ({
breakLine,
hideIdenticon = false,
hideAddress = false,
isNameLoading = false,
}) => {
const { copy, copied } = useCopied()

Expand All @@ -54,6 +56,7 @@ export const AccountDetails: React.FC<Props> = ({
nameOrAddressOnly={nameOrAddressOnly}
breakLine={breakLine}
hideAddress={hideAddress}
isNameLoading={isNameLoading}
/>
{!disableCopy && (
<div
Expand Down
26 changes: 21 additions & 5 deletions apps/multisig/src/components/AddressInput/NameAndAddress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useOnchainIdentity } from '@domains/identity/useOnchainIdentity'
import { Address } from '@util/addresses'
import { Check } from 'lucide-react'
import { useEffect, useMemo, useState } from 'react'
import { CircularProgressIndicator } from '@talismn/ui'

export const NameAndAddress: React.FC<{
address: Address
Expand All @@ -12,7 +13,8 @@ export const NameAndAddress: React.FC<{
nameOrAddressOnly?: boolean
breakLine?: boolean
hideAddress?: boolean
}> = ({ address, name, chain, nameOrAddressOnly, breakLine, hideAddress }) => {
isNameLoading?: boolean
}> = ({ address, name, chain, nameOrAddressOnly, breakLine, hideAddress, isNameLoading = false }) => {
const { resolve } = useAzeroID()
const [azeroId, setAzeroId] = useState<string | undefined>()
const onchainIdentity = useOnchainIdentity(address, chain)
Expand Down Expand Up @@ -55,12 +57,26 @@ export const NameAndAddress: React.FC<{
return null
}, [address, azeroId, chain, name, nameOrAddressOnly, onchainIdentityUi])

if (!secondaryText)
if (!secondaryText) {
return (
<p className="text-offWhite overflow-hidden text-ellipsis mt-[3px] w-full max-w-max whitespace-nowrap">
{primaryText}
</p>
<div className="flex flex-col gap-1">
{isNameLoading && !name ? (
<>
<CircularProgressIndicator size={16} />
{!nameOrAddressOnly && (
<p className="text-gray-200 text-[12px] leading-[1] whitespace-nowrap overflow-hidden text-ellipsis max-w-max w-full pt-[3px]">
{primaryText}
</p>
)}
</>
) : (
<p className="text-offWhite overflow-hidden text-ellipsis mt-[3px] w-full max-w-max whitespace-nowrap">
{primaryText}
</p>
)}
</div>
)
}

return (
<div
Expand Down
9 changes: 8 additions & 1 deletion apps/multisig/src/components/MemberRow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { css } from '@emotion/css'
import { ExternalLink, Trash } from '@talismn/icons'
import { AccountDetails } from '@components/AddressInput/AccountDetails'

const MemberRow = (props: { member: AugmentedAccount; chain: Chain; onDelete?: () => void; truncate?: boolean }) => {
const MemberRow = (props: {
member: AugmentedAccount
chain: Chain
onDelete?: () => void
truncate?: boolean
isNameLoading?: boolean
}) => {
return (
<div
className={css`
Expand All @@ -27,6 +33,7 @@ const MemberRow = (props: { member: AugmentedAccount; chain: Chain; onDelete?: (
disableCopy
withAddressTooltip
chain={props.chain}
isNameLoading={props.isNameLoading}
/>
{props.member.you ? <span className="text-offWhite text-[14px]"> (You)</span> : null}
</div>
Expand Down
3 changes: 2 additions & 1 deletion apps/multisig/src/components/ScanVaults/VaultCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const VaultCard: React.FC<{ vault: ScannedVault; onAdded?: () => void }> = ({ on
const { toast } = useToast()
const setImportedTeams = useSetRecoilState(importedTeamsState)
const navigate = useNavigate()
const { contactByAddress } = useKnownAddresses()
const signerAddresses = vault.multisig.signers.map(s => s.toSs58())
const { contactByAddress } = useKnownAddresses({ addresses: showMultisig ? signerAddresses : [] })
useEffect(() => {
if (add && showMultisig) setShowMultisig(false)
}, [add, showMultisig])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useEffect, useState } from 'react'
export const AddressParamInput: ParamInputComponent<string> = ({ chain, onChange, arg }) => {
const [query, setQuery] = useState('')
const [selectedMultisig] = useSelectedMultisig()
const { addresses } = useKnownAddresses(selectedMultisig.orgId, { includeSelectedMultisig: true })
const { addresses } = useKnownAddresses({ orgId: selectedMultisig.orgId, includeSelectedMultisig: true })

useEffect(() => {
if (!arg) setQuery('')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@ import { Address } from '@util/addresses'
import { useSelectedMultisig } from '@domains/multisig'

export const TransactionSidesheetApprovals: React.FC<{ t: Transaction }> = ({ t }) => {
const { contactByAddress } = useKnownAddresses(t.multisig.orgId)
const [{ isEthereumAccount }] = useSelectedMultisig()
const approversAddresses = Object.keys(t.approvals).reduce<string[]>((acc, address) => {
const decodedAddress = isEthereumAccount ? Address.fromSs58(address) : Address.fromPubKey(address)
if (decodedAddress) {
acc.push(decodedAddress.toSs58())
}
return acc
}, [])

const { contactByAddress, isLoading } = useKnownAddresses({ orgId: t.multisig.orgId, addresses: approversAddresses })
return (
<div css={{ display: 'grid', gap: '14px' }}>
{Object.entries(t.approvals).map(([address, approval]) => {
Expand All @@ -24,6 +32,7 @@ export const TransactionSidesheetApprovals: React.FC<{ t: Transaction }> = ({ t
<MemberRow
member={{ address: decodedAddress, nickname: contact?.name, you: contact?.extensionName !== undefined }}
chain={t.multisig.chain}
isNameLoading={isLoading}
/>
</div>
{(t.rawPending || t.executedAt) && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { requestSignetBackend } from '@domains/offchain-data/hasura'
import { selectedAccountState } from '@domains/auth'
import { SignedInAccount } from '@domains/auth'
import { useRecoilValue } from 'recoil'
import { useQuery } from '@tanstack/react-query'
import { ADDRESSES_BY_ORG_ID_AND_ADDRESS } from '@domains/offchain-data/address-book/queries/queries'
import { useSelectedMultisig } from '@domains/multisig'
import { Address } from '@util/addresses'
import { Contact } from '../address-book'

export type ContactAddress = Omit<Contact, 'orgId'> & { team_id?: string; org_id: string }
export type ContactAddressIO = Omit<ContactAddress, 'address'> & { address: string }

export type PaginatedAddresses = {
rows: ContactAddress[]
pageCount: number
rowCount: number
}

const fetchGraphQLData = async ({
orgId,
addresses,
selectedAccount,
}: {
orgId: string
addresses: string[]
selectedAccount: SignedInAccount
}): Promise<ContactAddress[]> => {
const { data } = await requestSignetBackend(
ADDRESSES_BY_ORG_ID_AND_ADDRESS,
{
orgId,
addresses,
},
selectedAccount
)

return (
data.address?.map((contact: ContactAddressIO) => ({ ...contact, address: Address.fromSs58(contact.address) })) ?? []
)
}

const useGetAddressesByOrgIdAndAddress = (addresses: string[]) => {
const selectedAccount = useRecoilValue(selectedAccountState)
const [selectedMultisig] = useSelectedMultisig()
return useQuery({
queryKey: ['addresses', selectedMultisig.id, addresses],
queryFn: () => fetchGraphQLData({ orgId: selectedMultisig.orgId, addresses, selectedAccount: selectedAccount! }),
enabled: !!selectedAccount && addresses.length > 0,
})
}

export default useGetAddressesByOrgIdAndAddress
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ export const PAGINATED_SUB_CATEGORIES_BY_ORG_ID = gql`
}
`

export const ADDRESSES_BY_ORG_ID_AND_ADDRESS = gql`
query AddressesByOrgIdAndAddress($orgId: uuid!, $addresses: [String!]!) {
address(where: { org_id: { _eq: $orgId }, address: { _in: $addresses } }) {
id
org_id
name
address
category {
id
name
}
sub_category {
id
name
}
}
}
`

export const UPSERT_ADDRESSES = gql`
mutation UpsertAddressesMutation($orgId: String!, $teamId: String!, $addressesInput: [AddressInput!]!) {
UpsertAddresses(addressesInput: { addresses: $addressesInput, org_id: $orgId, team_id: $teamId }) {
Expand Down
32 changes: 21 additions & 11 deletions apps/multisig/src/hooks/useKnownAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,30 @@ import { useMemo } from 'react'
import { useSelectedMultisig } from '@domains/multisig'
import { useSmartContracts } from '../domains/offchain-data/smart-contract'
import { Contact } from '../domains/offchain-data/address-book/address-book'
import useGetAddressesByOrgIdAndAddress from '../domains/offchain-data/address-book/hooks/useGetAddressesByOrgIdAndAddress'

type ContactWithNameAndCategory = Partial<Contact> & AddressWithName

export const useKnownAddresses = (
teamId?: string,
{
includeSelectedMultisig = false,
includeContracts = false,
}: { includeSelectedMultisig?: boolean; includeContracts?: boolean } = {}
): { addresses: ContactWithNameAndCategory[]; contactByAddress: Record<string, ContactWithNameAndCategory> } => {
export const useKnownAddresses = ({
orgId,
includeSelectedMultisig,
includeContracts,
addresses,
}: {
orgId?: string
includeSelectedMultisig?: boolean
includeContracts?: boolean
addresses?: string[]
} = {}): {
addresses: ContactWithNameAndCategory[]
contactByAddress: Record<string, ContactWithNameAndCategory>
isLoading: boolean
} => {
const extensionAccounts = useRecoilValue(accountsState)
const addressBookByOrgId = useRecoilValue(addressBookByOrgIdState)
const [multisig] = useSelectedMultisig()
const { contracts } = useSmartContracts()
const { data: addressBookData, isLoading } = useGetAddressesByOrgIdAndAddress(addresses ?? [])

const extensionContacts = extensionAccounts.reduce<AddressWithName[]>(
(acc, { address, meta: { name = '' } = {} }) => {
Expand All @@ -37,9 +47,9 @@ export const useKnownAddresses = (
)

const addressBookContacts = useMemo(() => {
if (!teamId) return []
if (!orgId || !addressBookData?.length) return []

const addresses = addressBookByOrgId[teamId ?? ''] ?? []
const addresses = [...(addressBookByOrgId[orgId ?? ''] ?? []), ...(addressBookData ?? [])]

return addresses.reduce<ContactWithNameAndCategory[]>((acc, { address, name, category, sub_category }) => {
if (multisig.isEthereumAccount === address.isEthereum) {
Expand All @@ -54,7 +64,7 @@ export const useKnownAddresses = (
}
return acc
}, [])
}, [addressBookByOrgId, multisig.isEthereumAccount, teamId])
}, [addressBookByOrgId, addressBookData, multisig.isEthereumAccount, orgId])

const combinedList = useMemo(() => {
let list = extensionContacts
Expand Down Expand Up @@ -130,5 +140,5 @@ export const useKnownAddresses = (
}, {} as Record<string, ContactWithNameAndCategory>)
}, [combinedList])

return { addresses: combinedList, contactByAddress }
return { addresses: combinedList, contactByAddress, isLoading }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const AddCollaboratorModal: React.FC<Props> = ({ isOpen, onClose }) => {
const [selectedMultisig] = useSelectedMultisig()
const [address, setAddress] = useState<Address | undefined>()
const [error, setError] = useState<boolean>(false)
const { addresses } = useKnownAddresses(selectedMultisig.orgId)
const { addresses } = useKnownAddresses({ orgId: selectedMultisig.orgId })
const { addCollaborator, adding } = useAddOrgCollaborator()

const handleAddressChange = (address: Address | undefined) => {
Expand Down
13 changes: 11 additions & 2 deletions apps/multisig/src/layouts/Collaborators/CollaboratorRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ export const CollaboratorRow: React.FC<{ orgId: string; userId: string; address:
userId,
address,
}) => {
const { contactByAddress } = useKnownAddresses(orgId, { includeContracts: true })
const { contactByAddress, isLoading } = useKnownAddresses({
orgId,
includeContracts: true,
addresses: [address.toSs58()],
})
const { deleteCollaborator, deleting } = useDeleteCollaborator()
const { isCollaborator } = useUser()

Expand All @@ -25,7 +29,12 @@ export const CollaboratorRow: React.FC<{ orgId: string; userId: string; address:
return (
<div className="w-full bg-gray-900 p-[16px] rounded-[12px] flex items-center justify-between">
<div>
<AccountDetails address={address} name={contactByAddress?.[address.toSs58()]?.name} withAddressTooltip />
<AccountDetails
address={address}
name={contactByAddress?.[address.toSs58()]?.name}
withAddressTooltip
isNameLoading={isLoading}
/>
</div>
{!isCollaborator && (
<Tooltip content="Remove collaborator">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const MultiSend = () => {
const apiLoadable = useRecoilValueLoadable(pjsApiSelector(multisig.chain.genesisHash))
const { toast } = useToast()
const permissions = hasPermission(multisig, 'transfer')
const { addresses } = useKnownAddresses(multisig.orgId)
const { addresses } = useKnownAddresses({ orgId: multisig.orgId })
const newSends = useRecoilValue(multisendSendsAtom)
const unit = useRecoilValue(multisendAmountUnitAtom)
const token = useRecoilValue(multisendTokenAtom)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const DetailsForm: React.FC<Props> = ({
}) => {
const [addressError, setAddressError] = useState<boolean>(false)
const [multisig] = useSelectedMultisig()
const { addresses } = useKnownAddresses(multisig.orgId)
const { addresses } = useKnownAddresses({ orgId: multisig.orgId })
const { hasDelayedPermission, hasNonDelayedPermission } = hasPermission(multisig, 'transfer')
const vestingConsts = useRecoilValueLoadable(vestingConstsSelector(multisig.chain.genesisHash))

Expand Down
Loading

0 comments on commit 85324e2

Please sign in to comment.