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

Staking frontend #132

Merged
merged 7 commits into from
Sep 11, 2024
Merged
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
10 changes: 7 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import React from "react";
// import { useBlock } from "@starknet-react/core";
import Header from "./components/Header";
import { useContractRead } from "@starknet-react/core";
import { useContractRead, useAccount } from "@starknet-react/core";
//import Tokens from "./helpers/tokens";
import { abi } from "./lib/abi";
import Proposal from "./components/Proposal";
import { CONTRACT_ADDR } from "./lib/config";
// import { useAccount } from "@starknet-react/core";
import SubmitProposalModal from "./components/SubmitProposalModal";
import TreasuryStatus from "./components/TreasuryStatus";
import VotingPower from "./components/staking/VotingPower";

function App() {
const [isModalOpen, setIsModalOpen] = React.useState(false);
const [isModalOpen, setIsModalOpen] = React.useState(false);
const { address } = useAccount();

// Call the contract function get_live_proposals to get the live proposals
const { data, isError, isLoading,error } = useContractRead({
const { data, isError, isLoading, error } = useContractRead({
functionName: "get_live_proposals",
args: [],
abi,
Expand Down Expand Up @@ -68,6 +70,8 @@ function App() {
</div>

<TreasuryStatus />

{address && <VotingPower />}
</main>
);
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/apiService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from "axios";
import { BASE_API_URL } from "../constants/amm";
import { BASE_API_URL } from "../lib/config";

type CommentPayload = {
address: string;
Expand Down
27 changes: 0 additions & 27 deletions frontend/src/api/index.ts

This file was deleted.

40 changes: 20 additions & 20 deletions frontend/src/components/CommentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
import { useContractRead } from '@starknet-react/core';
import React, { } from 'react';
import { TOKEN_CONTRACT } from '../lib/config';
import React, { } from 'react';
import { VOTING_TOKEN_CONTRACT } from '../lib/config';
import { TokenABI } from '../lib/tokenContractABI';

interface CommentCardProps {
address: string;
text: string;

}
const CommentCard = ({address, text}: CommentCardProps) => {
const CommentCard = ({ address, text }: CommentCardProps) => {

const { data, isSuccess } = useContractRead({
functionName: "balance_of",
args: [address.toString()],
abi:TokenABI,
address: TOKEN_CONTRACT,
abi: TokenABI,
address: VOTING_TOKEN_CONTRACT,
watch: false,
retry: false
});

return (
<div >
<div className="grid grid-cols-[1fr_3fr] gap-3 ">
<p className="text-sm font-[400] ">Senders Address:</p>
<div className="flex items-center gap-2">
<p className="font-[600] text-sm">{address.slice(0, 20)}</p>

</div>
<div>
<div className="grid grid-cols-[1fr_3fr] gap-3 ">
<p className="text-sm font-[400] ">Senders Address:</p>
<div className="flex items-center gap-2">
<p className="font-[600] text-sm">{address.slice(0, 20)}</p>

<p className="text-sm font-[400] ">Comment:</p>
<p className="font-[600] text-sm">{text}</p>
</div>

<p className="text-sm font-[400]">Token Balance:</p>
<p className="font-[600] text-sm">{isSuccess && parseInt(data?.toString()) / 10**18}</p>
<p className="text-sm font-[400] ">Comment:</p>
<p className="font-[600] text-sm">{text}</p>

<p className="text-sm font-[400]">Token Balance:</p>
<p className="font-[600] text-sm">{isSuccess && parseInt(data?.toString()) / 10 ** 18}</p>
</div>
<div className="border border-b-gray-200 mt-2" />
</div>
<div className="border border-b-gray-200 mt-2" />
</div>
);
}

Expand Down
39 changes: 39 additions & 0 deletions frontend/src/components/TokenBalance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react";
import { formatBalance } from "../lib/erc20";

interface TokenBalanceItem {
name: string;
balance: bigint;
}

interface TokenBalanceProps {
balances: TokenBalanceItem[];
title: string;
isLoading: boolean;
}

export default function TokenBalance({ balances, title, isLoading }: TokenBalanceProps) {
return (
<div>
<div className="flex w-full flex-grow pb-4 text-2xl font-bold">{title}</div>
{isLoading ? (
<div>Loading...</div>
) : (
<div className="w-[50rem] max-w-[50rem] grid grid-cols-2 items-center p-2 pl-0 rounded-lg bg-slate-200">
{balances.map((token, index) => (
<div key={index} className="flex items-center">
<div className="self-stretch pl-5 pr-4 mr-4 font-mono border-r grid text-slate-400 place-content-center border-slate-400">
{token.name}
</div>
<div className="flex justify-between items-center gap-20">
<div className="flex-grow font-bold">
{formatBalance(token.balance)}
</div>
</div>
</div>
))}
</div>
)}
</div>
);
}
56 changes: 10 additions & 46 deletions frontend/src/components/TreasuryStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,20 @@
import { TREASURY_ADDRESS, ETH_ADDRESS, STRK_ADDRESS } from '../constants/config.json';
import React, { useMemo } from "react";
import { useContractRead } from "@starknet-react/core";
import { abi, formatBalance } from "../lib/erc20";
import { TREASURY_ADDRESS, ETH_ADDRESS, STRK_ADDRESS } from '../lib/config';
import React from "react";
import TokenBalance from './TokenBalance';
import { useTokenBalances } from "../lib/useTokenBalances";

export default function TreasuryStatus() {
const tokens = [
{ name: "ETH", address: ETH_ADDRESS },
{ name: "STRK", address: STRK_ADDRESS },
];

const balanceReads = tokens.map(token =>
useContractRead({
functionName: "balanceOf",
args: [TREASURY_ADDRESS],
abi,
address: token.address,
watch: true,
})
);

const balances = useMemo(() =>
tokens.map((token, index) => ({
name: token.name,
balance: balanceReads[index].data,
isLoading: balanceReads[index].isLoading,
})),
[balanceReads.map(read => read.data)]
);

const isLoading = balances.some(b => b.isLoading);
const { balances, isLoading } = useTokenBalances(tokens, TREASURY_ADDRESS);

return (
<div className="p-6 mb-6">
<div className="flex w-full flex-grow pb-4 text-2xl font-bold">Treasury status</div>
{isLoading ? (
<div>Loading...</div>
) : (
<div className="w-[50rem] max-w-[50rem] grid grid-cols-2 items-center p-2 pl-0 rounded-lg bg-slate-200">
{balances.map((token, index) => (
<div key={index} className="flex items-center">
<div className="self-stretch pl-5 pr-4 mr-4 font-mono border-r grid text-slate-400 place-content-center border-slate-400">
{token.name}
</div>
<div className="flex justify-between items-center gap-20">
<div className="flex-grow font-bold">
{formatBalance(BigInt(token.balance.toString()))}
</div>
</div>
</div>
))}
</div>
)}
</div>
<TokenBalance
balances={balances}
isLoading={isLoading}
title="Treasury status"
/>
);
}
6 changes: 3 additions & 3 deletions frontend/src/components/proposal-form/Distribution.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import { ETH_ADDRESS, STRK_ADDRESS } from '../../constants/config.json';
import { ETH_ADDRESS, STRK_ADDRESS } from '../../lib/config';
import { toast } from 'react-hot-toast';

interface DistributionProps {
Expand All @@ -14,13 +14,13 @@ export const Distribution: React.FC<DistributionProps> = ({ onSubmit }) => {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
let tok: string;
if(token == "ETH") {
if (token == "ETH") {
tok = ETH_ADDRESS;
} else if (token == "STRK") {
tok = STRK_ADDRESS;
}

if(!recipient.startsWith("0x")) {
if (!recipient.startsWith("0x")) {
toast.error('Address must start with 0x');
return;
}
Expand Down
89 changes: 89 additions & 0 deletions frontend/src/components/staking/NewStake.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState, useMemo } from "react";
import { useContractWrite } from "@starknet-react/core";
import { CONTRACT_ADDR, FLOATING_TOKEN_CONTRACT } from '../../lib/config'; //
import toast from "react-hot-toast";

const stakingPeriods = [
{ label: "1 month", value: "2629743" }
];

interface NewStakeProps {
floatingBalance: string;
}

export default function NewStake({ floatingBalance }: NewStakeProps) {
const [amount, setAmount] = useState<string>("");
const [period, setPeriod] = useState<string>(stakingPeriods[0].value);

const calls = useMemo(() => {
if (!amount) return [];
return [
{
contractAddress: FLOATING_TOKEN_CONTRACT,
entrypoint: "approve",
calldata: [CONTRACT_ADDR, 0, amount]
},
{
contractAddress: CONTRACT_ADDR,
entrypoint: "stake",
calldata: [period, amount],
}
];
}, [amount, period]);

const { writeAsync } = useContractWrite({ calls });

const handleStake = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!amount) {
toast.error("Please enter an amount to stake");
return;
}
writeAsync()
.then(() => toast.success("Stake successful"))
.catch((e) => {
toast.error("Staking failed");
console.error(e);
});
};

if (BigInt(floatingBalance) === 0n) return null;

return (
<form onSubmit={handleStake} className="mt-4 space-y-4">
<div className="flex w-full flex-grow pb-4 text-xl font-bold">Stake your floating token</div>
<div>
<label htmlFor="stakePeriod" className="block mb-1">Staking Period</label>
<select
id="stakePeriod"
className="w-full p-2 border rounded-lg border-slate-300"
value={period}
onChange={(e) => setPeriod(e.target.value)}
>
{stakingPeriods.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
<div>
<label htmlFor="stakeAmount" className="block mb-1">Stake Amount</label>
<input
id="stakeAmount"
type="text"
placeholder="Amount in wei"
className="w-full p-2 border rounded-lg border-slate-300"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
</div>
<button
type="submit"
className="w-full p-2 bg-blue-500 text-white rounded-lg"
>
Stake
</button>
</form>
);
}
Loading