Skip to content

Commit

Permalink
Fixed linting bug? Added USDC to contracts and frontend, still needs …
Browse files Browse the repository at this point in the history
…approval on frontend and likes integration on contracts
  • Loading branch information
luloxi committed Dec 14, 2024
1 parent 5289dfb commit a5047df
Show file tree
Hide file tree
Showing 10 changed files with 2,635 additions and 62 deletions.
6 changes: 4 additions & 2 deletions packages/foundry/contracts/MockUSDC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ERC20Permit } from
"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

contract USDC is ERC20, ERC20Permit {
constructor() ERC20("USDC", "USDC") ERC20Permit("USDC") { }
contract MockUSDC is ERC20, ERC20Permit {
constructor() ERC20("USDC", "USDC") ERC20Permit("USDC") {
_mint(msg.sender, 100000 * 1e18);
}

function decimals() public view virtual override returns (uint8) {
return 6;
Expand Down
11 changes: 10 additions & 1 deletion packages/foundry/contracts/PunkSociety.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { PunkProfile } from "./PunkProfile.sol";
import { PunkPosts } from "./PunkPosts.sol";

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
// import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

Expand Down Expand Up @@ -65,6 +67,7 @@ contract PunkSociety is Ownable {
uint256 public postIds;
PunkProfile public punkProfile;
PunkPosts public punkPosts;
IERC20 public mockUSDC;

mapping(uint256 => address) public postIdToUser;
mapping(address => uint256[]) public userPosts;
Expand Down Expand Up @@ -94,9 +97,14 @@ contract PunkSociety is Ownable {
CONSTRUCTOR FUNCTION
//////////////////////////////////////////////////////////////*/

constructor(address _punkProfile, address _punkPosts) Ownable(msg.sender) {
constructor(
address _punkProfile,
address _punkPosts,
address _mockUSDC
) Ownable(msg.sender) {
punkProfile = PunkProfile(_punkProfile);
punkPosts = PunkPosts(_punkPosts);
mockUSDC = IERC20(_mockUSDC);
}

/*//////////////////////////////////////////////////////////////
Expand All @@ -111,6 +119,7 @@ contract PunkSociety is Ownable {
postIdToUser[postId] = msg.sender;
userPosts[msg.sender].push(postId);

mockUSDC.transferFrom(msg.sender, owner(), 3 * 1e6);
punkPosts.mint(_tokenURI);
// payable(owner()).transfer(3 ether);

Expand Down
22 changes: 17 additions & 5 deletions packages/foundry/contracts/SimpleFaucet.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

error FailedToTransfer();

contract SimpleFaucet {
// Mapping to track if an address has claimed ETH
mapping(address => bool) public hasClaimed;

// Ether to be dispensed (10 USDC in 18 decimals)
// uint256 public constant AMOUNT = 10 ether;
uint256 public constant AMOUNT = 0.01 ether;
uint256 public constant AMOUNT = 10 * 1e6;
// uint256 public constant AMOUNT = 0.01 ether;
IERC20 public mockUSDC;

constructor(
address _mockUSDC
) {
mockUSDC = IERC20(_mockUSDC);
}

// Only allow each address to claim once
modifier onlyOnce() {
Expand All @@ -19,13 +28,16 @@ contract SimpleFaucet {

// Function to claim ETH
function claim() external onlyOnce {
require(address(this).balance >= AMOUNT, "Insufficient faucet balance");
require(
mockUSDC.balanceOf(address(this)) >= AMOUNT, "Insufficient faucet balance"
);

// Mark address as having claimed
hasClaimed[msg.sender] = true;

// Transfer 10 ETH to the claimant
payable(msg.sender).transfer(AMOUNT);
// Transfer 10 USDC to the claimant
// payable(msg.sender).transfer(AMOUNT);
mockUSDC.transfer(msg.sender, AMOUNT);
}

// Function to deposit ETH into the faucet
Expand Down
4 changes: 2 additions & 2 deletions packages/foundry/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ libs = ['lib']
fs_permissions = [{ access = "read-write", path = "./"}]

[rpc_endpoints]
default_network = "${PUNKSOCIETY_RPC_URL}"
localhost = "${PUNKSOCIETY_RPC_URL}"
default_network = "http://127.0.0.1:8545"
localhost = "http://127.0.0.1:8545"

punksociety = "${PUNKSOCIETY_RPC_URL}"
avalancheFuji = "https://api.avax-test.network/ext/bc/C/rpc"
Expand Down
16 changes: 13 additions & 3 deletions packages/foundry/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PunkPosts } from "../contracts/PunkPosts.sol";
import { PunkProfile } from "../contracts/PunkProfile.sol";
import { PunkSociety } from "../contracts/PunkSociety.sol";
import { SimpleFaucet } from "../contracts/SimpleFaucet.sol";
import { MockUSDC } from "../contracts/MockUSDC.sol";
import "./DeployHelpers.s.sol";

contract DeployScript is ScaffoldETHDeploy {
Expand All @@ -14,6 +15,7 @@ contract DeployScript is ScaffoldETHDeploy {
PunkProfile punkProfile;
PunkSociety punkSociety;

MockUSDC mockUSDC;
SimpleFaucet simpleFaucet;

error InvalidPrivateKey(string);
Expand All @@ -27,7 +29,11 @@ contract DeployScript is ScaffoldETHDeploy {
}
vm.startBroadcast(deployerPrivateKey);

// Deploying just to get the ABI from the frontend
mockUSDC = new MockUSDC();
console.logString(
string.concat("MockUSDC deployed at: ", vm.toString(address(mockUSDC)))
);

punkPosts = new PunkPosts();
console.logString(
string.concat("PunkPosts deployed at: ", vm.toString(address(punkPosts)))
Expand All @@ -40,7 +46,9 @@ contract DeployScript is ScaffoldETHDeploy {
)
);

punkSociety = new PunkSociety(address(punkProfile), address(punkPosts));
punkSociety = new PunkSociety(
address(punkProfile), address(punkPosts), address(mockUSDC)
);
console.logString(
string.concat(
"PunkSociety deployed at: ", vm.toString(address(punkSociety))
Expand All @@ -55,13 +63,15 @@ contract DeployScript is ScaffoldETHDeploy {
)
);

simpleFaucet = new SimpleFaucet();
simpleFaucet = new SimpleFaucet(address(mockUSDC));
console.logString(
string.concat(
"SimpleFaucet deployed at: ", vm.toString(address(simpleFaucet))
)
);

mockUSDC.transfer(address(simpleFaucet), 50000 * 1e18);

// Transfer 5000 USDC to the simpleFaucet
// payable(address(simpleFaucet)).transfer(5000 * 1e18);
// payable(address(simpleFaucet)).transfer(0.5 * 1e18);
Expand Down
78 changes: 39 additions & 39 deletions packages/nextjs/app/explore/Explore.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"use client";

import { useCallback, useEffect, useRef, useState } from "react";
// import Image from "next/image";
import Image from "next/image";
import { LoadingBars } from "../../components/punk-society/LoadingBars";
import { NewsFeed } from "../../components/punk-society/NewsFeed";
// import { useAccount } from "wagmi";
import { useScaffoldEventHistory } from "~~/hooks/scaffold-eth";
// import { useScaffoldEventHistory, useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
import { useAccount } from "wagmi";
import { useScaffoldEventHistory, useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
import { notification } from "~~/utils/scaffold-eth";
import { getMetadataFromIPFS } from "~~/utils/simpleNFT/ipfs-fetch";
import { NFTMetaData } from "~~/utils/simpleNFT/nftsMetadata";
Expand All @@ -25,45 +24,45 @@ export const Explore = () => {
const [page, setPage] = useState(0);
const [activeTab, setActiveTab] = useState("Global");

// const { address: connectedAddress } = useAccount();
// const { writeContractAsync } = useScaffoldWriteContract("SimpleFaucet");
const { address: connectedAddress } = useAccount();
const { writeContractAsync } = useScaffoldWriteContract("SimpleFaucet");

const handleTabClick = (tab: any) => {
setActiveTab(tab);
};

const observer = useRef<IntersectionObserver | null>(null);

// const { data: isClaimed } = useScaffoldReadContract({
// contractName: "SimpleFaucet",
// functionName: "hasClaimed",
// args: [connectedAddress],
// watch: true,
// });

// const handleClaimUSDC = async () => {
// if (!connectedAddress) {
// notification.error("Please connect your wallet");
// return;
// }

// setLoading(true);

// try {
// const contractResponse = await writeContractAsync({
// functionName: "claim",
// // args: [],
// });

// if (contractResponse) {
// notification.success("Claimed 10 USDC successfully!");
// }
// } catch (error) {
// console.error("Error during claiming USDC:", error);
// notification.error("Claiming USDC failed, please try again.");
// } finally {
// }
// };
const { data: isClaimed } = useScaffoldReadContract({
contractName: "SimpleFaucet",
functionName: "hasClaimed",
args: [connectedAddress],
watch: true,
});

const handleClaimUSDC = async () => {
if (!connectedAddress) {
notification.error("Please connect your wallet");
return;
}

setLoading(true);

try {
const contractResponse = await writeContractAsync({
functionName: "claim",
// args: [],
});

if (contractResponse) {
notification.success("Claimed 10 USDC successfully!");
}
} catch (error) {
console.error("Error during claiming USDC:", error);
notification.error("Claiming USDC failed, please try again.");
} finally {
}
};

const {
data: createEvents,
Expand All @@ -72,7 +71,8 @@ export const Explore = () => {
} = useScaffoldEventHistory({
contractName: "PunkSociety",
eventName: "PostCreated",
fromBlock: 18350669n,
// fromBlock: 18350669n,
fromBlock: 0n,
watch: true,
});

Expand Down Expand Up @@ -150,15 +150,15 @@ export const Explore = () => {

return (
<div className="flex flex-col items-center justify-center">
{/* {!isClaimed && (
{!isClaimed && (
<button
onClick={handleClaimUSDC}
className="btn btn-primary text-white bg-[#2E79CC] hover:bg-blue-700 active:bg-blue-700 border-0 mt-2"
>
<Image src="/usdc-logo.png" alt="USDC logo" width={40} height={40} className="mr-2" />
<span>Claim 10 USDC from Faucet</span>
</button>
)} */}
)}
<div className="tabs-bar ">
<button className={`tab ${activeTab === "Global" ? "active" : ""}`} onClick={() => handleTabClick("Global")}>
Global
Expand Down
3 changes: 2 additions & 1 deletion packages/nextjs/app/profile/[address]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const ProfilePage: NextPage = () => {
} = useScaffoldEventHistory({
contractName: "PunkSociety",
eventName: "PostCreated",
fromBlock: 18350669n,
// fromBlock: 18350669n,
fromBlock: 0n,
watch: true,
});

Expand Down
40 changes: 33 additions & 7 deletions packages/nextjs/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
"use client";

import React from "react";
import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { ConfigMenu } from "./punk-society/ConfigMenu";
import { PunkConnectButton } from "./punk-society/PunkConnectButton";
import { FaucetButton } from "./scaffold-eth";
import { useAccount } from "wagmi";
import { BellIcon, EnvelopeIcon, HomeIcon, MagnifyingGlassIcon } from "@heroicons/react/24/solid";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";

/**
* Site header
*/
export const Header = () => {
const pathname = usePathname();

const { address: connectedAddress } = useAccount();

const { data: usdcBalance } = useScaffoldReadContract({
contractName: "MockUSDC",
functionName: "balanceOf",
args: [connectedAddress],
watch: true,
});

const formattedUsdcBalance = usdcBalance ? (Number(usdcBalance.toString()) / 1e6).toFixed(2) : "0.00";

return (
<div className="sticky top-0 navbar bg-base-100 min-h-0 flex-shrink-0 justify-between z-20 px-0 sm:px-2">
<div className="navbar-start lg:ml-2">
<div className="flex lg:hidden">
{/* <ConfigMenu /> */}
<div className="flex justify-center items-center ml-8 lg:ml-0">
{/* <div className="flex justify-center items-center ml-8 lg:ml-0">
<Link href="/" passHref>
<span className="inline-flex items-center gap-2">
<strong>PunkSociety</strong>{" "}
Expand All @@ -28,7 +42,11 @@ export const Header = () => {
</span>
</span>
</Link>
</div>
</div> */}
<span className="items-center justify-center gap-1 ml-4 text-lg text-blue-600 font-bold">
<Image src="/usdc-logo.png" alt="USDC" width={20} height={20} className="inline-block" />
<span>{formattedUsdcBalance}</span>
</span>
</div>
<div className="flex flex-row gap-3 ">
<Link href="/" passHref>
Expand Down Expand Up @@ -100,20 +118,28 @@ export const Header = () => {
</div>

<div className="navbar-end relative ">
<div className="flex justify-center items-center ">
{/* <div className="flex justify-center items-center ">
<span className="text-blue-600">USDC {usdcBalance}</span>
</div> */}

<div className="flex flex-row items-center justify-center gap-3">
<span className="hidden lg:flex items-center justify-center gap-1 text-lg text-blue-600 font-bold">
<Image src="/usdc-logo.png" alt="USDC" width={20} height={20} className="inline-block" />
{formattedUsdcBalance}
</span>
<div className="flex items-center justify-center">
<PunkConnectButton />
</div>

<div>
<FaucetButton />
</div>
</div>
<div className="flex flex-row items-center justify-center gap-3">
<div className="mr-2 lg:mr-0">
<div>
<ConfigMenu />
</div>
</div>
<div className="flex flex-row items-center justify-center gap-3">
<div className="mr-2 lg:mr-0"></div>
</div>
</div>
</div>
);
Expand Down
Loading

0 comments on commit a5047df

Please sign in to comment.