Skip to content
This repository has been archived by the owner on Nov 15, 2024. It is now read-only.

Commit

Permalink
rebring#lostchanges#client
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJonaseb11 committed Oct 26, 2024
1 parent 8e70815 commit b1f2bde
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 8 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
9 changes: 8 additions & 1 deletion packages/nextjs/app/(app)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { Metadata } from "next";
import { ClaimRoleCard } from "~~/components/dashboard/ClaimRoleCard";
import { DataRegistry } from "~~/components/dashboard/DataRegistry";
import MineralToken from "~~/components/dashboard/MineralToken";
import { SupplyChain } from "~~/components/dashboard/SupplyChain";

export const metadata: Metadata = {
title: "Dashboard",
};

export default function DashboardPage() {
return (
<div className="w-full min-h-screen flex justify-center items-center">
<div className="w-full min-h-full flex justify-center bg-neutral-400 shadow-2xl">
<ClaimRoleCard />
<DataRegistry />
<MineralToken />
<SupplyChain />
</div>
);
}

76 changes: 69 additions & 7 deletions packages/nextjs/components/dashboard/ClaimRoleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
/* eslint-disable prettier/prettier */
"use client";

import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
import { useState } from "react";
import { ethers } from "ethers";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "../ui/select";
import ParticipantsABI from "../../contracts/Participants.json"; // Adjust the path as needed

const roles = [
type Role = {
label: string;
role: string;
};

const roles: Role[] = [
{ label: "Refiner", role: "REFINER" },
{ label: "Miner", role: "MINER" },
{ label: "Transporter", role: "TRANSPORTER" },
Expand All @@ -11,25 +26,72 @@ const roles = [
];

export const ClaimRoleCard: React.FC = () => {
const [selectedRole, setSelectedRole] = useState<string | null>(null);

const handleRoleChange = (role: string) => {
setSelectedRole(role);
};

const handleClaimRole = async (): Promise<void> => {
if (!selectedRole) return;

try {
if (!window.ethereum) {
alert("Please install MetaMask or any other EVM-wallet");
return;
}

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();

const contractAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512";
const contract = new ethers.Contract(
contractAddress,
ParticipantsABI.abi,
signer
);

const roleBytes32 = ethers.utils.formatBytes32String(selectedRole);

const tx = await contract.registerParticipant(
await signer.getAddress(),
"Participant's name",
"Participant's location",
roleBytes32
);

await tx.wait();
alert("Role claimed successfully!");
} catch (error: any) {
console.error("Error claiming role:", error);
alert("An error occurred while claiming the role.");
}
};

return (
<div className="flex flex-col max-w-72 gap-4 bg-neutral-100 px-6 py-4 rounded-xl shadow">
<div className="flex flex-col max-w-72 gap-4 bg-neutral-100 px-12 py-16 rounded-xl shadow mr-10">
<p className="text-2xl text-center text-neutral-800">Congratulations!</p>
<p className="text-center text-neutral-500">
Claim a role that will be used to identify you in Stoneproof platform.
Claim a role that will be used to identify you on the Stoneproof platform.
</p>
<Select>
<Select onValueChange={handleRoleChange}>
<SelectTrigger className="w-auto">
<SelectValue placeholder="Role in chain" />
</SelectTrigger>
<SelectContent className="bg-white">
{roles.map(role => (
{roles.map((role) => (
<SelectItem key={role.role} value={role.role}>
{role.label}
</SelectItem>
))}
</SelectContent>
</Select>
<button className="bg-sky-400 hover:bg-sky-500 transition-all text-white py-2 px-6 rounded-lg">Continue</button>
<button
onClick={handleClaimRole}
className="bg-sky-400 hover:bg-sky-500 transition-all text-white py-2 px-6 rounded-lg"
>
Continue
</button>
</div>
);
};
76 changes: 76 additions & 0 deletions packages/nextjs/components/dashboard/DataRegistry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* eslint-disable prettier/prettier */
"use client";

import { useState, useEffect } from "react";
import { ethers } from "ethers";
import DataRegistryABI from "../../contracts/DataRegistry.json";
type DataRecord = {
id: string;
description: string;
owner: string;
};

export const DataRegistry: React.FC = () => {
const [records, setRecords] = useState<DataRecord[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);

const fetchDataRecords = async () => {
setIsLoading(true);
try {
if (!window.ethereum) {
alert("Please install MetaMask or any other EVM-wallet");
return;
}

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contractAddress = "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0";
const contract = new ethers.Contract(contractAddress, DataRegistryABI.abi, signer);

const recordsData = await contract.getAllRecords();
const formattedRecords = recordsData.map((record: any) => ({
id: record.id,
description: record.description,
owner: record.owner,
}));

setRecords(formattedRecords);
} catch (error) {
console.error("Error fetching records:", error);
alert("An error occurred while fetching records.");
} finally {
setIsLoading(false);
}
};

useEffect(() => {
fetchDataRecords();
}, []);

return (
<div className="flex flex-col max-w-72 gap-4 bg-neutral-100 px-12 py-16 rounded-xl shadow mr-10">
<p className="text-2xl text-center text-neutral-800">Data Records</p>
<p className="text-center text-xl text-neutral-500">
View and manage data entries on the StoneProof platform.
</p>
{isLoading ? (
<p className="text-center text-neutral-500">Loading records...</p>
) : (
<ul className="bg-white rounded-lg p-4">
{records.map((record) => (
<li key={record.id} className="py-2 border-b border-neutral-200">
<p className="font-bold">{record.description}</p>
<p className="text-sm text-neutral-500">Owned by: {record.owner}</p>
</li>
))}
</ul>
)}
<button
onClick={fetchDataRecords}
className="bg-sky-400 hover:bg-sky-500 transition-all text-white py-2 px-6 rounded-lg mt-4"
>
Refresh Data
</button>
</div>
);
};
99 changes: 99 additions & 0 deletions packages/nextjs/components/dashboard/MineralToken.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use client";

import React, { ChangeEvent, useState } from "react";
// Import ABI correctly
import MineralTokenABI from "../../contracts/MineralToken.json";
import { ethers, providers } from "ethers";

// Props interface for optional address override
interface ClaimRoleCardProps {
contractAddress?: string;
}

// Default contract address used if not provided via props
const DEFAULT_CONTRACT_ADDRESS = "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9";

const ClaimRoleCard: React.FC<ClaimRoleCardProps> = ({ contractAddress = DEFAULT_CONTRACT_ADDRESS }) => {
// State hooks with proper types
const [role, setRole] = useState<string>("");
const [account, setAccount] = useState<string>("");
const [statusMessage, setStatusMessage] = useState<string>("");

// Helper function to get the contract instance
const getContract = (): Contract => {
const provider = new providers.Web3Provider(window.ethereum as any);
const signer = provider.getSigner();
return new ethers.Contract(contractAddress, MineralTokenABI.abi, signer);
};

// Grant role function
const handleGrantRole = async () => {
try {
const contract = getContract();
const tx = await contract.grantRole(ethers.utils.formatBytes32String(role), account);
setStatusMessage(`Transaction submitted: ${tx.hash}`);
await tx.wait();
setStatusMessage(`Transaction confirmed: ${tx.hash}`);
} catch (error: any) {
setStatusMessage(`Error: ${error.message}`);
}
};

// Revoke role function
const handleRevokeRole = async () => {
try {
const contract = getContract();
const tx = await contract.revokeRole(ethers.utils.formatBytes32String(role), account);
setStatusMessage(`Transaction submitted: ${tx.hash}`);
await tx.wait();
setStatusMessage(`Transaction confirmed: ${tx.hash}`);
} catch (error: any) {
setStatusMessage(`Error: ${error.message}`);
}
};

// Handle input changes with reusable setter function
const handleChange =
(setter: React.Dispatch<React.SetStateAction<string>>) => (event: ChangeEvent<HTMLInputElement>) => {
setter(event.target.value);
};

return (
<div className="flex flex-col max-w-72 gap-4 bg-neutral-100 px-12 py-16 rounded-xl shadow mr-10">
<h3 className="text-2xl text-center text-neutral-800">Manage Roles</h3>
<div className="flex flex-col gap-2">
<input
type="text"
placeholder="Role (bytes32)"
value={role}
onChange={handleChange(setRole)}
className="border rounded p-2"
/>
<input
type="text"
placeholder="Account Address"
value={account}
onChange={handleChange(setAccount)}
className="border rounded p-2"
/>
</div>
<div className="flex gap-2">
<button
onClick={handleGrantRole}
className="bg-green-500 hover:bg-green-600 transition-all text-white py-2 px-4 rounded-lg"
>
Grant Role
</button>
<button
onClick={handleRevokeRole}
className="bg-red-500 hover:bg-red-600 transition-all text-white py-2 px-4 rounded-lg"
>
Revoke Role
</button>
</div>
{statusMessage && <p className="text-center text-neutral-600">{statusMessage}</p>}
</div>
);
};

export default ClaimRoleCard;
Loading

0 comments on commit b1f2bde

Please sign in to comment.