Skip to content

Commit

Permalink
Display NFTs (#143)
Browse files Browse the repository at this point in the history
* Initial commit for NFTs

* Added a comment

* Added view more button

* Added test cases

* Incorporated review comments

* Fixed cypress issue

* Rename types and files

* Fix NFTCard unit tests

* Fix the way NFTs are displayed

- Display NFTs that don't embed a json
- Display NFTs without images
- Do not display NFTs without URIs

* Add NFT details modal

* Do not filter out NFTs without URIs

* Add cypress e2e tests

* Fix dependencies post rebase

* Clean up types

* Fix build

* Fix NFT cypress tests

* Improve NFTCard UI

* Fix NFT display when the URI is directly an img link

* Fix NFT display when the URI is an ipfs link without the .json extension

* Fix NFT display when the URI is in "image_url" property of the json

* Handle more NFT display edge cases

* Add NFTViewer unit tests

* Handle case when the image is an http link

* Move NFT image resolver into a dedicated util file

* Do not display NFT without data

* Fix NFTCard unit tests

* Handle .gif direct links in NFT Viewer

* Display NFT without data with a fallback description

* Cleaning up code

* Fix post review

* Simplify formatStringToBeDisplayed function

* Add post review changes

* Wrap fetchNFTs into useCallback

* Fix typing in NFTCard.test.tsx

* Extract NFT parts into dedicated components

* Change code post review

* Introduce TruncatedText component

* Fix post rebase

* Handle parsing of XLS-24 standard

* Fix unit tests

* Refactor TruncatedText & introduce TruncatedMultiLinesText components

* Rework TruncatedText and TruncatedMultiLinesText components

* Remove NFTListItem component

* Refactor TruncatedText component

* Fix code post review

* Refactor TruncatedText

* Edit default NFT image

---------

Co-authored-by: thibautbremand <[email protected]>
Co-authored-by: Florian Bouron <[email protected]>
  • Loading branch information
3 people authored Aug 14, 2023
1 parent 60e0fb8 commit 4215764
Show file tree
Hide file tree
Showing 45 changed files with 988 additions and 70 deletions.
11 changes: 3 additions & 8 deletions packages/constants/src/payload/payload.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SetAccountFlags,
CreateOfferFlags
} from '../xrpl/basic.types';
import { AccountNFToken } from './../xrpl/nft.types';
import { AccountNFToken, AccountNFTokenResponse, NFTokenIDResponse } from './../xrpl/nft.types';

/*
* Request Payloads
Expand Down Expand Up @@ -323,18 +323,13 @@ export interface SetTrustlineResponseDeprecated {
hash: string | null | undefined;
}

export interface GetNFTResponse
extends BaseResponse<{ account_nfts: AccountNFToken[]; marker?: unknown }> {}
export interface GetNFTResponse extends BaseResponse<AccountNFTokenResponse> {}

export interface GetNFTResponseDeprecated {
nfts: AccountNFToken[] | null | undefined;
}

export interface MintNFTResponse
extends BaseResponse<{
NFTokenID: string;
hash: string;
}> {}
export interface MintNFTResponse extends BaseResponse<NFTokenIDResponse> {}

export interface CreateNFTOfferResponse
extends BaseResponse<{
Expand Down
1 change: 1 addition & 0 deletions packages/constants/src/xrpl/nft.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const IPFSResolverPrefix = 'https://ipfs.io/ipfs/';
25 changes: 25 additions & 0 deletions packages/constants/src/xrpl/nft.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,28 @@ export interface AccountNFToken {
URI?: string;
nft_serial: number;
}

export interface AccountNFTokenResponse {
account_nfts: AccountNFToken[];
marker?: unknown;
}

export interface NFTData {
NFTokenID: string;

// XLS-24 standard fields
nftType?: string;
schema?: string;
name?: string;
description?: string;
image?: string;
collection?: {
name?: string;
family?: string;
};
}

export interface NFTokenIDResponse {
hash: string;
NFTokenID: string;
}
34 changes: 26 additions & 8 deletions packages/extension/cypress/e2e/NFT.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { formatFlags } from '../../src/utils';
describe('Mint', () => {
// deepcode ignore NoHardcodedPasswords: password used for testing purposes
const PASSWORD = 'SECRET_PASSWORD';
const MINT_NFT_URL = `http://localhost:3000?mint-nft?URI=4d696e746564207468726f7567682047656d57616c6c657421&flags=%7B%22tfOnlyXRP%22%3Afalse%2C%22tfTransferable%22%3Atrue%7D&fee=199&transferFee=3000&NFTokenTaxon=0&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210324818&requestMessage=undefined&transaction=mintNFT`;
const MINT_NFT_URL = `http://localhost:3000?URI=4d696e746564207468726f7567682047656d57616c6c657421&flags=%7B%22tfOnlyXRP%22%3Afalse%2C%22tfTransferable%22%3Atrue%7D&fee=199&transferFee=3000&NFTokenTaxon=0&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210324818&requestMessage=undefined&transaction=mintNFT`;

beforeEach(() => {
// Mock the localStorage with a wallet already loaded
Expand Down Expand Up @@ -54,7 +54,25 @@ describe('Mint', () => {
cy.get('p[data-testid="transaction-subtitle"]').should('have.text', 'Transaction Successful');
});

it('Read the minted NFT Token ID', () => {
it('View a NFT in the NFT Viewer', () => {
navigate('localhost:3000', PASSWORD);

// Wait for the wallet to load
cy.get('[data-testid="token-loader"]').should('not.exist');

// Go to NFT Viewer
cy.contains('button', 'NFTs').click();

// Find a NFT and open the details
cy.get('[data-testid="OpenInNewOutlinedIcon"]').parent('button').first().click();

// Check that the details view is open
cy.contains('NFT Details');
cy.contains('Token ID');
cy.contains('Description');
});

it('Read the minted NFT Token ID from the transaction history', () => {
navigate('localhost:3000', PASSWORD);

// Wait for the wallet to load
Expand All @@ -76,7 +94,7 @@ describe('Mint', () => {
});

it('Create NFT Offer (50 XRP)', function () {
const url = `http://localhost:3000?create-nft-offer&amount=50000000&NFTokenID=${this.NFTokenID}&fee=199&flags=%7B%22tfSellNFToken%22%3Atrue%7D&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325582&requestMessage=undefined&transaction=createNFTOffer`;
const url = `http://localhost:3000?amount=50000000&NFTokenID=${this.NFTokenID}&fee=199&flags=%7B%22tfSellNFToken%22%3Atrue%7D&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325582&requestMessage=undefined&transaction=createNFTOffer`;
navigate(url, PASSWORD);

// Confirm
Expand Down Expand Up @@ -196,7 +214,7 @@ describe('Mint', () => {
});

it('Accept NFT Offer', function () {
const url = `http://localhost:3000?accept-nft-offer&NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;
const url = `http://localhost:3000?NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;

navigate(url, PASSWORD);

Expand Down Expand Up @@ -227,7 +245,7 @@ describe('Mint', () => {
issuer: 'rHZwvHEs56GCmHupwjA4RY7oPA3EoAJWuN',
value: '0.1'
});
const url = `http://localhost:3000?accept-nft-offer&NFTokenBrokerFee=${amount}&NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;
const url = `http://localhost:3000?NFTokenBrokerFee=${amount}&NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;

navigate(url, PASSWORD);

Expand All @@ -254,7 +272,7 @@ describe('Mint', () => {
issuer: 'rHZwvHEs56GCmHupwjA4RY7oPA3EoAJWuN',
value: '0.1'
});
const url = `http://localhost:3000?accept-nft-offer&NFTokenBrokerFee=${amount}&NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;
const url = `http://localhost:3000?NFTokenBrokerFee=${amount}&NFTokenSellOffer=${this.OfferID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=acceptNFTOffer`;

navigate(url, PASSWORD);

Expand All @@ -276,7 +294,7 @@ describe('Mint', () => {
});

it('Cancel NFT Offer', function () {
const url = `http://localhost:3000?cancel-nft-offer&NFTokenOffers=%5B%22${this.OfferID}%22%5D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=cancelNFTOffer`;
const url = `http://localhost:3000?NFTokenOffers=%5B%22${this.OfferID}%22%5D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=cancelNFTOffer`;
navigate(url, PASSWORD);

// Confirm
Expand All @@ -300,7 +318,7 @@ describe('Mint', () => {
});

it('Burn NFT', function () {
const url = `http://localhost:3000?burn-nft&NFTokenID=${this.NFTokenID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=burnNFT`;
const url = `http://localhost:3000?NFTokenID=${this.NFTokenID}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210325959&requestMessage=undefined&transaction=burnNFT`;
navigate(url, PASSWORD);

// Confirm
Expand Down
12 changes: 6 additions & 6 deletions packages/extension/cypress/e2e/offers.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Offers', () => {
});

it('Create offer (XRP to ETH)', () => {
const url = `http://localhost:3000?create-offer&takerGets=10000000&takerPays=%7B%22currency%22%3A%22ETH%22%2C%22issuer%22%3A%22rnm76Qgz4G9G4gZBJVuXVvkbt7gVD7szey%22%2C%22value%22%3A%220.1%22%7D&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
const url = `http://localhost:3000?takerGets=10000000&takerPays=%7B%22currency%22%3A%22ETH%22%2C%22issuer%22%3A%22rnm76Qgz4G9G4gZBJVuXVvkbt7gVD7szey%22%2C%22value%22%3A%220.1%22%7D&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Create Offer');
Expand Down Expand Up @@ -54,7 +54,7 @@ describe('Offers', () => {
value: '0.1'
});

const url = `http://localhost:3000?create-offer&takerGets=10000000&takerPays=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
const url = `http://localhost:3000?takerGets=10000000&takerPays=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Create Offer');
Expand Down Expand Up @@ -87,7 +87,7 @@ describe('Offers', () => {
value: '0.1'
});

const url = `http://localhost:3000?create-offer&takerPays=10000000&takerGets=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
const url = `http://localhost:3000?takerPays=10000000&takerGets=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Create Offer');
Expand Down Expand Up @@ -120,7 +120,7 @@ describe('Offers', () => {
value: '0.1'
});

const url = `http://localhost:3000?create-offer&takerGets=10000000&takerPays=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
const url = `http://localhost:3000?takerGets=10000000&takerPays=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Create Offer');
Expand Down Expand Up @@ -153,7 +153,7 @@ describe('Offers', () => {
value: '0.1'
});

const url = `http://localhost:3000?create-offer&takerPays=10000000&takerGets=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
const url = `http://localhost:3000?takerPays=10000000&takerGets=${amount}&flags=%7B%22tfPassive%22%3Atrue%7D&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328024&requestMessage=undefined&transaction=createOffer`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Create Offer');
Expand Down Expand Up @@ -202,7 +202,7 @@ describe('Offers', () => {

it('Cancel offer', function () {
navigate(
`http://localhost:3000?cancel-offer&offerSequence=${this.sequence}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328126&requestMessage=undefined&transaction=cancelOffer`,
`http://localhost:3000?offerSequence=${this.sequence}&fee=199&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210328126&requestMessage=undefined&transaction=cancelOffer`,
PASSWORD
);

Expand Down
2 changes: 1 addition & 1 deletion packages/extension/cypress/e2e/set_account.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('Set Account', () => {

it('Set Account', () => {
cy.visit(
`http://localhost:3000?set-account&emailHash=1D1382344586ECFF844DACFF698C2EFB&fee=199&flags=%7B%22tfAllowXRP%22%3Atrue%7D&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210327555&requestMessage=undefined&transaction=setAccount`,
`http://localhost:3000?emailHash=1D1382344586ECFF844DACFF698C2EFB&fee=199&flags=%7B%22tfAllowXRP%22%3Atrue%7D&memos=%5B%7B%22memo%22%3A%7B%22memoType%22%3A%224465736372697074696f6e%22%2C%22memoData%22%3A%2254657374206d656d6f%22%7D%7D%5D&id=210327555&requestMessage=undefined&transaction=setAccount`,
{
onBeforeLoad(win) {
(win as any).chrome = (win as any).chrome || {};
Expand Down
4 changes: 2 additions & 2 deletions packages/extension/cypress/e2e/submit_transaction.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Submit Transaction', () => {
});

it('Submit Transaction', () => {
const url = `http://localhost:3000?submit-transaction&transaction=%7B%22TransactionType%22%3A%22Payment%22%2C%22Destination%22%3A%22rhikRdkFw28csKw9z7fVoBjWncz1HSoQij%22%2C%22Amount%22%3A%22100000%22%7D&id=210329246&requestMessage=undefined&submit=transaction`;
const url = `http://localhost:3000?transaction=%7B%22TransactionType%22%3A%22Payment%22%2C%22Destination%22%3A%22rhikRdkFw28csKw9z7fVoBjWncz1HSoQij%22%2C%22Amount%22%3A%22100000%22%7D&id=210329246&requestMessage=undefined&submit=transaction`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Confirm Transaction');
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('Submit Transaction', () => {
],
Fee: '199'
});
const url = `http://localhost:3000?submit-transaction&transaction=${transaction}&requestMessage=undefined&submit=transaction`;
const url = `http://localhost:3000?transaction=${transaction}&requestMessage=undefined&submit=transaction`;
navigate(url, PASSWORD);

cy.get('h1[data-testid="page-title"]').should('have.text', 'Confirm Transaction');
Expand Down
4 changes: 2 additions & 2 deletions packages/extension/cypress/e2e/wallet_management.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ describe('Edit wallet', () => {

// Lock the extension
cy.get('button[aria-label="close"]').click();
cy.contains('button', 'Wallets').parent().children().eq(2).click();
cy.contains('button', 'Wallets').parent().children().eq(3).click();
cy.contains('button', 'Lock').click();

// Check if the wallets are properly loaded with the name changed
Expand Down Expand Up @@ -600,7 +600,7 @@ describe('Switch wallet', () => {
cy.contains('Wallet 3').should('be.visible');

// Lock the extension
cy.contains('button', 'Wallets').parent().children().eq(2).click();
cy.contains('button', 'Wallets').parent().children().eq(3).click();
cy.contains('button', 'Lock').click();

// Check if the default wallet is properly loaded
Expand Down
3 changes: 3 additions & 0 deletions packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"react": "^17.0.2",
"react-content-loader": "^6.2.0",
"react-dom": "^17.0.2",
"react-infinite-scroll-component": "^6.1.0",
"react-json-view": "^1.21.3",
"react-lazy-load-image-component": "^1.6.0",
"react-router-dom": "6",
"react-scripts": "4.0.3",
"ripple-keypairs": "^1.1.5",
Expand All @@ -41,6 +43,7 @@
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-lazy-load-image-component": "^1.5.2",
"cypress": "^12.9.0",
"jest-canvas-mock": "^2.4.0",
"ts-loader": "~8.2.0"
Expand Down
45 changes: 45 additions & 0 deletions packages/extension/src/components/atoms/NFTImage/NFTImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { CSSProperties, FC } from 'react';

import { CircularProgress } from '@mui/material';
import { LazyLoadImage } from 'react-lazy-load-image-component';

import { GemWallet } from '../index';

interface NFTImageProps {
imageURL?: string;
height?: number;
width?: number;
style?: CSSProperties;
}

export const NFTImage: FC<NFTImageProps> = ({ imageURL, height = 250, width = 250, style }) => {
return imageURL ? (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', ...style }}>
<LazyLoadImage
alt="NFT"
height={height}
style={{ borderRadius: '4px', boxShadow: '4px 4px 0px black' }}
beforeLoad={() => <CircularProgress />}
effect="blur"
src={imageURL}
width={width}
/>
</div>
) : (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height,
width,
backgroundColor: '#1e1e1e',
borderRadius: '4px',
boxShadow: '4px 4px 0px black',
...style
}}
>
<GemWallet style={{ transform: 'scale(2)' }} />
</div>
);
};
1 change: 1 addition & 0 deletions packages/extension/src/components/atoms/NFTImage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './NFTImage';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC } from 'react';
import { FC, SVGProps } from 'react';

export const GemWallet: FC = (props) => (
export const GemWallet: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg width={45} height={45} xmlns="http://www.w3.org/2000/svg" {...props} data-testid="gem-icon">
<circle cx="22.492" cy="22.51" r="22.363" fill="#1e1e1e" stroke="null" />
<g fill="none" stroke="null">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ComponentProps, FC, useMemo } from 'react';

import { SxProps, Theme, Typography } from '@mui/material';

type TruncatedTextProps = ComponentProps<typeof Typography> & {
isMultiline?: boolean;
maxLines?: string;
};

export const TruncatedText: FC<TruncatedTextProps> = ({
isMultiline = false,
maxLines = '4',
sx,
children,
...rest
}) => {
const styleProps: SxProps<Theme> | undefined = useMemo(
() =>
isMultiline
? {
overflow: 'hidden',
display: '-webkit-box',
width: '100%', // if the string is very long without spaces, it will not overflow the view
WebkitBoxOrient: 'vertical',
WebkitLineClamp: maxLines, // start showing ellipsis when X line is reached
whiteSpace: 'pre-wrap' // let the text wrap preserving spaces
}
: {
display: 'block',
overflow: 'hidden',
textOverflow: 'ellipsis',
width: '100%'
},
[isMultiline, maxLines]
);

return (
<Typography
sx={{
...styleProps,
...sx
}}
{...rest}
>
{children}
</Typography>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TruncatedText';
2 changes: 2 additions & 0 deletions packages/extension/src/components/atoms/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export * from './ButtonOption';
export * from './Logo';
export * from './NFTImage';
export * from './NumericInput';
export * from './PrivateRoute';
export * from './TileLoader';
export * from './TokenLoader';
export * from './Tokens';
export * from './TruncatedText';
export * from './WalletIcon';
Loading

0 comments on commit 4215764

Please sign in to comment.