- {imageUrl ? (
-
- ) : (
- <>
-
-
- >
- )}
+
{chain !== undefined && (
= [];
if (bridgeRequests[0]?.req.chain_src === "eth") {
requestMetadata = await alchemy.nft.getNftMetadataBatch(
diff --git a/apps/web/src/server/api/routers/l1Nfts.ts b/apps/web/src/server/api/routers/l1Nfts.ts
index eac02d1f..736838a9 100644
--- a/apps/web/src/server/api/routers/l1Nfts.ts
+++ b/apps/web/src/server/api/routers/l1Nfts.ts
@@ -1,10 +1,24 @@
import { Alchemy, Network, NftFilters } from "alchemy-sdk";
+import { createClient, getContract, http } from "viem";
+import { mainnet } from "viem/chains";
import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
+import l1_bridge_contract from "../../../app/_abis/bridge_l1_abi.json";
import { type Collection, type Nft } from "../types";
+const viemClient = createClient({
+ chain: mainnet,
+ transport: http(process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_RPC_ENDPOINT ?? ""),
+});
+
+const bridgeL1Contract = getContract({
+ abi: l1_bridge_contract,
+ address: process.env.NEXT_PUBLIC_L1_BRIDGE_ADDRESS as `0x${string}`,
+ client: viemClient,
+});
+
const alchemy = new Alchemy({
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_MAINNET,
@@ -39,18 +53,23 @@ export const l1NftsRouter = createTRPCRouter({
pageSize,
});
+ const whitelistedCollections =
+ (await bridgeL1Contract.read?.getWhiteListedCollections?.()) as
+ | Array
+ | undefined;
+
const collections: Array = contracts.map((contract) => {
- const media =
- contract.address === process.env.EVERAI_L1_CONTRACT_ADDRESS
- ? contract.media[0]?.raw
- : contract.media[0]?.thumbnail;
+ const media = contract.media[0];
+ const mediaSrc = media?.gateway ?? media?.thumbnail ?? media?.raw;
+ const mediaFormat = media?.format === "mp4" ? "video" : "image";
+ const isBridgeable =
+ whitelistedCollections !== undefined &&
+ whitelistedCollections.includes(contract.address);
return {
contractAddress: contract.address,
- image: media,
- // isBridgeable:
- // contract.address === process.env.EVERAI_L1_CONTRACT_ADDRESS,
- isBridgeable: true,
+ isBridgeable,
+ media: { format: mediaFormat, src: mediaSrc },
name: contract.name ?? contract.symbol ?? "Unknown",
totalBalance: contract.totalBalance,
};
@@ -77,14 +96,13 @@ export const l1NftsRouter = createTRPCRouter({
);
return response.map((nft) => {
- const media =
- nft.contract.address === process.env.EVERAI_L1_CONTRACT_ADDRESS
- ? nft.media[0]?.raw
- : nft.media[0]?.thumbnail;
+ const media = nft.media[0];
+ const mediaSrc = media?.gateway ?? media?.thumbnail ?? media?.raw;
+ const mediaFormat = media?.format === "mp4" ? "video" : "image";
return {
collectionName: nft.contract.name,
- image: media,
+ media: { format: mediaFormat, src: mediaSrc },
tokenId: nft.tokenId,
tokenName: nft.title.length > 0 ? nft.title : `#${nft.tokenId}`,
};
@@ -119,14 +137,13 @@ export const l1NftsRouter = createTRPCRouter({
// TODO @YohanTz: Handle videos
const ownedNfts: Array = nfts.map((nft) => {
- const media =
- nft.contract.address === process.env.EVERAI_L1_CONTRACT_ADDRESS
- ? nft.media[0]?.raw
- : nft.media[0]?.thumbnail;
+ const media = nft.media[0];
+ const mediaSrc = media?.gateway ?? media?.thumbnail ?? media?.raw;
+ const mediaFormat = media?.format === "mp4" ? "video" : "image";
return {
contractAddress: nft.contract.address,
- image: media,
+ media: { format: mediaFormat, src: mediaSrc },
name:
nft.title.length > 0
? nft.title
diff --git a/apps/web/src/server/api/routers/l2Nfts.ts b/apps/web/src/server/api/routers/l2Nfts.ts
index 94b841be..3449925b 100644
--- a/apps/web/src/server/api/routers/l2Nfts.ts
+++ b/apps/web/src/server/api/routers/l2Nfts.ts
@@ -89,18 +89,26 @@ export const l2NftsRouter = createTRPCRouter({
});
const contracts =
(await contractsResponse.json()) as ArkCollectionsApiResponse;
-
const collections: Array = contracts.result.map(
- (contract) => ({
- contractAddress: contract.contract_address,
- image: contract.image,
-
- isBridgeable:
- contract.contract_address ===
- process.env.EVERAI_L2_CONTRACT_ADDRESS,
- name: contract.name ?? contract.symbol,
- totalBalance: contract.tokens_count,
- })
+ (contract) => {
+ const mediaSrc = contract.image?.replace(
+ "ipfs://",
+ process.env.IPFS_GATEWAY ?? ""
+ );
+ const mediaFormat =
+ mediaSrc?.split(".").pop() === "mp4" ? "video" : "image";
+
+ return {
+ contractAddress: contract.contract_address,
+ isBridgeable: true,
+
+ // isBridgeable:
+ // contract.contract_address ===
+ media: { format: mediaFormat, src: mediaSrc },
+ name: contract.name ?? contract.symbol,
+ totalBalance: contract.tokens_count,
+ };
+ }
);
return { collections, totalCount: contracts.total_count };
@@ -152,12 +160,21 @@ export const l2NftsRouter = createTRPCRouter({
validateAndParseAddress(nft.owner) ===
validateAndParseAddress(ownerAddress)
)
- .map((nft) => ({
- collectionName: "EveraiDuo",
- image: nft.metadata?.normalized.image,
- tokenId: nft.token_id,
- tokenName: nft.metadata?.normalized.name ?? `#${nft.token_id}`,
- }));
+ .map((nft) => {
+ const mediaSrc = nft.metadata?.normalized.image?.replace(
+ "ipfs://",
+ process.env.IPFS_GATEWAY ?? ""
+ );
+ const mediaFormat =
+ mediaSrc?.split(".").pop() === "mp4" ? "video" : "image";
+
+ return {
+ collectionName: "EveraiDuo",
+ media: { format: mediaFormat, src: mediaSrc },
+ tokenId: nft.token_id,
+ tokenName: nft.metadata?.normalized.name ?? `#${nft.token_id}`,
+ };
+ });
} catch (error) {
console.error("getL2NftMetadataBatch error:", error);
return [];
@@ -201,15 +218,24 @@ export const l2NftsRouter = createTRPCRouter({
const nfts = (await nftsResponse.json()) as ArkNftsApiResponse;
- const ownedNfts: Array = nfts.result.map((nft) => ({
- contractAddress: nft.contract_address,
- image: nft.metadata?.normalized.image ?? undefined,
- name:
- nft.metadata?.normalized.name?.length ?? 0 > 0
- ? nft.metadata?.normalized?.name ?? ""
- : `${nft.token_id}`,
- tokenId: nft.token_id,
- }));
+ const ownedNfts: Array = nfts.result.map((nft) => {
+ const mediaSrc = nft.metadata?.normalized.image?.replace(
+ "ipfs://",
+ process.env.IPFS_GATEWAY ?? ""
+ );
+ const mediaFormat =
+ mediaSrc?.split(".").pop() === "mp4" ? "video" : "image";
+
+ return {
+ contractAddress: nft.contract_address,
+ media: { format: mediaFormat, src: mediaSrc },
+ name:
+ nft.metadata?.normalized.name?.length ?? 0 > 0
+ ? nft.metadata?.normalized?.name ?? ""
+ : `${nft.token_id}`,
+ tokenId: nft.token_id,
+ };
+ });
return { ownedNfts, totalCount: nfts.total_count };
} catch (error) {
diff --git a/apps/web/src/server/api/types.ts b/apps/web/src/server/api/types.ts
index c8f39957..db0021f9 100644
--- a/apps/web/src/server/api/types.ts
+++ b/apps/web/src/server/api/types.ts
@@ -1,14 +1,16 @@
+export type NftMedia = { format: string; src: string | undefined };
+
export type Nft = {
contractAddress: string;
- image: string | undefined;
+ media: NftMedia;
name: string;
tokenId: string;
};
export type Collection = {
contractAddress: string;
- image: string | undefined;
isBridgeable: boolean;
+ media: NftMedia;
name: string;
totalBalance: number;
};
diff --git a/turbo.json b/turbo.json
index e417fbbb..4db019c2 100644
--- a/turbo.json
+++ b/turbo.json
@@ -18,8 +18,6 @@
"HOSTNAME_L1",
"HOSTNAME_L2",
"L2_DEPLOYER_PRIVATE_KEY",
- "EVERAI_L1_CONTRACT_ADDRESS",
- "EVERAI_L2_CONTRACT_ADDRESS",
"L2_DEPLOYER_ADDRESS",
"NEXT_PUBLIC_ARKLANE_API_DOMAIN",
"GOERLI_ALCHEMY_KEY",
@@ -30,7 +28,8 @@
"NEXT_PUBLIC_ARK_API_DOMAIN",
"VERCEL_URL",
"NODE_ENV",
- "PORT"
+ "PORT",
+ "IPFS_GATEWAY"
],
"pipeline": {
"build:l1": {