Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 4 additions & 3 deletions contracts/scripts/migration-framework/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ export class MigrationRunner {
return result.hash;
}

async migrate(toVersion: number, data: Buffer = Buffer.alloc(0)): Promise<string> {
async migrate(toVersion: number, data: Buffer = Buffer.alloc(0)): Promise<any> {
console.log(`Running migration to version ${toVersion}`);
const result = await this.invoke('migrate', [
xdr.ScVal.scvU32(toVersion),
xdr.ScVal.scvBytes(data)
]);
return result.hash;
return result;
}

async invoke(fnName: string, args: any[], simulate: boolean = false): Promise<any> {
Expand Down Expand Up @@ -116,14 +116,15 @@ export class MigrationRunner {
return txResult;
}

async dryRun(toVersion: number, data: Buffer = Buffer.alloc(0)): Promise<void> {
async dryRun(toVersion: number, data: Buffer = Buffer.alloc(0)): Promise<any> {
console.log(`[Dry Run] Simulating migration to version ${toVersion}`);
const result = await this.invoke('migrate', [
xdr.ScVal.scvU32(toVersion),
xdr.ScVal.scvBytes(data)
], true);

console.log(`[Dry Run] Success. Estimated resources:`, result.minResourceFee);
return result;
}

async rollback(oldWasmHash: string, fromVersion: number, toVersion: number, data: Buffer = Buffer.alloc(0)): Promise<string> {
Expand Down
30 changes: 18 additions & 12 deletions contracts/scripts/migration-framework/test-framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ export interface PerformanceBenchmark {
migrationName: string;
dataSize: string;
executionTime: number;
gasUsed: number;
memoryUsage: number;
instructions: number;
memoryBytes: number;
storageReadBytes: number;
storageWriteBytes: number;
}

export class MigrationTestFramework {
Expand Down Expand Up @@ -264,30 +266,34 @@ export class MigrationTestFramework {
const testName = `Large Data Volume (${size} entries)`;

try {
const testData = await this.generateTestData(size);
await this.setupTestData(testData);

const { result, time } = await this.measureExecutionTime(async () => {
const testData = await this.generateTestData(size);
await this.setupTestData(testData);
return await this.runner.migrate(2);
});

const gasUsed = await this.estimateGasUsage();
const simulation = await this.runner.dryRun(2);
const cost = simulation.cost || { cpuInsns: 0, memBytes: 0 };

this.benchmarks.push({
migrationName: testName,
dataSize: `${size} entries`,
executionTime: time,
gasUsed,
memoryUsage: await this.estimateMemoryUsage()
instructions: Number(cost.cpuInsns),
memoryBytes: Number(cost.memBytes),
storageReadBytes: Number(simulation.results?.[0]?.readBytes || 0),
storageWriteBytes: Number(simulation.results?.[0]?.writeBytes || 0)
});

this.results.push({
testName,
passed: true,
executionTime: time,
gasUsed
gasUsed: Number(cost.cpuInsns)
});

console.log(`✓ ${testName} test PASSED (${time}ms)`);
console.log(`✓ ${testName} test PASSED (${time}ms, ${cost.cpuInsns} instructions)`);
} catch (error) {
this.results.push({
testName,
Expand Down Expand Up @@ -522,11 +528,11 @@ export class MigrationTestFramework {

if (this.benchmarks.length > 0) {
report += `## Performance Benchmarks\n\n`;
report += `| Migration | Data Size | Time (ms) | Gas Used | Memory (bytes) |\n`;
report += `|-----------|-----------|-----------|----------|----------------|\n`;
report += `| Migration | Data Size | Time (ms) | Instructions | Memory (bytes) | Read (bytes) | Write (bytes) |\n`;
report += `|-----------|-----------|-----------|--------------|----------------|--------------|---------------|\n`;

for (const benchmark of this.benchmarks) {
report += `| ${benchmark.migrationName} | ${benchmark.dataSize} | ${benchmark.executionTime} | ${benchmark.gasUsed} | ${benchmark.memoryUsage} |\n`;
report += `| ${benchmark.migrationName} | ${benchmark.dataSize} | ${benchmark.executionTime} | ${benchmark.instructions} | ${benchmark.memoryBytes} | ${benchmark.storageReadBytes} | ${benchmark.storageWriteBytes} |\n`;
}
report += `\n`;
}
Expand Down
8 changes: 4 additions & 4 deletions frontend/app/admin/whistleblower-verification/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import {
AlertCircle,
CheckCircle,
Expand Down Expand Up @@ -55,7 +55,7 @@ export default function WhistleblowerVerificationPanel() {
? applications.find((application) => application.applicationId === selectedApplicationId) ?? null
: null;

async function fetchApplications() {
const fetchApplications = useCallback(async () => {
setLoading(true);
setError(null);

Expand Down Expand Up @@ -87,11 +87,11 @@ export default function WhistleblowerVerificationPanel() {
} finally {
setLoading(false);
}
}
}, [filterStatus]);

useEffect(() => {
void fetchApplications();
}, [filterStatus]);
}, [fetchApplications]);

async function handleApprove(applicationId: string) {
setActionLoading(applicationId);
Expand Down
18 changes: 18 additions & 0 deletions frontend/app/properties/[id]/PropertyDetailClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ import { AmenitiesLegend } from "@/components/properties/AmenitiesLegend";
import { showSuccessToast, showErrorToast } from "@/lib/toast";
import { VerificationBadge, VerificationStatus } from "@/components/properties/verification-badge";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { ApartmentReviews } from "@/components/properties/ApartmentReviews";
import { Suspense } from "react";
import { Loader2 } from "lucide-react";

const properties = allProperties;

Expand Down Expand Up @@ -482,6 +485,21 @@ export default function PropertyDetailClient({
})}
</div>
</div>

{/* Reviews Section */}
<div className="border-3 border-foreground bg-card p-6 shadow-[4px_4px_0px_0px_rgba(26,26,26,1)]">
<h2 className="font-mono text-xl font-bold mb-6">
User Feedback & Reviews
</h2>
<Suspense fallback={
<div className="flex flex-col items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-primary mb-4" />
<p className="text-muted-foreground font-mono">Loading reviews...</p>
</div>
}>
<ApartmentReviews key={propertyId} propertyId={propertyId} />
</Suspense>
</div>
</div>

{/* Sidebar - Pricing & CTA */}
Expand Down
Loading
Loading