@msquared/etherbase-client
Version:
React hooks for interacting with Etherbase smart contracts
116 lines (115 loc) • 5.07 kB
JavaScript
"use client";
import { useCallback, useState } from "react";
import { parseEther } from "viem";
import { useEtherbaseContext } from "../EtherbaseProvider";
import { EtherbaseSourceAbi } from "../abi/EtherbaseSource";
import useWebThree from "./useWebThree";
export default function useEtherbasePermissions({ sourceAddress, }) {
useEtherbaseContext();
const { publicClient, getWalletClient } = useWebThree();
const [canGrantRoles, setCanGrantRoles] = useState({});
const getWalletClientInternal = useCallback(async () => {
const walletClient = await getWalletClient();
if (!walletClient) {
throw new Error("Wallet client not found");
}
return walletClient;
}, [getWalletClient]);
const executeWriteBrowser = useCallback(async (writeFunctionName, args) => {
if (!publicClient) {
throw new Error("Public client not found");
}
const walletClient = await getWalletClientInternal();
// check the function name is valid
if (!Array.from(EtherbaseSourceAbi).find((f) => f.type === "function" && f.name === writeFunctionName)) {
throw new Error(`Invalid function name: ${writeFunctionName}`);
}
const hash = await walletClient.writeContract({
address: sourceAddress,
abi: EtherbaseSourceAbi,
// @ts-ignore
functionName: writeFunctionName,
// @ts-ignore
args,
gas: 7920027n,
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log("Execute write receipt:", receipt);
}, [sourceAddress, publicClient, getWalletClientInternal]);
const grantRoles = useCallback(async (walletAddress, roles) => {
await executeWriteBrowser("createWalletIdentity", [walletAddress, roles]);
}, [executeWriteBrowser]);
const revokeIdentity = useCallback(async (walletAddress) => {
await executeWriteBrowser("deleteIdentity", [walletAddress]);
}, [executeWriteBrowser]);
const grantRole = useCallback(async (walletAddress, role) => {
await executeWriteBrowser("grantRole", [walletAddress, role]);
}, [executeWriteBrowser]);
const revokeRole = useCallback(async (walletAddress, role) => {
await executeWriteBrowser("revokeRole", [walletAddress, role]);
}, [executeWriteBrowser]);
const deposit = useCallback(async (targetAddress, amount) => {
const walletClient = await getWalletClientInternal();
if (!walletClient.account) {
throw new Error("No account connected");
}
const hash = await walletClient.sendTransaction({
to: targetAddress,
value: parseEther(amount.toString()), // Convert amount to SOM
account: walletClient.account,
chain: walletClient.chain,
});
await publicClient?.waitForTransactionReceipt({ hash });
}, [publicClient, getWalletClientInternal]);
const fetchPermissions = useCallback(async () => {
if (!publicClient) {
throw new Error("Public client not found");
}
// Get owner address
const owner = await publicClient.readContract({
address: sourceAddress,
abi: EtherbaseSourceAbi,
functionName: "owner",
});
// Fetch all identities with roles
const identityViews = (await publicClient.readContract({
address: sourceAddress,
abi: EtherbaseSourceAbi,
functionName: "getAllIdentities",
}));
// Fetch balances for all addresses
const balancePromises = identityViews.map((identity) => publicClient.getBalance({
address: identity.walletAddress,
}));
const balances = await Promise.all(balancePromises);
// Get current user's wallet to check permissions
const accounts = (await window.ethereum?.request({
method: "eth_requestAccounts",
}));
const userWallet = accounts[0];
const userIdentity = identityViews.find((identity) => identity.walletAddress.toLowerCase() === userWallet.toLowerCase());
// For this example, we assume that only an identity with role 2 ("Grant") can grant permissions.
const roleChecks = Array.from({ length: 4 }, (_, i) => [
i,
userIdentity ? userIdentity.roles.includes(2) : false,
]);
setCanGrantRoles(Object.fromEntries(roleChecks));
const permissionsList = identityViews.map((identity, index) => ({
walletAddress: identity.walletAddress,
roles: identity.roles,
isOwner: identity.walletAddress.toLowerCase() ===
owner.toLowerCase(),
balance: balances[index],
}));
return permissionsList;
}, [publicClient, sourceAddress]);
return {
grantRoles,
revokeIdentity,
grantRole,
revokeRole,
deposit,
fetchPermissions,
canGrantRoles,
};
}