Skip to content

Commit

Permalink
✨feat(lld): add simplehash calls for ordis (#7783)
Browse files Browse the repository at this point in the history
✨feat(ui): add simplehash calls for ordis
  • Loading branch information
LucasWerey authored Sep 20, 2024
1 parent 2fd05ea commit e4b6647
Show file tree
Hide file tree
Showing 50 changed files with 3,531 additions and 402 deletions.
7 changes: 7 additions & 0 deletions .changeset/dry-parents-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"ledger-live-desktop": patch
"@ledgerhq/live-nft-react": patch
"@ledgerhq/live-nft": patch
---

Plug the front with simplehash api for the rare sats table and inscriptions table
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import { Flex, Icons, Text } from "@ledgerhq/react-ui";
import { useTranslation } from "react-i18next";

const Error: React.FC = () => {
const { t } = useTranslation();

return (
<Flex justifyContent="center" my={4} columnGap={2}>
<Icons.Warning size="S" color="error.c60" />
<Text color="error.c60">{t("crash.title")}</Text>
</Flex>
);
};

export default Error;
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,144 @@ import { Icons } from "@ledgerhq/react-ui";
import { IconProps } from "../../types/Collection";

export const mappingKeysWithIconAndName = {
alpha: { icon: (props: IconProps) => <Icons.OrdinalsAlpha {...props} />, name: "Alpha" },
alpha: {
icon: (props: IconProps) => <Icons.OrdinalsAlpha {...props} />,
name: "Alpha",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.alpha",
},
black_epic: {
icon: (props: IconProps) => <Icons.OrdinalsBlackEpic {...props} />,
name: "Black Epic",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.black_epic",
},
black_legendary: {
icon: (props: IconProps) => <Icons.OrdinalsBlackLegendary {...props} />,
name: "Black Legendary",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.black_legendary",
},
black_mythic: {
icon: (props: IconProps) => <Icons.OrdinalsBlackMythic {...props} />,
name: "Black Mythic",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.black_mythic",
},
black_rare: {
icon: (props: IconProps) => <Icons.OrdinalsBlackRare {...props} />,
name: "Black Rare",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.black_rare",
},
black_uncommon: {
icon: (props: IconProps) => <Icons.OrdinalsBlackUncommon {...props} />,
name: "Black Uncommon",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.black_uncommon",
},
block_9: {
icon: (props: IconProps) => <Icons.OrdinalsBlock9 {...props} />,
name: "Block 9",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.block_9",
},
block_9: { icon: (props: IconProps) => <Icons.OrdinalsBlock9 {...props} />, name: "Block 9" },
block_9_450x: {
icon: (props: IconProps) => <Icons.OrdinalsBlock9450X {...props} />,
name: "Block 9 450x",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.block_9_450x",
},
block_78: {
icon: (props: IconProps) => <Icons.OrdinalsBlock78 {...props} />,
name: "Block 78",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.block_78",
},
block_78: { icon: (props: IconProps) => <Icons.OrdinalsBlock78 {...props} />, name: "Block 78" },
block_286: {
icon: (props: IconProps) => <Icons.OrdinalsBlock286 {...props} />,
name: "Block 286",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.block_286",
},
block_666: {
icon: (props: IconProps) => <Icons.OrdinalsBlock666 {...props} />,
name: "Block 666",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.block_666",
},
common: {
icon: (props: IconProps) => <Icons.OrdinalsCommon {...props} />,
name: "Common",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.common",
},
epic: {
icon: (props: IconProps) => <Icons.OrdinalsEpic {...props} />,
name: "Epic",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.epic",
},
common: { icon: (props: IconProps) => <Icons.OrdinalsCommon {...props} />, name: "Common" },
epic: { icon: (props: IconProps) => <Icons.OrdinalsEpic {...props} />, name: "Epic" },
first_tx: {
icon: (props: IconProps) => <Icons.OrdinalsFirstTx {...props} />,
name: "First Transaction",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.first_tx",
},
hitman: {
icon: (props: IconProps) => <Icons.OrdinalsHitman {...props} />,
name: "Hitman",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.hitman",
},
jpeg: {
icon: (props: IconProps) => <Icons.OrdinalsJpeg {...props} />,
name: "JPEG",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.jpeg",
},
legacy: {
icon: (props: IconProps) => <Icons.OrdinalsLegacy {...props} />,
name: "Legacy",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.legacy",
},
hitman: { icon: (props: IconProps) => <Icons.OrdinalsHitman {...props} />, name: "Hitman" },
jpeg: { icon: (props: IconProps) => <Icons.OrdinalsJpeg {...props} />, name: "JPEG" },
legacy: { icon: (props: IconProps) => <Icons.OrdinalsLegacy {...props} />, name: "Legacy" },
legendary: {
icon: (props: IconProps) => <Icons.OrdinalsLegendary {...props} />,
name: "Legendary",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.legendary",
},
mythic: {
icon: (props: IconProps) => <Icons.OrdinalsMythic {...props} />,
name: "Mythic",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.mythic",
},
nakamoto: {
icon: (props: IconProps) => <Icons.OrdinalsNakamoto {...props} />,
name: "Nakamoto",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.nakamoto",
},
omega: {
icon: (props: IconProps) => <Icons.OrdinalsOmega {...props} />,
name: "Omega",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.omega",
},
mythic: { icon: (props: IconProps) => <Icons.OrdinalsMythic {...props} />, name: "Mythic" },
nakamoto: { icon: (props: IconProps) => <Icons.OrdinalsNakamoto {...props} />, name: "Nakamoto" },
omega: { icon: (props: IconProps) => <Icons.OrdinalsOmega {...props} />, name: "Omega" },
paliblock: {
icon: (props: IconProps) => <Icons.OrdinalsPaliblockPalindrome {...props} />,
name: "PaliBlock Palindrome",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.paliblock",
},
palindrome: {
icon: (props: IconProps) => <Icons.OrdinalsPalindrome {...props} />,
name: "Palindrome",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.palindrome",
},
palinception: {
icon: (props: IconProps) => <Icons.OrdinalsPalinception {...props} />,
name: "Palinception",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.palinception",
},
pizza: {
icon: (props: IconProps) => <Icons.OrdinalsPizza {...props} />,
name: "Pizza",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.pizza",
},
rare: {
icon: (props: IconProps) => <Icons.OrdinalsRare {...props} />,
name: "Rare",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.rare",
},
uncommon: {
icon: (props: IconProps) => <Icons.OrdinalsUncommon {...props} />,
name: "Uncommon",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.uncommon",
},
vintage: {
icon: (props: IconProps) => <Icons.OrdinalsVintage {...props} />,
name: "Vintage",
descriptionTranslationKey: "ordinals.rareSats.rareSat.description.vintage",
},
pizza: { icon: (props: IconProps) => <Icons.OrdinalsPizza {...props} />, name: "Pizza" },
rare: { icon: (props: IconProps) => <Icons.OrdinalsRare {...props} />, name: "Rare" },
uncommon: { icon: (props: IconProps) => <Icons.OrdinalsUncommon {...props} />, name: "Uncommon" },
vintage: { icon: (props: IconProps) => <Icons.OrdinalsVintage {...props} />, name: "Vintage" },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { InscriptionsItemProps } from "LLD/features/Collectibles/types/Inscriptions";
import TableRow from "LLD/features/Collectibles/components/Collection/TableRow";
import React from "react";

type ItemProps = {
isLoading: boolean;
} & InscriptionsItemProps;

const Item: React.FC<ItemProps> = ({
isLoading,
tokenName,
collectionName,
tokenIcons,
media,
rareSatName,
onClick,
}) => (
<TableRow
isLoading={isLoading}
tokenName={tokenName}
collectionName={collectionName}
tokenIcons={tokenIcons}
media={media}
rareSatName={rareSatName || []}
onClick={onClick}
/>
);

export default Item;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import { IconProps } from "LLD/features/Collectibles/types/Collection";
import { mappingKeysWithIconAndName } from "../Icons";
import { MappingKeys } from "LLD/features/Collectibles/types/Ordinals";

function matchCorrespondingIcon(
rareSats: SimpleHashNft[],
): Array<SimpleHashNft & { icons: Array<({ size, color, style }: IconProps) => JSX.Element> }> {
return rareSats.map(rareSat => {
const iconKeys: string[] = [];
const rarity = rareSat.extra_metadata?.ordinal_details?.sat_rarity?.toLowerCase();

if (rarity && rarity !== "common") {
iconKeys.push(rarity.replace(" ", "_"));
}

const icons = iconKeys
.map(
iconKey =>
mappingKeysWithIconAndName[iconKey as keyof typeof mappingKeysWithIconAndName]?.icon,
)
.filter(Boolean) as Array<({ size, color, style }: IconProps) => JSX.Element>;

return { ...rareSat, icons };
});
}

export function getInscriptionsData(inscriptions: SimpleHashNft[]) {
const inscriptionsWithIcons = matchCorrespondingIcon(inscriptions);
return inscriptionsWithIcons.map(item => ({
tokenName: item.name || item.contract.name || "",
collectionName: item.collection.name,
tokenIcons: item.icons,
rareSatName: [item.extra_metadata?.ordinal_details?.sat_rarity] as MappingKeys[],
media: {
uri: item.image_url || item.previews?.image_small_url,
isLoading: false,
useFallback: true,
contentType: item.extra_metadata?.ordinal_details?.content_type,
mediaType: "image",
},
onClick: () => {
console.log(`you clicked on : \x1b[32m${item.name}\x1b[0m inscription`);
},
// it does nothing for now but it will be used for the next PR with the drawer
}));
}
Original file line number Diff line number Diff line change
@@ -1,80 +1,65 @@
import React from "react";
import { Account } from "@ledgerhq/types-live";
import { Box, Flex } from "@ledgerhq/react-ui";
import { useInscriptionsModel } from "./useInscriptionsModel";
import TableContainer from "~/renderer/components/TableContainer";
import TableHeader from "LLD/features/Collectibles/components/Collection/TableHeader";
import { OrdinalsRowProps, TableHeaderTitleKey } from "LLD/features/Collectibles/types/Collection";
import TableRow from "LLD/features/Collectibles/components/Collection/TableRow";
import { TableHeaderTitleKey } from "LLD/features/Collectibles/types/Collection";
import ShowMore from "LLD/features/Collectibles/components/Collection/ShowMore";
import { MediaProps } from "LLD/features/Collectibles/types/Media";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import Loader from "../Loader";
import Error from "../Error";
import Item from "./Item";

type ViewProps = ReturnType<typeof useInscriptionsModel>;
type ViewProps = ReturnType<typeof useInscriptionsModel> & { isLoading: boolean; isError: boolean };

type Props = {
account: Account;
};

export type InscriptionsItemProps = {
inscriptions: SimpleHashNft[];
isLoading: boolean;
tokenName: string;
collectionName: string;
tokenIcons: OrdinalsRowProps["tokenIcons"];
media: MediaProps;
onClick: () => void;
isError: boolean;
};

const Item: React.FC<InscriptionsItemProps> = ({
const View: React.FC<ViewProps> = ({
displayShowMore,
isLoading,
tokenName,
collectionName,
tokenIcons,
media,
onClick,
isError,
inscriptions,
onShowMore,
}) => {
return (
<TableRow
isLoading={isLoading}
tokenName={tokenName}
collectionName={collectionName}
tokenIcons={tokenIcons}
media={media}
onClick={onClick}
/>
);
};
const hasInscriptions = inscriptions.length > 0 && !isError;
const nothingToShow = !hasInscriptions && !isLoading && !isError;

function View({ displayedObjects, displayShowMore, onShowMore }: ViewProps) {
return (
<Box>
<TableContainer id="oridinals-inscriptions">
<TableContainer id="ordinals-inscriptions">
<TableHeader titleKey={TableHeaderTitleKey.Inscriptions} />
{/** titlekey doesn't need to be translated so we keep it hard coded */}
{displayedObjects ? (
displayedObjects.map((item, index) => (
{isLoading && <Loader />}
{isError && <Error />}
{hasInscriptions &&
inscriptions.map((item, index) => (
<Item
key={index}
isLoading={item.isLoading}
isLoading={isLoading}
tokenName={item.tokenName}
collectionName={item.collectionName}
tokenIcons={item.tokenIcons}
media={item.media}
rareSatName={item.rareSatName}
onClick={item.onClick}
/>
))
) : (
<Flex justifyContent={"center"} my={12}>
{"NOTHING TO SHOW"}
))}
{nothingToShow && (
<Flex justifyContent="center" my={4}>
{"NOTHING TO SHOW WAITING FOR DESIGN"}
</Flex>
)}
{displayShowMore && <ShowMore onShowMore={onShowMore} />}
{displayShowMore && !isError && <ShowMore onShowMore={onShowMore} isInscriptions />}
</TableContainer>
</Box>
);
}

const Inscriptions: React.FC<Props> = ({ account }: Props) => {
return <View {...useInscriptionsModel({ account })} />;
};

const Inscriptions: React.FC<Props> = ({ inscriptions, isLoading, isError }) => (
<View isLoading={isLoading} isError={isError} {...useInscriptionsModel({ inscriptions })} />
);

export default Inscriptions;
Loading

0 comments on commit e4b6647

Please sign in to comment.