-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added contracts_interaction, AgreementTextArea.tsx and TransactionVie…
…w.tsx
- Loading branch information
Showing
14 changed files
with
400 additions
and
85 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React, { useState } from 'react'; | ||
|
||
const AgreementTextarea = () => { | ||
const [agreement, setAgreement] = useState(''); | ||
const wordLimit = 2000; | ||
|
||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
const value = e.target.value; | ||
const words = value.trim().split(/\s+/); // Split by whitespace to get words | ||
|
||
if (words.length <= wordLimit) { | ||
setAgreement(value); | ||
} else { | ||
alert(`Word limit of ${wordLimit} exceeded!`); | ||
} | ||
}; | ||
|
||
return ( | ||
<div> | ||
<textarea | ||
className="textarea w-full mb-2 textarea-bordered" | ||
placeholder="Describe The Agreement" | ||
name="description" | ||
value={agreement} | ||
onChange={handleChange} | ||
/> | ||
<div className="text-right text-sm text-gray-600"> | ||
{agreement.trim().split(/\s+/).length} / {wordLimit} words | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default AgreementTextarea; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,43 @@ | ||
|
||
export default function ProjectDemo() { | ||
return ( | ||
<> | ||
<div className="hero bg-base-100 min-h-screen"> | ||
<div className="hero-content flex-col lg:flex-row-reverse"> | ||
<div className="bg-base-100 flex flex-col lg:flex-row items-center lg:items-start px-4 lg:px-8 py-8 lg:py-16"> | ||
<div className="w-full lg:w-1/2"> | ||
<h2 className='text-base lg:text-xl font-thin landing-pg-intro-txt leading-loose mb-5 animate-slideDown'>Project Demo</h2> | ||
<p className="text-lg lg:text-xl animate-slideUp text-justify mb-5"> | ||
A decentralized escrow platform where parties can engage in agreements with full assurance that the terms of the deal will be met before any funds are released. Using smart contracts deployed on the Base blockchain, a secure environment for deal-making is assured. | ||
</p> | ||
|
||
<div> | ||
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/HoOt8NeLbv0?si=Iqey3wANeQ-5WGfU" | ||
title="YouTube video player" | ||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" > | ||
</iframe> | ||
</div> | ||
<div> | ||
<h2 className='text-base lg:text-xl font-thin landing-pg-intro-txt leading-loose mb-5 animate-slideDown'>Project Demo</h2> | ||
<p className="text-xl animate-slideUp text-justify">A decentralized escrow platform where parties can engage in | ||
agreements with full assurance that the terms of the deal will be met before any funds are released. Using smart | ||
contracts deployed on the Base blockchain, a secure environment for deal-making is assured. | ||
</p> | ||
<div> | ||
<h1 className=" text-lg text-teal-300 mt-5">Key Features of SealedTrust:</h1> | ||
<ul className="text-sm indent-8 "> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ Tamper-proof</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ Trustless Escrow</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ Fraud Protection</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ Transparent Process</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ User-Friendly Interface</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">✓ Global Accessibility</li> | ||
<li className="text-sm animate-slideUp text-teal-300 text-justify break-words leading-8">⨀ Dispute Resolution via Multisig Wallet</li> | ||
</ul> | ||
</div> | ||
<p className="py-6"></p> | ||
<button className="btn btn-outline btn-accent w-96 glass">Secure Your transaction now!</button> | ||
</div> | ||
</div> | ||
<h1 className="text-lg text-teal-300 mt-5">Key Features of SealedTrust:</h1> | ||
<ul className="text-sm lg:text-base indent-8 space-y-3"> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ Tamper-proof</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ Trustless Escrow</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ Fraud Protection</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ Transparent Process</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ User-Friendly Interface</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">✓ Global Accessibility</li> | ||
<li className="animate-slideUp text-teal-300 text-justify">⨀ Dispute Resolution via Multisig Wallet</li> | ||
</ul> | ||
</div> | ||
|
||
</> | ||
<div className="relative w-full lg:w-1/2 mt-8 lg:mt-0 lg:ml-10"> | ||
<div className="relative w-full" style={{ paddingTop: '56.25%' }}> {/* 16:9 Aspect Ratio */} | ||
<iframe | ||
className="absolute top-0 left-0 w-full h-full" | ||
src="https://www.youtube-nocookie.com/embed/HoOt8NeLbv0?si=Iqey3wANeQ-5WGfU" | ||
title="YouTube video player" | ||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" | ||
frameBorder="0" | ||
allowFullScreen | ||
></iframe> | ||
</div> | ||
|
||
<div className="mt-8"> | ||
<button className="btn btn-outline btn-accent w-full lg:w-96 glass"> | ||
Secure Your Transaction Now! | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { CreateAgreement } from './contracts_interaction/WriteContract/CreateAgreement'; | ||
import { GetAgreement } from './contracts_interaction/ReadContract/GetAgreement'; | ||
import { ConfirmDelivery } from './contracts_interaction/WriteContract/ConfirmDelivery'; | ||
|
||
|
||
export function TransactionsView() { | ||
|
||
return ( | ||
<div className='flex-cloumn lg:flex mt-20 mb-1'> | ||
|
||
{/* Create Aggreement */} | ||
<div className="mt-4 w-1/2 bg-base-100 p-6 h-1/2 container lg:mr-1 lg:ml-1 rounded-lg"> | ||
<h1 className="block text-justify lg:text-center pl-2 text-base lg:text-3xl text-teal-200 tracking-widest font-extrabold bg-opacity-80 bg-base-100 mb-4">Set Agreement</h1> | ||
|
||
<CreateAgreement /> | ||
|
||
</div> | ||
|
||
{/* View Agreement State */} | ||
<div className="mt-4 w-1/2 bg-base-100 p-6 h-1/2 container lg:mr-1 lg:ml-1 rounded-lg"> | ||
<h1 className="block text-justify lg:text-center pl-2 text-base lg:text-3xl text-teal-200 tracking-widest font-extrabold bg-opacity-80 bg-base-100 mb-4">Track Agreement State</h1> | ||
|
||
<GetAgreement /> | ||
<ConfirmDelivery /> | ||
|
||
</div> | ||
</div > | ||
) | ||
} |
149 changes: 149 additions & 0 deletions
149
src/components/contracts_interaction/ReadContract/GetAgreement.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import React, { FormEvent, useState, useCallback } from 'react'; | ||
import { type Hex, formatEther, BaseError } from 'viem'; | ||
import { useReadContract } from 'wagmi'; | ||
|
||
// Assuming you have your contract ABI and address defined somewhere | ||
import { contractAbi, contractAddress } from '../../../constants'; | ||
|
||
// Define the State enum to match your contract | ||
enum State { | ||
"AWAITING PAYMENT", | ||
"AWAITING DELIVERY", | ||
COMPLETE, | ||
REFUNDED | ||
} | ||
|
||
interface AgreementDetails { | ||
buyer: Hex; | ||
seller: Hex; | ||
amount: bigint; | ||
state: State; | ||
description: string; | ||
} | ||
|
||
const shortenAddress = (address: string) => { | ||
return `${address.slice(0, 6)}...${address.slice(-4)}`; | ||
}; | ||
|
||
interface CopyIconProps { | ||
isCopied: boolean; | ||
} | ||
|
||
const CopyIcon: React.FC<CopyIconProps> = ({ isCopied }) => ( | ||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={`transition-all duration-300 ${isCopied ? 'text-green-500' : 'text-gray-500'}`}> | ||
{isCopied ? ( | ||
<path d="M20 6L9 17l-5-5" /> | ||
) : ( | ||
<> | ||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" /> | ||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" /> | ||
</> | ||
)} | ||
</svg> | ||
); | ||
|
||
export function GetAgreement() { | ||
const [agreementId, setAgreementId] = useState<string>(''); | ||
const [agreementDetails, setAgreementDetails] = useState<AgreementDetails | null>(null); | ||
const [copiedStates, setCopiedStates] = useState({ | ||
buyer: false, | ||
seller: false | ||
}); | ||
|
||
const { data, error, isLoading, refetch } = useReadContract({ | ||
address: contractAddress, | ||
abi: contractAbi, | ||
functionName: 'getAgreement', | ||
args: [BigInt(agreementId || '0')], | ||
}); | ||
|
||
const fetchAgreementDetails = useCallback(async () => { | ||
if (agreementId) { | ||
const result = await refetch(); | ||
if (result.data) { | ||
setAgreementDetails({ | ||
buyer: result.data[0], | ||
seller: result.data[1], | ||
amount: result.data[2], | ||
state: result.data[3], | ||
description: result.data[4], | ||
}); | ||
} | ||
} | ||
}, [agreementId, refetch]); | ||
|
||
async function submit(e: FormEvent<HTMLFormElement>) { | ||
e.preventDefault(); | ||
const formData = new FormData(e.target as HTMLFormElement); | ||
const id = formData.get('agreementId') as string; | ||
setAgreementId(id); | ||
await fetchAgreementDetails(); | ||
} | ||
|
||
const copyToClipboard = (text: string, field: 'buyer' | 'seller') => { | ||
navigator.clipboard.writeText(text).then(() => { | ||
setCopiedStates(prev => ({ ...prev, [field]: true })); | ||
setTimeout(() => { | ||
setCopiedStates(prev => ({ ...prev, [field]: false })); | ||
}, 2000); // Reset after 2 seconds | ||
}).catch(err => { | ||
console.error('Failed to copy: ', err); | ||
}); | ||
}; | ||
|
||
const formatAmount = (amount: bigint) => { | ||
const ethAmount = parseFloat(formatEther(amount)); | ||
return `${ethAmount.toFixed(4)} ETH`; | ||
}; | ||
|
||
return ( | ||
<div className="pb-7"> | ||
<form className="set" onSubmit={submit}> | ||
<h1 className="pl-2 text-base lg:text-xl text-teal-200 tracking-widest font-extrabold bg-opacity-80 bg-base-100 mb-4">Check Agreement Status</h1> | ||
<label className="input input-bordered flex items-center gap-2 mb-4"> | ||
<input | ||
className="grow" | ||
name="agreementId" | ||
placeholder="Agreement ID" | ||
type="number" | ||
step="1" | ||
required | ||
value={agreementId} | ||
onChange={(e) => setAgreementId(e.target.value)} | ||
/> | ||
</label> | ||
<button disabled={isLoading} type="submit" className='btn btn-outline btn-accent w-full text-base'> | ||
{isLoading ? 'Fetching...' : 'Get Agreement Details'} | ||
</button> | ||
</form> | ||
{isLoading && <div>Fetching agreement details...</div>} | ||
{error && (<div>Error: {(error as BaseError).shortMessage || error.message}</div>)} | ||
{agreementDetails && ( | ||
|
||
<div className="mt-4"> | ||
<div tabIndex={0} className="collapse collapse-arrow border-base-300 bg-base-200 border"> | ||
<div className="collapse-title text-lg font-bold">View Agreement Details:</div> | ||
<div className="collapse-content"> | ||
<p className="flex items-center"> | ||
Buyer: {shortenAddress(agreementDetails.buyer)} | ||
<button onClick={() => copyToClipboard(agreementDetails.buyer, 'buyer')} className="ml-2 focus:outline-none"> | ||
<CopyIcon isCopied={copiedStates.buyer} /> | ||
</button> | ||
</p> | ||
<p className="flex items-center"> | ||
Seller: {shortenAddress(agreementDetails.seller)} | ||
<button onClick={() => copyToClipboard(agreementDetails.seller, 'seller')} className="ml-2 focus:outline-none"> | ||
<CopyIcon isCopied={copiedStates.seller} /> | ||
</button> | ||
</p> | ||
<p>Amount: {formatAmount(agreementDetails.amount)}</p> | ||
<p>State: {State[agreementDetails.state]}</p> | ||
<p>Description: {agreementDetails.description}</p> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
)} | ||
</div> | ||
); | ||
} |
Oops, something went wrong.