import React, { useState } from "react";
import {
ConnectButton,
TransactionButton,
useActiveAccount,
useWalletBalance,
useReadContract,
} from "thirdweb/react";
import { inAppWallet } from "thirdweb/wallets";
import { client } from "./client";
import {
getContract,
prepareContractCall,
sendAndConfirmTransaction,
} from "thirdweb";
import { defineChain } from "thirdweb/chains";
const { VITE_TEMPLATE_CLIENT_ID: THIRDWEB_API_KEY } = import.meta.env;
// Configure Sei network
const rpc = `https://1329.rpc.thirdweb.com/${THIRDWEB_API_KEY}`;
const seiChain = defineChain({
id: 1329,
rpc,
});
// Choose your target chain - EIP-7702 enabled chains
const targetChain = seiChain;
// Get contract address from environment
const CONTRACT_ADDRESS = import.meta.env.VITE_STORAGE_CONTRACT_ADDRESS;
// Configure the Storage contract
const storageContract = getContract({
client,
chain: targetChain,
address: CONTRACT_ADDRESS,
});
// Configure EIP-7702 enabled wallet
const wallets = [
inAppWallet({
auth: {
options: [
"google",
"email",
"passkey",
"apple",
"facebook",
"discord",
"x",
"telegram",
"phone",
"guest",
],
},
// Enable EIP-7702 smart account features
executionMode: {
mode: "EIP7702",
sponsorGas: true, // Enable gasless transactions
},
}),
];
function App() {
const account = useActiveAccount();
const [transactionStatus, setTransactionStatus] = useState<string>("");
// Get wallet balance
const { data: balance } = useWalletBalance({
client,
chain: targetChain,
address: account?.address,
});
const { data: storeValue } = useReadContract({
contract: storageContract,
method: "function retrieve() view returns (uint256)",
});
// Custom store function with status updates
const handleCustomStore = async (storeNumber: number) => {
if (!account) return;
setTransactionStatus("Preparing transaction...");
try {
const transaction = prepareContractCall({
contract: storageContract,
method: "function store(uint256 num)",
params: [BigInt(storeNumber)],
});
setTransactionStatus("Sending transaction...");
const result = await sendAndConfirmTransaction({
transaction,
account,
});
setTransactionStatus(`Success! Transaction: ${result.transactionHash}`);
// Reset status after 5 seconds
setTimeout(() => setTransactionStatus(""), 5000);
} catch (error) {
console.error("Store failed:", error);
setTransactionStatus(
`Error: ${
error instanceof Error ? error.message : "Transaction failed"
}`
);
// Reset status after 5 seconds
setTimeout(() => setTransactionStatus(""), 5000);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 py-8">
<div className="max-w-4xl mx-auto px-4">
<div className="text-center mb-8">
<h1 className="text-4xl font-bold text-gray-900 mb-2">
EIP-7702 Account Abstraction Demo
</h1>
</div>
{/* Connection Section */}
<div className="bg-white shadow-lg p-6 mb-6">
<h2 className="text-2xl font-semibold mb-4 text-gray-800">
Connect Your Smart Account
</h2>
<p className="text-gray-600 mb-4">
Connect with social login and get instant smart account features -
no wallet setup required!
</p>
<ConnectButton
client={client}
wallets={wallets}
chain={targetChain}
connectButton={{
label: "Connect with EIP-7702 Smart Account",
className:
"!bg-indigo-600 !hover:bg-indigo-700 !text-white !py-3 !px-6 ! !font-medium",
}}
/>
{/* Display account info */}
{account && (
<div className="mt-4 p-4 bg-green-50 ">
<h3 className="font-semibold text-green-800 mb-2">
✅ Smart Account Connected
</h3>
<p className="text-sm text-gray-700">
<strong>Address:</strong> {account.address}
</p>
<p className="text-sm text-gray-700">
<strong>Balance:</strong> {balance?.displayValue}{" "}
{balance?.symbol}
</p>
</div>
)}
</div>
{account && (
<>
{/* Contract Information */}
<div className="bg-white shadow-lg p-6 mb-6">
<div className="flex items-center justify-center gap-4">
<div className="text-center p-4 bg-blue-50 ">
<p className="text-sm text-gray-600 mb-1">Current Stored Value</p>
<p className="text-2xl font-bold text-purple-600">
{storeValue?.toString() || "0"}
</p>
</div>
</div>
</div>
{/* Transaction Section */}
<div className="bg-white shadow-lg p-6 mb-6">
<div className="space-y-6">
<div className="border-l-4 border-blue-500 pl-4">
<h4 className="font-semibold text-gray-800 mb-2">Store</h4>
<TransactionButton
transaction={() =>
prepareContractCall({
contract: storageContract,
method: "function store(uint256 num)",
params: [BigInt(37)],
})
}
onTransactionSent={(result) => {
console.log("Transaction sent:", result.transactionHash);
setTransactionStatus(
"Transaction sent, waiting for confirmation..."
);
}}
onTransactionConfirmed={(result) => {
console.log(
"Transaction confirmed:",
result.transactionHash
);
setTransactionStatus(
`Stored successfully! TX: ${result.transactionHash}`
);
setTimeout(() => setTransactionStatus(""), 5000);
}}
onError={(error) => {
console.error("Transaction error:", error);
setTransactionStatus(`❌ Error: ${error.message}`);
setTimeout(() => setTransactionStatus(""), 5000);
}}
>
Store 37
</TransactionButton>
</div>
</div>
</div>
{/* Custom Store Button */}
<div className="bg-white shadow-lg p-6 mb-6">
<div className="border-l-4 border-green-500 pl-4">
<h4 className="font-semibold text-gray-800 mb-2">
Custom Implementation
</h4>
<button
onClick={() => {
const amount = prompt("Enter number to store");
const num = Number(amount);
if (!isNaN(num)) {
handleCustomStore(num);
}
}}
className="bg-green-600 hover:bg-green-700 text-white px-4 py-2 font-medium transition-colors"
>
Store Custom Number
</button>
</div>
</div>
{/* Status Display */}
{transactionStatus && (
<div className="bg-white shadow-lg p-6 mb-6">
<h4 className="font-semibold mb-2">Transaction Status</h4>
<p className="text-sm text-gray-700 font-mono bg-gray-100 p-3 rounded">
{transactionStatus}
</p>
</div>
)}
</>
)}
</div>
</div>
);
}
export default App;