0%

Web3 前端開發實戰-第五週作業實做筆記

紀錄使用Wagmi套件來取得Ens上的資料。
及串接friend.sol智能合約來加入好友及顯示好友卡片

要取得ENS上的名稱,可以快速透過Wagmi的useEnsName來取得Ens的名稱,條件是要透過使用useAccount的回傳值來取得錢包地址,再將地址帶入useEnsName。

1
2
3
4
5
6
7
const useEns = () => {
const { address } = useAccount();
const { data, isError, isLoading } = useEnsName({
address: address,
});
if (isError) return console.log(Error);
};

只是Wagmi他沒有原生的用Wagmi來拿到 ENS text record 的方法,
而回到底層Ethers要取得ENS text record的方式,還是都得透過Provider來取得ENS上的資料,而Wagmi的底層一樣是Ethers,所以還是要定義變數 provider = useProvider(),再透過 provider去取得所有ENS text Record資料(範例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { useProvider, useAccount, useEnsName } from "wagmi";

const useEns = () => {
const [retEnsData,setRetEnsData] = useState({}) // 將之後取得的資料存放入react的state裡頭
const { address } = useAccount(); // 當錢包連上時,可以使用useAccount來取得錢包地址
// 使用useEnsName可以取得data,data為錢包地址的EnsName
const { data, isError, isLoading } = useEnsName({
address: address,
});
const provider = useProvider(); // 由wagmi提供,回傳provider的相關資料,因為是ethers.js的provider,所以可以接著使用provider的相關函數。

if (isError) return console.log(Error);
};

export default useEns;

隨後先新增一非同步function,來使用provider的getResolver(解析器),可以透過console.log來得知,provider.getResolver()回傳內容

1
2
3
4
async function setEnsData(ensName: string) {
const resolver = await provider.getResolver(ensName);
console.log('resolver:',resolver);
}

新增useEffect來console.log看看useEnsName及provider.getResolver()回傳什麼內容

useEnsName回傳為錢包地址的ENS的名稱,provider.getResolver()則回傳一物件,包含:
{provider: AlchemyProvider(物件), name: ‘edhal.eth’, address: ‘0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41’, _resolvedAddress: undefined}

確定resolver帶入參數ensName,可以取得provider的資料後
便可以開始透過resolover來取得ENS資料並存入變數,最後在setRetEnsDat中帶入物件,把所有變數存入

最後透過 console.log(retEnsData) 便可以看到存入retEnsData的所有ENS資料

回到index.tsx檔中引入hooks

1
import useEnsData from "../hooks/useEns";

並且宣告變數useEnsData,暫時手動把地址或Ens網域帶入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const [domainName, setDomainName] = useState("");
const [finalDomainName, setFinalDomainName] = useState(domainName);
const [currentAddr, setCurrentAddr] = useState(undefined);
const [isConnect, setIsConnect] = useState(false);
const ensData: ensDataType = useEnsData(currentAddr, finalDomainName);
const { connect, connectors, error, isLoading, pendingConnector, isSuccess } =
useConnect();

useEffect(() => {
if (isSuccess) {
setCurrentAddr("0x08C5E50244FC58bc15Bf07BDAbb67453e624CB17");
setFinalDomainName("edhal.ens");
}
}, [isSuccess]);

若有_ensName就可以帶入setEnsData來宣告變數resolver = provider.getResolver(ensName),若確定可以取得解析器,則可以再透過解析器取得ENS資料。
各項ENS資料的取得方式不太一樣大部分為使用resolver.getText
只有ethAddress是provider.resolveName(ensName)
Avatar為resolver.getAvatar()
avatarUrl為 avatar?.url

最後將範本components中的Card複製到我們的components下,將Card置入index.tsx中,並把ensData資料帶入。

1
2
3
4
<main className={styles.main}>
<ConnectButton />
<Card cardData={ensData} cardBgColor={"#cdcdcd"} colors={[]}></Card>
</main>

成功取得ensData並置入卡片中

開始設計新增好友功能,以及好友清單…
透過智能合約addFriends.sol,來製作相關功能。

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
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.2;

contract Friends {
// show all friends list (address => address[])
mapping(address => address[]) public myFriends;
// all friend requests
mapping(address => address[]) public friendRequests;

// send friend request
function sendFriendRequest(address newFriend) external {
require(newFriend != msg.sender, "Cannot send friend request to yourself!");
friendRequests[newFriend].push(msg.sender);
}

// accept friend request
function acceptFriendRequest(uint256 index) external {
address newFriend = friendRequests[msg.sender][index];
require(newFriend != address(0), "No such friend request");
myFriends[msg.sender].push(newFriend);
myFriends[newFriend].push(msg.sender);
delete friendRequests[msg.sender][index];
}

// view friends count
function friendsCount(address addr) external view returns (uint256 len){
return myFriends[addr].length;
}
// view friend requests count
function friendRequestsCount(address addr) external view returns (uint256 len){
return friendRequests[addr].length;
}
}

先製作好友數,好友數可以透過friendCount這個function來取得

1
2
3
4
// view friends count
function friendsCount(address addr) external view returns (uint256 len){
return myFriends[addr].length;
}

使用Wagimi 的 useContractRead 來讀取智能合約上的函數-friendsCount

1
2
3
4
5
6
7
const { data, isError, isLoading } = useContractRead({
address: "0x0d522A759cd763e763f2758a813F4620b15a6190", // 已上傳至goerli
abi: addFriendsAbi, // 將abi 文件從remix上複製下來,貼到abi資料夾,建立addFrieds.json檔案,並將abi貼上,然後import進hooks內
functionName: "friendsCount", // 智能合約上的function 名稱
args: [address], // 輸入想要查詢的錢包
chainId: 5, // goerli chainID
});

這時候透過console.log(data)來檢查後,發線回傳的值為Hex值,必須要轉譯才能成為十進位數字,透過ethers.js官方文件內搜尋到如何轉譯

1
2
3
console.log(ethers.utils.hexDataLength(data))
// 透過useContractRead取得data後,將data透過ethers.utils.hexDataLength(data)
// 則可取得正確十進位Number

Welcome to my other publishing channels