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
66 changes: 56 additions & 10 deletions frontend/src/lib/contracts.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { parseUserProfile, parseBotNFT, parseListing } from "./contracts";
import { parseListing, parseUserProfile, parseBotNFT } from "./contracts";

describe("parse helpers in contracts.ts", () => {
describe("parseUserProfile", () => {
it("should parse raw user profile data correctly with total_points or points", () => {
const rawData = {
username: "alice",
points: "150",
};

const result = parseUserProfile(rawData);

expect(result).toEqual({
username: "alice",
points: 150n,
});
});

it("parses correctly with bigint points", () => {
const raw = { username: "alice", points: 100n };
const parsed = parseUserProfile(raw);
Expand All @@ -25,6 +39,30 @@ describe("parse helpers in contracts.ts", () => {
last_claim_timestamp: 123456789n,
};

it("should parse raw bot NFT data correctly with string tier", () => {
const rawData = {
id: 10,
name: "Bot #10",
owner: "GXYZ987654321",
tier: "Gold",
accrual_rate: "50",
minted_at: 1690000000,
last_claim_timestamp: "1690005000",
};

const result = parseBotNFT(rawData);

expect(result).toEqual({
id: 10n,
name: "Bot #10",
owner: "GXYZ987654321",
tier: "Gold",
accrual_rate: 50n,
minted_at: 1690000000,
last_claim_timestamp: 1690005000n,
});
});

it("parses tier as string", () => {
const parsed = parseBotNFT({ ...baseRaw, tier: "Premium" });
expect(parsed.tier).toBe("Premium");
Expand Down Expand Up @@ -63,16 +101,24 @@ describe("parse helpers in contracts.ts", () => {
});

describe("parseListing", () => {
it("parses listing correctly", () => {
const raw = {
id: 100n,
seller: "GBDUJF...",
bot_id: 5n,
price: 500n,
listed_at: 123456789n,
it("should parse a valid raw marketplace listing map into a MarketplaceListing object", () => {
const rawData = {
id: "1",
seller: "GABC1234567890",
bot_id: 42,
price: "1000000000",
listed_at: 1700000000n,
};
const parsed = parseListing(raw);
expect(parsed).toEqual(raw);

const result = parseListing(rawData);

expect(result).toEqual({
id: 1n,
seller: "GABC1234567890",
bot_id: 42n,
price: 1000000000n,
listed_at: 1700000000n,
});
});

it("parses missing fields gracefully", () => {
Expand Down
41 changes: 17 additions & 24 deletions frontend/src/lib/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ export function parseBotNFT(rawData: Record<string, unknown>): BotNFT {
};
}

/**
* Parse a raw scVal map from the marketplace contract into a typed MarketplaceListing.
*/
export function parseListing(
rawData: Record<string, unknown>
): MarketplaceListing {
return {
id: toBigInt(rawData.id),
seller: String(rawData.seller ?? ""),
bot_id: toBigInt(rawData.bot_id),
price: toBigInt(rawData.price),
listed_at: toBigInt(rawData.listed_at),
};
}

/**
* Get the AMT token balance for a user.
* Calls token contract's balance() function.
Expand Down Expand Up @@ -208,16 +223,6 @@ export async function cancelListing(
);
}

export function parseListing(listing: Record<string, unknown>): MarketplaceListing {
return {
id: toBigInt(listing.id),
seller: String(listing.seller ?? ""),
bot_id: toBigInt(listing.bot_id),
price: toBigInt(listing.price),
listed_at: toBigInt(listing.listed_at),
};
}

/**
* Get all active marketplace listings.
* Returns array of listing objects.
Expand All @@ -238,13 +243,7 @@ export async function getActiveListings(
defaultSource(sourceAddress)
);
if (!Array.isArray(listingsRaw)) return [];
return listingsRaw.map((listing: Record<string, unknown>) => ({
id: toBigInt(listing.id),
seller: String(listing.seller ?? ""),
bot_id: toBigInt(listing.bot_id),
price: toBigInt(listing.price),
listed_at: toBigInt(listing.listed_at),
}));
return listingsRaw.map((listing: Record<string, unknown>) => parseListing(listing));
} catch {
return [];
}
Expand All @@ -265,13 +264,7 @@ export async function getUserListings(
userAddress
);
if (!Array.isArray(listingsRaw)) return [];
return listingsRaw.map((listing: Record<string, unknown>) => ({
id: toBigInt(listing.id),
seller: String(listing.seller ?? ""),
bot_id: toBigInt(listing.bot_id),
price: toBigInt(listing.price),
listed_at: toBigInt(listing.listed_at),
}));
return listingsRaw.map((listing: Record<string, unknown>) => parseListing(listing));
} catch {
return [];
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export interface MarketplaceListing {
listed_at: bigint;
}

export type Listing = MarketplaceListing;

export interface UserVault {
user: string;
balance: bigint;
Expand Down