Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ NEXT_PUBLIC_IPFS_GATEWAY="nxHSFa1jQsiF7IHeXWH-gXCY3LDLlZ7Run3aZXZc8DRCfQz4J4a94z
NEXT_PUBLIC_TOKEN_NETWORK="8453"

# Gnars
# NEXT_PUBLIC_NFT="0x880fb3cf5c6cc2d7dfc13a993e839a9411200c17"
# NEXT_PUBLIC_METADATA="0xdc9799d424ebfdcf5310f3bad3ddcce3931d4b58"
# NEXT_PUBLIC_AUCTION="0x494eaa55ecf6310658b8fc004b0888dcb698097f"
# NEXT_PUBLIC_TREASURY="0x72ad986ebac0246d2b3c565ab2a1ce3a14ce6f88"
# NEXT_PUBLIC_GOVERNOR="0x3dd4e53a232b7b715c9ae455f4e732465ed71b4c"
NEXT_PUBLIC_NFT="0x880fb3cf5c6cc2d7dfc13a993e839a9411200c17"
NEXT_PUBLIC_METADATA="0xdc9799d424ebfdcf5310f3bad3ddcce3931d4b58"
NEXT_PUBLIC_AUCTION="0x494eaa55ecf6310658b8fc004b0888dcb698097f"
NEXT_PUBLIC_TREASURY="0x72ad986ebac0246d2b3c565ab2a1ce3a14ce6f88"
NEXT_PUBLIC_GOVERNOR="0x3dd4e53a232b7b715c9ae455f4e732465ed71b4c"

# HackerDao
NEXT_PUBLIC_NFT="0x6940100C44D214cD1570b394A1C42949C3eB820d"
NEXT_PUBLIC_AUCTION="0x1ef59b5276466b99d2f6600ffeaf3ccefea001ab"
NEXT_PUBLIC_GOVERNOR="0x7c4c33efe412f06f83278acafc16b435be904b03"
NEXT_PUBLIC_TREASURY="0x7c27601741cbc96b66766d499c15b688abeefcca"
NEXT_PUBLIC_METADATA="0xaf2273eb279a37654a22ebf4c6bfec3366e9e3a3"
# NEXT_PUBLIC_NFT="0x6940100C44D214cD1570b394A1C42949C3eB820d"
# NEXT_PUBLIC_AUCTION="0x1ef59b5276466b99d2f6600ffeaf3ccefea001ab"
# NEXT_PUBLIC_GOVERNOR="0x7c4c33efe412f06f83278acafc16b435be904b03"
# NEXT_PUBLIC_TREASURY="0x7c27601741cbc96b66766d499c15b688abeefcca"
# NEXT_PUBLIC_METADATA="0xaf2273eb279a37654a22ebf4c6bfec3366e9e3a3"

# Skatehive
# NEXT_PUBLIC_NFT="0xfe10d3ce1b0f090935670368ec6de00d8d965523"
Expand Down
2 changes: 1 addition & 1 deletion components/DAO/Transaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ function TokenValueRender({ address, value }: { address: string, value: bigint }
return null;
}

function TokenDataRender({ address }: { address: string }) {
export function TokenDataRender({ address }: { address: string }) {
if (address === BASE_USDC_TOKEN_ADDRESS) {
return (
<div className="flex gap-1">
Expand Down
13 changes: 13 additions & 0 deletions components/FarcasterIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

function FarcasterIcon({ width, height, color }: { width?: number, height?: number, color?: string }) {
return (
<svg width={width} height={height} viewBox="0 0 1000 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M257.778 155.556H742.222V844.445H671.111V528.889H670.414C662.554 441.677 589.258 373.333 500 373.333C410.742 373.333 337.446 441.677 329.586 528.889H328.889V844.445H257.778V155.556Z" fill={color} />
<path d="M128.889 253.333L157.778 351.111H182.222V746.667C169.949 746.667 160 756.616 160 768.889V795.556H155.556C143.283 795.556 133.333 805.505 133.333 817.778V844.445H382.222V817.778C382.222 805.505 372.273 795.556 360 795.556H355.556V768.889C355.556 756.616 345.606 746.667 333.333 746.667H306.667V253.333H128.889Z" fill={color} />
<path d="M675.556 746.667C663.282 746.667 653.333 756.616 653.333 768.889V795.556H648.889C636.616 795.556 626.667 805.505 626.667 817.778V844.445H875.556V817.778C875.556 805.505 865.606 795.556 853.333 795.556H848.889V768.889C848.889 756.616 838.94 746.667 826.667 746.667V351.111H851.111L880 253.333H702.222V746.667H675.556Z" fill={color} />
</svg>
);
}

export default FarcasterIcon;
60 changes: 11 additions & 49 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
useState
} from "react";
import { useBalance } from "wagmi";
import FarcasterIcon from "./FarcasterIcon";
import { TokenData } from "../pages/api/treasury/[address]";

function Navbar() {
return (
Expand Down Expand Up @@ -124,51 +126,20 @@ function NavbarItem(props: NavbarItemProps) {
function TreasureBoxItem() {
const [treasureBalance, setTreasureBalance] = useState(0);

const { data: usdcData } = useBalance({
address: DAO_ADDRESS.treasury,
token: USDC_ADDRESS,
});
const { data: senditData } = useBalance({
address: DAO_ADDRESS.treasury,
token: BASE_SENDIT_TOKEN_ADDRESS,
});
const { data: wethData } = useBalance({
address: DAO_ADDRESS.treasury,
token: BASE_WETH_TOKEN_ADDRESS,
});
const { data: ethData } = useBalance({
address: DAO_ADDRESS.treasury,
});

useEffect(() => {
async function fetchPrices() {
async function fetchTreasureBalance() {
try {
const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=ethereum,sendit&vs_currencies=usd`);
const prices = await response.json();

const ethPrice = prices.ethereum.usd;
const senditPrice = prices.sendit.usd;

const usdcAmount = Number(usdcData?.value) / 10 ** Number(usdcData?.decimals);
const ethAmount = Number(ethData?.value) / 10 ** Number(ethData?.decimals);
const senditAmount = Number(senditData?.value) / 10 ** Number(senditData?.decimals);
const wethAmount = Number(wethData?.value) / 10 ** Number(wethData?.decimals);

const usdcBalance = usdcAmount; // Assuming USDC is already in USD
const ethBalance = ethAmount * ethPrice;
const wethBalance = wethAmount * ethPrice;
const senditBalance = senditAmount * senditPrice;

const totalBalance = usdcBalance + ethBalance + senditBalance + wethBalance;

setTreasureBalance(totalBalance);
const response = await fetch('/api/treasury/' + DAO_ADDRESS.treasury);
const data: { tokens: TokenData[] } = await response.json();
console.log({data})
// setTreasureBalance(data.totalBalance);
} catch (error) {
console.error("Failed to fetch prices:", error);
console.error("Failed to fetch treasure balance:", error);
}
}

fetchPrices();
}, [usdcData, senditData, ethData]);
fetchTreasureBalance();
}, []);

return (
<Link href={"/treasure"}>
Expand All @@ -185,13 +156,4 @@ function TreasureBoxItem() {
);
}

export default Navbar;


function FarcasterIcon({ width, height, color }: { width?: number, height?: number, color?: string }) {
return (<svg width={width} height={height} viewBox={`0 0 1000 1000`} fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M257.778 155.556H742.222V844.445H671.111V528.889H670.414C662.554 441.677 589.258 373.333 500 373.333C410.742 373.333 337.446 441.677 329.586 528.889H328.889V844.445H257.778V155.556Z" fill={color} />
<path d="M128.889 253.333L157.778 351.111H182.222V746.667C169.949 746.667 160 756.616 160 768.889V795.556H155.556C143.283 795.556 133.333 805.505 133.333 817.778V844.445H382.222V817.778C382.222 805.505 372.273 795.556 360 795.556H355.556V768.889C355.556 756.616 345.606 746.667 333.333 746.667H306.667V253.333H128.889Z" fill={color} />
<path d="M675.556 746.667C663.282 746.667 653.333 756.616 653.333 768.889V795.556H648.889C636.616 795.556 626.667 805.505 626.667 817.778V844.445H875.556V817.778C875.556 805.505 865.606 795.556 853.333 795.556H848.889V768.889C848.889 756.616 838.94 746.667 826.667 746.667V351.111H851.111L880 253.333H702.222V746.667H675.556Z" fill={color} />
</svg>)
}
export default Navbar;
4 changes: 4 additions & 0 deletions constants/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export const MANAGER_CONTRACT = {
"7777777": "0x3ac0e64fe2931f8e082c6bb29283540de9b5371c",
}[process.env.NEXT_PUBLIC_TOKEN_NETWORK ?? "1"]!;

export const BASE_USDC_TOKEN_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
export const BASE_SENDIT_TOKEN_ADDRESS = "0xBa5B9B2D2d06a9021EB3190ea5Fb0e02160839A4";
export const BASE_WETH_TOKEN_ADDRESS = "0x4200000000000000000000000000000000000006";

export const DAO_ADDRESS = {
nft: process.env.NEXT_PUBLIC_NFT as `0x${string}` || "0x880fb3cf5c6cc2d7dfc13a993e839a9411200c17",
metadata: process.env.NEXT_PUBLIC_METADATA as `0x${string}` || "0xdc9799d424ebfdcf5310f3bad3ddcce3931d4b58",
Expand Down
3 changes: 2 additions & 1 deletion hooks/fetch/useTreasuryBalance.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { BigNumber } from "ethers";
import { TokenData } from "pages/api/treasury/[address]";
import useSWR from "swr";

export const useTreasuryBalance = ({
treasuryContract,
}: {
treasuryContract?: string;
}) => {
return useSWR<BigNumber>(
return useSWR<{ tokens: TokenData[], totalBalance: number }>(
treasuryContract ? `/api/treasury/${treasuryContract}` : undefined
);
};
62 changes: 62 additions & 0 deletions pages/api/prices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { NextApiRequest, NextApiResponse } from "next";
import {
DAO_ADDRESS,
USDC_ADDRESS,
BASE_SENDIT_TOKEN_ADDRESS,
BASE_WETH_TOKEN_ADDRESS,
} from "constants/addresses";
import { useBalance } from "wagmi";

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
// const { data: usdcData } = useBalance({
// address: DAO_ADDRESS.treasury,
// token: USDC_ADDRESS,
// });
// const { data: senditData } = useBalance({
// address: DAO_ADDRESS.treasury,
// token: BASE_SENDIT_TOKEN_ADDRESS,
// });
// const { data: wethData } = useBalance({
// address: DAO_ADDRESS.treasury,
// token: BASE_WETH_TOKEN_ADDRESS,
// });
// const { data: ethData } = useBalance({
// address: DAO_ADDRESS.treasury,
// });

// const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=ethereum,sendit&vs_currencies=usd`);
// const prices = await response.json();

// const ethPrice = prices.ethereum.usd;
// const senditPrice = prices.sendit.usd;

// const usdcAmount = Number(usdcData?.value) / 10 ** Number(usdcData?.decimals);
// const ethAmount = Number(ethData?.value) / 10 ** Number(ethData?.decimals);
// const senditAmount = Number(senditData?.value) / 10 ** Number(senditData?.decimals);
// const wethAmount = Number(wethData?.value) / 10 ** Number(wethData?.decimals);

// const usdcBalance = usdcAmount; // Assuming USDC is already in USD
// const ethBalance = ethAmount * ethPrice;
// const wethBalance = wethAmount * ethPrice;
// const senditBalance = senditAmount * senditPrice;

// const totalBalance = usdcBalance + ethBalance + senditBalance + wethBalance;

// res.status(200).json({ totalBalance });

const res = await fetch(
`https://pioneers.dev/api/v1/portfolio/${DAO_ADDRESS.treasury}`
);
const data = await res.json();

console.log(data);
// console.dir({ data }, { depth: null, colors: true });
} catch (error) {
console.error("Failed to fetch prices:", error);
res.status(500).json({ error: "Failed to fetch prices" });
}
}
50 changes: 47 additions & 3 deletions pages/api/treasury/[address].tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,60 @@
import { BASE_SENDIT_TOKEN_ADDRESS, BASE_USDC_TOKEN_ADDRESS, BASE_WETH_TOKEN_ADDRESS } from "constants/addresses";
import { NextApiRequest, NextApiResponse } from "next";
import DefaultProvider from "utils/DefaultProvider";

export interface Token {
address: string;
network: string;
label: string;
name: string;
symbol: string;
decimals: string;
verified: boolean;
price: string;
balance: number;
balanceUSD: number;
balanceRaw: string;
}

export interface TokenData {
key: string;
address: string;
network: string;
updatedAt: string;
token: Token;
networkId: string;
assetCaip: string;
}

const TOKEN_ADDRESSES = [
BASE_USDC_TOKEN_ADDRESS.toLowerCase(),
BASE_SENDIT_TOKEN_ADDRESS.toLowerCase(),
BASE_WETH_TOKEN_ADDRESS.toLowerCase()
];

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const { address } = req.query;
const treasuryBalance = await DefaultProvider.getBalance(address as string);

const fetchRes = await fetch(
`https://pioneers.dev/api/v1/portfolio/${address as string}`
);
const data: { tokens: TokenData[], totalBalanceUsdTokens: number } = await fetchRes.json();

console.log({data})

const filteredTokens = data.tokens.filter((i: TokenData) =>
TOKEN_ADDRESSES.includes(i.token.address)
);

const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
res.setHeader(
"Cache-Control",
`s-maxage=60, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`
);
res.send(treasuryBalance);

res.send({
tokens: filteredTokens,
totalBalance: data.totalBalanceUsdTokens,
});
};

export default handler;
29 changes: 24 additions & 5 deletions pages/vote/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import Layout from "@/components/Layout";
import { Proposal } from "@/services/nouns-builder/governor";
import { TOKEN_CONTRACT } from "constants/addresses";
import { TOKEN_CONTRACT, BASE_USDC_TOKEN_ADDRESS, BASE_SENDIT_TOKEN_ADDRESS, BASE_WETH_TOKEN_ADDRESS } from "constants/addresses";
import Link from "next/link";
import { useDAOAddresses, useGetAllProposals, useTreasuryBalance } from "hooks";
import { getProposalName } from "@/utils/getProposalName";
Expand All @@ -17,6 +17,7 @@ import { useUserVotes } from "@/hooks/fetch/useUserVotes";
import { useCurrentThreshold } from "@/hooks/fetch/useCurrentThreshold";
import Loading from "@/components/Loading";
import { extractImageUrl } from "@/utils/getProposalImage";
import { TokenDataRender } from "@/components/DAO/Transaction";

export const getStaticProps = async (): Promise<
GetStaticPropsResult<{
Expand Down Expand Up @@ -58,6 +59,12 @@ export default function Vote({

const [selectedTab, setSelectedTab] = useState<"all" | "onboarding">("all");

const tokenAddresses = [
{ address: BASE_USDC_TOKEN_ADDRESS, name: "USDC" },
{ address: BASE_SENDIT_TOKEN_ADDRESS, name: "SENDIT" },
{ address: BASE_WETH_TOKEN_ADDRESS, name: "WETH" },
];

const getProposalNumber = (i: number) => {
if (!proposals) return 0;
return proposals.length - i;
Expand Down Expand Up @@ -88,18 +95,30 @@ export default function Vote({
)}
</div>
<div className="border border-skin-stroke rounded-2xl py-6 sm:py-0 px-6 mt-6 flex flex-col sm:flex-row sm:items-center justify-between sm:h-32">
<div className="sm:py-6 h-full">
<div className="sm:py-6 h-full flex gap-4">
<div className="font-heading text-2xl text-skin-muted">Treasury</div>
<div className="text-4xl font-bold font-heading mt-2 text-skin-base">
Ξ {treasuryBalance ? formatTreasuryBalance(treasuryBalance) : "0"} + 117k USD
{/* <div className="text-4xl font-bold font-heading mt-2 text-skin-base"> */}
{/* Ξ {treasuryBalance ? formatTreasuryBalance(treasuryBalance) : "0"} + 117k USD */}
{/* Total USD value: {treasuryBalance?.totalBalance.toFixed(2)} USD */}
<div className="mt-1">
{treasuryBalance?.tokens.map((tokenData) => {
const token = tokenData.token
return (
<div key={token.address}>
<div className="text-base">
{token.name} {token.balance}
</div>
</div>
)
})}
{/* </div> */}
</div>
</div>
<div className="sm:w-1/3 mt-4 sm:mt-0 sm:border-l border-skin-stroke sm:pl-6 h-full flex items-center text-skin-muted">
This treasury exists for DAO participants to allocate resources for
the long-term growth and prosperity of the project.
</div>
</div>

<div className="mt-12">
{/* Tab navigation */}
<div className="flex items-center justify-between">
Expand Down