diff --git a/src/renderer/domains/identity/model/identity/model.ts b/src/renderer/domains/identity/model/identity/model.ts index 43d198b9ed..1abebe4ddc 100644 --- a/src/renderer/domains/identity/model/identity/model.ts +++ b/src/renderer/domains/identity/model/identity/model.ts @@ -8,7 +8,6 @@ import { identityPallet } from '@/shared/pallet/identity'; import { type AccountId } from '@/shared/polkadotjs-schemas'; import { networkModel } from '@/entities/network'; -import { identityService } from './service'; import { type AccountIdentity } from './types'; type IdentityData = Record; @@ -79,14 +78,11 @@ const request = attach({ effect: requestIdentity, source: { apis: $apis, chains: $chains }, mapParams: ({ chainId, accounts }: RequestParams, { apis, chains }) => { - const identityChain = identityService.findIdentityChain(chains, chainId); - if (nullable(identityChain)) { - throw new Error(`Chain path from ${chainId} is broken, trace chain.parentId fields in config.`); - } + const identityChainId = chains[chainId]?.additional?.identityChain ?? chainId; - const api = apis[identityChain.chainId]; + const api = apis[identityChainId]; if (nullable(api)) { - throw new Error(`ApiPromise for chain ${identityChain.chainId} not found`); + throw new Error(`ApiPromise for chain ${identityChainId} not found`); } return { diff --git a/src/renderer/domains/identity/model/identity/service.ts b/src/renderer/domains/identity/model/identity/service.ts deleted file mode 100644 index 78730b1c36..0000000000 --- a/src/renderer/domains/identity/model/identity/service.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { type Chain, type ChainId } from '@/shared/core'; -import { nullable } from '@/shared/lib/utils'; - -const findIdentityChain = (chains: Record, initialChainId: ChainId) => { - let chainId = initialChainId; - let chain = chains[initialChainId]; - let identityChain: Chain | null = null; - - if (nullable(chain)) { - return null; - } - - while (nullable(identityChain)) { - if (chain.parentId) { - chainId = chain.parentId; - chain = chains[chainId]; - - if (nullable(chain)) { - break; - } - } else { - const identityChainId = chain.additional?.identityChain; - - if (nullable(identityChainId)) { - break; - } - - identityChain = chains[identityChainId] ?? null; - break; - } - } - - return identityChain; -}; - -export const identityService = { - findIdentityChain, -}; diff --git a/src/renderer/features/governance/aggregates/delegateRegistry.ts b/src/renderer/features/governance/aggregates/delegateRegistry.ts index e6f5cb282c..a0f165515d 100644 --- a/src/renderer/features/governance/aggregates/delegateRegistry.ts +++ b/src/renderer/features/governance/aggregates/delegateRegistry.ts @@ -5,7 +5,9 @@ import { readonly } from 'patronum'; import { type DelegateAccount, delegationService } from '@/shared/api/governance'; import { type Chain } from '@/shared/core'; -import { MONTH, getBlockTimeAgo, nonNullable } from '@/shared/lib/utils'; +import { MONTH, getBlockTimeAgo, nonNullable, toAccountId } from '@/shared/lib/utils'; +import { type AccountId } from '@/shared/polkadotjs-schemas'; +import { identityDomain } from '@/domains/identity'; import { networkSelectorModel } from '../model/networkSelector'; const requestDelegateRegistry = createEvent(); @@ -63,6 +65,33 @@ sample({ target: $delegateRegistry, }); +sample({ + clock: $delegateRegistry, + source: { + chain: networkSelectorModel.$governanceChain, + identity: identityDomain.identity.$list, + }, + filter: ({ chain }) => nonNullable(chain), + fn: ({ chain, identity }, delegates) => { + const accounts = new Set(); + + for (const delegate of delegates) { + if (nonNullable(delegate.name)) continue; + + const accountId = toAccountId(delegate.address ?? delegate.accountId); + if (nonNullable(identity[chain!.chainId]?.[accountId])) continue; + + accounts.add(accountId); + } + + return { + chainId: chain!.chainId, + accounts: Array.from(accounts), + }; + }, + target: identityDomain.identity.request, +}); + export const delegateRegistryAggregate = { $delegateRegistry: readonly($delegateRegistry), $isRegistryLoading: requestDelegateRegistryFx.pending, diff --git a/src/renderer/features/governance/aggregates/voting.ts b/src/renderer/features/governance/aggregates/voting.ts index c5d213036c..cb13767dbc 100644 --- a/src/renderer/features/governance/aggregates/voting.ts +++ b/src/renderer/features/governance/aggregates/voting.ts @@ -1,8 +1,10 @@ import { combine, createEvent, sample } from 'effector'; import { type Address, type TrackId, type VotingMap } from '@/shared/core'; -import { nonNullable, nullable } from '@/shared/lib/utils'; -import { votingModel } from '@/entities/governance'; +import { nonNullable, nullable, toAccountId } from '@/shared/lib/utils'; +import { type AccountId } from '@/shared/polkadotjs-schemas'; +import { identityDomain } from '@/domains/identity'; +import { votingModel, votingService } from '@/entities/governance'; import { accountUtils, walletModel, walletUtils } from '@/entities/wallet'; import { networkSelectorModel } from '../model/networkSelector'; @@ -89,6 +91,35 @@ sample({ target: requestVoting, }); +sample({ + clock: $activeWalletVotes, + source: { + chain: networkSelectorModel.$governanceChain, + identity: identityDomain.identity.$list, + }, + filter: ({ chain }) => nonNullable(chain), + fn: ({ chain, identity }, activeVotes) => { + const accounts = new Set(); + + for (const voteList of Object.values(activeVotes)) { + for (const vote of Object.values(voteList)) { + if (!votingService.isDelegating(vote)) continue; + + const accountId = toAccountId(vote.target); + if (nonNullable(identity[chain!.chainId]?.[accountId])) continue; + + accounts.add(accountId); + } + } + + return { + chainId: chain!.chainId, + accounts: Array.from(accounts), + }; + }, + target: identityDomain.identity.request, +}); + export const votingAggregate = { $activeWalletVotes, $possibleAccountsForVoting, diff --git a/src/renderer/features/governance/components/Delegations/DelegateIcon.tsx b/src/renderer/features/governance/components/Delegations/DelegateIcon.tsx index 27f341d4cf..803639e5b8 100644 --- a/src/renderer/features/governance/components/Delegations/DelegateIcon.tsx +++ b/src/renderer/features/governance/components/Delegations/DelegateIcon.tsx @@ -13,18 +13,20 @@ export const DelegateIcon = ({ delegate, className }: Props) => { if (!delegate.name) return ; if (isDefaultImage(delegate.image)) { -
- {delegate.isOrganization ? ( - - ) : ( - - )} -
; + return ( +
+ {delegate.isOrganization ? ( + + ) : ( + + )} +
+ ); } return {delegate.name}; diff --git a/src/renderer/features/governance/components/Delegations/DelegateTitle.tsx b/src/renderer/features/governance/components/Delegations/DelegateTitle.tsx index cb029767d7..965d6f5fd7 100644 --- a/src/renderer/features/governance/components/Delegations/DelegateTitle.tsx +++ b/src/renderer/features/governance/components/Delegations/DelegateTitle.tsx @@ -1,9 +1,10 @@ -import { useUnit } from 'effector-react'; +import { useStoreMap, useUnit } from 'effector-react'; import { type DelegateAccount } from '@/shared/api/governance'; -import { cnTw, nullable } from '@/shared/lib/utils'; +import { cnTw, nullable, toAccountId } from '@/shared/lib/utils'; import { HeadlineText } from '@/shared/ui'; import { Account } from '@/shared/ui-entities'; +import { identityDomain } from '@/domains/identity'; import { networkSelectorModel } from '../../model/networkSelector'; type Props = { @@ -13,11 +14,22 @@ type Props = { export const DelegateTitle = ({ delegate, className }: Props) => { const chain = useUnit(networkSelectorModel.$governanceChain); + + const delegateName = useStoreMap({ + store: identityDomain.identity.$list, + keys: [chain?.chainId, delegate.accountId, delegate.address], + fn: (identity, [chainId, accountId, address]) => { + if (nullable(chainId)) return null; + + return delegate.name ?? identity[chainId]?.[toAccountId(address ?? accountId)]?.name ?? null; + }, + }); + if (nullable(chain) || nullable(delegate.accountId)) return null; return ( - + ); }; diff --git a/src/renderer/widgets/CurrentDelegationsModal/components/CurrentDelegationModal.tsx b/src/renderer/widgets/CurrentDelegationsModal/components/CurrentDelegationModal.tsx index d9e5dd7052..9c02c88fc6 100644 --- a/src/renderer/widgets/CurrentDelegationsModal/components/CurrentDelegationModal.tsx +++ b/src/renderer/widgets/CurrentDelegationsModal/components/CurrentDelegationModal.tsx @@ -1,6 +1,7 @@ import { useUnit } from 'effector-react'; import { useI18n } from '@/shared/i18n'; +import { toAccountId } from '@/shared/lib/utils'; import { Button, Loader } from '@/shared/ui'; import { Modal, SearchInput } from '@/shared/ui-kit'; import { OperationTitle } from '@/entities/chain'; @@ -45,16 +46,20 @@ export const CurrentDelegationModal = () => {
    - {delegationList.map((delegate) => ( - - ))} + {delegationList.map((delegate) => { + const accountId = toAccountId(delegate.address ?? delegate.accountId); + + return ( + + ); + })}
diff --git a/src/renderer/widgets/DelegationModal/components/DelegationList.tsx b/src/renderer/widgets/DelegationModal/components/DelegationList.tsx index cdaef5b6a5..5fa5765503 100644 --- a/src/renderer/widgets/DelegationModal/components/DelegationList.tsx +++ b/src/renderer/widgets/DelegationModal/components/DelegationList.tsx @@ -2,6 +2,7 @@ import { useUnit } from 'effector-react'; import { type DelegateAccount } from '@/shared/api/governance'; import { useI18n } from '@/shared/i18n'; +import { toAccountId } from '@/shared/lib/utils'; import { Button, Loader } from '@/shared/ui'; import { Box, SearchInput, Select } from '@/shared/ui-kit'; import { SortType } from '../common/constants'; @@ -68,11 +69,15 @@ export const DelegationList = ({ onClick, onAddCustomClick }: Props) => {
    - {delegationList.map((delegate) => ( - - ))} + {delegationList.map((delegate) => { + const accountId = toAccountId(delegate.address ?? delegate.accountId); + + return ( + + ); + })}
{delegationList.length === 0 && }