Skip to content

Commit

Permalink
feat: request addressbook for address lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
schmanu committed Jun 9, 2024
1 parent 101cee1 commit 876d991
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 51 deletions.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"prepare": "husky install",
"generate-types": "typechain --target=ethers-v5 --out-dir src/contracts './node_modules/@openzeppelin/contracts/build/contracts/ERC20.json' './customabis/ERC721.json' './node_modules/@openzeppelin/contracts/build/contracts/ERC1155.json' './node_modules/@openzeppelin/contracts/build/contracts/ERC165.json'",
"postinstall": "yarn generate-types",
"serve": "npx -y serve build -p 3001"
"serve": "npx -y serve build -p 3001",
"update-safe-apps-sdk": "yarn add @safe-global/safe-apps-provider@latest @safe-global/safe-apps-react-sdk@latest @safe-global/safe-apps-sdk"
},
"dependencies": {
"@emotion/cache": "^11.10.1",
Expand All @@ -29,8 +30,8 @@
"@openzeppelin/contracts": "^5.0.2",
"@reduxjs/toolkit": "^1.9.5",
"@safe-global/safe-apps-provider": "^0.18.2",
"@safe-global/safe-apps-react-sdk": "^4.6.4",
"@safe-global/safe-apps-sdk": "^8.1.0",
"@safe-global/safe-apps-react-sdk": "^4.7.1",
"@safe-global/safe-apps-sdk": "^9.0.0",
"@safe-global/safe-gateway-typescript-sdk": "^3.13.2",
"@safe-global/safe-react-components": "2.0.5",
"@types/jest": "^29.5.12",
Expand Down
2 changes: 2 additions & 0 deletions src/AppInitializer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { useSafeAppsSDK } from "@safe-global/safe-apps-react-sdk";

import { useLoadAssets, useLoadCollectibles } from "./hooks/useBalances";
import { useLoadChains } from "./hooks/useChains";
import { useLoadAddressbook } from "./hooks/useLoadAddressbook";

export const AppInitializer = () => {
const { safe } = useSafeAppsSDK();
useLoadChains();
useLoadAssets(safe);
useLoadCollectibles(safe);
useLoadAddressbook();
return <></>;
};
12 changes: 7 additions & 5 deletions src/hooks/useBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ const useCollectibleBalances = (safeAddress?: string, chainId?: number) => {
});

// We load up to 10 pages of NFTs for performance reasons
if (data && data.length > 0) {
const totalPages = Math.max(COLLECTIBLE_MAX_PAGES, Math.ceil(data[0].count / COLLECTIBLE_LIMIT));
if (totalPages > size) {
setSize(Math.ceil(data[0].count / COLLECTIBLE_LIMIT));
useEffect(() => {
if (data && data.length > 0) {
const totalPages = Math.max(COLLECTIBLE_MAX_PAGES, Math.ceil(data[0].count / COLLECTIBLE_LIMIT));
if (totalPages > size && size !== COLLECTIBLE_LIMIT) {
setSize(Math.ceil(data[0].count / COLLECTIBLE_LIMIT));
}
}
}
}, [data, setSize, size]);

const flatData = useMemo(() => {
if (data === undefined) {
Expand Down
24 changes: 21 additions & 3 deletions src/hooks/useEnsResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { SafeAppProvider } from "@safe-global/safe-apps-provider";
import { useSafeAppsSDK } from "@safe-global/safe-apps-react-sdk";
import { ethers } from "ethers";
import { useCallback, useMemo } from "react";
import { selectAddressbook } from "src/stores/slices/addressbookSlice";
import { useAppSelector } from "src/stores/store";

export interface EnsResolver {
/**
Expand Down Expand Up @@ -35,6 +37,23 @@ export const useEnsResolver: () => EnsResolver = () => {

const lookupCache = useMemo(() => new Map<string, string | null>(), []);

const addressbook = useAppSelector(selectAddressbook);

const lookupAddress = useCallback(
async (address: string) => {
const nameFromAb = addressbook.find((abItem) => {
return abItem.address.toLowerCase() === address.toLowerCase() && abItem.chainId === safe.chainId.toString();
})?.name;

if (nameFromAb) {
return Promise.resolve(nameFromAb);
}

return await web3Provider.lookupAddress(address);
},
[addressbook, safe.chainId, web3Provider],
);

const cachedResolveName = useCallback(
async (ensName: string) => {
const cachedAddress = resolveCache.get(ensName);
Expand All @@ -50,14 +69,13 @@ export const useEnsResolver: () => EnsResolver = () => {
const cachedLookupAddress = useCallback(
async (address: string) => {
const cachedAddress = lookupCache.get(address);
const resolvedEnsName =
typeof cachedAddress !== "undefined" ? cachedAddress : await web3Provider.lookupAddress(address);
const resolvedEnsName = typeof cachedAddress !== "undefined" ? cachedAddress : await lookupAddress(address);
if (!lookupCache.has(address)) {
lookupCache.set(address, resolvedEnsName);
}
return resolvedEnsName;
},
[lookupCache, web3Provider],
[lookupAddress, lookupCache],
);

const isEnsEnabled = useCallback(async () => {
Expand Down
32 changes: 32 additions & 0 deletions src/hooks/useLoadAddressbook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useSafeAppsSDK } from "@safe-global/safe-apps-react-sdk";
import { useCallback, useEffect } from "react";
import { setAddressbook } from "src/stores/slices/addressbookSlice";
import { useAppDispatch } from "src/stores/store";

/**
* This hook requests the address book and stores it if the permission is granted.
*/
export const useLoadAddressbook = () => {
const { sdk } = useSafeAppsSDK();
const dispatch = useAppDispatch();

const request = useCallback(async () => sdk.safe.requestAddressBook(), [sdk.safe]);

useEffect(() => {
let isMounted = true;

request()
.then((ab) => {
if (isMounted) {
dispatch(setAddressbook(ab));
}
})
.catch(() => {
console.error("Addressbook request was rejected.");
});

return () => {
isMounted = false;
};
}, [request, dispatch]);
};
33 changes: 33 additions & 0 deletions src/stores/slices/addressbookSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

import { RootState } from "../store";

export type AddressbookEntry = {
address: string;
chainId: string;
name: string;
};

export interface AddressbookState {
namedAddresses: AddressbookEntry[];
}

const initialState: AddressbookState = {
namedAddresses: [],
};

export const addressbookSlice = createSlice({
name: "addressbook",
initialState,
reducers: {
setAddressbook: (state, action: PayloadAction<AddressbookEntry[]>) => {
state.namedAddresses = action.payload;
},
},
});

export const { setAddressbook } = addressbookSlice.actions;

export default addressbookSlice.reducer;

export const selectAddressbook = ({ addressbook }: RootState) => addressbook.namedAddresses;
2 changes: 2 additions & 0 deletions src/stores/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { setupListeners } from "@reduxjs/toolkit/dist/query";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";

import addressBookReducer from "./slices/addressbookSlice";
import assetBalanceReducer from "./slices/assetBalanceSlice";
import collectiblesReducer from "./slices/collectiblesSlice";
import csvReducer from "./slices/csvEditorSlice";
Expand All @@ -27,6 +28,7 @@ export const store = configureStore({
networks: networksReducer,
collectibles: collectiblesReducer,
assetBalance: assetBalanceReducer,
addressbook: addressBookReducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(listenerMiddlewareInstance.middleware),
});
Expand Down
45 changes: 5 additions & 40 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7"
integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==

"@adraffy/[email protected]":
version "1.9.4"
resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.4.tgz#aae21cb858bbb0411949d5b7b3051f4209043f62"
integrity sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==

"@ampproject/remapping@^2.2.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
Expand Down Expand Up @@ -2779,28 +2774,12 @@
"@safe-global/safe-apps-sdk" "^9.0.0"
events "^3.3.0"

"@safe-global/safe-apps-react-sdk@^4.6.4":
version "4.6.4"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-react-sdk/-/safe-apps-react-sdk-4.6.4.tgz#7163cb10eb6af82489d199002cc94e0e58b41e97"
integrity sha512-QFrKZldFw0JY5jD/B6X2TzArgNuyWALpTjJair3ooYwRU5ZE6lWJ6W8FQg7XOogfRYoXbDhAtBXoGrX/BHbM4Q==
dependencies:
"@safe-global/safe-apps-sdk" "7.10.0"

"@safe-global/[email protected]":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-sdk/-/safe-apps-sdk-7.10.0.tgz#e75fc581126f27c52ec2601da51bca5eb99b61f4"
integrity sha512-is0QAHVoGkP06YfOPcp4X3/YUEA3wRdgFUyKZ4rT47uOEnzxA9Sm8BFJrIZqZOjjqC+aJXRMF0cE2qucS953rg==
"@safe-global/safe-apps-react-sdk@^4.7.1":
version "4.7.1"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-react-sdk/-/safe-apps-react-sdk-4.7.1.tgz#3df442496edee9778ef7217ee78a031cac0e1701"
integrity sha512-sbVroIUxYy9XOzN7769wCTR2ytk6LMp8ECmFlc+d23/7EHOuX5Yw8Si+tf5SYbYhS9ygdSsMcVRQeNvKOhZnEw==
dependencies:
"@safe-global/safe-gateway-typescript-sdk" "^3.5.3"
ethers "^5.7.2"

"@safe-global/safe-apps-sdk@^8.1.0":
version "8.1.0"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-sdk/-/safe-apps-sdk-8.1.0.tgz#d1d0c69cd2bf4eef8a79c5d677d16971926aa64a"
integrity sha512-XJbEPuaVc7b9n23MqlF6c+ToYIS3f7P2Sel8f3cSBQ9WORE4xrSuvhMpK9fDSFqJ7by/brc+rmJR/5HViRr0/w==
dependencies:
"@safe-global/safe-gateway-typescript-sdk" "^3.5.3"
viem "^1.0.0"
"@safe-global/safe-apps-sdk" "^9.0.0"

"@safe-global/safe-apps-sdk@^9.0.0":
version "9.0.0"
Expand Down Expand Up @@ -12549,20 +12528,6 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==

viem@^1.0.0:
version "1.18.2"
resolved "https://registry.yarnpkg.com/viem/-/viem-1.18.2.tgz#2e9135d593e7a77b6b5a8cbd1800521ffda3b23c"
integrity sha512-ifobXCKwzztmjHbHowAWqTASO6tAqF6udKB9ONXkJQU1cmt830MABiMwJGtTO9Gb9ION1N+324G7nHDbpPn4wg==
dependencies:
"@adraffy/ens-normalize" "1.9.4"
"@noble/curves" "1.2.0"
"@noble/hashes" "1.3.2"
"@scure/bip32" "1.3.2"
"@scure/bip39" "1.2.1"
abitype "0.9.8"
isows "1.0.3"
ws "8.13.0"

viem@^1.6.0:
version "1.21.4"
resolved "https://registry.yarnpkg.com/viem/-/viem-1.21.4.tgz#883760e9222540a5a7e0339809202b45fe6a842d"
Expand Down

0 comments on commit 876d991

Please sign in to comment.