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

Creating the Batch page #13

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ node_modules

# cli
dist
.env
7 changes: 7 additions & 0 deletions package.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not using Chai, Hardhat, or Mocha on your personal page, so it's better to remove them.

Also, there are many unrelated changes in yarn.lock. I recommend resetting the file and reinstalling the dependencies so that only the changes related to lucide-react remain.

Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,17 @@
},
"packageManager": "[email protected]",
"devDependencies": {
"@types/chai": "^5",
"husky": "^9.1.6",
"lint-staged": "^15.2.10"
},
"engines": {
"node": ">=20.18.3"
},
"dependencies": {
"chai": "^5.2.0",
"hardhat": "^2.22.19",
"lucide-react": "^0.482.0",
"mocha": "^11.1.0"
}
}
29 changes: 29 additions & 0 deletions packages/hardhat/contracts/checkIn.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;


interface IBatchRegistry {
function checkIn() external;
}

contract CheckIn {

address public batchRegistryAddress;
address public owner;

constructor(address _batchRegistryAddress){
batchRegistryAddress = _batchRegistryAddress;
owner = msg.sender;
}

modifier onlyOwner() {
require(msg.sender == owner, "Ownable: caller is not the owner");
_;
}

function callCheckIn() public {
IBatchRegistry batchRegistry = IBatchRegistry(batchRegistryAddress);
batchRegistry.checkIn();
}
}
19 changes: 10 additions & 9 deletions packages/hardhat/deploy/00_deploy_your_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DeployFunction } from "hardhat-deploy/types";
import { Contract } from "ethers";

// Update with your Batch number
const BATCH_NUMBER = "14";
// const BATCH_NUMBER = "14";

/**
* Deploys a contract named "deployYourContract" using the deployer account and
Expand All @@ -24,29 +24,30 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn
*/
const { deployer } = await hre.getNamedAccounts();
const { deploy } = hre.deployments;
const batchAddress = "0x47FD1Ff08476d7c7196089D4f5BcabbED4f4ddbE";

await deploy("BatchRegistry", {
await deploy("CheckIn", {
from: deployer,
// Contract constructor arguments
args: [deployer, BATCH_NUMBER],
args: [batchAddress],
log: true,
// autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
// automatically mining the contract deployment transaction. There is no effect on live networks.
autoMine: true,
});

// Get the deployed contract to interact with it after deploying.
const batchRegistry = await hre.ethers.getContract<Contract>("BatchRegistry", deployer);
console.log("\nBatchRegistry deployed to:", await batchRegistry.getAddress());
const checkIn = await hre.ethers.getContract<Contract>("CheckIn", deployer);
console.log("\nCheckIn deployed to:", await checkIn.getAddress());
console.log("Remember to update the allow list!\n");

// The GraduationNFT contract is deployed on the BatchRegistry constructor.
const batchGraduationNFTAddress = await batchRegistry.batchGraduationNFT();
console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n");
// // The GraduationNFT contract is deployed on the BatchRegistry constructor.
// const batchGraduationNFTAddress = await checkIn.batchGraduationNFT();
// console.log("BatchGraduation NFT deployed to:", batchGraduationNFTAddress, "\n");
};

export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags YourContract
deployYourContract.tags = ["BatchRegistry"];
deployYourContract.tags = ["CheckIn"];
38 changes: 38 additions & 0 deletions packages/hardhat/test/CheckIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { CheckIn, BatchRegistry } from "../typechain-types";

describe("CheckIn", () => {
let _checkIn: CheckIn;
let _batchRegistry: BatchRegistry;

before(async () => {
const [owner] = await ethers.getSigners();
const checkInFactory = await ethers.getContractFactory("CheckIn");
const batchRegistryFactory = await ethers.getContractFactory("BatchRegistry");
_batchRegistry = (await batchRegistryFactory.deploy(owner.address, 14)) as BatchRegistry;
await _batchRegistry.waitForDeployment();
_checkIn = (await checkInFactory.deploy(_batchRegistry.target)) as CheckIn;
await _checkIn.waitForDeployment();
});

describe("Deployment", () => {
it("should deploy the contract successfully", async () => {
expect(_checkIn.target).to.not.equal(0);
});
it("should have the right owner", async () => {
const [owner] = await ethers.getSigners();
expect(await _checkIn.owner()).to.equal(owner.address);
});
});

describe("CheckIn Function", () => {
it("should call the checkIn function successfully", async () => {
const [owner] = await ethers.getSigners();
await _batchRegistry.updateAllowList([owner.address], [true]);
const tx = await _checkIn.callCheckIn();
await tx.wait();
expect(await _checkIn.owner()).to.equal(owner.address);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"use client";

import React, { useState } from "react";
import { Check, Copy, ExternalLink } from "lucide-react";

const Web3Profile = () => {
const name = "Joseph Aleonomoh";
const nickname = "LEO";
const description =
"Hello! I’m a dedicated blockchain and AI enthusiast with a strong interest in decentralized technologies and their applications. My experience includes working on DeFi projects, developing smart contracts, and exploring AI-driven solutions. I’m passionate about continuous learning and collaboration, and I’m always excited to connect with others who share my interests. If you’d like to discuss ideas, collaborate on projects, or simply exchange knowledge, I’d love to hear from you!";
const walletAddress = "0xA35D2C518710D3f953Ce4F69CDDEAaFc0c6b156c";
const avatarUrl =
"https://static.vecteezy.com/system/resources/previews/002/469/825/non_2x/black-and-white-line-art-of-the-front-of-the-lion-head-it-is-sign-of-leo-zodiac-good-use-for-symbol-mascot-icon-avatar-tattoo-t-shirt-design-logo-or-any-design-free-vector.jpg";

const socialLinks = [
{
platform: "twitter",
url: "https://x.com/easybrane",
icon: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/X_icon_2.svg/1024px-X_icon_2.svg.png",
},
{
platform: "github",
url: "https://github.com/leojay-net",
icon: "https://cdn-icons-png.flaticon.com/512/25/25231.png",
},
{
platform: "linkedin",
url: "https://www.linkedin.com/in/joseph-aleonomoh/",
icon: "https://cdn-icons-png.flaticon.com/512/174/174857.png",
},
{
platform: "BuidlGuidl",
url: "https://app.buidlguidl.com/builders/0xA35D2C518710D3f953Ce4F69CDDEAaFc0c6b156c",
icon: "https://pbs.twimg.com/profile_images/1742235046038114304/xKk0nNN0_400x400.jpg",
},
];
const [copied, setCopied] = useState(false);

const truncateAddress = (address: string) => address.slice(0, 6) + "..." + address.slice(-4);

const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};

return (
<div className="w-full max-w-4xl mx-auto bg-white text-gray-800 rounded-xl shadow-md overflow-hidden">
{/* Avatar and Name Section */}
<div className="px-6 md:px-10 py-8">
<div className="flex flex-col items-center md:flex-row md:gap-6">
{/* Avatar */}
<div className="w-28 h-28 rounded-full border-4 border-gray-200 shadow-lg overflow-hidden">
<img src={avatarUrl} alt={name} className="w-full h-full object-cover" />
</div>

{/* Name and Wallet Address */}
<div className="mt-4 md:mt-0 text-center md:text-left">
<h1 className="text-2xl font-bold">
{name} <span className="text-gray-500 text-lg">{nickname}</span>
</h1>
<div className="flex items-center gap-2 mt-1">
<div className="px-2 py-1 bg-gray-100 rounded-full text-xs font-medium text-blue-600 flex items-center">
<span>{truncateAddress(walletAddress)}</span>
<button
onClick={() => copyToClipboard(walletAddress)}
className="ml-2 p-1 rounded-full hover:bg-gray-200 transition-colors"
aria-label="Copy wallet address"
>
{copied ? <Check size={12} className="text-green-600" /> : <Copy size={12} />}
</button>
</div>
<a
href={`https://etherscan.io/address/${walletAddress}`}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:text-blue-500"
>
<ExternalLink size={14} />
</a>
</div>
</div>
</div>
</div>

{/* Bio Section */}
<div className="px-6 md:px-10 pb-6">
<div className="bg-gray-50 rounded-lg p-6 text-center">
<h2 className="text-lg font-semibold mb-3 text-blue-600 ">About</h2>
<p className="text-gray-700 leading-relaxed mx-auto max-w-2xl text-justify">{description}</p>
</div>
</div>

{/* Socials Section */}
<div className="px-6 md:px-10 pb-8">
<div className="bg-gray-50 rounded-lg p-6">
<h2 className="text-lg font-semibold mb-4 text-blue-600 text-center">Connect</h2>
<div className="flex gap-3 mx-auto max-w-xs justify-center gap-8">
{socialLinks.map((link, index) => (
<a
key={index}
href={link.url}
className="w-10 h-10 bg-white-200 rounded-lg flex items-center justify-center text-gray-700 hover:scale-150 transition-transform duration-300 transition-colors"
target="_blank"
rel="noopener noreferrer"
aria-label={`${link.platform} profile`}
>
<img src={link.icon} alt={link.platform} className="w-full h-full object-cover" />
</a>
))}
</div>
</div>
</div>
</div>
);
};

export default Web3Profile;
55 changes: 54 additions & 1 deletion packages/nextjs/contracts/deployedContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@
*/
import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";

const deployedContracts = {} as const;
const deployedContracts = {
42161: {
CheckIn: {
address: "0x37D810F1A7025fb3901f3f8Ea6a22919a42BfaA8",
abi: [
{
inputs: [
{
internalType: "address",
name: "_batchRegistryAddress",
type: "address",
},
],
stateMutability: "nonpayable",
type: "constructor",
},
{
inputs: [],
name: "batchRegistryAddress",
outputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "callCheckIn",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [],
name: "owner",
outputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
stateMutability: "view",
type: "function",
},
],
inheritedFunctions: {},
},
},
} as const;

export default deployedContracts satisfies GenericContractsDeclaration;
Loading