Skip to content

Commit c376785

Browse files
edit/delete listings without contract changes
1 parent 07919e4 commit c376785

File tree

4 files changed

+177
-254
lines changed

4 files changed

+177
-254
lines changed

packages/indexer/src/index.ts

Lines changed: 18 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,6 @@ async function fetchIpfsJson(cidOrUrl: string): Promise<any | null> {
8080
return null;
8181
}
8282

83-
const denormalizeMetadata = (json: any): any => {
84-
return {
85-
metadata: json,
86-
title: typeof json?.title === "string" ? json.title : null,
87-
description: typeof json?.description === "string" ? json.description : null,
88-
category: typeof json?.category === "string" ? json.category : null,
89-
image: typeof json?.image === "string" ? json.image : null,
90-
contact: typeof json?.contact === "object" ? json.contact : (typeof json?.contact === "string" ? json.contact : null),
91-
tags: Array.isArray(json?.tags) ? json.tags : (typeof json?.tags === "string" ? json.tags : null),
92-
price: typeof json?.price === "string" || typeof json?.price === "number" ? String(json.price) : null,
93-
currency: typeof json?.currency === "string" ? json.currency : null,
94-
locationId: typeof json?.locationId === "string" ? json.locationId : null,
95-
};
96-
}
97-
9883
// Minimal ABI to read listing pointer + data from Marketplace
9984
const marketplaceGetListingAbi = [
10085
{
@@ -112,12 +97,6 @@ const marketplaceGetListingAbi = [
11297
},
11398
] as const;
11499

115-
const erc20MetaAbi = [
116-
{ name: "name", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
117-
{ name: "symbol", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
118-
{ name: "decimals", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
119-
];
120-
121100
function signatureToSelector(signature: string): `0x${string}` {
122101
const hash = keccak256(stringToHex(signature));
123102
return (`0x${hash.slice(2, 10)}`) as `0x${string}`;
@@ -174,6 +153,11 @@ ponder.on("Marketplace:ListingCreated" as any, async ({ event, context }) => {
174153
.set({ tokenName: "Ether", tokenSymbol: "ETH", tokenDecimals: 18 })
175154
.where(eq(listings.id, id));
176155
} else {
156+
const erc20MetaAbi = [
157+
{ name: "name", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
158+
{ name: "symbol", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
159+
{ name: "decimals", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
160+
] as const;
177161
const [name, symbol, decimals] = await Promise.all([
178162
publicClient.readContract({ address: pt as `0x${string}`, abi: erc20MetaAbi, functionName: "name" }).catch(() => null),
179163
publicClient.readContract({ address: pt as `0x${string}`, abi: erc20MetaAbi, functionName: "symbol" }).catch(() => null),
@@ -197,7 +181,19 @@ ponder.on("Marketplace:ListingCreated" as any, async ({ event, context }) => {
197181
try {
198182
const json: any | null = await fetchIpfsJson(cid);
199183
if (json) {
200-
const denorm = denormalizeMetadata(json);
184+
const denorm: any = {
185+
metadata: json,
186+
// Top-level denormalized fields for convenient querying & UI
187+
title: typeof json?.title === "string" ? json.title : null,
188+
description: typeof json?.description === "string" ? json.description : null,
189+
category: typeof json?.category === "string" ? json.category : null,
190+
image: typeof json?.image === "string" ? json.image : null,
191+
contact: typeof json?.contact === "object" ? json.contact : (typeof json?.contact === "string" ? json.contact : null),
192+
tags: Array.isArray(json?.tags) ? json.tags : (typeof json?.tags === "string" ? json.tags : null),
193+
price: typeof json?.price === "string" || typeof json?.price === "number" ? String(json.price) : null,
194+
currency: typeof json?.currency === "string" ? json.currency : null,
195+
locationId: typeof json?.locationId === "string" ? json.locationId : null,
196+
};
201197
await db.sql.update(listings).set(denorm).where(eq(listings.id, id));
202198
}
203199
} catch {}
@@ -241,88 +237,7 @@ ponder.on("Marketplace:ListingActivationChanged" as any, async ({ event, context
241237
.where(eq(listings.id, args.listingId.toString()));
242238
});
243239

244-
<<<<<<< Updated upstream
245-
<<<<<<< Updated upstream
246-
ponder.on("Marketplace:ListingDeleted" as any, async ({ event, context }) => {
247-
const { db } = context;
248-
const args = (event as any).args;
249-
const listingId = args.id.toString();
250-
await db.sql.delete(listings).where(eq(listings.id, listingId));
251-
});
252-
253-
ponder.on("Marketplace:ListingContenthashUpdated" as any, async ({ event, context }) => {
254-
const { db } = context;
255-
const listingId = (event as any).args.id.toString();
256-
const cid = (event as any).args.contenthash as string;
257-
258-
try {
259-
await db.sql.update(listings).set({ cid }).where(eq(listings.id, listingId));
260-
const json: any | null = await fetchIpfsJson(cid);
261-
if (json) {
262-
const denorm = denormalizeMetadata(json);
263-
await db.sql.update(listings).set(denorm).where(eq(listings.id, listingId));
264-
}
265-
266-
try {
267-
const mpAddress = ((event as any).log?.address as string) || ((event as any).transaction?.to as string);
268-
if (mpAddress) {
269-
const [, , , , listingData] = (await publicClient.readContract({
270-
address: mpAddress as `0x${string}`,
271-
abi: marketplaceGetListingAbi,
272-
functionName: "getListing",
273-
args: [BigInt(listingId)],
274-
})) as unknown as [string, string, string, boolean, Hex];
275-
276-
if (listingData && (listingData).length > 0) {
277-
try {
278-
const [paymentToken, price] = decodeAbiParameters(
279-
[{ type: "address" }, { type: "uint256" }],
280-
listingData,
281-
);
282-
await db.sql
283-
.update(listings)
284-
.set({
285-
paymentToken: paymentToken?.toLowerCase?.() ?? null,
286-
priceWei: price?.toString?.() ?? null,
287-
})
288-
.where(eq(listings.id, listingId));
289-
290-
const isEth = !paymentToken || paymentToken === zeroAddress;
291-
if (isEth) {
292-
await db.sql
293-
.update(listings)
294-
.set({ tokenName: "Ether", tokenSymbol: "ETH", tokenDecimals: 18 })
295-
.where(eq(listings.id, listingId));
296-
} else {
297-
const [name, symbol, decimals] = await Promise.all([
298-
publicClient.readContract({ address: paymentToken as `0x${string}`, abi: erc20MetaAbi, functionName: "name" }),
299-
publicClient.readContract({ address: paymentToken as `0x${string}`, abi: erc20MetaAbi, functionName: "symbol" }),
300-
publicClient.readContract({ address: paymentToken as `0x${string}`, abi: erc20MetaAbi, functionName: "decimals" }),
301-
]);
302-
await db.sql
303-
.update(listings)
304-
.set({
305-
tokenName: typeof name === "string" ? name : null,
306-
tokenSymbol: typeof symbol === "string" ? symbol : null,
307-
tokenDecimals: typeof decimals === "number" ? decimals : (typeof decimals === "bigint" ? Number(decimals) : null),
308-
})
309-
.where(eq(listings.id, listingId));
310-
}
311-
} catch {}
312-
}
313-
}
314-
} catch (chainErr) {
315-
console.error(`[Ponder] Error refreshing on-chain listing data for ${listingId}:`, chainErr);
316-
}
317-
} catch (e) {
318-
console.error(`[Ponder] Error handling ListingContenthashUpdated for ${listingId}:`, e);
319-
}
320-
});
321-
=======
322-
=======
323-
>>>>>>> Stashed changes
324240
// (No SimpleListings event handlers required)
325-
>>>>>>> Stashed changes
326241

327242
// --- EAS Reviews indexing ---
328243
// Read new per-chain keyed shape only

packages/nextjs/app/listing/[id]/page.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Suspense, useCallback, useEffect, useMemo, useState } from "react";
44
import Image from "next/image";
55
import { useRouter, useSearchParams } from "next/navigation";
66
import { useParams } from "next/navigation";
7-
import { Hex, decodeAbiParameters, formatUnits } from "viem";
7+
import { Hex, decodeAbiParameters, formatUnits, keccak256, stringToHex } from "viem";
88
import { useAccount } from "wagmi";
99
import { useMiniapp } from "~~/components/MiniappProvider";
1010
import FcAddressRating from "~~/components/marketplace/FcAddressRating";
@@ -152,14 +152,19 @@ const ListingDetailsPageInner = () => {
152152
setShowDeleteModal(false);
153153
setDeleting(true);
154154
try {
155+
// Call the close action to deactivate the listing instead of deleting it
156+
const sigHash = keccak256(stringToHex("close(uint256,address,bool,address,bytes)"));
157+
const selector = `0x${sigHash.slice(2, 10)}` as `0x${string}`;
158+
const action = (selector + "0".repeat(64 - 8)) as `0x${string}`;
159+
155160
await writeMarketplace({
156-
functionName: "deleteListing",
157-
args: [idNum],
161+
functionName: "callAction",
162+
args: [idNum, action, "0x"],
158163
});
159164
router.push("/");
160165
} catch (error) {
161-
console.error("Error deleting listing:", error);
162-
alert("Failed to delete listing. Please try again.");
166+
console.error("Error closing listing:", error);
167+
alert("Failed to close listing. Please try again.");
163168
setDeleting(false);
164169
}
165170
}, [idNum, writeMarketplace, router]);

0 commit comments

Comments
 (0)