Skip to content

Commit

Permalink
fix: add delegation to multiple delegates (#2173)
Browse files Browse the repository at this point in the history
  • Loading branch information
Asmadek authored Aug 22, 2024
1 parent 64f12ff commit 7a1946f
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 44 deletions.
12 changes: 8 additions & 4 deletions src/renderer/features/governance/aggregates/delegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ const $totalDelegations = combine(
);

const $activeDelegations = votingAggregate.$activeWalletVotes.map((activeVotes) => {
const activeBalances: Record<Address, { conviction: Conviction; balance: BN }> = {};
const activeBalances: Record<Address, Record<Address, { conviction: Conviction; balance: BN }>> = {};

for (const [address, delegations] of Object.entries(activeVotes)) {
const delegation = Object.values(delegations).find(votingService.isDelegating);
for (const delegation of Object.values(delegations)) {
if (!votingService.isDelegating(delegation)) continue;

if (delegation) {
activeBalances[address] = {
if (!activeBalances[delegation.target]) {
activeBalances[delegation.target] = {};
}

activeBalances[delegation.target][address] = {
conviction: delegation.conviction,
balance: delegation.balance,
};
Expand Down
1 change: 1 addition & 0 deletions src/renderer/shared/api/governance/off-chain/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export type DelegateDetails = {
};

export type DelegateStat = {
// Address actually
accountId: Address;
delegators: any[];
delegatorVotes: any[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { combine, createEvent, createStore, sample } from 'effector';
import { type DelegateAccount } from '@/shared/api/governance';
import { type Address } from '@/shared/core';
import { toAddress } from '@/shared/lib/utils';
import { votingService } from '@/entities/governance';
import { accountUtils, permissionUtils, walletModel } from '@/entities/wallet';
import { delegationAggregate, networkSelectorModel, votingAggregate } from '@/features/governance';

Expand All @@ -13,23 +14,37 @@ const $isModalOpen = createStore(false);
const $isDelegationsOpen = createStore(false);
const $delegate = createStore<DelegateAccount | null>(null);

const $activeTracks = votingAggregate.$activeWalletVotes.map((activeVotes) => {
const activeTracks: Record<Address, Set<string>> = {};
const $activeTracks = combine(
{ votes: votingAggregate.$activeWalletVotes, delegate: $delegate },
({ votes, delegate }) => {
const activeTracks: Record<Address, Set<string>> = {};

for (const [address, delegations] of Object.entries(activeVotes)) {
for (const key of Object.keys(delegations)) {
if (!activeTracks[address]) {
activeTracks[address] = new Set();
}
for (const [address, delegations] of Object.entries(votes)) {
for (const [key, vote] of Object.entries(delegations)) {
if (votingService.isDelegating(vote) && vote.target === delegate?.accountId) {
if (!activeTracks[address]) {
activeTracks[address] = new Set();
}

activeTracks[address].add(key);
activeTracks[address].add(key);
}
}
}
}

return activeTracks;
});
return activeTracks;
},
);

const $activeDelegations = combine(
{ delegations: delegationAggregate.$activeDelegations, delegate: $delegate },
({ delegations, delegate }) => {
if (!delegate) return {};

return delegations[delegate.accountId];
},
);

const $activeAccounts = delegationAggregate.$activeDelegations.map(Object.keys);
const $activeAccounts = $activeDelegations.map(Object.keys);

const $canDelegate = walletModel.$activeWallet.map((wallet) => !!wallet && permissionUtils.canDelegate(wallet));

Expand All @@ -53,14 +68,9 @@ const $isAddAvailable = combine(
},
);

const $isViewAvailable = combine(
{
activeDelegations: delegationAggregate.$activeDelegations,
},
({ activeDelegations }) => {
return Object.values(activeDelegations).length > 1;
},
);
const $isViewAvailable = $activeDelegations.map((delegations) => {
return Object.values(delegations).length > 1;
});

sample({
clock: flowStarted,
Expand Down Expand Up @@ -91,7 +101,7 @@ export const delegateDetailsModel = {
.flat(),
),
]),
$activeDelegations: delegationAggregate.$activeDelegations,
$activeDelegations,

$isAddAvailable,
$isViewAvailable,
Expand Down
9 changes: 4 additions & 5 deletions src/renderer/widgets/DelegateModal/model/delegate-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,14 @@ sample({ clock: stepChanged, target: $step });

sample({
clock: flowStarted,
source: $walletData,
filter: (walletData) => Boolean(walletData.chain),
fn: (walletData) => walletData.chain!,
target: selectTracksModel.events.formInitiated,
target: $target,
});

sample({
clock: flowStarted,
target: $target,
source: $target,
filter: (target) => !!target,
target: selectTracksModel.events.formInitiated,
});

sample({
Expand Down
36 changes: 26 additions & 10 deletions src/renderer/widgets/DelegateModal/model/select-tracks-model.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { combine, createEvent, createStore, restore, sample } from 'effector';

import { type Account, type Chain } from '@/shared/core';
import { type DelegateAccount } from '@/shared/api/governance';
import { type Account } from '@/shared/core';
import { addUniqueItems, removeItemsFromCollection, toAddress } from '@/shared/lib/utils';
import { votingService } from '@/entities/governance';
import { accountUtils, walletModel } from '@/entities/wallet';
import { delegationAggregate, tracksAggregate, votingAggregate } from '@/features/governance';
import { adminTracks, fellowshipTracks, governanceTracks, treasuryTracks } from '../lib/constants';

const formInitiated = createEvent<Chain>();
const formInitiated = createEvent<DelegateAccount>();
const formSubmitted = createEvent<{ tracks: number[]; accounts: Account[] }>();
const trackToggled = createEvent<number>();
const tracksSelected = createEvent<number[]>();
const accountsChanged = createEvent<Account[]>();

const $chain = restore(formInitiated, null);
const $delegate = restore(formInitiated, null);

const $tracks = createStore<number[]>([]).reset(formInitiated);
const $accounts = createStore<Account[]>([]);
Expand All @@ -22,16 +23,28 @@ const $availableTracks = combine(tracksAggregate.$tracks, (tracks) => {
return Object.keys(tracks);
});

const $addresses = combine({ accounts: $accounts, chain: delegationAggregate.$chain }, ({ accounts, chain }) => {
if (!chain) return [];

return accounts.map((a) => toAddress(a.accountId, { prefix: chain.addressPrefix }));
});

const $votedTracks = combine(
{
votes: votingAggregate.$activeWalletVotes,
addresses: $addresses,
},
({ votes }) => {
({ votes, addresses }) => {
const activeTracks = new Set<string>();

for (const voteList of Object.values(votes)) {
for (const [address, voteList] of Object.entries(votes)) {
if (!addresses.includes(address)) continue;

for (const [track, vote] of Object.entries(voteList)) {
if (votingService.isCasting(vote) && !votingService.isUnlockingDelegation(vote)) {
if (
(votingService.isCasting(vote) && !votingService.isUnlockingDelegation(vote)) ||
votingService.isDelegating(vote)
) {
activeTracks.add(track);
}
}
Expand All @@ -46,13 +59,16 @@ const $availableAccounts = combine(
wallet: walletModel.$activeWallet,
delegations: delegationAggregate.$activeDelegations,
chain: delegationAggregate.$chain,
delegate: $delegate,
},
({ wallet, delegations, chain }) => {
if (!wallet || !chain) return [];
({ wallet, delegations, chain, delegate }) => {
if (!wallet || !chain || !delegate) return [];

return wallet.accounts
.filter((a) => accountUtils.isNonBaseVaultAccount(a, wallet) && accountUtils.isChainIdMatch(a, chain.chainId))
.filter((account) => !delegations[toAddress(account.accountId, { prefix: chain.addressPrefix })]);
.filter(
(account) => !delegations[delegate.accountId]?.[toAddress(account.accountId, { prefix: chain.addressPrefix })],
);
},
);

Expand Down Expand Up @@ -117,7 +133,7 @@ export const selectTracksModel = {

$accounts,
$availableAccounts,
$chain,
$chain: delegationAggregate.$chain,

events: {
formInitiated,
Expand Down
13 changes: 9 additions & 4 deletions src/renderer/widgets/DelegateModal/ui/SelectTracksForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,39 @@ export const SelectTrackForm = ({ isOpen, onClose }: Props) => {
<div className="flex flex-1 flex-col gap-6 px-5">
<div className="flex gap-3">
<Button
disabled={accounts.length === 0}
pallet={getGroupPallet(allTracks, votedTracks, tracks)}
variant="chip"
onClick={() => selectTracksModel.events.tracksSelected(getTrackIds(allTracks, votedTracks))}
>
{t('governance.addDelegation.group.selectAll')}
</Button>
<Button
disabled={accounts.length === 0}
pallet={getGroupPallet(adminTracks, votedTracks, tracks)}
variant="chip"
onClick={() => selectTracksModel.events.tracksSelected(getTrackIds(adminTracks, votedTracks))}
>
{t('governance.addDelegation.group.admin')}
</Button>
<Button
disabled={accounts.length === 0}
pallet={getGroupPallet(governanceTracks, votedTracks, tracks)}
variant="chip"
onClick={() => selectTracksModel.events.tracksSelected(getTrackIds(governanceTracks, votedTracks))}
>
{t('governance.addDelegation.group.governance')}
</Button>
<Button
disabled={accounts.length === 0}
pallet={getGroupPallet(treasuryTracks, votedTracks, tracks)}
variant="chip"
onClick={() => selectTracksModel.events.tracksSelected(getTrackIds(treasuryTracks, votedTracks))}
>
{t('governance.addDelegation.group.treasury')}
</Button>
<Button
disabled={accounts.length === 0}
pallet={getGroupPallet(fellowshipTracks, votedTracks, tracks)}
variant="chip"
onClick={() => selectTracksModel.events.tracksSelected(getTrackIds(fellowshipTracks, votedTracks))}
Expand All @@ -88,7 +93,7 @@ export const SelectTrackForm = ({ isOpen, onClose }: Props) => {
<Checkbox
key={track.id}
checked={tracks.includes(Number(track.id))}
disabled={votedTracks.includes(track.id)}
disabled={votedTracks.includes(track.id) || accounts.length === 0}
onChange={() => selectTracksModel.events.trackToggled(Number(track.id))}
>
<div className="flex w-full items-center justify-between">
Expand All @@ -105,7 +110,7 @@ export const SelectTrackForm = ({ isOpen, onClose }: Props) => {
<Checkbox
key={track.id}
checked={tracks.includes(Number(track.id))}
disabled={votedTracks.includes(track.id)}
disabled={votedTracks.includes(track.id) || accounts.length === 0}
onChange={() => selectTracksModel.events.trackToggled(Number(track.id))}
>
<div className="flex w-full items-center justify-between">
Expand All @@ -122,7 +127,7 @@ export const SelectTrackForm = ({ isOpen, onClose }: Props) => {
<Checkbox
key={track.id}
checked={tracks.includes(Number(track.id))}
disabled={votedTracks.includes(track.id)}
disabled={votedTracks.includes(track.id) || accounts.length === 0}
onChange={() => selectTracksModel.events.trackToggled(Number(track.id))}
>
<div className="flex w-full items-center justify-between">
Expand All @@ -139,7 +144,7 @@ export const SelectTrackForm = ({ isOpen, onClose }: Props) => {
<Checkbox
key={track.id}
checked={tracks.includes(Number(track.id))}
disabled={votedTracks.includes(track.id)}
disabled={votedTracks.includes(track.id) || accounts.length === 0}
onChange={() => selectTracksModel.events.trackToggled(Number(track.id))}
>
<div className="flex w-full items-center justify-between">
Expand Down

0 comments on commit 7a1946f

Please sign in to comment.