-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathuseNetworkMotionStates.ts
107 lines (86 loc) · 3.12 KB
/
useNetworkMotionStates.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { type MotionState, VotingReputationFactory } from '@colony/colony-js';
import { useEffect, useState } from 'react';
import { useAppContext } from '~context/AppContext/AppContext.ts';
import useEnabledExtensions from './useEnabledExtensions.ts';
import type { Provider } from '@ethersproject/providers';
export type MotionStatesMap = Map<string, MotionState | null>;
export type RefetchMotionStates = (motionIdsToRefetch?: string[]) => void;
/**
* Hook that accepts an array of motion IDs and returns a map of motion IDs to their states
* Make sure to memoize the array of motion IDs to avoid infinite loops
*/
const useNetworkMotionStates = (nativeMotionIds: string[], skip?: boolean) => {
const { wallet } = useAppContext();
const { votingReputationAddress } = useEnabledExtensions();
const [loading, setLoading] = useState(false);
const [motionStatesMap, setMotionStatesMap] = useState<MotionStatesMap>(
new Map(),
);
useEffect(() => {
const { ethersProvider } = wallet || {};
if (
skip ||
!nativeMotionIds.length ||
!votingReputationAddress ||
!ethersProvider
) {
return;
}
const newMotionIds = nativeMotionIds.filter(
(nativeMotionId) => !motionStatesMap.has(nativeMotionId),
);
const deletedMotionIds = Array.from(motionStatesMap.keys()).filter(
(nativeMotionId) => !nativeMotionIds.includes(nativeMotionId),
);
if (!newMotionIds.length && !deletedMotionIds.length) {
return;
}
// Properly initialize the signer with the current wallet address
const votingRepClient = VotingReputationFactory.connect(
votingReputationAddress,
// We need to cast this to a Provider since colonyJS methods expect a "standard" provider,
// while ours is a custom one (which extends the base, standard provider)
ethersProvider as unknown as Provider,
);
const fetchMotionStates = async () => {
setLoading(true);
const statesMap = new Map(motionStatesMap);
await Promise.all(
newMotionIds.map(async (nativeMotionId) => {
try {
const motionState =
await votingRepClient.getMotionState(nativeMotionId);
statesMap.set(nativeMotionId, motionState);
} catch {
statesMap.set(nativeMotionId, null);
}
}),
);
deletedMotionIds.forEach((nativeMotionId) =>
statesMap.delete(nativeMotionId),
);
setMotionStatesMap(statesMap);
setLoading(false);
};
fetchMotionStates();
}, [motionStatesMap, nativeMotionIds, skip, votingReputationAddress, wallet]);
const refetch: RefetchMotionStates = (motionIdsToRefetch) => {
if (!motionIdsToRefetch?.length) {
setMotionStatesMap(new Map());
} else {
setMotionStatesMap((prevMotionStatesMap) => {
const newMotionStatesMap = new Map(prevMotionStatesMap);
motionIdsToRefetch.forEach((motionId) =>
newMotionStatesMap.delete(motionId),
);
return newMotionStatesMap;
});
}
};
return {
motionStatesMap,
loading,
refetch,
};
};
export default useNetworkMotionStates;