Skip to content

Commit

Permalink
fix(api): use marketplace api (#255)
Browse files Browse the repository at this point in the history
* fix(api): use marketplace api

* fix: env

* fix: lint

* fix: lint

* fix(api): marketplace api

* fix: api
  • Loading branch information
remiroyc authored Nov 18, 2024
1 parent a8d26f3 commit 6e5edb2
Show file tree
Hide file tree
Showing 7 changed files with 2,272 additions and 1,585 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"next-themes": "^0.2.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"sharp": "^0.33.5",
"starknet": "^5.25.5",
"superjson": "1.12.2",
"tailwindcss-animate": "^1.0.7",
Expand Down
162 changes: 107 additions & 55 deletions apps/web/src/server/api/helpers/l2nfts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,102 +8,152 @@ const requestsHeader = {
};
const nftApiUrl = process.env.NEXT_PUBLIC_ARK_API_DOMAIN ?? "";

type ArkCollectionsApiResponse = {
result: Array<{
contract_address: string;
contract_type: string;
image?: string;
name: string;
symbol: string;
tokens_count: number;
type PortfolioApiResponse = {
data: Array<{
best_offer: null | string;
collection_address: string;
collection_name: string;
currency_address: string;
floor: string;
list_price: string;
metadata?: {
animation_key: null | string;
animation_mime_type: null | string;
animation_url: null | string;
attributes: null | string;
background_color: null | string;
description: null | string;
external_url: null | string;
image: null | string;
image_data: null | string;
image_key: null | string;
image_mime_type: null | string;
name: null | string;
youtube_url: null | string;
};
token_id: string;
}>;
total_count: number;
token_count: number;
};
export async function getL2ContractsForOwner(address: string) {
const url = `${nftApiUrl}/v1/owners/${validateAndParseAddress(
address
)}/contracts`;
const url = `${nftApiUrl}/portfolio/${validateAndParseAddress(address)}`;

const contractsResponse = await fetch(url, {
headers: requestsHeader,
});
const contracts =
(await contractsResponse.json()) as ArkCollectionsApiResponse;
const apiResponse = (await contractsResponse.json()) as PortfolioApiResponse;

return contracts;
return apiResponse;
}

type ArkBatchNftsApiResponse = {
result: Array<{
contract_address: string;
contract_name: string;
metadata?: { normalized: { image?: string; name?: string } };
type TokenApiResponse = {
data: Array<{
collection_address: string;
collection_image: null | string;
collection_name: null | string;
metadata: {
animation_key: null | string;
animation_mime_type: null | string;
animation_url: null | string;
background_color: null | string;
description: null | string;
external_url: null | string;
image: null | string;
image_data: null | string;
image_key: null | string;
image_key_540_540: null | string;
image_mime_type: null | string;
name: null | string;
youtube_url: null | string;
};
owner: string;
token_id: string;
}>;
};

export async function getL2NftsMetadataBatch(
tokens: Array<{ contract_address: string; token_id: string }>
) {
const url = `${nftApiUrl}/v1/tokens/batch`;

const body = JSON.stringify({
tokens: tokens.map((token) => ({
contract_address: validateAndParseAddress(token.contract_address),
token_id: token.token_id,
})),
});

const nftsResponse = await fetch(url, {
body,
headers: requestsHeader,
method: "POST",
});

const nfts = (await nftsResponse.json()) as ArkBatchNftsApiResponse;
let nfts: {
collection_address: string;
collection_image: null | string;
collection_name: null | string;
metadata: {
animation_key: null | string;
animation_mime_type: null | string;
animation_url: null | string;
background_color: null | string;
description: null | string;
external_url: null | string;
image: null | string;
image_data: null | string;
image_key: null | string;
image_key_540_540: null | string;
image_mime_type: null | string;
name: null | string;
youtube_url: null | string;
};
owner: string;
token_id: string;
}[] = [];

for (const token of tokens) {
const url = `${nftApiUrl}/tokens/${token.contract_address}/0x534e5f4d41494e/${token.token_id}`;
const nftsResponse = await fetch(url, {
body,
headers: requestsHeader,
method: "POST",
});

const response = (await nftsResponse.json()) as TokenApiResponse;
nfts = nfts.concat(response.data);
}

return nfts;
}

type ArkNftsApiResponse = {
result: Array<{
contract_address: string;
metadata: {
normalized: { image: null | string; name: null | string };
} | null;
owner: string;
token_id: string;
}>;
total_count: number;
};
export async function getL2NftsForOwner(
userAddress: string,
contractAddress: string | undefined
) {
const url = `${nftApiUrl}/v1/owners/${validateAndParseAddress(
userAddress
)}/tokens${
contractAddress !== undefined
? `?contract_address=${validateAndParseAddress(contractAddress)}`
: ""
}`;
const url = `${nftApiUrl}/portfolio/${validateAndParseAddress(userAddress)}`;

const nftsResponse = await fetch(url, {
headers: requestsHeader,
});

const nfts = (await nftsResponse.json()) as ArkNftsApiResponse;

return nfts;
const nfts = (await nftsResponse.json()) as PortfolioApiResponse;

return {
data: contractAddress
? nfts.data.filter(
(d) =>
d.collection_address === validateAndParseAddress(contractAddress)
)
: nfts.data,
token_count: nfts.token_count,
};
}

type ArkCollectionInfoApiResponse = {
result: { contract_address: string; name: string; symbol: string };
data: {
address: string;
description: null | string;
image: null | string;
name: null | string;
};
};
export async function getL2ContractMetadata(contractAddress: string) {
const url = `${nftApiUrl}/v1/contracts/${validateAndParseAddress(
const url = `${nftApiUrl}/collections/${validateAndParseAddress(
contractAddress
)}`;
)}/0x534e5f4d41494e`;

const contractInfoResponse = await fetch(url, {
headers: requestsHeader,
Expand Down Expand Up @@ -152,11 +202,13 @@ export async function getL2WhitelistedCollections() {
}
}

export function getMediaObjectFromUrl(image: string | undefined): NftMedia {
export function getMediaObjectFromUrl(
image: null | string | undefined
): NftMedia {
if (image === undefined) {
return { format: "image", src: undefined };
}
const mediaSrc = image.replace("ipfs://", process.env.IPFS_GATEWAY ?? "");
const mediaSrc = image?.replace("ipfs://", process.env.IPFS_GATEWAY ?? "");
const mediaFormat = mediaSrc?.split(".").pop() === "mp4" ? "video" : "image";

return { format: mediaFormat, src: mediaSrc };
Expand Down
23 changes: 9 additions & 14 deletions apps/web/src/server/api/routers/bridgeRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,15 @@ export const bridgeRequestRouter = createTRPCRouter({
}, {} as Record<string, { contract_address: string; token_id: string }>)
)
);
requestMetadataByReqHash = requestMetadatas.result.reduce(
(acc, current) => {
return {
...acc,
[`${current.token_id}`]: {
contractName: current.contract_name,
media: getMediaObjectFromUrl(
current.metadata?.normalized.image
),
},
};
},
{}
);
requestMetadataByReqHash = requestMetadatas.reduce((acc, current) => {
return {
...acc,
[`${current.token_id}`]: {
contractName: current.collection_name,
media: getMediaObjectFromUrl(current.metadata?.image),
},
};
}, {});
}

const bridgeRequestsWithMetadata = bridgeRequests.map(
Expand Down
75 changes: 37 additions & 38 deletions apps/web/src/server/api/routers/l2Nfts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const l2NftsRouter = createTRPCRouter({
try {
const contractInfo = await getL2ContractMetadata(contractAddress);

return { name: contractInfo.result.name };
return { name: contractInfo.data.name };
} catch (error) {
return { name: "" };
}
Expand All @@ -36,35 +36,34 @@ export const l2NftsRouter = createTRPCRouter({
} = input;

try {
const contractsForOwner = await getL2ContractsForOwner(address);
const response = await getL2ContractsForOwner(address);

// console.log("=> response", response);

const whitelistedCollections = await getL2WhitelistedCollections();

const collections: Array<Collection> = contractsForOwner.result.map(
(contract) => {
const media = getMediaObjectFromUrl(contract.image);
const isBridgeable =
whitelistedCollections === undefined ||
whitelistedCollections.some(
(whitelistedCollection) =>
validateAndParseAddress(
whitelistedCollection
).toLowerCase() ===
validateAndParseAddress(
contract.contract_address
).toLowerCase()
);
const collections: Array<Collection> = response.data.map((contract) => {
const media = getMediaObjectFromUrl(contract.metadata?.image);
const isBridgeable =
whitelistedCollections === undefined ||
whitelistedCollections.some(
(whitelistedCollection) =>
validateAndParseAddress(whitelistedCollection).toLowerCase() ===
validateAndParseAddress(
contract.collection_address
).toLowerCase()
);

return {
contractAddress: contract.contract_address,
isBridgeable,
media,
name: contract.name ?? contract.symbol ?? "Unknown",
totalBalance: contract.tokens_count,
};
}
);
return {
contractAddress: contract.collection_address,
isBridgeable,
media,
name: contract.collection_name ?? "Unknown",
totalBalance: 1,
};
});

return { collections, totalCount: contractsForOwner.total_count };
return { collections, totalCount: response.token_count };
} catch (error) {
console.error("getL2NftCollectionsByWallet error: ", error);
return { collections: [], totalCount: 0 };
Expand Down Expand Up @@ -93,21 +92,21 @@ export const l2NftsRouter = createTRPCRouter({
}))
);

return nfts.result
return nfts
.filter(
(nft) =>
ownerAddress === undefined ||
validateAndParseAddress(nft.owner) ===
validateAndParseAddress(ownerAddress)
)
.map((nft) => {
const media = getMediaObjectFromUrl(nft.metadata?.normalized.image);
const media = getMediaObjectFromUrl(nft.metadata?.image);

return {
collectionName: nft.contract_name,
collectionName: nft.collection_name,
media,
tokenId: nft.token_id,
tokenName: nft.metadata?.normalized.name ?? `#${nft.token_id}`,
tokenName: nft.metadata?.name ?? `#${nft.token_id}`,
};
});
} catch (error) {
Expand Down Expand Up @@ -138,24 +137,24 @@ export const l2NftsRouter = createTRPCRouter({
try {
const nfts = await getL2NftsForOwner(userAddress, contractAddress);

const ownedNfts: Array<Nft> = nfts.result.map((nft) => {
const media = getMediaObjectFromUrl(
nft.metadata?.normalized.image ?? undefined
);
const ownedNfts: Array<Nft> = nfts.data.map((nft) => {
console.log("=> nft", nft);

const media = getMediaObjectFromUrl(nft.metadata?.image);
const name =
nft.metadata?.normalized.name?.length ?? 0 > 0
? nft.metadata?.normalized?.name ?? ""
nft.metadata?.name?.length ?? 0 > 0
? nft.metadata?.name ?? ""
: `${nft.token_id}`;

return {
contractAddress: nft.contract_address,
contractAddress: nft.collection_address,
media,
name,
tokenId: nft.token_id,
};
});

return { ownedNfts, totalCount: nfts.total_count };
return { ownedNfts, totalCount: nfts.token_count };
} catch (error) {
console.error("getL2OwnerNftsFromCollection error: ", error);
return { ownedNfts: [], totalCount: 0 };
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
},
"dependencies": {
"dotenv-cli": "^7.0.0"
}
},
"packageManager": "[email protected]"
}
Loading

0 comments on commit 6e5edb2

Please sign in to comment.