Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GSC button and toasts #431

Merged
merged 11 commits into from
Jun 25, 2024
Merged
6 changes: 4 additions & 2 deletions apps/council-sdk-starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
"setLockDuration": "tesm-node -r dotenv/config src/scripts/setLockDuration.ts",
"changeVaultStatus": "tesm-node -r dotenv/config src/scripts/changeVaultStatus.ts",
"getGSCMembers": "tesm-node -r dotenv/config ./src/scripts/getGSCMembers.ts",
"getProposalResults": "tesm-node -r dotenv/config src/scripts/getProposalResults.ts"
"getProposalResults": "tesm-node -r dotenv/config src/scripts/getProposalResults.ts",
"dev": "tesm-node -r dotenv/config src/scripts/dev.ts",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@delvtech/council-viem": "^0.0.3",
"viem": "^2.7.12"
"viem": "^2.16.2"
},
"devDependencies": {
"@council/tsconfig": "*",
Expand Down
2 changes: 1 addition & 1 deletion apps/council-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"react-hot-toast": "^2.4.1",
"react-loading-skeleton": "^3.4.0",
"react-tooltip": "^5.26.0",
"viem": "^2.8.16",
"viem": "^2.16.2",
"wagmi": "^2.5.11"
},
"devDependencies": {
Expand Down
27 changes: 22 additions & 5 deletions apps/council-ui/src/lib/rainbowKit.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
import {
injectedWallet,
metaMaskWallet,
rainbowWallet,
safeWallet,
walletConnectWallet,
} from "@rainbow-me/rainbowkit/wallets";
import { chains, transports } from "src/lib/wagmi";

const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID;
const { NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID, NODE_ENV } = process.env;
const wallets = [injectedWallet, safeWallet, rainbowWallet, metaMaskWallet];

if (!projectId) {
throw new Error(
"Missing WalletConnect project ID. Please set the NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID variable in your environment.",
// WalletConnect
if (NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID) {
wallets.push(walletConnectWallet);
} else if (NODE_ENV === "development") {
console.warn(
"Missing WalletConnect project ID. Set the NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID variable in your environment to use WalletConnect.",
);
}

export const wagmiConfig = getDefaultConfig({
appName: "Council",
projectId,
projectId: NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || "0",
chains: chains as any,
transports,
wallets: [
{
groupName: "Wallets",
wallets,
},
],
});
3 changes: 3 additions & 0 deletions apps/council-ui/src/ui/airdrop/hooks/useClaimAirdrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export function useClaimAirdrop(): {
const enabled = !!airdrop && !!claimableAmount && !!airdropData;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Claiming airdrop...",
successMessage: "Airdrop claimed!",
errorMessage: "Failed to claim airdrop.",
writeFn: ({ recipient }: ClaimOptions) => {
if (!enabled) {
throw new Error("No claimable airdrop found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export function useClaimAndDelegateAirdrop(): {
const enabled = !!airdrop && !!claimableAmount && !!airdropData;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Claiming and delegating airdrop...",
successMessage: "Airdrop claimed and delegated!",
errorMessage: "Failed to claim and delegate airdrop.",
writeFn: ({ delegate, recipient }: ClaimAndDelegateOptions) => {
if (!enabled) {
throw new Error("No claimable airdrop found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ export function makeTransactionErrorToast(
chainId: SupportedChainId,
): void {
toast.error(
<div className="flex gap-4 items-center">
<div className="flex items-center gap-4">
<div>
<p>{message}</p>
{hash && (
<p>
<a
href={makeEtherscanTransactionURL(hash, chainId)}
className="underline"
target="_blank"
rel="noreferrer"
>
View on Etherscan
</a>
Expand All @@ -25,9 +27,9 @@ export function makeTransactionErrorToast(
</div>
<button
onClick={() => toast.dismiss(hash)}
className="daisy-btn daisy-btn-circle daisy-btn-sm daisy-btn-ghost group"
className="group daisy-btn daisy-btn-circle daisy-btn-ghost daisy-btn-sm"
>
<XMarkIcon className="w-5 opacity-50 group-hover:opacity-100 transition-all" />
<XMarkIcon className="w-5 opacity-50 transition-all group-hover:opacity-100" />
</button>
</div>,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,25 @@ export function makeTransactionSubmittedToast(
chainId: SupportedChainId,
): void {
toast.loading(
<div className="flex gap-4 items-center">
<div className="flex items-center gap-4">
<div>
<p>{message}</p>
<p>
<a
href={makeEtherscanTransactionURL(hash, chainId)}
className="underline"
target="_blank"
rel="noreferrer"
>
View on Etherscan
</a>
</p>
</div>
<button
onClick={() => toast.dismiss(hash)}
className="daisy-btn daisy-btn-circle daisy-btn-sm daisy-btn-ghost group"
className="group daisy-btn daisy-btn-circle daisy-btn-ghost daisy-btn-sm"
>
<XMarkIcon className="w-5 opacity-50 group-hover:opacity-100 transition-all" />
<XMarkIcon className="w-5 opacity-50 transition-all group-hover:opacity-100" />
</button>
</div>,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,25 @@ export function makeTransactionSuccessToast(
chainId: SupportedChainId,
): void {
toast.success(
<div className="flex gap-4 items-center">
<div className="flex items-center gap-4">
<div>
<p>{message}</p>
<p>
<a
href={makeEtherscanTransactionURL(hash, chainId)}
className="underline"
target="_blank"
rel="noreferrer"
>
View on Etherscan
</a>
</p>
</div>
<button
onClick={() => toast.dismiss(hash)}
className="daisy-btn daisy-btn-circle daisy-btn-sm daisy-btn-ghost group"
className="group daisy-btn daisy-btn-circle daisy-btn-ghost daisy-btn-sm"
>
<XMarkIcon className="w-5 opacity-50 group-hover:opacity-100 transition-all" />
<XMarkIcon className="w-5 opacity-50 transition-all group-hover:opacity-100" />
</button>
</div>,
{
Expand Down
12 changes: 9 additions & 3 deletions apps/council-ui/src/ui/contract/hooks/useWrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ export function useWrite<
TFunction extends (...args: any[]) => Promise<`0x${string}`>,
>({
writeFn,
pendingMessage = "Transaction pending...",
successMessage = "Transaction successful!",
errorMessage = "Transaction failed.",
}: {
writeFn: TFunction;
pendingMessage?: string;
successMessage?: string;
errorMessage?: string;
}): {
write: TFunction;
status: MutationStatus;
Expand All @@ -38,21 +44,21 @@ export function useWrite<
const mutationFn = async (...args: Parameters<TFunction>) => {
const hash = await writeFn(...args);
setTransactionHash(hash);
makeTransactionSubmittedToast("Approving", hash, chainId);
makeTransactionSubmittedToast(pendingMessage, hash, chainId);
await publicClient?.waitForTransactionReceipt({ hash });
return hash;
};

const { mutate, status } = useMutation({
mutationFn: mutationFn as TFunction,
onSuccess: (hash) => {
makeTransactionSuccessToast("Successfully approved!", hash, chainId);
makeTransactionSuccessToast(successMessage, hash, chainId);
// All query cache can be invalidated. The SDK uses it's own cache which
// has built-in invalidation logic based on the methods called.
queryClient.invalidateQueries();
},
onError(error) {
makeTransactionErrorToast("Failed to approve", transactionHash, chainId);
makeTransactionErrorToast(errorMessage, transactionHash, chainId);
console.error(error);
},
});
Expand Down
8 changes: 4 additions & 4 deletions apps/council-ui/src/ui/vaults/gscVault/GSCVaultDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import { VaultDetails } from "src/ui/vaults/VaultDetails/VaultDetails";
import { VaultDetailsSkeleton } from "src/ui/vaults/VaultDetails/VaultDetailsSkeleton";

import { VaultHeader } from "src/ui/vaults/VaultHeader";
import {
getGscMembers,
GscMemberInfo,
} from "src/utils/gscVault/getGscMembers";
import { getGscMembers, GscMemberInfo } from "src/utils/gscVault/getGscMembers";
import { getGscStatus } from "src/utils/gscVault/getGscStatus";
import { GscStatus } from "src/utils/gscVault/types";
import { PublicClient } from "viem";
import { useAccount, usePublicClient } from "wagmi";
import { useJoinGsc } from "./hooks/useJoinGsc";
import { useReadGscVault } from "./hooks/useReadGscVault";

interface GscVaultDetailsProps {
Expand All @@ -31,6 +29,7 @@ export function GscVaultDetails({
vaultAddress,
account,
});
const { joinGsc, status: joinGscStatus } = useJoinGsc();

if (status === "error") {
return <ErrorMessage error={error} />;
Expand All @@ -52,6 +51,7 @@ export function GscVaultDetails({
accountMembership={data.gscStatus}
membersCount={data.members.length}
requiredVotingPower={data.requiredVotingPower}
onJoin={joinGsc}
/>
}
actions={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function GscMembershipStatusStat({
<div className="flex items-center gap-2">
{status}

{onJoin && (
{onJoin && status === "Eligible" && (
<button
className="daisy-btn daisy-btn-outline daisy-btn-primary daisy-btn-xs mt-1"
onClick={onJoin}
Expand Down
4 changes: 3 additions & 1 deletion apps/council-ui/src/ui/vaults/gscVault/GscVaultStatsRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ interface GSCVaultStatsRowProps {
accountMembership: GscStatus;
membersCount: number;
requiredVotingPower: bigint;
onJoin?: () => void;
}

export function GSCVaultsStatsRow({
accountMembership,
membersCount,
requiredVotingPower,
onJoin,
}: GSCVaultStatsRowProps): ReactElement {
return (
<div className="flex flex-wrap gap-4">
{accountMembership && (
<GscMembershipStatusStat status={accountMembership} />
<GscMembershipStatusStat status={accountMembership} onJoin={onJoin} />
)}

{membersCount >= 0 && (
Expand Down
3 changes: 3 additions & 0 deletions apps/council-ui/src/ui/vaults/gscVault/hooks/useJoinGsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function useJoinGsc(): {
const enabled = !!address && !!coreVoting && !!gscVault;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Joining GSC...",
successMessage: "GSC joined!",
errorMessage: "Failed to join GSC.",
writeFn: async () => {
if (!enabled) {
throw new Error("GSC Vault not found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export function useKickGscMember(): {
const enabled = !!gscVault;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Kicking GSC member...",
successMessage: "GSC member kicked!",
errorMessage: "Failed to kick GSC member.",
writeFn: async (account: `0x${string}`) => {
if (!enabled) {
throw new Error("GSC Vault not found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export function useApprove(): {
const enabled = !!council && !!address;

const { status, transactionHash, write } = useWrite({
pendingMessage: "Approving...",
successMessage: "Approved!",
errorMessage: "Failed to approve.",
writeFn: async (vaultAddress: `0x${string}`) => {
if (!enabled) {
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function useChangeDelegate(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Changing delegate...",
successMessage: "Delegate changed!",
errorMessage: "Failed to change delegate.",
writeFn: ({
newDelegate,
vaultAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export function useDeposit(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Depositing...",
successMessage: "Deposited!",
errorMessage: "Failed to deposit.",
writeFn: ({
vaultAddress,
amount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function useWithdraw(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Withdrawing...",
successMessage: "Withdrawn!",
errorMessage: "Failed to withdraw.",
writeFn: ({
vaultAddress,
amount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function useChangeDelegate(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Changing delegate...",
successMessage: "Delegate changed!",
errorMessage: "Failed to change delegate.",
writeFn: ({
newDelegate,
vaultAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export function useClaimGrant(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Claiming grant...",
successMessage: "Grant claimed!",
errorMessage: "Failed to claim grant.",
writeFn: (vaultAddress: `0x${string}`) => {
if (!enabled) {
throw new Error(
Expand Down
3 changes: 3 additions & 0 deletions apps/council-ui/src/ui/voting/hooks/useSubmitVote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export function useSubmitVote(): {
const enabled = !!council;

const { write, status, transactionHash } = useWrite({
pendingMessage: "Submitting vote...",
successMessage: "Vote submitted!",
errorMessage: "Failed to submit vote.",
writeFn: async ({
coreVotingAddress,
proposalId,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"prettier": "^3.2.5",
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-tailwindcss": "^0.5.11",
"viem": "^2.7.12",
"viem": "^2.16.2",
"wagmi": "^2.5.7"
},
"engines": {
Expand Down
Loading