Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix/LIVE-11922
Browse files Browse the repository at this point in the history
  • Loading branch information
kallen-ledger committed Aug 2, 2024
2 parents 5c0a440 + 2dd1292 commit e4cd831
Show file tree
Hide file tree
Showing 31 changed files with 673 additions and 196 deletions.
5 changes: 5 additions & 0 deletions .changeset/calm-elephants-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/live-wallet": patch
---

Live-Wallet - Sending trustchain id to cloudsync api
6 changes: 6 additions & 0 deletions .changeset/funny-cooks-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"ledger-live-desktop": patch
"@ledgerhq/live-common": patch
---

replace static data by cdn data
5 changes: 5 additions & 0 deletions .changeset/spotty-chefs-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/live-wallet": patch
---

Live-Wallet - Fix a wallet sync parser issue happening when the info field was null
5 changes: 5 additions & 0 deletions .changeset/strong-forks-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"live-mobile": minor
---

feat(web3hub): add confirmation bottom modal before opening app
5 changes: 5 additions & 0 deletions .changeset/tall-panthers-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ledger-live-desktop": patch
---

Fix unstable integration test
22 changes: 0 additions & 22 deletions apps/ledger-live-desktop/src/config/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,28 +159,6 @@ export const urls = {
info: "https://www.ledger.com/swap?utm_source=ledger_live_desktop&utm_medium=self_referral&utm_content=swap_intro",
learnMore:
"https://www.ledger.com/swap?utm_source=ledger_live_desktop&utm_medium=self_referral&utm_content=swap_footer",
providers: {
changelly: {
main: "https://changelly.com/",
tos: "https://changelly.com/terms-of-use",
support: "https://support.changelly.com/en/support/tickets/new",
},
cic: {
main: "https://criptointercambio.com/",
tos: "https://criptointercambio.com/terms-of-use",
support: "https://criptointercambio.com/en/about",
},
exodus: {
main: "https://www.exodus.com/",
tos: "https://www.exodus.com/terms/",
support: "mailto:support@xopay.com",
},
moonpay: {
main: "https://www.moonpay.com/",
tos: "https://www.moonpay.com/legal/terms_of_use",
support: "https://support.moonpay.com",
},
},
},
exchange: {
learnMore:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { getAccountCurrency, getMainAccount } from "@ledgerhq/live-common/account/index";
import { getSwapProvider } from "@ledgerhq/live-common/exchange/providers/swap";
import { AdditionalProviderConfig } from "@ledgerhq/live-common/exchange/providers/swap";
import { isSwapOperationPending } from "@ledgerhq/live-common/exchange/swap/index";
import { MappedSwapOperation } from "@ledgerhq/live-common/exchange/swap/types";
import { getProviderName } from "@ledgerhq/live-common/exchange/swap/utils/index";
import { getDefaultExplorerView, getTransactionExplorer } from "@ledgerhq/live-common/explorers";
import { Account, SubAccount } from "@ledgerhq/types-live";
import uniq from "lodash/uniq";
import React, { useCallback } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import styled from "styled-components";
import { urls } from "~/config/urls";
import { setTrackingSource } from "~/renderer/analytics/TrackPage";
import Box from "~/renderer/components/Box";
import CopyWithFeedback from "~/renderer/components/CopyWithFeedback";
Expand Down Expand Up @@ -108,6 +109,7 @@ const SwapOperationDetails = ({
mappedSwapOperation: MappedSwapOperation;
onClose?: () => void;
}) => {
const [providerData, setproviderData] = useState<AdditionalProviderConfig | undefined>(undefined);
const { fromAccount, toAccount, operation, provider, swapId, status, fromAmount, toAmount } =
mappedSwapOperation;
const fromAccountName = useAccountName(fromAccount);
Expand All @@ -128,6 +130,14 @@ const SwapOperationDetails = ({
fromCurrency.type === "CryptoCurrency" &&
getTransactionExplorer(getDefaultExplorerView(fromCurrency), operation.hash);

useEffect(() => {
const getProvideData = async () => {
const data = await getSwapProvider(provider);
setproviderData(data);
};
getProvideData();
}, [provider]);

const openAccount = useCallback(
(account: Account | SubAccount) => {
const parentAccount =
Expand Down Expand Up @@ -167,12 +177,12 @@ const SwapOperationDetails = ({
},
});
} else {
openURL(urls.swap.providers[provider as keyof typeof urls.swap.providers]?.main);
openURL(providerData!.mainUrl);
}
if (onClose) {
onClose();
}
}, [provider, fromAccount, history, accounts, onClose, language]);
}, [provider, fromAccount, history, accounts, onClose, language, providerData]);

return (
<Box flow={3} px={20} mt={20}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { getProviderName } from "@ledgerhq/live-common/exchange/swap/utils/index";
import React, { useCallback } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { Trans } from "react-i18next";
import styled from "styled-components";
import { urls } from "~/config/urls";
import Box from "~/renderer/components/Box/Box";
import LinkWithExternalIcon from "~/renderer/components/LinkWithExternalIcon";
import Text from "~/renderer/components/Text";
import { openURL } from "~/renderer/linking";
import { Separator } from "./Separator";
import {
getSwapProvider,
AdditionalProviderConfig,
} from "@ledgerhq/live-common/exchange/providers/swap";

const Terms = styled(Text).attrs({
ff: "Inter|SemiBold",
Expand All @@ -18,15 +21,22 @@ const Terms = styled(Text).attrs({
`;

export function DrawerFooter({ provider }: { provider: string }) {
const swapProvider =
urls.swap.providers?.[provider as keyof typeof urls.swap.providers] ?? undefined;
const url = (swapProvider && "tos" in swapProvider && swapProvider?.tos) || undefined;
const [providerData, setproviderData] = useState<AdditionalProviderConfig>();

useEffect(() => {
const getProvideData = async () => {
const data = await getSwapProvider(provider);
setproviderData(data);
};
getProvideData();
}, [provider]);

const url = providerData?.termsOfUseUrl;
const onLinkClick = useCallback(() => openURL(url!), [url]);
if (!url) {
return null;
}
const providerName = getProviderName(provider);

return (
<>
<Separator />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { getProviderName } from "@ledgerhq/live-common/exchange/swap/utils/index";
import { Icon, Link } from "@ledgerhq/react-ui";
import React, { useCallback } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { Trans } from "react-i18next";
import styled from "styled-components";
import { urls } from "~/config/urls";
import Alert from "~/renderer/components/Alert";
import Box from "~/renderer/components/Box";
import CopyWithFeedback from "~/renderer/components/CopyWithFeedback";
Expand All @@ -15,6 +14,10 @@ import IconClock from "~/renderer/icons/Clock";
import { openURL } from "~/renderer/linking";
import { colors } from "~/renderer/styles/theme";
import { track } from "~/renderer/analytics/segment";
import {
getSwapProvider,
AdditionalProviderConfig,
} from "@ledgerhq/live-common/exchange/providers/swap";

const IconWrapper = styled(Box)`
background: ${colors.lightGreen};
Expand Down Expand Up @@ -76,10 +79,20 @@ const SwapCompleted = ({
provider: string;
targetCurrency: string;
}) => {
const openProviderSupport = useCallback(() => {
openURL(urls.swap.providers[provider as keyof typeof urls.swap.providers]?.support);
const [providerData, setproviderData] = useState<AdditionalProviderConfig>();

useEffect(() => {
const getProvideData = async () => {
const data = await getSwapProvider(provider);
setproviderData(data);
};
getProvideData();
}, [provider]);

const openProviderSupport = useCallback(() => {
openURL(providerData!.supportUrl);
}, [providerData]);

const openFeedbackFormTrack = () => {
track("button_clicked", {
page: "ModalStep-finished",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ test("Ethereum staking flows via portfolio, asset page and market page @smoke",
const marketCoinPage = new MarketCoinPage(page);
const analytics = new Analytics(page);

const maskItemsInMarket = {
mask: [
page.getByTestId("market-small-graph"),
page.getByTestId("market-coin-price"),
page.getByTestId("market-cap"),
page.getByTestId("market-price-change"),
page.getByRole("row").filter({ hasText: new RegExp("^(?!.*(?:Bitcoin|Ethereum)).*$") }),
],
};

const maskPartOfItemsInMarket = {
mask: [page.getByRole("row").filter({ hasText: new RegExp("^(?!.*(?:Bitcoin|Ethereum)).*$") })],
};

await test.step("Entry buttons load with feature flag enabled", async () => {
await expect.soft(page).toHaveScreenshot("portfolio-entry-buttons.png", {
mask: [layout.marketPerformanceWidget],
Expand Down Expand Up @@ -150,16 +164,6 @@ test("Ethereum staking flows via portfolio, asset page and market page @smoke",
});

await test.step("Market page loads with ETH staking available", async () => {
const maskItemsInMarket = {
mask: [
page.getByTestId("market-small-graph"),
page.getByTestId("market-coin-price"),
page.getByTestId("market-cap"),
page.getByTestId("market-price-change"),
page.getByRole("row").filter({ hasText: new RegExp("^(?!.*(?:Bitcoin|Ethereum)).*$") }),
],
};

await layout.goToMarket();
await marketPage.waitForLoading();
await expect
Expand All @@ -170,7 +174,9 @@ test("Ethereum staking flows via portfolio, asset page and market page @smoke",
await test.step("start stake flow via Stake entry button", async () => {
await marketPage.startStakeFlowByTicker("eth");
await drawer.waitForDrawerToBeVisible();
await expect.soft(page).toHaveScreenshot("stake-drawer-opened-from-market-page.png");
await expect
.soft(page)
.toHaveScreenshot("stake-drawer-opened-from-market-page.png", maskPartOfItemsInMarket);

Check failure on line 179 in apps/ledger-live-desktop/tests/specs/services/ethereumStaking.spec.ts

View workflow job for this annotation

GitHub Actions / Desktop Tests E2E (Ubuntu)

[mocked_tests] › specs/services/ethereumStaking.spec.ts:67:5 › Ethereum staking flows via portfolio

1) [mocked_tests] › specs/services/ethereumStaking.spec.ts:67:5 › Ethereum staking flows via portfolio, asset page and market page @smoke › start stake flow via Stake entry button Error: Screenshot comparison failed: 268657 pixels (ratio 0.35 of all image pixels) are different. Expected: /home/runner/_work/ledger-live/ledger-live/apps/ledger-live-desktop/tests/specs/services/ethereumStaking.spec.ts-snapshots/stake-drawer-opened-from-market-page-linux.png Received: /home/runner/_work/ledger-live/ledger-live/apps/ledger-live-desktop/tests/artifacts/test-results/services-ethereumStaking-E-30b12--page-and-market-page-smoke-mocked-tests/stake-drawer-opened-from-market-page-actual.png Diff: /home/runner/_work/ledger-live/ledger-live/apps/ledger-live-desktop/tests/artifacts/test-results/services-ethereumStaking-E-30b12--page-and-market-page-smoke-mocked-tests/stake-drawer-opened-from-market-page-diff.png Call log: - expect.soft.toHaveScreenshot(stake-drawer-opened-from-market-page.png) with timeout 41000ms - verifying given screenshot expectation - taking page screenshot - disabled all CSS animations - waiting for fonts to load... - fonts loaded - 268657 pixels (ratio 0.35 of all image pixels) are different. - waiting 100ms before taking screenshot - taking page screenshot - disabled all CSS animations - waiting for fonts to load... - fonts loaded - captured a stable screenshot - 268657 pixels (ratio 0.35 of all image pixels) are different. 177 | await expect 178 | .soft(page) > 179 | .toHaveScreenshot("stake-drawer-opened-from-market-page.png", maskPartOfItemsInMarket); | ^ 180 | await drawer.close(); 181 | }); 182 | at /home/runner/_work/ledger-live/ledger-live/apps/ledger-live-desktop/tests/specs/services/ethereumStaking.spec.ts:179:8 at /home/runner/_work/ledger-live/ledger-live/apps/ledger-live-desktop/tests/specs/services/ethereumStaking.spec.ts:174:3
await drawer.close();
});

Expand Down
7 changes: 3 additions & 4 deletions apps/ledger-live-mobile/__tests__/jest-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,9 @@ jest.mock("react-native-localize", () => ({
findBestAvailableLanguage: jest.fn(),
}));

jest.mock("@react-native-async-storage/async-storage", () => ({
getItem: jest.fn(),
setItem: jest.fn(),
}));
jest.mock("@react-native-async-storage/async-storage", () =>
require("@react-native-async-storage/async-storage/jest/async-storage-mock"),
);

jest.mock("react-native-version-number", () => ({
appVersion: "1.0.0",
Expand Down
5 changes: 5 additions & 0 deletions apps/ledger-live-mobile/src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -6795,6 +6795,11 @@
}
},
"web3hub": {
"disclaimer": {
"clearSigningEnabled": "Clear signing enabled",
"checkbox": "Do not remind me again.",
"CTA": "Open {{app}}"
},
"manifestsList": {
"title": "Explore",
"description": "Discover the best of web3 curated by Ledger"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ describe("Web3Hub integration test", () => {

expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

Expand Down Expand Up @@ -65,6 +68,9 @@ describe("Web3Hub integration test", () => {

expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

Expand Down Expand Up @@ -104,6 +110,9 @@ describe("Web3Hub integration test", () => {
expect(screen.queryByText("Wallet API Tools")).not.toBeOnTheScreen();
expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

Expand Down Expand Up @@ -167,6 +176,9 @@ describe("Web3Hub integration test", () => {
expect(screen.queryByText("Wallet API Tools")).not.toBeOnTheScreen();
expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

Expand Down Expand Up @@ -208,7 +220,7 @@ describe("Web3Hub integration test", () => {

await user.press(screen.getByRole("button", { name: /back/i }));

expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
expect((await screen.findAllByText("Wallet API Tools"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Wallet API Tools")[0]);
expect(await screen.findByText("wallet-api-tools-0")).toBeOnTheScreen();
expect(await screen.findByText("Wallet API Tools")).toBeOnTheScreen();
Expand All @@ -232,4 +244,50 @@ describe("Web3Hub integration test", () => {
expect(await screen.findByRole("searchbox")).toBeOnTheScreen();
expect(screen.getByRole("searchbox")).toBeDisabled();
});

it("Should only show the confirmation bottom modal if not dismissed previously", async () => {
const { user } = render(<Web3HubTest />);

expect(await screen.findByText("Explore web3")).toBeOnTheScreen();

await waitForLoader();

// TODO: Would be nice to test the close on bottom modal by tapping the close icon or the backdrop
expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
// await user.press(screen.getByText("Do not remind me again."));
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

expect(await screen.findByRole("button", { name: /back/i })).toBeOnTheScreen();
await user.press(screen.getByRole("button", { name: /back/i }));
expect(await screen.findByText("Explore web3")).toBeOnTheScreen();

expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("Do not remind me again.")).toBeOnTheScreen();
await user.press(screen.getByText("Do not remind me again."));
expect(await screen.findByText("Open Dummy Wallet App")).toBeOnTheScreen();
await user.press(screen.getByText("Open Dummy Wallet App"));
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

expect(await screen.findByRole("button", { name: /back/i })).toBeOnTheScreen();
await user.press(screen.getByRole("button", { name: /back/i }));
expect(await screen.findByText("Explore web3")).toBeOnTheScreen();

expect((await screen.findAllByText("Dummy Wallet App"))[0]).toBeOnTheScreen();
// Strange bug where I need to press on something else (that will not receive the press) to be able to press again
await user.press(screen.getAllByText("Dummy Wallet App")[1]);
await user.press(screen.getAllByText("Dummy Wallet App")[0]);
expect(await screen.findByText("dummy-0")).toBeOnTheScreen();
expect(await screen.findByText("Dummy Wallet App")).toBeOnTheScreen();

expect(await screen.findByRole("button", { name: /back/i })).toBeOnTheScreen();
await user.press(screen.getByRole("button", { name: /back/i }));
expect(await screen.findByText("Explore web3")).toBeOnTheScreen();
});
});
Loading

0 comments on commit e4cd831

Please sign in to comment.