Skip to content
Open
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: 0 additions & 1 deletion session-2/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import './App.css';
import WalletContextProvider from "./components/WalletContextProvider";
import {AppBar} from "./components/AppBar/AppBar";
Expand Down
109 changes: 57 additions & 52 deletions session-2/src/components/BalanceCard/BalanceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,65 @@
import { FC, useState, useEffect, useCallback } from 'react';
import { useWallet } from '@solana/wallet-adapter-react';
import { Connection, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
import { FC, useState, useEffect, useCallback } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
import { SOLANA_TESTNET_URL } from "../../const";
import './BalanceCard.css';
import "./BalanceCard.css";

// Create a connection to the cluster
const connection = new Connection(SOLANA_TESTNET_URL, "confirmed");

export const BalanceCard: FC = () => {
const { publicKey, connected } = useWallet();
const [balance, setBalance] = useState<number | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const { publicKey, connected } = useWallet();
const [balance, setBalance] = useState<number | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);

const fetchBalance = useCallback(async () => {
if (!publicKey) {
console.log("No public key");
return;
}
setLoading(true);
setError(null);
try {
const balanceInLamports = await connection.getBalance(publicKey);
const balanceInSOL = balanceInLamports / LAMPORTS_PER_SOL;
console.log("Public Key:", publicKey.toBase58());
console.log("Balance in SOL:", balanceInSOL);
setBalance(balanceInSOL);
} catch (err) {
console.error("Error fetching balance:", err);
setError("Failed to fetch balance");
}
setLoading(false);
}, [publicKey]);
const fetchBalance = useCallback(async () => {
if (!publicKey) {
console.log("No public key");
return;
}
setLoading(true);
setError(null);
try {
// Fetch the balance of the connected wallet
const balanceInLamports = await connection.getBalance(publicKey);

useEffect(() => {
if (connected) {
fetchBalance();
}
}, [connected, fetchBalance]);
// Convert the balance to SOL
const balanceInSOL = balanceInLamports / LAMPORTS_PER_SOL;

return (
<div className="BalanceCard">
<div className="title">
<h2>Wallet Balance</h2>
</div>
<div className="balance">
{connected ? (
<h2>{loading ? "Loading..." : `${balance ?? 0} SOL`}</h2>
) : (
<p>Please Connect Wallet</p>
)}
{connected && (
<button className="refresh-button" onClick={fetchBalance}>
<img src="refresh.png" alt="refresh" />
</button>
)}
</div>
</div>
);
};
console.log("Public Key:", publicKey.toBase58());
console.log("Balance in SOL:", balanceInSOL);
setBalance(balanceInSOL);
} catch (err) {
console.error("Error fetching balance:", err);
setError("Failed to fetch balance");
}
setLoading(false);
}, [publicKey]);

useEffect(() => {
if (connected) {
fetchBalance();
}
}, [connected, fetchBalance]);

return (
<div className="BalanceCard">
<div className="title">
<h2>Wallet Balance</h2>
</div>
<div className="balance">
{connected ? (
<h2>{loading ? "Loading..." : `${balance ?? 0} SOL`}</h2>
) : (
<p>Please Connect Wallet</p>
)}
{connected && (
<button className="refresh-button" onClick={fetchBalance}>
<img src="refresh.png" alt="refresh" />
</button>
)}
</div>
</div>
);
};
234 changes: 129 additions & 105 deletions session-2/src/components/History/History.tsx
Original file line number Diff line number Diff line change
@@ -1,122 +1,146 @@
import { FC, useState, useEffect, useCallback } from 'react';
import { useWallet } from '@solana/wallet-adapter-react';
import { ConfirmedSignatureInfo, Connection, PublicKey } from '@solana/web3.js';
import { FC, useState, useEffect, useCallback } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { ConfirmedSignatureInfo, Connection } from "@solana/web3.js";
import { SOLANA_TESTNET_URL, SOLANA_DEVNET_URL } from "../../const";
// @ts-ignore
import * as timeago from 'timeago.js';
import './History.css';
import * as timeago from "timeago.js";
import "./History.css";

const connection = new Connection(SOLANA_TESTNET_URL, "confirmed");

const shortenSignature = (signature: string) => {
return `${signature.slice(0, 7)}.........${signature.slice(-7)}`;
return `${signature.slice(0, 7)}.........${signature.slice(-7)}`;
};

interface Transaction {
signature: string;
slot: number;
blockTime: number;
success: boolean;
signature: string;
slot: number;
blockTime: number;
success: boolean;
}

export const History: FC = () => {
const { publicKey, connected } = useWallet();
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const { publicKey, connected } = useWallet();
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [loading, setLoading] = useState<boolean>(true);

const fetchTransactionHistory = useCallback(async () => {
if (!publicKey) return;
setLoading(true);
try {
const confirmedSignatures = await connection.getSignaturesForAddress(publicKey, { limit: 10 });
const confirmedTransactions = await Promise.all(
confirmedSignatures.map(async (signatureInfo: ConfirmedSignatureInfo) => {
const transaction = await connection.getTransaction(signatureInfo.signature);
return {
signature: signatureInfo.signature,
slot: transaction!.slot,
blockTime: transaction!.blockTime!,
success: transaction!.meta!.err === null,
};
})
const fetchTransactionHistory = useCallback(async () => {
if (!publicKey) return;
setLoading(true);
try {
// Fetch the transaction signatures for the connected wallet
const confirmedSignatures = await connection.getSignaturesForAddress(
publicKey,
{ limit: 10 }
);

// Fetch the transaction details for each signature
const confirmedTransactions = await Promise.all(
confirmedSignatures.map(
async (signatureInfo: ConfirmedSignatureInfo) => {
const transaction = await connection.getTransaction(
signatureInfo.signature
);
setTransactions(confirmedTransactions);
} catch (error) {
console.error('Error fetching transactions:', error);
}
setLoading(false);
}, [publicKey]);
return {
signature: signatureInfo.signature,
slot: transaction!.slot,
blockTime: transaction!.blockTime!,
success: transaction!.meta!.err === null,
};
}
)
);
setTransactions(confirmedTransactions);
} catch (error) {
console.error("Error fetching transactions:", error);
}
setLoading(false);
}, [publicKey]);

useEffect(() => {
if (connected) {
fetchTransactionHistory();
} else {
setTransactions([]);
setLoading(false);
}
}, [connected, fetchTransactionHistory]);
useEffect(() => {
if (connected) {
fetchTransactionHistory();
} else {
setTransactions([]);
setLoading(false);
}
}, [connected, fetchTransactionHistory]);

const copyToClipboard = (signature: string) => {
navigator.clipboard.writeText(signature)
.then(() => {
// alert("Signature copied to clipboard!");
})
.catch(err => {
console.error('Failed to copy signature: ', err);
});
};
const copyToClipboard = (signature: string) => {
navigator.clipboard
.writeText(signature)
.then(() => {
// alert("Signature copied to clipboard!");
})
.catch((err) => {
console.error("Failed to copy signature: ", err);
});
};

return (
<div className="history-card">
<div className="title">
<h2>Transaction History</h2>
{connected && (
<button className="refresh-button" onClick={fetchTransactionHistory}>
<img src="refresh.png" alt="Refresh" />
</button>
)}
</div>
<div className="table-container">
{loading ? (
<p>Loading...</p>
) : (
<table className="transaction-table">
<thead>
<tr>
<th>Transaction Signature</th>
<th>Block</th>
<th>Timestamp</th>
<th>Ago</th>
<th>Result</th>
</tr>
</thead>
<tbody>
{transactions.length === 0 ? (
<tr>
<td colSpan={5} className="no-history-text">No transactions found</td>
</tr>
) : (
transactions.map((transaction, index) => (
<tr key={index}>
<td onClick={() => copyToClipboard(transaction.signature)} className="pointer-cursor">
<img src="copy.png" alt="" className="copy-icon" />
{shortenSignature(transaction.signature)}
</td>
<td>{transaction.slot}</td>
<td>{new Date(transaction.blockTime * 1000).toString().replace('GMT+0530 (India Standard Time)', '')}</td>
<td>{timeago.format(new Date(transaction.blockTime * 1000))}</td>
<td>
<span className={transaction.success ? 'success' : 'error'}>
{transaction.success ? 'Success' : 'Failed'}
</span>
</td>
</tr>
))
)}
</tbody>
</table>
)}
</div>
</div>
);
};
return (
<div className="history-card">
<div className="title">
<h2>Transaction History</h2>
{connected && (
<button className="refresh-button" onClick={fetchTransactionHistory}>
<img src="refresh.png" alt="Refresh" />
</button>
)}
</div>
<div className="table-container">
{loading ? (
<p>Loading...</p>
) : (
<table className="transaction-table">
<thead>
<tr>
<th>Transaction Signature</th>
<th>Block</th>
<th>Timestamp</th>
<th>Ago</th>
<th>Result</th>
</tr>
</thead>
<tbody>
{transactions.length === 0 ? (
<tr>
<td colSpan={5} className="no-history-text">
No transactions found
</td>
</tr>
) : (
transactions.map((transaction, index) => (
<tr key={index}>
<td
onClick={() => copyToClipboard(transaction.signature)}
className="pointer-cursor"
>
<img src="copy.png" alt="" className="copy-icon" />
{shortenSignature(transaction.signature)}
</td>
<td>{transaction.slot}</td>
<td>
{new Date(transaction.blockTime * 1000)
.toString()
.replace("GMT+0530 (India Standard Time)", "")}
</td>
<td>
{timeago.format(new Date(transaction.blockTime * 1000))}
</td>
<td>
<span
className={transaction.success ? "success" : "error"}
>
{transaction.success ? "Success" : "Failed"}
</span>
</td>
</tr>
))
)}
</tbody>
</table>
)}
</div>
</div>
);
};
Loading