()
| 139 | }; |
| 140 | |
| 141 | export const GetTokens = () => { |
| 142 | const [tokens, setTokens] = useAtom(globalTokensAtom); |
| 143 | const [loading, setLoading] = useState(false); |
| 144 | const [error, setError] = useState(''); |
| 145 | const [checkedRecords, setCheckedRecords] = useAtom(checkedTokensAtom); |
| 146 | |
| 147 | const { address, isConnected, chain } = useAccount(); |
| 148 | |
| 149 | const fetchData = useCallback(async () => { |
| 150 | setLoading(true); |
| 151 | try { |
| 152 | setError(''); |
| 153 | const newTokens = await httpFetchTokens( |
| 154 | chain?.id as number, |
| 155 | address as string, |
| 156 | ); |
| 157 | setTokens((newTokens as any).data.erc20s); |
| 158 | } catch (error) { |
| 159 | const message = error instanceof Error ? error.message : String(error); |
| 160 | setError(`Chain ${chain?.id}: ${message}`); |
| 161 | } |
| 162 | setLoading(false); |
| 163 | }, [address, chain, setTokens]); |
| 164 | |
| 165 | useEffect(() => { |
| 166 | if (address) { |
| 167 | // eslint-disable-next-line react-hooks/set-state-in-effect |
| 168 | fetchData(); |
| 169 | setCheckedRecords({}); |
| 170 | } |
| 171 | }, [address, chain, fetchData, setCheckedRecords]); |
| 172 | |
| 173 | useEffect(() => { |
| 174 | if (!isConnected) { |
| 175 | setTokens([]); |
| 176 | setCheckedRecords({}); |
| 177 | } |
| 178 | }, [isConnected, setTokens, setCheckedRecords]); |
| 179 | |
| 180 | const checkedCount = Object.values(checkedRecords).filter( |
| 181 | (r) => r.isChecked, |
| 182 | ).length; |
| 183 | const allChecked = tokens.length > 0 && checkedCount === tokens.length; |
| 184 | |
| 185 | const toggleAll = () => { |
| 186 | if (allChecked) { |
| 187 | setCheckedRecords({}); |
| 188 | } else { |
| 189 | setCheckedRecords( |
| 190 | Object.fromEntries( |
| 191 | tokens.map((t) => [t.contract_address, { isChecked: true }]), |
| 192 | ), |
| 193 | ); |
| 194 | } |
| 195 | }; |
| 196 | |
| 197 | if (loading) { |
| 198 | return ( |
nothing calls this directly
no test coverage detected