📄 src/web3/vue/handlers/sessionVoteHandler.ts
D-OPEN SOVEREIGN
1import { sessionStore } from '../../session/store';
2import type { ChainMutation, MutationHandler } from '../MutationBus';
3
4type VoteMutation = Extract<ChainMutation, { type: 'vote' }>;
5
6interface VoteSnapshot {
7 chainId: number;
8 account: string;
9 donationsPerProject?: number[];
10 projectBalance?: { contributions: number; allocated: number; remaining: number };
11}
12
13export const sessionVoteHandler: MutationHandler<VoteMutation> = {
14 applyOptimistic: (mutation): VoteSnapshot | null => {
15 const account = sessionStore
16 .getState()
17 .known.find((a) => a.account.toLowerCase() === mutation.account.toLowerCase() && a.chainId === mutation.chainId);
18 if (!account) return null;
19
20 const snapshot: VoteSnapshot = {
21 chainId: mutation.chainId,
22 account: mutation.account,
23 donationsPerProject: account.donationsPerProject ? [...account.donationsPerProject] : undefined,
24 projectBalance: account.projectBalance ? { ...account.projectBalance } : undefined,
25 };
26
27 const votes = account.donationsPerProject ? [...account.donationsPerProject] : [];
28 votes[mutation.projectId - 1] = (votes[mutation.projectId - 1] || 0) + mutation.amount;
29
30 const patch: { donationsPerProject: number[]; projectBalance?: typeof account.projectBalance } = {
31 donationsPerProject: votes,
32 };
33 if (account.projectBalance) {
34 patch.projectBalance = {
35 ...account.projectBalance,
36 allocated: account.projectBalance.allocated + mutation.amount,
37 remaining: account.projectBalance.remaining - mutation.amount,
38 };
39 }
40
41 sessionStore.updateAccount(mutation.account, mutation.chainId, patch);
42 return snapshot;
43 },
44
45 rollback: (snapshot: VoteSnapshot | null) => {
46 if (!snapshot) return;
47 sessionStore.updateAccount(snapshot.account, snapshot.chainId, {
48 donationsPerProject: snapshot.donationsPerProject,
49 projectBalance: snapshot.projectBalance,
50 });
51 },
52};
53