Skip to content

Commit

Permalink
Merge pull request #725 from hats-finance/feature/airdrop
Browse files Browse the repository at this point in the history
Feature/airdrop
  • Loading branch information
shayzluf authored Jul 24, 2024
2 parents b7873d1 + 473bccc commit ce1ebe8
Show file tree
Hide file tree
Showing 45 changed files with 591 additions and 162 deletions.
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hats.finance/shared",
"version": "1.1.107",
"version": "1.1.109",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
11 changes: 10 additions & 1 deletion packages/shared/src/config/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export interface IChainConfiguration {
arbitratorContract: string;
paymentSplitterFactory: string;
rewardController?: string;
govMultisig?: string;
govMultisig: string;
growthMultisig: string;
whitelistedReviewers?: string[];
chain: wagmiChains.Chain;
subgraph: string;
Expand All @@ -53,6 +54,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/2cbCwzhBbKkdpXtuNYkG5ch5dJDNAnTmeRhePDpkR4JV",
coingeckoId: "ethereum",
govMultisig: "0xBA5Ddb6Af728F01E91D77D12073548D823f6D1ef",
growthMultisig: "0x53E9152417EcD338E7e85cCFBc1F5eDA053C910c",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
uniswapSubgraph: "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3",
paymentSplitterFactory: "0x0aA1464dB005857Db8FC3E0470d306FB9E54b908",
Expand All @@ -71,6 +73,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/6q8vE8znoVRd2AqdGcgaF7j99Gtrrki4HwYDVMK8qaCf",
coingeckoId: undefined,
govMultisig: "0xFA6579F3Bb1793eFaB541de06763b872E11bfCBe",
growthMultisig: "0xA5BA173Cf84D532FE368690D37eff843678E0bFF",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
uniswapSubgraph: undefined,
paymentSplitterFactory: "0x09959581544511916A80185FFe3De3Df11D623D7",
Expand All @@ -89,6 +92,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/vMkoKYXdwa5dww7FD6ra9EdLgA2E3hmz2Q3BxF8DEAW",
coingeckoId: "optimistic-ethereum",
govMultisig: "0x5A6910528b047d3371970dF764ba4046b7DfAd6a",
growthMultisig: "0x862966C9e09a3058DF47a29d30a429565E176D8B",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
uniswapSubgraph: "https://api.thegraph.com/subgraphs/name/ianlapham/optimism-post-regenesis",
paymentSplitterFactory: "0x028A7C6873dFA8357c9dcF9C9d76EF2abb66256E",
Expand All @@ -107,6 +111,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/GXUgxLXF1Ad2dmmxF5J24JUGKj6ko22t6esPkdLhKAz4",
coingeckoId: "arbitrum-one",
govMultisig: "0x022B95b4c02bbA85604506E6114485615b0aD09A",
growthMultisig: "0xBCa8856B5995092Df3f100436b0Ee8056A2E065a",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
uniswapSubgraph: "https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-minimal",
paymentSplitterFactory: "0x028A7C6873dFA8357c9dcF9C9d76EF2abb66256E",
Expand All @@ -125,6 +130,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/GH7Cv6XKuWYTMUrXcAfcqRmJRERPxFThyHtz1AeNCZQa",
coingeckoId: "polygon-pos",
govMultisig: "0xa5c6d757ca69c92eea05b22924d9774658e10c62",
growthMultisig: "0xa5c6d757ca69c92eea05b22924d9774658e10c62",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
uniswapSubgraph: "https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon",
paymentSplitterFactory: "0xadd155731473A9501881234A865FF79668F1B6cF",
Expand All @@ -143,6 +149,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/HPwWDxud8fSarSK8XfwSxcTkyKMQf7RwFmS7kPmTX9dD",
coingeckoId: "xdai",
govMultisig: "0xE650ba24115AE0260d8f723F89603DaF63b496cA",
growthMultisig: "0xE650ba24115AE0260d8f723F89603DaF63b496cA",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
paymentSplitterFactory: "0x878Cab06E6f4a85D90E5f236d326a41Ef6f44F9f",
// infuraKey: "polygon-mainnet",
Expand All @@ -160,6 +167,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
"https://gateway-arbitrum.network.thegraph.com/api/0ed4473ee53352068095380ea517339c/subgraphs/id/4TWs2Y9gCpUPh1vMSogFuRbBqsUzE4FXgYFAoJmcx9Fc",
coingeckoId: "binance-smart-chain",
govMultisig: "0xbFBC2Ab80bD0A12258db952739238e403Be01ece",
growthMultisig: "0x6C4654Fe6Efe491D601ca2ff1842e179A5612c38",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
paymentSplitterFactory: "0xadd155731473A9501881234A865FF79668F1B6cF",
provider: "https://damp-dawn-scion.bsc.quiknode.pro/fa80c7f866eee193fef38c879e941fcb02e98dfb",
Expand All @@ -174,6 +182,7 @@ export const ChainsConfig: { [index: number]: IChainConfiguration } = {
subgraph: "https://api.goldsky.com/api/public/project_clx0j1z1v44iz01wb4qol83tv/subgraphs/hats_oasis/0.0.1/gn",
coingeckoId: "oasis-sapphire",
govMultisig: "0xf2935671015c896D5E1fE4c97caF111F5eEe2b3c",
growthMultisig: "0xf2935671015c896D5E1fE4c97caF111F5eEe2b3c",
whitelistedReviewers: ["0x5b7B59862447Cf3dE479C8166cc2784cbf8e53D6"],
paymentSplitterFactory: "0xe198CBb727758b9Ad38a12E1ad475a843e5e730F",
provider: "https://sapphire.oasis.io",
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/types/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ export interface ICreateVaultOnChainCall {
isTokenLockRevocable: boolean; // New in v3
}

export type IAddressRoleInVault = "gov" | "committee" | "committee-multisig" | "reviewer" | "none";
export type IAddressRoleInVault = "gov" | "growth" | "committee" | "committee-multisig" | "reviewer" | "none";

export interface IVaultStatusData {
descriptionHash: string;
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/src/utils/vaults.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,18 +246,21 @@ export const getAddressRoleOnVault = async (
if (!address || !vaultCommittee || !vaultChainId) return "none";

const govMultisig = ChainsConfig[Number(vaultChainId)].govMultisig;
const growthMultisig = ChainsConfig[Number(vaultChainId)].growthMultisig;
const committeeMultisig = vaultCommittee;

const isCommitteeMultisig = committeeMultisig === address;
const isCommitteeMultisigMember = await isAddressAMultisigMember(committeeMultisig, address, vaultChainId);
const isGovMember = await isAddressAMultisigMember(govMultisig, address, vaultChainId);
const isGrowthMember = await isAddressAMultisigMember(growthMultisig, address, vaultChainId);
const whitelistedReviewers = ChainsConfig[Number(vaultChainId)].whitelistedReviewers ?? [];
const whitelistedReviewersLowerCase = whitelistedReviewers.map((reviewer) => reviewer.toLowerCase());
const isWhiteListedEditor = whitelistedReviewersLowerCase.includes(address.toLowerCase());

if (isCommitteeMultisigMember) return "committee";
if (isCommitteeMultisig) return "committee-multisig";
if (isGovMember) return "gov";
if (isGrowthMember) return "growth";
if (isWhiteListedEditor) return "reviewer";
return "none";
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { StyledHackerProfileImage } from "./styles";

export type IHackerProfileImageProps = {
hackerProfile?: IHackerProfile;
size?: "xxsmall" | "xsmall" | "small" | "medium" | "large";
size?: "xxsmall" | "xsmall" | "small" | "medium" | "large" | "fit";
noMargin?: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@ const getSize = (size: IHackerProfileImageProps["size"]) => {

export const StyledHackerProfileImage = styled.div<{ size: IHackerProfileImageProps["size"]; noMargin: boolean }>(
({ size, noMargin }) => css`
width: ${getSpacing(getSize(size))};
height: ${getSpacing(getSize(size))};
margin-bottom: ${noMargin ? 0 : getSpacing(4)};
width: ${size === "fit" ? "100%" : getSpacing(getSize(size))};
height: ${size === "fit" ? "100%" : getSpacing(getSize(size))};
margin-bottom: ${noMargin || size === "fit" ? 0 : getSpacing(4)};
${size === "fit" &&
css`
display: flex;
justify-content: center;
align-items: center;
`}
.avatar-preview {
width: 100%;
height: 100%;
object-fit: contain;
object-fit: ${size === "fit" ? "cover" : "contain"};
border-radius: 100px;
}
Expand Down
17 changes: 10 additions & 7 deletions packages/web/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import CloseIcon from "@mui/icons-material/Close";
import MenuIcon from "@mui/icons-material/Menu";
import { toggleMenu } from "actions/index";
import { Button, HackerProfileImage, SafePeriodBar, WalletButton, WhereverWidget } from "components";
import { isAirdropEnabled } from "constants/constants";
import useModal from "hooks/useModal";
import { RoutePaths } from "navigation";
import { CreateProfileFormModal } from "pages/HackerProfile/components";
Expand Down Expand Up @@ -57,7 +58,7 @@ const Header = () => {
}

function handleGoToMyWallet() {
if (!account || !createdProfile) return;
if (!account) return;
navigate(`${RoutePaths.myWallet}`);
}

Expand All @@ -75,11 +76,13 @@ const Header = () => {
<h1 className="page-title">{getPageTitle()}</h1>

<div className="buttons">
<div className="airdrop-button">
<Button size="big" noRadius styleType="outlined" onClick={handleGoToAirdrop}>
{t("airdrop")}
</Button>
</div>
{isAirdropEnabled && (
<div className="airdrop-button">
<Button size="big" noRadius styleType="outlined" onClick={handleGoToAirdrop}>
{t("airdrop")}
</Button>
</div>
)}

<div className="profile-button">
{isSafeAddress !== undefined && !isSafeAddress && account && !isLoadingProfile && (
Expand All @@ -103,7 +106,7 @@ const Header = () => {
)}
</div>

{account && createdProfile && (
{isAirdropEnabled && account && (
<Button size="big" noRadius styleType="outlined" onClick={handleGoToMyWallet}>
{t("Header.myWallet")}
</Button>
Expand Down
5 changes: 4 additions & 1 deletion packages/web/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface ModalProps {
removeHorizontalPadding?: boolean;
capitalizeTitle?: boolean;
disableClose?: boolean;
hideCloseIcon?: boolean;
disableOnOverlayClose?: boolean;
overflowVisible?: boolean;
removeAnimation?: boolean;
Expand All @@ -35,6 +36,7 @@ export function Modal({
capitalizeTitle = false,
overflowVisible = false,
removeAnimation = false,
hideCloseIcon = false,
}: ModalProps) {
const [localShowModal, setLocalShowModal] = useState(isShowing);
// const inTransaction = useTransactions().transactions.some((tx) => !tx.receipt);
Expand Down Expand Up @@ -80,6 +82,7 @@ export function Modal({
removeHorizontalPadding={removeHorizontalPadding}
overflowVisible={overflowVisible}
capitalizeTitle={capitalizeTitle}
hideCloseIcon={hideCloseIcon}
>
<div className="header">
<div className="title">
Expand All @@ -91,7 +94,7 @@ export function Modal({
{titleIcon && typeof titleIcon === "string" ? <img src={titleIcon} alt="icon" /> : titleIcon}
<span>{title && <span>{title}</span>}</span>
</div>
{!disableClose && (
{!disableClose && !hideCloseIcon && (
<button disabled={inTransaction} type="button" className="close" onClick={handleOnHide}>
<span aria-hidden="true">&times;</span>
</button>
Expand Down
7 changes: 7 additions & 0 deletions packages/web/src/components/Modal/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const ModalContainer = styled.div<{
withIcon: boolean;
disableClose: boolean;
overflowVisible: boolean;
hideCloseIcon: boolean;
}>(
({
withTitleDivider,
Expand All @@ -52,6 +53,7 @@ export const ModalContainer = styled.div<{
disableClose,
removeTopPadding,
overflowVisible,
hideCloseIcon,
}) => css`
position: relative;
max-width: calc(100vw - ${getSpacing(6)});
Expand All @@ -72,6 +74,11 @@ export const ModalContainer = styled.div<{
align-items: center;
padding: ${getSpacing(1)} ${getSpacing(4)};
${hideCloseIcon &&
css`
padding: ${getSpacing(3)} ${getSpacing(4)};
`}
${withIcon &&
css`
padding: ${getSpacing(2)} ${getSpacing(4)} ${getSpacing(1)};
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/components/Sidebar/NavLinks/NavLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ReactComponent as VaultEditorIcon } from "assets/icons/custom/vault_edi
import { utils } from "ethers";
import { useVaults } from "hooks/subgraph/vaults/useVaults";
import { useIsGovMember } from "hooks/useIsGovMember";
import { useIsGrowthMember } from "hooks/useIsGrowthMember";
import { useIsReviewer } from "hooks/useIsReviewer";
import useOnClickOutside from "hooks/useOnClickOutside";
import { RoutePaths } from "navigation";
Expand All @@ -33,6 +34,7 @@ export default function NavLinks() {

const isGovMember = useIsGovMember();
const isReviewer = useIsReviewer();
const isGrowthMember = useIsGrowthMember();
const [isInvitedToPrivateAudits, setIsInvitedToPrivateAudits] = useState(false);
const [isCommitteeAddress, setIsCommitteeAddress] = useState(false);
const [showCommitteeToolsSubroutes, setshowCommitteeToolsSubroutes] = useState(false);
Expand Down Expand Up @@ -105,7 +107,7 @@ export default function NavLinks() {
<p className="collapsed">{t("competitions")}</p>
</StyledNavLink>
<StyledNavLink
hidden={!isInvitedToPrivateAudits && !isGovMember && !isReviewer}
hidden={!isInvitedToPrivateAudits && !isGovMember && !isReviewer && !isGrowthMember}
className="audits"
to={`${HoneypotsRoutePaths.privateAudits}`}
onClick={handleClick}
Expand All @@ -131,7 +133,7 @@ export default function NavLinks() {
</StyledNavLink>
<div className="committee-tools">
<StyledNavLinkNoRouter
hidden={!isCommitteeAddress && !isGovMember && !isReviewer}
hidden={!isCommitteeAddress && !isGovMember && !isReviewer && !isGrowthMember}
className={`${location.pathname.includes(`${RoutePaths.committee_tools}`) ? "active" : ""}`}
onClick={() => setshowCommitteeToolsSubroutes((prev) => !prev)}
>
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/components/VaultCard/VaultAuditDraftCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useAuditFrameGame } from "hooks/auditFrameGame";
import { useSiweAuth } from "hooks/siwe/useSiweAuth";
import useConfirm from "hooks/useConfirm";
import { useIsGovMember } from "hooks/useIsGovMember";
import { useIsGrowthMember } from "hooks/useIsGrowthMember";
import { useIsReviewer } from "hooks/useIsReviewer";
import useModal from "hooks/useModal";
import millify from "millify";
Expand Down Expand Up @@ -45,6 +46,7 @@ export const VaultAuditDraftCard = ({ vaultDraft }: VaultAuditDraftCardProps) =>

const isGovMember = useIsGovMember();
const isReviewer = useIsReviewer();
const isGrowthMember = useIsGrowthMember();

const isOptInOpen = useMemo(() => {
const startTime = vaultDraft.editedDescription["project-metadata"].starttime;
Expand Down Expand Up @@ -121,7 +123,7 @@ export const VaultAuditDraftCard = ({ vaultDraft }: VaultAuditDraftCardProps) =>
};

const goToEditSession = async () => {
if (!isGovMember && !isReviewer) return;
if (!isGovMember && !isReviewer && !isGrowthMember) return;
if (!vaultDraft._id) return;

navigate(`${RoutePaths.vault_editor}/${vaultDraft._id}`);
Expand Down Expand Up @@ -196,7 +198,7 @@ export const VaultAuditDraftCard = ({ vaultDraft }: VaultAuditDraftCardProps) =>
</div>
</div>

{(isGovMember || isReviewer) && (
{(isGovMember || isReviewer || isGrowthMember) && (
<div className="draft-actions">
<Button className="mt-3" size="medium" onClick={goToEditSession}>
{t("goToEditSession")}
Expand Down
3 changes: 3 additions & 0 deletions packages/web/src/components/WalletButton/WalletButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Dot, DropdownSelector, WithTooltip } from "components";
import { Colors } from "constants/constants";
import { useSiweAuth } from "hooks/siwe/useSiweAuth";
import { useIsGovMember } from "hooks/useIsGovMember";
import { useIsGrowthMember } from "hooks/useIsGrowthMember";
import { useIsReviewer } from "hooks/useIsReviewer";
import { useSupportedNetwork } from "hooks/wagmi/useSupportedNetwork";
import { useCallback, useEffect, useState } from "react";
Expand Down Expand Up @@ -34,6 +35,7 @@ const WalletButton = ({ expanded = false }: WalletButtonProps) => {
>();
const [showConnectors, setShowConnectors] = useState(false);
const isGovMember = useIsGovMember();
const isGrowthMember = useIsGrowthMember();
const isReviewer = useIsReviewer();

const { isAuthenticated, updateProfile } = useSiweAuth();
Expand Down Expand Up @@ -73,6 +75,7 @@ const WalletButton = ({ expanded = false }: WalletButtonProps) => {
const getTitle = () => {
if (isReviewer) return "[Rev]";
if (isGovMember) return "[Gov]";
if (isGrowthMember) return "[Growth]";
return "";
};

Expand Down
4 changes: 4 additions & 0 deletions packages/web/src/constants/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BigNumber } from "ethers";
import { IS_PROD } from "settings";

export enum LocalStorage {
Cookies = "HATS_ACCEPTED_COOKIES",
Expand Down Expand Up @@ -125,3 +126,6 @@ export enum Transactions {
export const HAT_TOKEN_ADDRESS_V1 = "0x436cA314A2e6FfDE52ba789b257b51DaCE778F1a";
export const HAT_TOKEN_DECIMALS_V1 = "18";
export const HAT_TOKEN_SYMBOL_V1 = "HAT";

export const TGE_ENABLE_TIMESTAMP = IS_PROD ? 1721934000000 : 1721773234000;
export const isAirdropEnabled = Date.now() > TGE_ENABLE_TIMESTAMP;
4 changes: 3 additions & 1 deletion packages/web/src/hooks/subgraph/vaults/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ export const fixPayoutVaultFees = (payouts: IPayoutGraph[]): IPayoutGraph[] => {

return {
...payout,
totalPaidOut: !!payout.approvedAt ? parseUnits(`${paidOutHackers}`, vault.stakingTokenDecimals).toString() : undefined,
totalPaidOut: !!payout.approvedAt
? parseUnits(`${paidOutHackers.toFixed(8)}`, vault.stakingTokenDecimals).toString()
: undefined,
};
});
};
26 changes: 26 additions & 0 deletions packages/web/src/hooks/useIsGrowthMember.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { isAddressAMultisigMember } from "@hats.finance/shared";
import { useEffect, useState } from "react";
import { appChains } from "settings";
import { useAccount, useNetwork } from "wagmi";

export const useIsGrowthMember = () => {
const { address } = useAccount();
const { chain } = useNetwork();

const [isGrowthMember, setIsGrowthMember] = useState(false);

useEffect(() => {
const checkGrowthMember = async () => {
if (address && chain && chain.id) {
const chainId = Number(chain.id);
const growthMultisig = appChains[Number(chainId)]?.growthMultisig;

const isGrowth = await isAddressAMultisigMember(growthMultisig, address, chainId);
setIsGrowthMember(isGrowth);
}
};
checkGrowthMember();
}, [address, chain]);

return isGrowthMember;
};
Loading

0 comments on commit ce1ebe8

Please sign in to comment.