Автообновление наград каждую секунду без перезагрузки
Добавим: ✅ Автоматическое обновление баланса и вознаграждений ✅ Использование setInterval для обновления данных ✅ Оптимизированный рендеринг, чтобы избежать лишних запросов
Автообновление наград каждую секунду без перезагрузки
Добавим:
✅ Автоматическое обновление баланса и вознаграждений
✅ Использование setInterval
для обновления данных
✅ Оптимизированный рендеринг, чтобы избежать лишних запросов
1. Обновленный код pages/index.js
pages/index.js
import { useWallet } from "@solana/wallet-adapter-react";
import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
import { useEffect, useState } from "react";
import { Connection, PublicKey } from "@solana/web3.js";
import { Program, AnchorProvider, web3, BN } from "@project-serum/anchor";
import { motion } from "framer-motion";
const programId = new PublicKey("9HhvqA...pXr"); // Ваш Program ID
const network = "https://api.devnet.solana.com";
export default function Home() {
const { publicKey } = useWallet();
const [provider, setProvider] = useState(null);
const [program, setProgram] = useState(null);
const [amount, setAmount] = useState(100);
const [stakeInfo, setStakeInfo] = useState(null);
const [reward, setReward] = useState(0);
useEffect(() => {
if (publicKey) {
const connection = new Connection(network, "processed");
const walletProvider = new AnchorProvider(connection, window.solana, {});
const idl = require("../idl.json"); // Подключение IDL контракта
setProvider(walletProvider);
setProgram(new Program(idl, programId, walletProvider));
fetchStakeInfo(publicKey);
// Устанавливаем интервал обновления каждые 1 секунду
const interval = setInterval(() => {
fetchStakeInfo(publicKey);
}, 1000);
return () => clearInterval(interval); // Очистка интервала при размонтировании
}
}, [publicKey]);
// Получаем текущий стейк пользователя
const fetchStakeInfo = async (walletAddress) => {
if (!program) return;
try {
const userStakeAccount = await program.account.userStaking.fetch(walletAddress);
setStakeInfo(userStakeAccount);
// Рассчитываем награды
const currentTime = Math.floor(Date.now() / 1000);
const duration = currentTime - userStakeAccount.startTime.toNumber();
const rewardAmount = (userStakeAccount.amount.toNumber() * 10 * duration) / 1_000_000;
setReward(rewardAmount);
} catch (error) {
console.log("No staking found for user.");
setStakeInfo(null);
setReward(0);
}
};
const stakeTokens = async () => {
if (!publicKey || !program) return;
await program.rpc.stake(new BN(amount), {
accounts: {
stakingAccount: programId,
userStaking: publicKey,
userTokenAccount: publicKey,
tokenProgram: web3.TOKEN_PROGRAM_ID,
},
});
alert(`Staked ${amount} RUM!`);
fetchStakeInfo(publicKey);
};
const unstakeTokens = async () => {
if (!publicKey || !program) return;
await program.rpc.unstake({
accounts: {
stakingAccount: programId,
userStaking: publicKey,
userTokenAccount: publicKey,
tokenProgram: web3.TOKEN_PROGRAM_ID,
},
});
alert("Unstaked successfully!");
fetchStakeInfo(publicKey);
};
return (
<div className="min-h-screen bg-gray-900 text-white flex flex-col items-center justify-center p-6">
<motion.h1
className="text-4xl font-bold mb-4"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
RentumAI Staking
</motion.h1>
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
>
<WalletMultiButton className="mb-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" />
</motion.div>
{publicKey && (
<motion.div
className="bg-gray-800 p-6 rounded-lg shadow-lg text-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<h2 className="text-xl font-semibold mb-4">Staking Details</h2>
{stakeInfo ? (
<motion.div
key={stakeInfo.amount.toString()}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.4 }}
>
<p className="mb-2">Staked Amount: <strong>{stakeInfo.amount.toNumber()} RUM</strong></p>
<p className="mb-2">Reward: <strong>{reward.toFixed(2)} RUM</strong></p>
</motion.div>
) : (
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.4 }}
className="mb-4"
>
You have no active stake.
</motion.p>
)}
<motion.input
type="number"
value={amount}
onChange={(e) => setAmount(e.target.value)}
className="w-full px-3 py-2 mb-4 text-black rounded"
placeholder="Enter amount"
whileFocus={{ scale: 1.05 }}
/>
<motion.button
onClick={stakeTokens}
className="w-full bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded mb-2"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
Stake
</motion.button>
<motion.button
onClick={unstakeTokens}
className="w-full bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
Unstake
</motion.button>
</motion.div>
)}
</div>
);
}
2. Что изменилось?
✅ Автообновление стейка и наград каждую секунду
✅ Используется setInterval
для обновления данных
✅ Очистка интервала (clearInterval
) при отключении кошелька
✅ Оптимизированный рендеринг — без лишних запросов
3. Запуск проекта
npm run dev
Открываем http://localhost:3000
, подключаем Phantom Wallet и видим автообновление наград 🚀
Last updated