Skip to content

Commit 2691efc

Browse files
Merge pull request #171 from chiscookeke11/feat/issue-147-transaction-history-dashboard
feat(dashboard): transaction history dashboard
2 parents 57ccf58 + 2e78c01 commit 2691efc

3 files changed

Lines changed: 523 additions & 0 deletions

File tree

app/api/transactions/route.ts

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
3+
export interface TransactionRecord {
4+
id: string;
5+
hash: string;
6+
contract_name: string;
7+
amount: number;
8+
asset: string;
9+
status: "confirmed" | "pending" | "failed";
10+
date: string;
11+
explorer_url: string;
12+
}
13+
14+
// Sample dataset of blockchain transactions
15+
const MOCK_TRANSACTIONS: TransactionRecord[] = [
16+
{
17+
id: "tx_1",
18+
hash: "0xa84f3e9c1d2b7a85e6f3c4b5a6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
19+
contract_name: "EscrowContract",
20+
amount: 1500.0,
21+
asset: "USDC",
22+
status: "confirmed",
23+
date: "2026-07-26T14:30:00Z",
24+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xa84f3e9c1d2b7a85e6f3c4b5a6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
25+
},
26+
{
27+
id: "tx_2",
28+
hash: "0xb73e2d1c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3",
29+
contract_name: "PaymentDistributor",
30+
amount: 450.5,
31+
asset: "USDC",
32+
status: "confirmed",
33+
date: "2026-07-25T18:15:30Z",
34+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xb73e2d1c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3",
35+
},
36+
{
37+
id: "tx_3",
38+
hash: "0xc62d1c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2",
39+
contract_name: "InvoiceToken",
40+
amount: 2500.0,
41+
asset: "XLM",
42+
status: "pending",
43+
date: "2026-07-25T11:45:00Z",
44+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xc62d1c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2",
45+
},
46+
{
47+
id: "tx_4",
48+
hash: "0xd51c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1",
49+
contract_name: "EscrowContract",
50+
amount: 800.0,
51+
asset: "USDC",
52+
status: "confirmed",
53+
date: "2026-07-24T09:20:10Z",
54+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xd51c0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1",
55+
},
56+
{
57+
id: "tx_5",
58+
hash: "0xe40b9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0",
59+
contract_name: "StellarSettle",
60+
amount: 320.0,
61+
asset: "USDC",
62+
status: "failed",
63+
date: "2026-07-23T16:05:44Z",
64+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xe40b9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0",
65+
},
66+
{
67+
id: "tx_6",
68+
hash: "0xf39a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9",
69+
contract_name: "PaymentDistributor",
70+
amount: 1200.0,
71+
asset: "USDC",
72+
status: "confirmed",
73+
date: "2026-07-22T20:10:00Z",
74+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xf39a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9",
75+
},
76+
{
77+
id: "tx_7",
78+
hash: "0xa28b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8",
79+
contract_name: "EscrowContract",
80+
amount: 3500.0,
81+
asset: "USDC",
82+
status: "confirmed",
83+
date: "2026-07-21T13:40:12Z",
84+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xa28b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8",
85+
},
86+
{
87+
id: "tx_8",
88+
hash: "0xb17c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7",
89+
contract_name: "InvoiceToken",
90+
amount: 600.0,
91+
asset: "XLM",
92+
status: "confirmed",
93+
date: "2026-07-20T10:15:00Z",
94+
explorer_url: "https://stellar.expert/explorer/testnet/tx/0xb17c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7",
95+
},
96+
];
97+
98+
export async function GET(request: NextRequest) {
99+
try {
100+
const { searchParams } = new URL(request.url);
101+
const search = searchParams.get("search")?.toLowerCase().trim() || "";
102+
const status = searchParams.get("status")?.toLowerCase() || "all";
103+
const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10));
104+
const limit = Math.max(1, parseInt(searchParams.get("limit") || "10", 10));
105+
106+
// Filter transactions
107+
let filtered = MOCK_TRANSACTIONS.filter((tx) => {
108+
const matchesSearch =
109+
!search ||
110+
tx.hash.toLowerCase().includes(search) ||
111+
tx.contract_name.toLowerCase().includes(search);
112+
const matchesStatus = status === "all" || tx.status === status;
113+
return matchesSearch && matchesStatus;
114+
});
115+
116+
const total = filtered.length;
117+
const totalPages = Math.ceil(total / limit) || 1;
118+
const offset = (page - 1) * limit;
119+
const paginated = filtered.slice(offset, offset + limit);
120+
121+
// Compute stats
122+
const totalVolume = MOCK_TRANSACTIONS.reduce(
123+
(sum, tx) => (tx.status === "confirmed" ? sum + tx.amount : sum),
124+
0
125+
);
126+
const confirmedCount = MOCK_TRANSACTIONS.filter(
127+
(tx) => tx.status === "confirmed"
128+
).length;
129+
const pendingCount = MOCK_TRANSACTIONS.filter(
130+
(tx) => tx.status === "pending"
131+
).length;
132+
const failedCount = MOCK_TRANSACTIONS.filter(
133+
(tx) => tx.status === "failed"
134+
).length;
135+
136+
return NextResponse.json({
137+
transactions: paginated,
138+
pagination: {
139+
page,
140+
limit,
141+
total,
142+
totalPages,
143+
},
144+
stats: {
145+
totalTransactions: MOCK_TRANSACTIONS.length,
146+
totalVolume,
147+
confirmedCount,
148+
pendingCount,
149+
failedCount,
150+
},
151+
});
152+
} catch (error) {
153+
console.error("[GET /api/transactions] error:", error);
154+
return NextResponse.json(
155+
{ error: "Failed to fetch transactions" },
156+
{ status: 500 }
157+
);
158+
}
159+
}

0 commit comments

Comments
 (0)