@sodax/dapp-kit 1.0.2-beta → 1.0.4-beta-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sodax/dapp-kit",
3
3
  "license": "MIT",
4
- "version": "1.0.2-beta",
4
+ "version": "1.0.4-beta-rc1",
5
5
  "description": "dapp-kit of New World",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "viem": "2.29.2",
19
- "@sodax/types": "1.0.2-beta",
20
- "@sodax/sdk": "1.0.2-beta"
19
+ "@sodax/sdk": "1.0.4-beta-rc1",
20
+ "@sodax/types": "1.0.4-beta-rc1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/react": "19.0.8",
@@ -7,5 +7,6 @@ export * from './useReservesData';
7
7
  export * from './useMMAllowance';
8
8
  export * from './useMMApprove';
9
9
  export * from './useAToken';
10
+ export * from './useATokensBalances';
10
11
  export * from './useReservesUsdFormat';
11
12
  export * from './useUserFormattedSummary';
@@ -0,0 +1,87 @@
1
+ // packages/dapp-kit/src/hooks/mm/useATokens.ts
2
+ import { isAddress, type Address } from 'viem';
3
+ import { useQuery, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
4
+ import { useSodaxContext } from '../shared/useSodaxContext';
5
+ import type { SpokeProvider } from '@sodax/sdk';
6
+ import { deriveUserWalletAddress } from '@sodax/sdk';
7
+
8
+ export type UseATokensBalancesParams = {
9
+ aTokens: readonly Address[];
10
+ spokeProvider?: SpokeProvider;
11
+ userAddress?: string;
12
+ queryOptions?: UseQueryOptions<Map<Address, bigint>, Error>;
13
+ };
14
+
15
+ /**
16
+ * React hook to fetch and cache aToken balances for multiple aToken addresses in a single multicall.
17
+ *
18
+ * Accepts an array of aToken addresses, a spoke provider, and user address. The hook derives the user's
19
+ * hub wallet address and then fetches balanceOf for each aToken in a single multicall. Returns a Map
20
+ * of aToken address to balance, with querying/caching powered by React Query. This hook uses viem's
21
+ * multicall to batch all requests into a single RPC call for better performance.
22
+ *
23
+ * @param {UseATokensBalancesParams} params - Required params object:
24
+ * @property {readonly Address[]} aTokens - Array of aToken contract addresses to query balances for.
25
+ * @property {SpokeProvider} spokeProvider - The spoke provider to derive hub wallet address from.
26
+ * @property {string} userAddress - User's wallet address on the spoke chain.
27
+ * @property {UseQueryOptions<Map<Address, bigint>, Error>} queryOptions - React Query options to control query (e.g., staleTime, refetch, etc.).
28
+ *
29
+ * @returns {UseQueryResult<Map<Address, bigint>, Error>} React Query result object:
30
+ * - data: Map of aToken address to balance, if available
31
+ * - isLoading: Boolean loading state
32
+ * - error: Error, if API call fails
33
+ *
34
+ * @example
35
+ * const { data: aTokenBalances, isLoading, error } = useATokensBalances({
36
+ * aTokens: [aToken1, aToken2, aToken3],
37
+ * spokeProvider,
38
+ * userAddress: '0x...',
39
+ * queryOptions: {}
40
+ * });
41
+ * const aToken1Balance = aTokenBalances?.get(aToken1);
42
+ */
43
+ export function useATokensBalances({
44
+ aTokens,
45
+ spokeProvider,
46
+ userAddress,
47
+ queryOptions,
48
+ }: UseATokensBalancesParams): UseQueryResult<Map<Address, bigint>, Error> {
49
+ const { sodax } = useSodaxContext();
50
+ const defaultQueryOptions = {
51
+ queryKey: ['mm', 'aTokensBalances', aTokens, spokeProvider?.chainConfig.chain.id, userAddress],
52
+ enabled: aTokens.length > 0 && aTokens.every(token => isAddress(token)) && !!spokeProvider && !!userAddress,
53
+ };
54
+ queryOptions = {
55
+ ...defaultQueryOptions,
56
+ ...queryOptions, // override default query options if provided
57
+ };
58
+
59
+ return useQuery({
60
+ ...queryOptions,
61
+ queryFn: async () => {
62
+ if (aTokens.length === 0) {
63
+ return new Map();
64
+ }
65
+
66
+ if (!spokeProvider || !userAddress) {
67
+ throw new Error('Spoke provider and user address are required');
68
+ }
69
+
70
+ // Validate all addresses
71
+ for (const aToken of aTokens) {
72
+ if (!isAddress(aToken)) {
73
+ throw new Error(`Invalid aToken address: ${aToken}`);
74
+ }
75
+ }
76
+
77
+ // Derive user's hub wallet address
78
+ const hubWalletAddress = await deriveUserWalletAddress(
79
+ sodax.hubProvider,
80
+ spokeProvider.chainConfig.chain.id,
81
+ userAddress,
82
+ );
83
+
84
+ return await sodax.moneyMarket.data.getATokensBalances(aTokens, hubWalletAddress);
85
+ },
86
+ });
87
+ }