Skip to content

Commit

Permalink
Merge branch 'develop' into fix/LIVE-15628-pass-correct-id-to-dapp
Browse files Browse the repository at this point in the history
  • Loading branch information
adammino-ledger committed Jan 13, 2025
2 parents b0525e8 + a15ee92 commit 648b74e
Show file tree
Hide file tree
Showing 20 changed files with 304 additions and 56 deletions.
5 changes: 5 additions & 0 deletions .changeset/poor-students-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"live-mobile": minor
---

Fix braze related performance issues
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export async function launchApp() {
launchArgs: {
wsPort: port,
detoxURLBlacklistRegex:
'\\(".*sdk.*.braze.*",".*.googleapis.com/.*",".*clients3.google.com.*"\\)',
'\\(".*sdk.*.braze.*",".*.googleapis.com/.*",".*clients3.google.com.*",".*tron.coin.ledger.com/wallet/getBrokerage.*"\\)',
mock: getEnv("MOCK") ? getEnv("MOCK") : "0",
disable_broadcast: getEnv("DISABLE_TRANSACTION_BROADCAST")
? getEnv("DISABLE_TRANSACTION_BROADCAST")
Expand Down
2 changes: 2 additions & 0 deletions apps/ledger-live-mobile/e2e/page/nft/nftViewer.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ export default class NftViewerPage {
mainScrollView = () => getElementById("nft-viewer-page-scrollview");
backButton = () => getElementById("navigation-header-back-button");

@Step("Navigate back to NFT gallery")
async navigateToNftGallery() {
await tapByElement(this.backButton());
}

@Step("Expect NFT viewer page to be visible")
async expectVisible() {
await expect(this.mainScrollView()).toBeVisible();
}
Expand Down
54 changes: 49 additions & 5 deletions apps/ledger-live-mobile/e2e/page/wallet/nftGallery.page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { getElementById, openDeeplink, tapByElement, waitForElementById } from "../../helpers";
import {
getElementById,
getIdOfElement,
openDeeplink,
tapByElement,
waitForElementById,
} from "../../helpers";
import { expect } from "detox";

const baseLink = "nftgallery";
Expand All @@ -7,8 +13,9 @@ export default class NftGalleryPage {
root = () => getElementById("wallet-nft-gallery-screen");
emptyScreen = () => getElementById("wallet-nft-gallery-empty");
emptyScreenResetButton = () => getElementById("wallet-nft-gallery-empty-reset-button");
nftListComponentId = "wallet-nft-gallery-list";
nftListComponent = () => getElementById(this.nftListComponentId);
nftListPrefix = "wallet-nft-gallery-list-";
nftListRegexp = new RegExp(`^${this.nftListPrefix}.`);
nftListComponent = () => getElementById(this.nftListRegexp);
nftAddNewListItem = () => getElementById("wallet-nft-gallery-add-new-list-item");
receiveNftButton = () => getElementById("wallet-nft-gallery-receive-nft-button");
nftReceiveModalContinueButton = () =>
Expand All @@ -17,12 +24,15 @@ export default class NftGalleryPage {
nftFilterDrawer = () => getElementById("wallet-nft-gallery-filter-drawer");
selectAndHide = () => getElementById("wallet-nft-gallery-select-and-hide");
confirmHide = () => getElementById("wallet-nft-gallery-confirm-hide");
nftListItem = (index: number) => getElementById(`wallet-nft-gallery-list-item-${index}`);
nftListItemId = (index = 0) => `wallet-nft-gallery-list-item-${index}`;
nftListItem = (index = 0) => getElementById(this.nftListItemId(index));

@Step("Open NFT Gallery via deeplink")
async openViaDeeplink() {
await openDeeplink(baseLink);
}

@Step("Select NFT")
async clickOnNft(index = 0) {
await tapByElement(this.nftListItem(index));
}
Expand All @@ -35,39 +45,73 @@ export default class NftGalleryPage {
await expect(this.nftListItem(index)).not.toBeVisible();
}

@Step("Hide All Nft")
async hideAllNft() {
// Get total number of NFTs given by the list identifier
const nftNumber = Number.parseInt(
(await getIdOfElement(this.nftListRegexp)).replace(this.nftListPrefix, ""),
);

// Select all NFTs and confirm hidding
await tapByElement(this.selectAndHide());
for (let nb = nftNumber; nb > 0; nb--) await this.clickOnNft(nb - 1);
await tapByElement(this.confirmHide());

// Expect no NFT displayed
await expect(this.nftListItem()).not.toBeVisible();
}

async continueFromReceiveNFTsModal() {
await tapByElement(this.nftReceiveModalContinueButton());
}

@Step("Wait for NFT list")
async waitForList() {
await waitForElementById(this.nftListComponentId);
await waitForElementById(this.nftListRegexp);
}

@Step("Expect NFT Gallery visible")
async expectGalleryVisible() {
await expect(this.root()).toBeVisible();
}

@Step("Expect NFT Gallery not visible")
async expectGalleryNotVisible() {
await expect(this.root()).not.toBeVisible();
}

@Step("Expect Gallery empty state")
async expectGalleryEmptyState() {
await this.expectGalleryVisible();
await expect(this.emptyScreen()).toBeVisible(50);
}

@Step("Expect NFT visible")
async expectNftVisible(index = 0) {
await expect(this.nftListItem(index)).toBeVisible();
}

@Step("Expect Filter drawer to be visible")
async expectFilterDrawerVisible() {
await expect(this.nftFilterDrawer()).toBeVisible();
}

@Step("Expect Filter Drawer not to be visible")
async expectFilterDrawerNotVisible() {
await expect(this.nftFilterDrawer()).not.toBeVisible();
}

@Step("Click on reset filters")
async tapResetFilters() {
await tapByElement(this.emptyScreenResetButton());
}

@Step("Click on Add new NFT")
async tapAddNew() {
await tapByElement(this.nftAddNewListItem());
}

@Step("Expect NFT receive modal visible")
async expectNftReceiveModalVisible() {
await expect(this.nftReceiveModal()).toBeVisible();
}
Expand Down
1 change: 1 addition & 0 deletions apps/ledger-live-mobile/e2e/page/wallet/portfolio.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export default class PortfolioPage {
await scrollToId(this.seeAllTransactionButton, this.accountsListView);
}

@Step("Expect Portfolio with accounts")
async expectPortfolioWithAccounts() {
await expect(getElementById(this.accountsListView)).toBeVisible();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ export default class WalletTabNavigatorPage {
portfolioTab = () => getElementById(`wallet-tab-${ScreenName.Portfolio}`);
marketTab = () => getElementById(`wallet-tab-${NavigatorName.Market}`);

@Step("Click on NFT Gallery tab")
async navigateToNftGallery() {
await tapByElement(this.nftGalleryTab());
}

@Step("Click on Portfolio tab")
async navigateToPortfolio() {
await tapByElement(this.portfolioTab());
}

@Step("Click on Market tab")
async navigateToMarket() {
await tapByElement(this.marketTab());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe(`Ledger Sync Accounts`, () => {
}

$TmsLink(tmsLink);
$Issue("LIVE-15614");
it(`Synchronize one instance then delete the backup`, async () => {
await app.accounts.openViaDeeplink();
await app.accounts.expectAccountsNumber(0);
Expand Down
74 changes: 74 additions & 0 deletions apps/ledger-live-mobile/e2e/specs/speculos/nftGallery.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { CLI } from "../../utils/cliUtils";
import { Application } from "../../page";
import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos";
import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency";

const app = new Application();
const nanoApp = AppInfos.ETHEREUM;
const accountCurrency = Currency.ETH.currencyId;

describe("NFT Gallery screen", () => {
beforeAll(async () => {
await app.init({
speculosApp: nanoApp,
cliCommands: [
async () => {
return CLI.liveData({
currency: nanoApp.name,
index: 0,
appjson: app.userdataPath,
add: true,
});
},
],
});
await app.portfolio.waitForPortfolioPageToLoad();
await app.nftGallery.openViaDeeplink();
});

$TmsLink("B2CQA-132");
it("should navigate to/from portfolio on tab press", async () => {
await app.walletTabNavigator.navigateToPortfolio();
await app.nftGallery.expectGalleryNotVisible();
await app.portfolio.expectPortfolioWithAccounts();

await app.walletTabNavigator.navigateToNftGallery();
await app.nftGallery.expectGalleryVisible();

await app.nftGallery.waitForList();
await app.nftGallery.expectNftVisible();
});

it("should navigate to NFT viewer page on NFT gallery item press", async () => {
await app.nftGallery.clickOnNft();
await app.nftViewer.expectVisible();
await app.nftGallery.expectGalleryNotVisible();

await app.nftViewer.navigateToNftGallery();
await app.nftGallery.expectGalleryVisible();
});

it('should show receive NFT\'s modal when "Adding new item" from list', async () => {
await app.nftGallery.tapAddNew();
await app.nftGallery.expectNftReceiveModalVisible();

await app.nftGallery.continueFromReceiveNFTsModal();
await app.receive.expectFirstStep();
await app.receive.selectCurrency(accountCurrency);
await app.receive.expectSecondStepNetworks([accountCurrency]);
await app.receive.selectNetwork(accountCurrency);
await app.receive.expectSecoundStepAccounts();
await app.common.closePage();
});

it("should let users hide NFT's", async () => {
await app.nftGallery.openViaDeeplink();
await app.nftGallery.hideAllNft();
await app.nftGallery.expectGalleryEmptyState();

// show filters on "reset" button tap
await app.nftGallery.expectFilterDrawerNotVisible();
await app.nftGallery.tapResetFilters();
await app.nftGallery.expectFilterDrawerVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe("Receive Flow", () => {

$TmsLink("B2CQA-1856");
$TmsLink("B2CQA-1862");
$Issue("LIVE-14453");
it("Should create an account on a network", async () => {
await openReceive();
await app.receive.selectAsset("ETH");
Expand Down
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"e2e:build": "pnpm detox build",
"e2e:ci": "zx ./scripts/e2e-ci.mjs",
"e2e:test": "export MOCK=1 && pnpm detox test",
"e2e:test:speculos": "export MOCK=0 && pnpm detox test --testMatch \"$(pwd)/e2e/specs/speculos/**/*.spec.ts\" --testTimeout=300000",
"e2e:test:speculos": "export MOCK=0 && pnpm detox test --testMatch \"{$(pwd)/e2e/specs/speculos/*.spec.ts,$(pwd)/e2e/specs/speculos/**/*.spec.ts}\" --testTimeout=300000",
"prebeta": "bundle install",
"debug:detox": "pnpm detox test -c ios.manual currencies.spec.ts",
"ios:staging": "ENVFILE=.env.ios.staging react-native run-ios --mode Staging",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ const NftList = ({ data, hasNextPage, fetchNextPage, isLoading }: Props) => {
initialNumToRender={6}
windowSize={11}
contentContainerStyle={{ marginTop: 0, marginHorizontal: space[6] }}
testID={"wallet-nft-gallery-list"}
testID={"wallet-nft-gallery-list-" + data.length}
onEndReached={fetchNextPage}
onEndReachedThreshold={0.2}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import Braze from "@braze/react-native-sdk";
import { useCallback, useRef } from "react";
import { useSelector, useDispatch, shallowEqual } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import { track } from "~/analytics";
import { setDismissedContentCard } from "~/actions/settings";
import { trackingEnabledSelector } from "~/reducers/settings";
import { mobileCardsSelector } from "~/reducers/dynamicContent";

export const useBrazeContentCard = () => {
export const useBrazeContentCard = (mobileCards: Braze.ContentCard[]) => {
const isTrackedUser = useSelector(trackingEnabledSelector);
const mobileCards = useSelector(mobileCardsSelector, shallowEqual);
const mobileCardRef = useRef(mobileCards);
const dispatch = useDispatch();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import { setDynamicContentMobileCards } from "~/actions/dynamicContent";

const useDynamicContent = () => {
const dispatch = useDispatch();
const { logClickCard, logDismissCard, logImpressionCard, refreshDynamicContent } =
useBrazeContentCard();
const notificationCards = useSelector(notificationsCardsSelector);
const assetsCards = useSelector(assetsCardsSelector);
const walletCards = useSelector(walletCardsSelector);
Expand All @@ -35,6 +33,9 @@ const useDynamicContent = () => {
const mobileCards = useSelector(mobileCardsSelector);
const hiddenCards: string[] = useSelector(dismissedDynamicCardsSelector);

const { logClickCard, logDismissCard, logImpressionCard, refreshDynamicContent } =
useBrazeContentCard(mobileCards);

const walletCardsDisplayed = useMemo(
() => walletCards.filter((wc: WalletContentCard) => !hiddenCards.includes(wc.id)),
[walletCards, hiddenCards],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Braze from "@braze/react-native-sdk";
import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
Expand All @@ -10,7 +11,6 @@ import {
setIsDynamicContentLoading,
setDynamicContentLandingPageStickyCtaCards,
} from "../actions/dynamicContent";
import { useBrazeContentCard } from "./brazeContentCard";
import {
filterByPage,
filterByType,
Expand All @@ -31,7 +31,7 @@ import { clearDismissedContentCards } from "~/actions/settings";

export const useDynamicContentLogic = () => {
const dispatch = useDispatch();
const { Braze, refreshDynamicContent } = useBrazeContentCard();
const refreshDynamicContent = useCallback(() => Braze.requestContentCardsRefresh(), []);
const dismissedContentCards = useSelector(dismissedContentCardsSelector) || {};
const dismissedContentCardsIds = Object.keys(dismissedContentCards);

Expand Down Expand Up @@ -90,7 +90,7 @@ export const useDynamicContentLogic = () => {
dispatch(setDynamicContentLearnCards(learnCards));
dispatch(setDynamicContentLandingPageStickyCtaCards(landingPageStickyCtaCards));
dispatch(setIsDynamicContentLoading(false));
}, [Braze, dismissedContentCardsIds, dispatch]);
}, [dismissedContentCardsIds, dispatch]);

const clearOldDismissedContentCards = () => {
const oldCampaignIds = getOldCampaignIds(dismissedContentCards || {});
Expand Down
1 change: 1 addition & 0 deletions libs/coin-modules/coin-xrp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
"lint:fix": "pnpm lint --fix",
"test": "jest",
"test-watch": "jest --watch",
"test-integ": "DOTENV_CONFIG_PATH=.env.integ.test jest --config=jest.integ.config.js",
"typecheck": "tsc --noEmit",
"unimported": "unimported"
Expand Down
7 changes: 6 additions & 1 deletion libs/coin-modules/coin-xrp/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ async function operations(
address: string,
{ limit, start }: Pagination,
): Promise<[Operation[], number]> {
const [ops, index] = await listOperations(address, { limit, startAt: start ?? 0 });
const options: {
limit?: number;
minHeight?: number;
} = { limit: limit };
if (start) options.minHeight = start;
const [ops, index] = await listOperations(address, options);
return [
ops.map(op => {
const { simpleType, blockHash, blockTime, blockHeight, ...rest } = op;
Expand Down
2 changes: 1 addition & 1 deletion libs/coin-modules/coin-xrp/src/bridge/synchronization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async function filterOperations(
address: string,
blockHeight: number,
): Promise<Operation[]> {
const [operations, _] = await listOperations(address, { startAt: blockHeight });
const [operations, _] = await listOperations(address, { minHeight: blockHeight });

return operations.map(
op =>
Expand Down
Loading

0 comments on commit 648b74e

Please sign in to comment.