Skip to content

Commit b9e81e5

Browse files
committed
doc: added docs to useGetSmartWalletTransactions
1 parent dbd2767 commit b9e81e5

File tree

1 file changed

+55
-6
lines changed

1 file changed

+55
-6
lines changed

src/hooks/use-get-smart-wallet-transactions.ts

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import { GLOBAL_CONSTANTS } from '@src/config-global.ts';
66
import LedgerVaultAbi from '@src/config/abi/LedgerVault.json';
77
import { addTransaction, setTransactions } from '@redux/transactions';
88

9+
/**
10+
* Type definition for a transaction log, including event data and relevant block/transaction metadata.
11+
*/
912
export type TransactionLog = {
1013
address: string;
1114
args: {
@@ -29,13 +32,23 @@ export type TransactionLog = {
2932
transactionIndex: number;
3033
};
3134

35+
/**
36+
* Configuration object for each event:
37+
* - eventName: Name of the event in the smart contract ABI.
38+
* - args: Address-related arguments used to filter logs (e.g., recipient, origin).
39+
* - getEventType: Function to determine a custom "event type" (e.g., transferTo, transferFrom) based on the log contents and the user's address.
40+
*/
3241
type EventConfig = {
3342
eventName: string;
3443
args: Record<string, string | bigint>;
3544
getEventType: (log: any, userAddress: string) => string;
3645
};
3746

38-
export const useGetSmartWalletTransactions = () => {
47+
/**
48+
* Hook to retrieve smart wallet transactions by querying logs from the LedgerVault contract.
49+
* It also manages live updates when new events are detected in real time.
50+
*/
51+
export default function useGetSmartWalletTransactions() {
3952
const dispatch = useDispatch();
4053
const sessionData = useSelector((state: any) => state.auth.session);
4154
const blockchainEvents = useSelector((state: any) => state.blockchainEvents.events);
@@ -44,6 +57,13 @@ export const useGetSmartWalletTransactions = () => {
4457
const [loading, setLoading] = useState<boolean>(true);
4558
const [error, setError] = useState<string | null>(null);
4659

60+
/**
61+
* We define all event configurations that we want to capture.
62+
* Each configuration includes:
63+
* - The event name.
64+
* - An object "args" that indicates which fields in the log must match the user's address.
65+
* - A function to map the raw event to a custom "event type" (transferFrom, transferTo, deposit, etc.).
66+
*/
4767
const eventConfigs: EventConfig[] = [
4868
{
4969
eventName: 'FundsTransferred',
@@ -94,6 +114,10 @@ export const useGetSmartWalletTransactions = () => {
94114
},
95115
];
96116

117+
/**
118+
* Helper function to create the event signature needed by viem's parseAbiItem().
119+
* For example, an event signature looks like "event FundsTransferred(address indexed origin, address indexed recipient, ...)".
120+
*/
97121
const createEventSignature = (event: any): string => {
98122
if (!event || !event.name || !event.inputs) {
99123
throw new Error('Invalid event in ABI');
@@ -104,21 +128,30 @@ export const useGetSmartWalletTransactions = () => {
104128
return `event ${event.name}(${inputs})`;
105129
};
106130

131+
/**
132+
* Generate a dictionary (object) of parsed ABIs based on all unique event names in the eventConfigs.
133+
* a) Extract unique event names (e.g. FundsTransferred, FundsDeposited, etc.).
134+
* b) Find those events in the LedgerVaultAbi and parse them with parseAbiItem().
135+
*/
107136
const uniqueEventNames = Array.from(
108-
new Set(eventConfigs.map((config) => config.eventName))
137+
new Set(eventConfigs.map((config) => config.eventName)) // Removes duplicates
109138
);
110139

111140
const parsedAbis = uniqueEventNames.reduce((acc, eventName) => {
112141
const eventAbi = LedgerVaultAbi.abi.find(
113142
(item: any) => item.type === 'event' && item.name === eventName
114143
);
115144
if (!eventAbi) {
116-
throw new Error(`The event is not fund ${eventName} on the ABI`);
145+
throw new Error(`No definition found for event ${eventName} in the ABI`);
117146
}
118147
acc[eventName] = parseAbiItem(createEventSignature(eventAbi));
119148
return acc;
120149
}, {} as Record<string, ReturnType<typeof parseAbiItem>>);
121150

151+
/**
152+
* Function to fetch historical logs from the LedgerVault contract, using the user's address as a filter.
153+
* The logs are then sorted, processed, and stored in Redux.
154+
*/
122155
const fetchLogs = async () => {
123156
if (!sessionData?.address) {
124157
setLoading(false);
@@ -129,6 +162,7 @@ export const useGetSmartWalletTransactions = () => {
129162
setLoading(true);
130163
setError(null);
131164

165+
// a) Build an array of promises, one for each eventConfig, calling publicClient.getLogs.
132166
const promises = eventConfigs.map(({ eventName, args }) => {
133167
return publicClient.getLogs({
134168
address: GLOBAL_CONSTANTS.LEDGER_VAULT_ADDRESS as Address,
@@ -139,14 +173,18 @@ export const useGetSmartWalletTransactions = () => {
139173
});
140174
});
141175

176+
// b) Execute all the promises in parallel.
142177
const results = await Promise.all(promises);
143178

179+
// c) Flatten the array of arrays of logs into one array.
144180
const allLogs = results.flat();
145181

182+
// d) Fetch block timestamps for each log and map them to a structured format.
146183
const logsWithDetails = await Promise.all(
147184
allLogs.map(async (log: any) => {
148185
const block = await publicClient.getBlock({ blockNumber: log.blockNumber });
149186

187+
// Find the event config to determine the custom "eventType".
150188
const foundConfig = eventConfigs.find((c) => c.eventName === log.eventName);
151189
const eventType = foundConfig
152190
? foundConfig.getEventType(log, sessionData?.address)
@@ -162,21 +200,27 @@ export const useGetSmartWalletTransactions = () => {
162200
})
163201
);
164202

203+
// e) Sort logs by blockNumber descending, then by transactionIndex descending.
165204
const sortedLogs = logsWithDetails.sort((a, b) => {
166205
const blockDifference = Number(b.blockNumber) - Number(a.blockNumber);
167206
if (blockDifference !== 0) return blockDifference;
168207
return Number(b.transactionIndex) - Number(a.transactionIndex);
169208
});
170209

210+
// Finally, update Redux state with the sorted logs.
171211
dispatch(setTransactions(sortedLogs));
172212
} catch (err) {
173213
console.error('Error fetching logs:', err);
174-
setError(err instanceof Error ? err.message : 'An unknown error occurred');
214+
setError(err instanceof Error ? err.message : 'Unknown error');
175215
} finally {
176216
setLoading(false);
177217
}
178218
};
179219

220+
/**
221+
* useEffect hook that fires when the user's address changes, triggering the fetchLogs function.
222+
* If there's already a list of transactions, we can stop showing the loader.
223+
*/
180224
useEffect(() => {
181225
fetchLogs();
182226
if (transactions.length) {
@@ -185,10 +229,17 @@ export const useGetSmartWalletTransactions = () => {
185229
// eslint-disable-next-line react-hooks/exhaustive-deps
186230
}, [sessionData?.address]);
187231

232+
/**
233+
* Real-time events handling:
234+
* When a new event is picked up in `blockchainEvents`, we check if it's from the LedgerVault contract and
235+
* if it's one of the recognized event names. If yes, we process it similarly (fetch block info, add extra fields)
236+
* and then dispatch addTransaction to Redux.
237+
*/
188238
useEffect(() => {
189239
if (!blockchainEvents?.length) return;
190240

191241
blockchainEvents.forEach(async (log: any) => {
242+
// Filter out logs not from our contract or event names not in use.
192243
if (
193244
log.address !== GLOBAL_CONSTANTS.LEDGER_VAULT_ADDRESS ||
194245
!uniqueEventNames.includes(log.eventName)
@@ -220,5 +271,3 @@ export const useGetSmartWalletTransactions = () => {
220271

221272
return { transactions, loading, error };
222273
}
223-
224-
export default useGetSmartWalletTransactions;

0 commit comments

Comments
 (0)