From 3360f0cd7a873266c63b021f612e9795e7593b07 Mon Sep 17 00:00:00 2001 From: Pete Watters <2938440+pete-watters@users.noreply.github.com> Date: Tue, 16 Apr 2024 06:41:48 +0100 Subject: [PATCH] chore: add BRC-20 and SRC-20 to collectibles --- src/app/common/utils/sort-assets-by-symbol.ts | 23 +++++ .../components/receive-collectibles.tsx | 4 +- .../receive/components/receive-tokens.tsx | 86 ++++++++++++++++++- src/app/pages/receive/receive-dialog.tsx | 33 ++++--- tests/page-object-models/home.page.ts | 4 - tests/specs/receive/receive.spec.ts | 20 +++++ 6 files changed, 148 insertions(+), 22 deletions(-) create mode 100644 src/app/common/utils/sort-assets-by-symbol.ts create mode 100644 tests/specs/receive/receive.spec.ts diff --git a/src/app/common/utils/sort-assets-by-symbol.ts b/src/app/common/utils/sort-assets-by-symbol.ts new file mode 100644 index 00000000000..20e1baa3fa4 --- /dev/null +++ b/src/app/common/utils/sort-assets-by-symbol.ts @@ -0,0 +1,23 @@ +interface Asset { + name: string; + icon: string; +} + +export function sortAssetsBySymbol(assets: Asset[]) { + return assets + .sort((a, b) => { + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; + }) + .sort((a, b) => { + if (a.name === 'STX') return -1; + if (b.name !== 'STX') return 1; + return 0; + }) + .sort((a, b) => { + if (a.name === 'BTC') return -1; + if (b.name !== 'BTC') return 1; + return 0; + }); +} diff --git a/src/app/pages/receive/components/receive-collectibles.tsx b/src/app/pages/receive/components/receive-collectibles.tsx index 49043c369fc..f21c7c7a438 100644 --- a/src/app/pages/receive/components/receive-collectibles.tsx +++ b/src/app/pages/receive/components/receive-collectibles.tsx @@ -12,16 +12,16 @@ import { receiveTabStyle } from '../receive-dialog'; import { ReceiveItem } from './receive-item'; interface ReceiveCollectiblesProps { - btcAddressTaproot: string; btcAddressNativeSegwit: string; + btcAddressTaproot: string; stxAddress: string; onClickQrOrdinal(): void; onClickQrStacksNft(): void; onClickQrStamp(): void; } export function ReceiveCollectibles({ - btcAddressTaproot, btcAddressNativeSegwit, + btcAddressTaproot, stxAddress, onClickQrOrdinal, onClickQrStacksNft, diff --git a/src/app/pages/receive/components/receive-tokens.tsx b/src/app/pages/receive/components/receive-tokens.tsx index e1dfe81c93c..e2e89d4e9e3 100644 --- a/src/app/pages/receive/components/receive-tokens.tsx +++ b/src/app/pages/receive/components/receive-tokens.tsx @@ -1,10 +1,22 @@ +import { useMemo } from 'react'; + import { HomePageSelectors } from '@tests/selectors/home.selectors'; import { css } from 'leather-styles/css'; import { Stack } from 'leather-styles/jsx'; +import { isDefined } from '@shared/utils'; + import { copyToClipboard } from '@app/common/utils/copy-to-clipboard'; +import { sortAssetsBySymbol } from '@app/common/utils/sort-assets-by-symbol'; import { useToast } from '@app/features/toasts/use-toast'; +import { useAlexSdkSwappableCurrencyQuery } from '@app/query/common/alex-sdk/swappable-currency.query'; +import { useConfigRunesEnabled } from '@app/query/common/remote-config/remote-config.query'; +import { useCurrentNetwork } from '@app/store/networks/networks.selectors'; +import { Avatar, defaultFallbackDelay, getAvatarFallback } from '@app/ui/components/avatar/avatar'; +import { Brc20AvatarIcon } from '@app/ui/components/avatar/brc20-avatar-icon'; import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon'; +import { RunesAvatarIcon } from '@app/ui/components/avatar/runes-avatar-icon'; +import { Src20AvatarIcon } from '@app/ui/components/avatar/src20-avatar-icon'; import { StxAvatarIcon } from '@app/ui/components/avatar/stx-avatar-icon'; import { receiveTabStyle } from '../receive-dialog'; @@ -12,17 +24,35 @@ import { ReceiveItem } from './receive-item'; interface ReceiveTokensProps { btcAddressNativeSegwit: string; + btcAddressTaproot: string; stxAddress: string; onClickQrBtc(): void; onClickQrStx(): void; } export function ReceiveTokens({ btcAddressNativeSegwit, + btcAddressTaproot, stxAddress, onClickQrBtc, onClickQrStx, }: ReceiveTokensProps) { const toast = useToast(); + const network = useCurrentNetwork(); + const runesEnabled = useConfigRunesEnabled(); + const { data: supportedCurrencies = [] } = useAlexSdkSwappableCurrencyQuery(); + + const receivableAssets = useMemo( + () => + sortAssetsBySymbol(supportedCurrencies.filter(isDefined)) + .filter(asset => asset.name !== 'STX') + .map(asset => ({ + address: stxAddress, + fallback: getAvatarFallback(asset.name), + icon: asset.icon, + name: asset.name, + })), + [stxAddress, supportedCurrencies] + ); return ( + } + dataTestId={HomePageSelectors.ReceiveBtcTaprootQrCodeBtn} + onCopyAddress={async () => { + await copyToClipboard(btcAddressTaproot); + toast.success('Copied to clipboard!'); + }} + // onClickQrCode={onClickQrOrdinal} + title="BRC-20" /> + } + // onClickQrCode={onClickQrStamp} + onCopyAddress={async () => { + await copyToClipboard(btcAddressNativeSegwit); + toast.success('Copied to clipboard!'); + }} + title="SRC-20" + /> + {(network.chain.bitcoin.bitcoinNetwork === 'testnet' || runesEnabled) && ( + } + // onClickQrCode={onClickQrStamp} + onCopyAddress={async () => { + await copyToClipboard(btcAddressNativeSegwit); + toast.success('Copied to clipboard!'); + }} + title="Runes" + /> + )} + + {receivableAssets.map(asset => ( + + + {asset.fallback} + + } + // onClickQrCode={() => null} + onCopyAddress={async () => { + await copyToClipboard(asset.address); + toast.success('Copied to clipboard!'); + }} + title={asset.name} + /> + ))} ); } diff --git a/src/app/pages/receive/receive-dialog.tsx b/src/app/pages/receive/receive-dialog.tsx index 1060e68bac8..c3d189dce5a 100644 --- a/src/app/pages/receive/receive-dialog.tsx +++ b/src/app/pages/receive/receive-dialog.tsx @@ -1,6 +1,7 @@ import { useLocation, useNavigate } from 'react-router-dom'; import { HomePageSelectors } from '@tests/selectors/home.selectors'; +import { Box } from 'leather-styles/jsx'; import get from 'lodash.get'; import { RouteUrls } from '@shared/route-urls'; @@ -109,20 +110,24 @@ export function ReceiveDialog({ type = 'full' }: ReceiveDialogProps) { - - navigate(`${RouteUrls.Home}${RouteUrls.ReceiveBtc}`, { - state: { backgroundLocation }, - }) - } - onClickQrStx={() => - navigate(`${RouteUrls.Home}${RouteUrls.ReceiveStx}`, { - state: { backgroundLocation, btcAddressTaproot }, - }) - } - /> + {/* FIXME 96px should be sizes.footerHeight */} + + + navigate(`${RouteUrls.Home}${RouteUrls.ReceiveBtc}`, { + state: { backgroundLocation }, + }) + } + onClickQrStx={() => + navigate(`${RouteUrls.Home}${RouteUrls.ReceiveStx}`, { + state: { backgroundLocation, btcAddressTaproot }, + }) + } + /> + diff --git a/tests/page-object-models/home.page.ts b/tests/page-object-models/home.page.ts index 477bee70a79..8854dac5bc7 100644 --- a/tests/page-object-models/home.page.ts +++ b/tests/page-object-models/home.page.ts @@ -56,10 +56,6 @@ export class HomePage { await this.page.getByTestId(HomePageSelectors.ReceiveCryptoAssetBtn).click(); } - async goToSwapPage() { - await this.page.getByTestId(HomePageSelectors.SwapBtn).click(); - } - // Open issue with Playwright's ability to copyToClipboard from legacy tests: // https://github.com/microsoft/playwright/issues/8114#issuecomment-1103317576 // Also, an open issue to consistently determine `isMac` in the workaround: diff --git a/tests/specs/receive/receive.spec.ts b/tests/specs/receive/receive.spec.ts new file mode 100644 index 00000000000..1c318d96218 --- /dev/null +++ b/tests/specs/receive/receive.spec.ts @@ -0,0 +1,20 @@ +import { test } from '../../fixtures/fixtures'; + +test.describe('Receive Dialog', () => { + test.beforeAll(async ({ extensionId, globalPage, onboardingPage, homePage }) => { + await globalPage.setupAndUseApiCalls(extensionId); + await onboardingPage.signInExistingUser(); + await homePage.goToReceiveDialog(); + }); + + test('That the Receive dialog renders and shows the correct assets', async ({ homePage }) => { + test.expect(homePage.page.getByText('CHOOSE ASSET TO RECEIVE')).toBeTruthy(); + test.expect(homePage.page.getByText('Tokens')).toBeTruthy(); + test.expect(homePage.page.getByText('Collectibles')).toBeTruthy(); + + test.expect(homePage.page.getByText('Bitcoin')).toBeTruthy(); + test.expect(homePage.page.getByText('Stacks')).toBeTruthy(); + test.expect(homePage.page.getByText('BRC-20')).toBeTruthy(); + test.expect(homePage.page.getByText('SRC-20')).toBeTruthy(); + }); +});