Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/odd-pillows-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"live-mobile": minor
"@ledgerhq/live-common": minor
Comment thread
dilaouid marked this conversation as resolved.
"ledger-live-mobile-e2e-tests": minor
---
Comment thread
henri-ly marked this conversation as resolved.

tests(e2e): add detox for evm native staking (sei_evm) and mock smoke under `apps/ledger-live-mobile/e2e` and Speculos delegate flow under `e2e/mobile`
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ const TransactionConfirm = ({
const Footer = r?.footer;

return (
<Container style={{ paddingBottom: 0 }}>
<Container style={{ paddingBottom: 0 }} data-testid="device-action-transaction-confirm">
<Container paddingX={26}>
<DeviceBlocker />
<Animation animation={getDeviceAnimation(device.modelId, type, "verify")} />
Expand Down
6 changes: 6 additions & 0 deletions apps/ledger-live-mobile/e2e/page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import SendPage from "./trade/send.page";
import SettingsGeneralPage from "./settings/settingsGeneral.page";
import SettingsPage from "./settings/settings.page";
import StakePage from "./trade/stake.page";
import EvmDelegatePage from "./trade/evmDelegate.page";
import SwapPage from "./trade/swap.page";
import TransferMenuDrawer from "./wallet/transferMenu.drawer";
import WalletTabNavigatorPage from "./wallet/walletTabNavigator.page";
Expand Down Expand Up @@ -83,6 +84,7 @@ export class Application {
private settingsPageInstance = lazyInit(SettingsPage);
private settingsGeneralPageInstance = lazyInit(SettingsGeneralPage);
private stakePageInstance = lazyInit(StakePage);
private evmDelegatePageInstance = lazyInit(EvmDelegatePage);
private swapPageInstance = lazyInit(SwapPage);
private transferMenuDrawerInstance = lazyInit(TransferMenuDrawer);
private walletTabNavigatorPageInstance = lazyInit(WalletTabNavigatorPage);
Expand Down Expand Up @@ -197,6 +199,10 @@ export class Application {
return this.stakePageInstance();
}

public get evmDelegate() {
return this.evmDelegatePageInstance();
}

public get swap() {
return this.swapPageInstance();
}
Expand Down
80 changes: 80 additions & 0 deletions apps/ledger-live-mobile/e2e/page/trade/evmDelegate.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { expect } from "detox";
import { Step } from "jest-allure2-reporter/api";

const FEE_ESTIMATION_TIMEOUT = 120000;

export default class EvmDelegatePage {
startStakeButtonId = "account-quick-action-button-cta";
addDelegationButtonId = "account-quick-action-button-addDelegation";
validatorName = "Ledger by Figment";
validatorRowId = "evm-validator-row-seivaloper1mockvalidator000000000000000000000001";
amountInputId = "evm-delegation-amount-input";
useMaxButtonId = "evm-delegation-use-max";
amountContinueButtonId = "enabled-evm-delegation-amount-continue";
delegationSummaryLabel = "Delegated assets";

@Step("Start EVM delegation flow from account quick actions")
async startDelegate() {
await waitForElementById(this.startStakeButtonId);
await tapById(this.startStakeButtonId);
}
Comment thread
dilaouid marked this conversation as resolved.
Comment thread
dilaouid marked this conversation as resolved.
Comment thread
dilaouid marked this conversation as resolved.
Comment thread
dilaouid marked this conversation as resolved.
Comment thread
dilaouid marked this conversation as resolved.

@Step("Wait for validator list to be visible")
async waitForValidatorListVisible() {
await waitForElementByText(this.validatorName);
}

@Step("Select the first validator in the list")
async selectFirstValidator() {
await waitForElementByText(this.validatorName);
await tapById(this.validatorRowId);
if (await IsIdVisible(this.amountInputId)) {
return;
}
await tapByText(this.validatorName);
await waitForElementById(this.amountInputId);
}

@Step("Set delegation amount to {amount}")
async setAmount(amount: string) {
await waitForElementById(this.amountInputId);
await typeTextById(this.amountInputId, amount);
}

@Step("Wait until network fees are loaded and continue is enabled")
async waitForAmountContinueEnabled(timeout = FEE_ESTIMATION_TIMEOUT) {
await waitForElementById(this.amountContinueButtonId, timeout);
}

@Step("Tap use max amount button")
async useMaxAmount() {
await waitForElementById(this.useMaxButtonId);
await tapById(this.useMaxButtonId);
await this.waitForAmountContinueEnabled();
}

@Step("Continue from amount screen")
async continueAmount() {
await waitForElementById(this.amountContinueButtonId);
await tapById(this.amountContinueButtonId);
}

@Step("Set amount and continue once fees are ready")
async setAmountAndContinue(amount: string) {
await this.setAmount(amount);
await this.waitForAmountContinueEnabled();
await this.continueAmount();
}

@Step("Expect delegated assets summary visible")
async expectDelegatedAssetsVisible() {
await waitForElementByText(this.delegationSummaryLabel);
await expect(getElementByText(this.delegationSummaryLabel)).toBeVisible();
}

@Step("Expect add delegation CTA visible")
async expectAddDelegationCtaVisible() {
await waitForElementById(this.addDelegationButtonId);
await expect(getElementById(this.addDelegationButtonId)).toBeVisible();
}
}
37 changes: 37 additions & 0 deletions apps/ledger-live-mobile/e2e/specs/delegate/sei.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
describe("SEI EVM Native Staking - Delegate flow", () => {
Comment thread
dilaouid marked this conversation as resolved.
const SEI_CURRENCY_ID = "sei_evm";
const DELEGATION_AMOUNT = "2";
const EMPTY_ACCOUNT_ID = "mock:2:sei_evm:0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707:";
const STAKED_ACCOUNT_ID = "mock:2:sei_evm:0x18E9A4F2A5A2B01F35E7D086E75D7D01530A1A9F:";

async function selectAccount(accountId: string) {
const accountRowId = `account-row-${accountId}`;
if (!(await IsIdVisible(accountRowId))) {
await scrollToId(accountRowId);
}
await waitForElementById(accountRowId);
await tapById(accountRowId);
}

beforeAll(async () => {
await app.init({
userdata: "seiEvmStaking",
});
await app.portfolio.waitForPortfolioPageToLoad();
});

it("Delegate happy path: start delegating, validator list is shown, validator selected", async () => {
await app.assetAccountsPage.openViaDeeplink(SEI_CURRENCY_ID);
await selectAccount(EMPTY_ACCOUNT_ID);
await app.evmDelegate.startDelegate();
await app.evmDelegate.selectFirstValidator();
await app.evmDelegate.setAmountAndContinue(DELEGATION_AMOUNT);
});

it("Already-delegated validator is reflected on the account page", async () => {
await app.assetAccountsPage.openViaDeeplink(SEI_CURRENCY_ID);
await selectAccount(STAKED_ACCOUNT_ID);
await app.evmDelegate.expectDelegatedAssetsVisible();
await app.evmDelegate.expectAddDelegationCtaVisible();
});
});
209 changes: 209 additions & 0 deletions apps/ledger-live-mobile/e2e/userdata/seiEvmStaking.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
{
"data": {
"SPECTRON_RUN": {
"localStorage": {
"acceptedTermsVersion": "2019-12-04"
}
},
"settings": {
"hasCompletedOnboarding": true,
"counterValue": "USD",
"language": "en",
"theme": "light",
"region": null,
"locale": "en-US",
"orderAccounts": "balance|desc",
"countervalueFirst": false,
"autoLockTimeout": 10,
"selectedTimeRange": "month",
"marketIndicator": "western",
"currenciesSettings": {},
"pairExchanges": {},
"developerMode": false,
"loaded": true,
"shareAnalytics": true,
"sentryLogs": true,
"readOnlyModeEnabled": false,
"hasOrderedNano": true,
"lastUsedVersion": "99.99.99",
"dismissedBanners": [],
"accountsViewMode": "list",
"showAccountsHelperBanner": true,
"hideEmptyTokenAccounts": false,
"sidebarCollapsed": false,
"discreetMode": false,
"preferredDeviceModel": "nanoX",
"hasInstalledApps": true,
"dismissedDynamicCards": [],
"seenDevices": [],
"blacklistedTokenIds": [],
"swapAcceptedProviderIds": [],
"deepLinkUrl": null,
"firstTimeLend": false,
"swapProviders": [],
"showClearCacheBanner": false,
"starredAccountIds": [],
"hasPassword": false
},
"user": {
"id": "08cf3393-c5eb-4ea7-92de-0deea22e3971"
},
"accounts": [
{
"data": {
"id": "mock:2:sei_evm:0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707:",
"seedIdentifier": "0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707",
"name": "SEI Network (EVM) 1",
"starred": false,
"used": true,
"derivationMode": "",
"index": 0,
"freshAddress": "0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707",
"freshAddressPath": "44'/60'/0'/0/0",
"blockHeight": 100000,
"creationDate": "2024-01-01T00:00:00.000Z",
"operationsCount": 0,
"operations": [],
"pendingOperations": [],
"currencyId": "sei_evm",
"unitMagnitude": 18,
"lastSyncDate": "2024-01-01T00:00:00.000Z",
"balance": "10000000000000000000",
"spendableBalance": "10000000000000000000",
"xpub": "0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707",
"stakingResources": {
"delegations": [],
"redelegations": [],
"unbondings": [],
"delegatedBalance": "0",
"pendingRewardsBalance": "0",
"unbondingBalance": "0",
"validators": [
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000001",
"name": "Ledger by Figment",
"votingPower": 0,
"commission": 0.05,
"estimatedYearlyRewardsRate": 0.12,
"tokens": 123456789000000
},
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000002",
"name": "Chorus One",
"votingPower": 1,
"commission": 0.07,
"estimatedYearlyRewardsRate": 0.1,
"tokens": 99000000000000
},
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000003",
"name": "Everstake",
"votingPower": 2,
"commission": 0.1,
"estimatedYearlyRewardsRate": 0.09,
"tokens": 77000000000000
}
]
},
"swapHistory": []
},
"version": 1
},
{
"data": {
"id": "mock:2:sei_evm:0x18E9A4F2A5A2B01F35E7D086E75D7D01530A1A9F:",
"seedIdentifier": "0x6EB963EFD0FEF7A4CFAB6CE6F1421C3279D11707",
"name": "SEI Network (EVM) Staked",
"starred": false,
"used": true,
"derivationMode": "",
"index": 1,
"freshAddress": "0x18E9A4F2A5A2B01F35E7D086E75D7D01530A1A9F",
"freshAddressPath": "44'/60'/1'/0/0",
"blockHeight": 100000,
"creationDate": "2024-01-01T00:00:00.000Z",
"operationsCount": 0,
"operations": [],
"pendingOperations": [],
"currencyId": "sei_evm",
"unitMagnitude": 18,
"lastSyncDate": "2024-01-01T00:00:00.000Z",
"balance": "10000000000000000000",
"spendableBalance": "7500000000000000000",
"xpub": "0x18E9A4F2A5A2B01F35E7D086E75D7D01530A1A9F",
"stakingResources": {
"delegations": [
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000001",
"amount": "2500000000000000000",
"pendingRewards": "120000000000000000",
"status": "bonded"
}
],
"redelegations": [
{
"validatorSrcAddress": "seivaloper1mockvalidator000000000000000000000002",
"validatorDstAddress": "seivaloper1mockvalidator000000000000000000000003",
"amount": "1000000000000000000",
"completionDate": "2042-01-02T03:04:05.000Z"
}
],
"unbondings": [
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000001",
"amount": "500000000000000000",
"completionDate": "2042-01-02T03:04:05.000Z"
}
],
"delegatedBalance": "2500000000000000000",
"pendingRewardsBalance": "120000000000000000",
"unbondingBalance": "500000000000000000",
"validators": [
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000001",
"name": "Ledger by Figment",
"votingPower": 0,
"commission": 0.05,
"estimatedYearlyRewardsRate": 0.12,
"tokens": 123456789000000
},
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000002",
"name": "Chorus One",
"votingPower": 1,
"commission": 0.07,
"estimatedYearlyRewardsRate": 0.1,
"tokens": 99000000000000
},
{
"validatorAddress": "seivaloper1mockvalidator000000000000000000000003",
"name": "Everstake",
"votingPower": 2,
"commission": 0.1,
"estimatedYearlyRewardsRate": 0.09,
"tokens": 77000000000000
}
]
},
"swapHistory": []
},
"version": 1
}
],
"countervalues": {},
"featureFlags": {
"overrides": {
"evmNativeStaking": {
"enabled": true,
"params": {
"supportedCurrencyIds": ["sei_evm"]
}
},
"llmAccountListUI": {
"enabled": false
}
},
"bannerVisible": false
}
}
}
2 changes: 2 additions & 0 deletions e2e/desktop/tests/page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AssetPage } from "./asset.page";
import { BuyAndSellPage } from "./buyAndSell.page";
import { DelegateDrawer } from "./drawer/delegate.drawer";
import { DelegateModal } from "./modal/delegate.modal";
import { EvmDelegateModal } from "./modal/evmDelegate.modal";
import { Drawer } from "tests/component/drawer.component";
import { EarnV2Page } from "./earn.v2.dashboard.page";
import { Layout } from "tests/component/layout.component";
Expand Down Expand Up @@ -53,6 +54,7 @@ export class Application extends PageHolder {
public assetPage = new AssetPage(this.page);
public buyAndSell = new BuyAndSellPage(this.page, this.electronApp);
public delegate = new DelegateModal(this.page);
public evmDelegate = new EvmDelegateModal(this.page);
public delegateDrawer = new DelegateDrawer(this.page);
public drawer = new Drawer(this.page);
public earnV2Dashboard = new EarnV2Page(this.page, this.electronApp);
Expand Down
Loading
Loading