diff --git a/.changeset/afraid-poems-speak.md b/.changeset/afraid-poems-speak.md new file mode 100644 index 000000000000..f1bee09860c3 --- /dev/null +++ b/.changeset/afraid-poems-speak.md @@ -0,0 +1,6 @@ +--- +"ledger-live-desktop": minor +"live-mobile": minor +--- + +Improve MEV analytics diff --git a/.changeset/blue-pigs-add.md b/.changeset/blue-pigs-add.md new file mode 100644 index 000000000000..424622dbce18 --- /dev/null +++ b/.changeset/blue-pigs-add.md @@ -0,0 +1,5 @@ +--- +"ledger-live-desktop": minor +--- + +fix style for a completed sell tx diff --git a/.changeset/curly-pets-sniff.md b/.changeset/curly-pets-sniff.md new file mode 100644 index 000000000000..aa7a85ac82cb --- /dev/null +++ b/.changeset/curly-pets-sniff.md @@ -0,0 +1,5 @@ +--- +"ledger-live-desktop": minor +--- + +Fix flaky portfolio e2e test diff --git a/.changeset/dirty-walls-dream.md b/.changeset/dirty-walls-dream.md new file mode 100644 index 000000000000..dbaf8400d6a7 --- /dev/null +++ b/.changeset/dirty-walls-dream.md @@ -0,0 +1,5 @@ +--- +"live-mobile": minor +--- + +Add reborn landing pages diff --git a/.changeset/hot-cameras-fly.md b/.changeset/hot-cameras-fly.md new file mode 100644 index 000000000000..af48f850ead9 --- /dev/null +++ b/.changeset/hot-cameras-fly.md @@ -0,0 +1,5 @@ +--- +"ledger-live-desktop": minor +--- + +broadcasting on e2e tests only on scheduled workflows on Monday diff --git a/.changeset/khaki-llamas-flow.md b/.changeset/khaki-llamas-flow.md new file mode 100644 index 000000000000..2d1fc36ea9a7 --- /dev/null +++ b/.changeset/khaki-llamas-flow.md @@ -0,0 +1,5 @@ +--- +"@ledgerhq/live-common": minor +--- + +swap history works for DEX swaps diff --git a/.changeset/slow-tips-camp.md b/.changeset/slow-tips-camp.md new file mode 100644 index 000000000000..81d985413475 --- /dev/null +++ b/.changeset/slow-tips-camp.md @@ -0,0 +1,9 @@ +--- +"@ledgerhq/coin-polkadot": minor +"@ledgerhq/coin-stellar": minor +"@ledgerhq/coin-tezos": minor +"@ledgerhq/coin-xrp": minor +"@ledgerhq/coin-framework": minor +--- + +Alpaca allows delegate and undelegate tx crafting diff --git a/.changeset/thin-planets-accept.md b/.changeset/thin-planets-accept.md new file mode 100644 index 000000000000..55789124f459 --- /dev/null +++ b/.changeset/thin-planets-accept.md @@ -0,0 +1,5 @@ +--- +"ledger-live-desktop": minor +--- + +Add swap related analytic events diff --git a/.changeset/tidy-baboons-divide.md b/.changeset/tidy-baboons-divide.md new file mode 100644 index 000000000000..fac0ca4993eb --- /dev/null +++ b/.changeset/tidy-baboons-divide.md @@ -0,0 +1,5 @@ +--- +"live-mobile": minor +--- + +Landing Page Sticky CTA Content Card diff --git a/.changeset/two-pigs-buy.md b/.changeset/two-pigs-buy.md new file mode 100644 index 000000000000..8d8aa32c4462 --- /dev/null +++ b/.changeset/two-pigs-buy.md @@ -0,0 +1,7 @@ +--- +"@ledgerhq/coin-vechain": minor +"live-mobile": minor +"@ledgerhq/live-common": minor +--- + +move vechain to its own coin module diff --git a/.github/workflows/changeset-enforce.yml b/.github/workflows/changeset-enforce.yml deleted file mode 100644 index 7b489745eb0c..000000000000 --- a/.github/workflows/changeset-enforce.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: No patch level changesets -on: - pull_request - -jobs: - check_changesets: - runs-on: ubuntu-22.04 - - steps: - - name: Checkout repository (feature branch) - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - fetch-depth: 200 - - - name: Fetch develop branch - run: | - git fetch origin develop:develop --depth=1 - - - name: Verify develop branch - run: git branch --all - - - uses: pnpm/action-setup@v4 - with: - version: 9.12.3 - - - name: Install changesets - run: pnpm add -g @changesets/cli@2.27.7 - - - name: Generate changeset status - run: pnpm changeset status --output=changeset-status.json - - - name: Check for patch level changesets - run: | - PATCH_CHANGESET_IDS=$(jq -r '.changesets[] | select(.releases[].type == "patch") | .id' changeset-status.json) - if [ -n "$PATCH_CHANGESET_IDS" ]; then - echo "Patch changesets found:" - echo "$PATCH_CHANGESET_IDS" - echo "❌ Patch level changesets are reserved for hotfixes, use major or minor only" - exit 1 - else - echo "✅ No patch level changesets found." - fi \ No newline at end of file diff --git a/.github/workflows/test-mobile-e2e-reusable.yml b/.github/workflows/test-mobile-e2e-reusable.yml index b16a451db50f..c6c192311443 100644 --- a/.github/workflows/test-mobile-e2e-reusable.yml +++ b/.github/workflows/test-mobile-e2e-reusable.yml @@ -52,10 +52,15 @@ permissions: id-token: write contents: read +env: + SPECULOS_IMAGE_TAG: ghcr.io/ledgerhq/speculos:0.11 + COINAPPS: ${{ github.workspace }}/coin-apps + jobs: detox-tests-ios: name: "LLM - iOS Detox Tests" runs-on: [m1, ARM64] + if: ${{ !inputs.speculos_tests }} env: NODE_OPTIONS: "--max-old-space-size=7168" LANG: en_US.UTF-8 @@ -89,7 +94,7 @@ jobs: id: detox-build with: path: ${{ github.workspace }}/apps/ledger-live-mobile/ios/build/Build/Products/Release-iphonesimulator - key: ${{ runner.os }}-detox-${{ hashFiles('apps/ledger-live-mobile/ios/Podfile.lock', 'apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj', 'apps/ledger-live-mobile/detox.config.js') }} + key: ${{ runner.os }}-detox-${{ hashFiles('apps/ledger-live-mobile/ios/Podfile.lock', 'apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj', 'apps/ledger-live-mobile/detox.config.js', 'apps/ledger-live-mobile/.env.mock') }} accessKey: ${{ env.AWS_ACCESS_KEY_ID }} secretKey: ${{ env.AWS_SECRET_ACCESS_KEY }} sessionToken: ${{ env.AWS_SESSION_TOKEN}} @@ -121,10 +126,21 @@ jobs: - name: Build JS Bundle app for Detox test run if: steps.detox-build.outputs.cache-hit == 'true' run: pnpm mobile e2e:ci -p ios --bundle + - name: Setup Speculos image and Coin Apps + if: ${{ inputs.speculos_tests }} + uses: LedgerHQ/ledger-live/tools/actions/composites/setup-speculos_image@develop + with: + coinapps_path: ${{ env.COINAPPS }} + speculos_tag: ${{ env.SPECULOS_IMAGE_TAG }} + bot_id: ${{ secrets.GH_BOT_APP_ID }} + bot_key: ${{ secrets.GH_BOT_PRIVATE_KEY }} - name: Test iOS app id: detox timeout-minutes: 75 - run: pnpm mobile e2e:ci -p ios -t + run: pnpm mobile e2e:ci -p ios -t $([[ "$INPUT_SPECULOS" == "true" ]] && printf %s '--speculos') + env: + SEED: ${{ secrets.SEED_QAA_B2C }} + INPUT_SPECULOS: ${{ inputs.speculos_tests }} - name: Delete iOS simulator if: ${{ always() && steps.simulator.outputs.id }} run: | @@ -180,8 +196,6 @@ jobs: AVD_CORES: 4 AVD_RAM_SIZE: 4096M AVD_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - SPECULOS_IMAGE_TAG: ghcr.io/ledgerhq/speculos:0.11 - COINAPPS: ${{ github.workspace }}/coin-apps outputs: status: ${{ steps.detox.outcome }} steps: diff --git a/.github/workflows/test-ui-e2e-only-desktop.yml b/.github/workflows/test-ui-e2e-only-desktop.yml index d800be14f6cd..8e6fd7839ed4 100644 --- a/.github/workflows/test-ui-e2e-only-desktop.yml +++ b/.github/workflows/test-ui-e2e-only-desktop.yml @@ -37,11 +37,6 @@ on: required: false type: string default: "B2CQA-2461" - enable_send_test: - description: Enable broadcast - required: false - type: boolean - default: false concurrency: group: ${{ github.workflow }}-${{ github.ref_name != 'develop' && github.ref || github.run_id }} @@ -61,7 +56,6 @@ jobs: CI_OS: "ubuntu-latest" PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 SPECULOS_IMAGE_TAG: ghcr.io/ledgerhq/speculos:0.11 - ENABLE_BROADCAST_TEST: ${{ inputs.enable_send_test }} runs-on: [ledger-live-4xlarge] strategy: fail-fast: false @@ -73,16 +67,6 @@ jobs: with: ref: ${{ inputs.ref || github.sha }} - - name: Setup broadcast environment variables - id: set-env - run: | - day=$(date +%u) - if [ $day -eq 1 ] || "$ENABLE_BROADCAST_TEST" = "1" ; then - echo "ENABLE_TRANSACTION_BROADCAST=1" >> $GITHUB_ENV - else - echo "DISABLE_TRANSACTION_BROADCAST=1" >> $GITHUB_ENV - fi - - name: Setup caches id: caches uses: LedgerHQ/ledger-live/tools/actions/composites/setup-caches@develop diff --git a/apps/ledger-live-desktop/README.md b/apps/ledger-live-desktop/README.md index c25d686124d7..5a8f19eb0e57 100644 --- a/apps/ledger-live-desktop/README.md +++ b/apps/ledger-live-desktop/README.md @@ -60,7 +60,7 @@ LLD is using vite and will import in priority the esm libs so we need to watch a ```bash # watch common -pnpm watch:common +pnpm watch:es:common # watch ljs pnpm watch:es:ljs diff --git a/apps/ledger-live-desktop/src/renderer/analytics/segment.ts b/apps/ledger-live-desktop/src/renderer/analytics/segment.ts index e43f241e4395..1fbde6811db2 100644 --- a/apps/ledger-live-desktop/src/renderer/analytics/segment.ts +++ b/apps/ledger-live-desktop/src/renderer/analytics/segment.ts @@ -22,6 +22,7 @@ import { languageSelector, lastSeenDeviceSelector, localeSelector, + mevProtectionSelector, shareAnalyticsSelector, sharePersonalizedRecommendationsSelector, sidebarCollapsedSelector, @@ -77,6 +78,17 @@ const getLedgerSyncAttributes = (state: State) => { }; }; +const getMEVAttributes = (state: State) => { + if (!analyticsFeatureFlagMethod) return false; + const mevProtection = analyticsFeatureFlagMethod("llMevProtection"); + + const hasMEVActivated = mevProtectionSelector(state); + + return { + MEVProtectionActivated: !mevProtection?.enabled ? "Null" : hasMEVActivated ? "Yes" : "No", + }; +}; + const getPtxAttributes = () => { if (!analyticsFeatureFlagMethod) return {}; const fetchAdditionalCoins = analyticsFeatureFlagMethod("fetchAdditionalCoins"); @@ -148,6 +160,7 @@ const extraProperties = (store: ReduxStore) => { const ptxAttributes = getPtxAttributes(); const ledgerSyncAtributes = getLedgerSyncAttributes(state); + const mevProtectionAtributes = getMEVAttributes(state); const deviceInfo = device ? { @@ -203,6 +216,7 @@ const extraProperties = (store: ReduxStore) => { ...ptxAttributes, ...deviceInfo, ...ledgerSyncAtributes, + ...mevProtectionAtributes, }; }; diff --git a/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/TransactionBroadcastedContent.tsx b/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/TransactionBroadcastedContent.tsx index 7fb6c3bfc732..28b22b30ca7c 100644 --- a/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/TransactionBroadcastedContent.tsx +++ b/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/TransactionBroadcastedContent.tsx @@ -54,7 +54,7 @@ export function TransactionBroadcastedContent(props: TransactionBroadcastedConte )} {mode === ExchangeModeEnum.Sell && sourceCurrency && ( <> - + diff --git a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/FeesDrawerLiveApp/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/FeesDrawerLiveApp/index.tsx index a03755344b9a..157327bec91b 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/FeesDrawerLiveApp/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/FeesDrawerLiveApp/index.tsx @@ -13,6 +13,7 @@ import { getMainAccount } from "@ledgerhq/live-common/account/index"; import LowGasAlertBuyMore from "~/renderer/families/evm/SendAmountFields/LowGasAlertBuyMore"; import TranslatedError from "~/renderer/components/TranslatedError"; import Alert from "~/renderer/components/Alert"; +import { useTrack } from "~/renderer/analytics/segment"; type Props = { setTransaction: SwapTransactionType["setTransaction"]; @@ -36,6 +37,7 @@ export default function FeesDrawerLiveApp({ disableSlowStrategy = false, }: Props) { const swapDefaultTrack = useGetSwapTrackingProperties(); + const track = useTrack(); const [isOpen, setIsOpen] = useState(true); const [transaction, setTransactionState] = useState(initialTransaction); @@ -67,6 +69,15 @@ export default function FeesDrawerLiveApp({ (updater: (arg0: Transaction) => Transaction) => { setTransactionState(prevTransaction => { let updatedTransaction = updater(prevTransaction); + + if (prevTransaction.feesStrategy !== updatedTransaction.feesStrategy) { + track("button_clicked", { + ...swapDefaultTrack, + button: updatedTransaction.feesStrategy, + page: "quoteSwap", + }); + } + bridge .prepareTransaction(mainAccount, updatedTransaction) .then(preparedTransaction => @@ -84,7 +95,7 @@ export default function FeesDrawerLiveApp({ return updatedTransaction; }); }, - [setTransaction, bridge, mainAccount], + [setTransaction, bridge, mainAccount, swapDefaultTrack, track], ); const mapStrategies = useCallback( diff --git a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Navbar/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Navbar/index.tsx index 8ed2a77d40f9..3f0ea2c5cd82 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Navbar/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Navbar/index.tsx @@ -37,8 +37,8 @@ const Navbar = () => { ); const onWrappedTabChange = (nextIndex: number) => { - track("button_clicked2", { - button: `${swapRoutes[nextIndex].name} Tab`, + track("button_clicked", { + button: `${swapRoutes[nextIndex].name}`, page: "Page Swap Form", ...swapDefaultTrack, }); diff --git a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/utils/index.ts b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/utils/index.ts index 2cf92502a3ae..9ccdec5f376e 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/utils/index.ts +++ b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/utils/index.ts @@ -10,6 +10,7 @@ export const SWAP_VERSION = "2.35"; const SWAP_TRACKING_PROPERTIES = { swapVersion: SWAP_VERSION, flow: "swap", + live_app: "swap", }; export const useGetSwapTrackingProperties = () => { diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx b/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx index 7ab5bfe641cc..46e8b0714cea 100644 --- a/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx +++ b/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx @@ -7,6 +7,8 @@ import { languageSelector } from "~/renderer/reducers/settings"; import { useSelector } from "react-redux"; import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index"; import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index"; +import { useTrack } from "~/renderer/analytics/segment"; +import { useGetSwapTrackingProperties } from "../exchange/Swap2/utils"; type Props = { match: { @@ -31,6 +33,8 @@ type Props = { export function LiveApp({ match, appId: propsAppId, location }: Props) { const history = useHistory(); + const track = useTrack(); + const swapTrackingProperties = useGetSwapTrackingProperties(); const { params: internalParams, search } = location; const { state: urlParams, customDappUrl } = useLocation() as ReturnType & Props["location"] & { @@ -55,7 +59,17 @@ export function LiveApp({ match, appId: propsAppId, location }: Props) { ); }, [search, customDappUrl, urlParams?.customDappUrl, internalParams?.customDappUrl]); - const handleClose = useCallback(() => history.push(returnTo || `/platform`), [history, returnTo]); + const handleClose = useCallback(() => { + if (returnTo.startsWith("/swap")) { + track("button_click", { + ...swapTrackingProperties, + button: "close X", + partner: appId, + page: "swap", + }); + } + history.push(returnTo || `/platform`); + }, [history, returnTo, appId, swapTrackingProperties, track]); const themeType = useTheme().colors.palette.type; const lang = useSelector(languageSelector); const params = { diff --git a/apps/ledger-live-desktop/src/sentry/install.ts b/apps/ledger-live-desktop/src/sentry/install.ts index f29122f2c389..2d6882c050fc 100644 --- a/apps/ledger-live-desktop/src/sentry/install.ts +++ b/apps/ledger-live-desktop/src/sentry/install.ts @@ -72,8 +72,6 @@ const ignoreErrors = [ "CantOpenDevice", "could not read from HID device", "DeviceOnDashboardExpected", - "DisconnectedDevice", - "DisconnectedDeviceDuringOperation", "EthAppPleaseEnableContractData", "VechainAppPleaseEnableContractDataAndMultiClause", "failed with status code", diff --git a/apps/ledger-live-desktop/tests/component/drawer.component.ts b/apps/ledger-live-desktop/tests/component/drawer.component.ts index 5aeb8d1b4527..8a2d0c4eadbd 100644 --- a/apps/ledger-live-desktop/tests/component/drawer.component.ts +++ b/apps/ledger-live-desktop/tests/component/drawer.component.ts @@ -1,6 +1,6 @@ import { Component } from "tests/page/abstractClasses"; import { step } from "tests/misc/reporters/step"; -import { Account } from "tests/enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class Drawer extends Component { readonly content = this.page.getByTestId("drawer-content"); diff --git a/apps/ledger-live-desktop/tests/families/algorand.ts b/apps/ledger-live-desktop/tests/families/algorand.ts index b1f7a016305f..69097bfbb50d 100644 --- a/apps/ledger-live-desktop/tests/families/algorand.ts +++ b/apps/ledger-live-desktop/tests/families/algorand.ts @@ -5,7 +5,7 @@ import { pressUntilTextFound, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendAlgorand(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.CAPS_APPROVE); diff --git a/apps/ledger-live-desktop/tests/families/bitcoin.ts b/apps/ledger-live-desktop/tests/families/bitcoin.ts index 4c363d4fbc62..bacff2ab6955 100644 --- a/apps/ledger-live-desktop/tests/families/bitcoin.ts +++ b/apps/ledger-live-desktop/tests/families/bitcoin.ts @@ -6,7 +6,7 @@ import { waitFor, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendBTCBasedCoin(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.ACCEPT); diff --git a/apps/ledger-live-desktop/tests/families/cardano.ts b/apps/ledger-live-desktop/tests/families/cardano.ts index 7433b878e87c..3487f653c343 100644 --- a/apps/ledger-live-desktop/tests/families/cardano.ts +++ b/apps/ledger-live-desktop/tests/families/cardano.ts @@ -6,7 +6,7 @@ import { containsSubstringInEvent, waitFor, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendCardano(tx: Transaction) { await waitFor(DeviceLabels.NEW_ORDINARY_TRANSACTION); diff --git a/apps/ledger-live-desktop/tests/families/cosmos.ts b/apps/ledger-live-desktop/tests/families/cosmos.ts index 3c6279a8170a..f7a97ccb64d5 100644 --- a/apps/ledger-live-desktop/tests/families/cosmos.ts +++ b/apps/ledger-live-desktop/tests/families/cosmos.ts @@ -7,7 +7,7 @@ import { waitFor, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function delegateCosmos(delegatingAccount: Delegate) { await waitFor(DeviceLabels.PLEASE_REVIEW); diff --git a/apps/ledger-live-desktop/tests/families/evm.ts b/apps/ledger-live-desktop/tests/families/evm.ts index 714d98a70607..2dca0d54492f 100644 --- a/apps/ledger-live-desktop/tests/families/evm.ts +++ b/apps/ledger-live-desktop/tests/families/evm.ts @@ -6,7 +6,7 @@ import { containsSubstringInEvent, waitFor, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendEVM(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.ACCEPT); diff --git a/apps/ledger-live-desktop/tests/families/near.ts b/apps/ledger-live-desktop/tests/families/near.ts index 3cf2b2fac1ff..c01adab9f6c5 100644 --- a/apps/ledger-live-desktop/tests/families/near.ts +++ b/apps/ledger-live-desktop/tests/families/near.ts @@ -6,7 +6,7 @@ import { waitFor, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function delegateNear(delegatingAccount: Delegate) { await waitFor(DeviceLabels.VIEW_HEADER); diff --git a/apps/ledger-live-desktop/tests/families/polkadot.ts b/apps/ledger-live-desktop/tests/families/polkadot.ts index 1bd049d350c4..a12540c6842c 100644 --- a/apps/ledger-live-desktop/tests/families/polkadot.ts +++ b/apps/ledger-live-desktop/tests/families/polkadot.ts @@ -5,7 +5,7 @@ import { pressUntilTextFound, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendPolkadot(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.CAPS_APPROVE); diff --git a/apps/ledger-live-desktop/tests/families/solana.ts b/apps/ledger-live-desktop/tests/families/solana.ts index 1ea252ccd0c3..05840ed319cf 100644 --- a/apps/ledger-live-desktop/tests/families/solana.ts +++ b/apps/ledger-live-desktop/tests/families/solana.ts @@ -5,7 +5,7 @@ import { waitFor, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; import { Transaction } from "tests/models/Transaction"; export async function delegateSolana() { diff --git a/apps/ledger-live-desktop/tests/families/stellar.ts b/apps/ledger-live-desktop/tests/families/stellar.ts index 3936ad2ffe71..cd29898f9dc1 100644 --- a/apps/ledger-live-desktop/tests/families/stellar.ts +++ b/apps/ledger-live-desktop/tests/families/stellar.ts @@ -5,7 +5,7 @@ import { pressUntilTextFound, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendStellar(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.SIGN); diff --git a/apps/ledger-live-desktop/tests/families/tron.ts b/apps/ledger-live-desktop/tests/families/tron.ts index 2e48c9ba0767..7727b9acbe91 100644 --- a/apps/ledger-live-desktop/tests/families/tron.ts +++ b/apps/ledger-live-desktop/tests/families/tron.ts @@ -5,7 +5,7 @@ import { pressUntilTextFound, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendTron(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.SIGN); diff --git a/apps/ledger-live-desktop/tests/families/xrp.ts b/apps/ledger-live-desktop/tests/families/xrp.ts index b1c2aa9859d8..2f724f0532b2 100644 --- a/apps/ledger-live-desktop/tests/families/xrp.ts +++ b/apps/ledger-live-desktop/tests/families/xrp.ts @@ -5,7 +5,7 @@ import { pressUntilTextFound, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; export async function sendXRP(tx: Transaction) { const events = await pressUntilTextFound(DeviceLabels.SIGN); diff --git a/apps/ledger-live-desktop/tests/fixtures/common.ts b/apps/ledger-live-desktop/tests/fixtures/common.ts index 18c0c3fe7b83..abc8522a502d 100644 --- a/apps/ledger-live-desktop/tests/fixtures/common.ts +++ b/apps/ledger-live-desktop/tests/fixtures/common.ts @@ -11,7 +11,7 @@ import { safeAppendFile } from "tests/utils/fileUtils"; import { launchApp } from "tests/utils/electronUtils"; import { captureArtifacts } from "tests/utils/allureUtils"; import { randomUUID } from "crypto"; -import { AppInfos } from "tests/enum/AppInfos"; +import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos"; import { lastValueFrom, Observable } from "rxjs"; import { commandCLI } from "tests/utils/cliUtils"; import { registerSpeculosTransport } from "@ledgerhq/live-cli/src/live-common-setup"; @@ -152,8 +152,7 @@ export const test = base.extend({ FEATURE_FLAGS: JSON.stringify(featureFlags), MANAGER_DEV_MODE: IS_NOT_MOCK ? true : undefined, SPECULOS_API_PORT: IS_NOT_MOCK ? getEnv("SPECULOS_API_PORT")?.toString() : undefined, - DISABLE_TRANSACTION_BROADCAST: - process.env.ENABLE_TRANSACTION_BROADCAST == "1" || !IS_NOT_MOCK ? undefined : 1, + DISABLE_TRANSACTION_BROADCAST: !IS_NOT_MOCK ? undefined : 1, }, env, ); diff --git a/apps/ledger-live-desktop/tests/models/Delegate.ts b/apps/ledger-live-desktop/tests/models/Delegate.ts index f4142fb9b65e..60811212792c 100644 --- a/apps/ledger-live-desktop/tests/models/Delegate.ts +++ b/apps/ledger-live-desktop/tests/models/Delegate.ts @@ -1,4 +1,4 @@ -import { Account } from "../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class Delegate { constructor( diff --git a/apps/ledger-live-desktop/tests/models/Swap.ts b/apps/ledger-live-desktop/tests/models/Swap.ts index 8e9affb5cf7e..db010055ff56 100644 --- a/apps/ledger-live-desktop/tests/models/Swap.ts +++ b/apps/ledger-live-desktop/tests/models/Swap.ts @@ -1,7 +1,7 @@ import { Transaction } from "tests/models/Transaction"; -import { Fee } from "tests/enum/Fee"; -import { Account } from "../enum/Account"; -import { Provider, Rate } from "../enum/Swap"; +import { Fee } from "@ledgerhq/live-common/e2e/enum/Fee"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Provider, Rate } from "@ledgerhq/live-common/e2e/enum/Swap"; export class Swap extends Transaction { provider: Provider; diff --git a/apps/ledger-live-desktop/tests/models/Transaction.ts b/apps/ledger-live-desktop/tests/models/Transaction.ts index ce6a39e1c37e..3e94c17ba638 100644 --- a/apps/ledger-live-desktop/tests/models/Transaction.ts +++ b/apps/ledger-live-desktop/tests/models/Transaction.ts @@ -1,5 +1,5 @@ -import { Fee } from "tests/enum/Fee"; -import { Account } from "../enum/Account"; +import { Fee } from "@ledgerhq/live-common/e2e/enum/Fee"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class Transaction { constructor( diff --git a/apps/ledger-live-desktop/tests/page/account.page.ts b/apps/ledger-live-desktop/tests/page/account.page.ts index 69af224484aa..a62d7e0d1590 100644 --- a/apps/ledger-live-desktop/tests/page/account.page.ts +++ b/apps/ledger-live-desktop/tests/page/account.page.ts @@ -1,7 +1,7 @@ import { expect } from "@playwright/test"; import { step } from "tests/misc/reporters/step"; import { AppPage } from "tests/page/abstractClasses"; -import { Account } from "tests/enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class AccountPage extends AppPage { readonly settingsButton = this.page.getByTestId("account-settings-button"); diff --git a/apps/ledger-live-desktop/tests/page/accounts.page.ts b/apps/ledger-live-desktop/tests/page/accounts.page.ts index 96c1126ac402..978945b7ea99 100644 --- a/apps/ledger-live-desktop/tests/page/accounts.page.ts +++ b/apps/ledger-live-desktop/tests/page/accounts.page.ts @@ -1,7 +1,7 @@ import { expect } from "@playwright/test"; import { step } from "tests/misc/reporters/step"; import { AppPage } from "tests/page/abstractClasses"; -import { Currency } from "../enum/Currency"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; export class AccountsPage extends AppPage { private addAccountButton = this.page.getByTestId("accounts-add-account-button"); diff --git a/apps/ledger-live-desktop/tests/page/drawer/asset.drawer.ts b/apps/ledger-live-desktop/tests/page/drawer/asset.drawer.ts index c3761fb7510f..02343f8dd2ec 100644 --- a/apps/ledger-live-desktop/tests/page/drawer/asset.drawer.ts +++ b/apps/ledger-live-desktop/tests/page/drawer/asset.drawer.ts @@ -1,7 +1,7 @@ import { step } from "tests/misc/reporters/step"; import { Drawer } from "tests/component/drawer.component"; -import { Currency } from "tests/enum/Currency"; -import { Account } from "tests/enum/Account"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class AssetDrawer extends Drawer { private assetInput = this.page.getByTestId("select-asset-drawer-search-input"); diff --git a/apps/ledger-live-desktop/tests/page/drawer/delegate.drawer.ts b/apps/ledger-live-desktop/tests/page/drawer/delegate.drawer.ts index bec74710af40..3312d8d8497c 100644 --- a/apps/ledger-live-desktop/tests/page/drawer/delegate.drawer.ts +++ b/apps/ledger-live-desktop/tests/page/drawer/delegate.drawer.ts @@ -1,6 +1,6 @@ import { step } from "tests/misc/reporters/step"; import { Drawer } from "tests/component/drawer.component"; -import { Currency } from "tests/enum/Currency"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; import { Delegate } from "tests/models/Delegate"; import { expect } from "@playwright/test"; import { Transaction } from "tests/models/Transaction"; diff --git a/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts b/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts index 241c9bc619c8..b37b8c894ee1 100644 --- a/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts +++ b/apps/ledger-live-desktop/tests/page/modal/add.account.modal.ts @@ -1,8 +1,8 @@ import { expect } from "@playwright/test"; import { Modal } from "../../component/modal.component"; import { step } from "tests/misc/reporters/step"; -import { Account } from "tests/enum/Account"; -import { Currency } from "tests/enum/Currency"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; export class AddAccountModal extends Modal { private selectAccount = this.page.locator("text=Choose a crypto asset"); // FIXME: I need an id diff --git a/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts b/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts index 10c88bb0694d..afd6f1a40d82 100644 --- a/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts +++ b/apps/ledger-live-desktop/tests/page/modal/receive.modal.ts @@ -1,7 +1,7 @@ import { expect } from "@playwright/test"; import { Modal } from "../../component/modal.component"; import { step } from "tests/misc/reporters/step"; -import { Account } from "tests/enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; export class ReceiveModal extends Modal { private skipDeviceButton = this.page.getByTestId("receive-connect-device-skip-device-button"); diff --git a/apps/ledger-live-desktop/tests/page/speculos.page.ts b/apps/ledger-live-desktop/tests/page/speculos.page.ts index 64b0e95a76b3..e09ff5de2a75 100644 --- a/apps/ledger-live-desktop/tests/page/speculos.page.ts +++ b/apps/ledger-live-desktop/tests/page/speculos.page.ts @@ -6,12 +6,12 @@ import { waitFor, containsSubstringInEvent, } from "@ledgerhq/live-common/e2e/speculos"; -import { Account } from "../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { expect } from "@playwright/test"; import { NFTTransaction, Transaction } from "tests/models/Transaction"; import { Delegate } from "tests/models/Delegate"; -import { DeviceLabels } from "tests/enum/DeviceLabels"; -import { Currency } from "tests/enum/Currency"; +import { DeviceLabels } from "@ledgerhq/live-common/e2e/enum/DeviceLabels"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; import { Swap } from "tests/models/Swap"; import { extractNumberFromString } from "tests/utils/textParserUtils"; import { sendBTCBasedCoin } from "tests/families/bitcoin"; diff --git a/apps/ledger-live-desktop/tests/page/swap.page.ts b/apps/ledger-live-desktop/tests/page/swap.page.ts index b8332f731432..650f9e3b7531 100644 --- a/apps/ledger-live-desktop/tests/page/swap.page.ts +++ b/apps/ledger-live-desktop/tests/page/swap.page.ts @@ -3,7 +3,7 @@ import { waitFor } from "../utils/waitFor"; import { step } from "tests/misc/reporters/step"; import { ElectronApplication, expect } from "@playwright/test"; import { capitalizeFirstLetter } from "tests/utils/textParserUtils"; -import { Account } from "tests/enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { ChooseAssetDrawer } from "tests/page/drawer/choose.asset.drawer"; export class SwapPage extends AppPage { diff --git a/apps/ledger-live-desktop/tests/specs/general/portfolio.spec.ts b/apps/ledger-live-desktop/tests/specs/general/portfolio.spec.ts index 8423568f063f..b7530f96b313 100644 --- a/apps/ledger-live-desktop/tests/specs/general/portfolio.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/general/portfolio.spec.ts @@ -11,6 +11,9 @@ test("Portfolio @smoke", async ({ page }) => { await test.step("load portfolio", async () => { await layout.totalBalance.waitFor({ state: "visible" }); + await portfolioPage.checkBuySellButtonVisibility(); + await portfolioPage.checkSwapButtonVisibility(); + await portfolioPage.checkStakeButtonVisibility(); await expect.soft(page).toHaveScreenshot("portfolio.png", { mask: [layout.marketPerformanceWidget], }); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts index fcfa988b19bb..187dc09ebfe7 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/add.account.spec.ts @@ -1,5 +1,5 @@ import { test } from "../../fixtures/common"; -import { Currency } from "../../enum/Currency"; +import { Currency } from "@ledgerhq/live-common/e2e/enum/Currency"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; diff --git a/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts index e6900a7163af..58034272350e 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/delegate.spec.ts @@ -1,9 +1,10 @@ import { test } from "../../fixtures/common"; -import { Account } from "../../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { Delegate } from "../../models/Delegate"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; import { commandCLI } from "tests/utils/cliUtils"; +import { isRunningInScheduledWorkflow } from "tests/utils/githubUtils"; const e2eDelegationAccounts = [ { @@ -47,17 +48,120 @@ const validators = [ }, ]; -for (const account of e2eDelegationAccounts) { - test.describe("Delegate", () => { +test.describe("Delegate flows", () => { + test.beforeAll(async () => { + process.env.ENABLE_TRANSACTION_BROADCAST = + new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "1" : "0"; + }); + for (const account of e2eDelegationAccounts) { + test.describe("Delegate", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: account.delegate.account.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: account.delegate.account.currency.ticker, + index: account.delegate.account.index, + add: true, + appjson: "", + }, + }, + ], + }); + + test( + `[${account.delegate.account.currency.name}] Delegate`, + { + annotation: { + type: "TMS", + description: account.xrayTicket, + }, + }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName(account.delegate.account.accountName); + + await app.account.clickBannerCTA(); + await app.delegate.verifyProvider(account.delegate.provider); + + await app.delegate.continueDelegate(); + await app.delegate.fillAmount(account.delegate.amount); + await app.modal.countinueSendAmount(); + + await app.speculos.signDelegationTransaction(account.delegate); + await app.delegate.clickViewDetailsButton(); + + await app.drawer.waitForDrawerToBeVisible(); + await app.delegateDrawer.transactionTypeIsVisible(); + await app.delegateDrawer.providerIsVisible(account.delegate); + await app.delegateDrawer.amountValueIsVisible(); + await app.drawer.close(); + + await app.layout.syncAccounts(); + await app.account.clickOnLastOperation(); + await app.delegateDrawer.expectDelegationInfos(account.delegate); + }, + ); + }); + } + + for (const validator of validators) { + test.describe("Select a validator", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: validator.delegate.account.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: validator.delegate.account.currency.ticker, + index: validator.delegate.account.index, + add: true, + appjson: "", + }, + }, + ], + }); + + test( + `[${validator.delegate.account.currency.name}] - Select validator`, + { + annotation: { + type: "TMS", + description: validator.xrayTicket, + }, + }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName(validator.delegate.account.accountName); + + await app.account.startStakingFlowFromMainStakeButton(); + await app.modal.continue(); + + await app.delegate.verifyProvider(validator.delegate.provider); + await app.delegate.openSearchProviderModal(); + await app.delegate.checkValidatorListIsVisible(); + await app.delegate.selectProvider(1); + }, + ); + }); + } + + test.describe("Staking flow from different entry point", () => { + const delegateAccount = new Delegate(Account.ATOM_1, "0.001", "Ledger"); test.use({ userdata: "skip-onboarding", - speculosApp: account.delegate.account.currency.speculosApp, + speculosApp: delegateAccount.account.currency.speculosApp, cliCommands: [ { command: commandCLI.liveData, args: { - currency: account.delegate.account.currency.ticker, - index: account.delegate.account.index, + currency: delegateAccount.account.currency.ticker, + index: delegateAccount.account.index, add: true, appjson: "", }, @@ -66,142 +170,45 @@ for (const account of e2eDelegationAccounts) { }); test( - `[${account.delegate.account.currency.name}] Delegate`, + "Staking flow from portfolio entry point", { annotation: { type: "TMS", - description: account.xrayTicket, + description: "B2CQA-2769", }, }, async ({ app }) => { await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName(account.delegate.account.accountName); + await app.layout.goToPortfolio(); + await app.portfolio.startStakeFlow(); - await app.account.clickBannerCTA(); - await app.delegate.verifyProvider(account.delegate.provider); + await app.assetDrawer.selectAsset(delegateAccount.account.currency); + await app.assetDrawer.selectAccountByIndex(delegateAccount.account); + await app.delegate.verifyProvider(delegateAccount.provider); await app.delegate.continueDelegate(); - await app.delegate.fillAmount(account.delegate.amount); - await app.modal.countinueSendAmount(); - - await app.speculos.signDelegationTransaction(account.delegate); - await app.delegate.clickViewDetailsButton(); - - await app.drawer.waitForDrawerToBeVisible(); - await app.delegateDrawer.transactionTypeIsVisible(); - await app.delegateDrawer.providerIsVisible(account.delegate); - await app.delegateDrawer.amountValueIsVisible(); - await app.drawer.close(); - - await app.layout.syncAccounts(); - await app.account.clickOnLastOperation(); - await app.delegateDrawer.expectDelegationInfos(account.delegate); }, ); - }); -} - -for (const validator of validators) { - test.describe("Select a validator", () => { - test.use({ - userdata: "skip-onboarding", - speculosApp: validator.delegate.account.currency.speculosApp, - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: validator.delegate.account.currency.ticker, - index: validator.delegate.account.index, - add: true, - appjson: "", - }, - }, - ], - }); test( - `[${validator.delegate.account.currency.name}] - Select validator`, + "Staking flow from market entry point", { annotation: { type: "TMS", - description: validator.xrayTicket, + description: "B2CQA-2771", }, }, async ({ app }) => { await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName(validator.delegate.account.accountName); + await app.layout.goToMarket(); + await app.market.search(delegateAccount.account.currency.name); + await app.market.stakeButtonClick(delegateAccount.account.currency.ticker); - await app.account.startStakingFlowFromMainStakeButton(); - await app.modal.continue(); + await app.assetDrawer.selectAccountByIndex(delegateAccount.account); - await app.delegate.verifyProvider(validator.delegate.provider); - await app.delegate.openSearchProviderModal(); - await app.delegate.checkValidatorListIsVisible(); - await app.delegate.selectProvider(1); + await app.delegate.verifyProvider(delegateAccount.provider); + await app.delegate.continueDelegate(); }, ); }); -} - -test.describe("Staking flow from different entry point", () => { - const delegateAccount = new Delegate(Account.ATOM_1, "0.001", "Ledger"); - test.use({ - userdata: "skip-onboarding", - speculosApp: delegateAccount.account.currency.speculosApp, - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: delegateAccount.account.currency.ticker, - index: delegateAccount.account.index, - add: true, - appjson: "", - }, - }, - ], - }); - - test( - "Staking flow from portfolio entry point", - { - annotation: { - type: "TMS", - description: "B2CQA-2769", - }, - }, - async ({ app }) => { - await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToPortfolio(); - await app.portfolio.startStakeFlow(); - - await app.assetDrawer.selectAsset(delegateAccount.account.currency); - await app.assetDrawer.selectAccountByIndex(delegateAccount.account); - - await app.delegate.verifyProvider(delegateAccount.provider); - await app.delegate.continueDelegate(); - }, - ); - - test( - "Staking flow from market entry point", - { - annotation: { - type: "TMS", - description: "B2CQA-2771", - }, - }, - async ({ app }) => { - await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToMarket(); - await app.market.search(delegateAccount.account.currency.name); - await app.market.stakeButtonClick(delegateAccount.account.currency.ticker); - - await app.assetDrawer.selectAccountByIndex(delegateAccount.account); - - await app.delegate.verifyProvider(delegateAccount.provider); - await app.delegate.continueDelegate(); - }, - ); }); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/delete.account.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/delete.account.spec.ts index 85b4c5f39d9d..eaab81c0cde5 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/delete.account.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/delete.account.spec.ts @@ -1,5 +1,5 @@ import { test } from "../../fixtures/common"; -import { Account } from "../../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; import { commandCLI } from "tests/utils/cliUtils"; diff --git a/apps/ledger-live-desktop/tests/specs/speculos/manage.ledgersync.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/manage.ledgersync.spec.ts index 1291396fe02e..abd0ab3ede04 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/manage.ledgersync.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/manage.ledgersync.spec.ts @@ -1,5 +1,5 @@ import { test } from "../../fixtures/common"; -import { AppInfos } from "tests/enum/AppInfos"; +import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; diff --git a/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts index 5ecf99b5bc6e..6bb844f48edb 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/receive.address.spec.ts @@ -1,5 +1,5 @@ import { test } from "../../fixtures/common"; -import { Account } from "../../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; import { commandCLI } from "tests/utils/cliUtils"; diff --git a/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts index 7e3fb6bea36b..2d3895fdf204 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/send.tx.spec.ts @@ -1,10 +1,11 @@ import { test } from "../../fixtures/common"; -import { Account } from "../../enum/Account"; -import { Fee } from "../../enum/Fee"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { Fee } from "@ledgerhq/live-common/e2e/enum/Fee"; import { Transaction, NFTTransaction } from "../../models/Transaction"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; import { commandCLI } from "tests/utils/cliUtils"; +import { isRunningInScheduledWorkflow } from "tests/utils/githubUtils"; //Warning 🚨: XRP Tests may fail due to API HTTP 429 issue - Jira: LIVE-14237 @@ -210,221 +211,187 @@ const tokenTransactionInvalid = [ }, ]; -//Warning 🚨: Test may fail due to the GetAppAndVersion issue - Jira: LIVE-12581 or insufficient funds +test.describe("Send flows", () => { + test.beforeAll(async () => { + process.env.ENABLE_TRANSACTION_BROADCAST = + new Date().getDay() === 1 && isRunningInScheduledWorkflow() ? "1" : "0"; + }); + //Warning 🚨: Test may fail due to the GetAppAndVersion issue - Jira: LIVE-12581 or insufficient funds + + for (const transaction of transactionE2E) { + test.describe("Send from 1 account to another", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToCredit.currency.currencyId, + index: transaction.transaction.accountToCredit.index, + add: true, + appjson: "", + }, + }, + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToDebit.currency.currencyId, + index: transaction.transaction.accountToDebit.index, + add: true, + appjson: "", + }, + }, + ], + }); -for (const transaction of transactionE2E) { - test.describe("Send from 1 account to another", () => { - test.use({ - userdata: "skip-onboarding", - speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, - cliCommands: [ + test( + `Send from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}`, { - command: commandCLI.liveData, - args: { - currency: transaction.transaction.accountToCredit.currency.currencyId, - index: transaction.transaction.accountToCredit.index, - add: true, - appjson: "", + annotation: { + type: "TMS", + description: transaction.xrayTicket, }, }, - { - command: commandCLI.liveData, - args: { - currency: transaction.transaction.accountToDebit.currency.currencyId, - index: transaction.transaction.accountToDebit.index, - add: true, - appjson: "", - }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToDebit.accountName, + ); + + await app.account.clickSend(); + await app.send.craftTx(transaction.transaction); + await app.send.expectTxInfoValidity(transaction.transaction); + await app.send.clickContinueToDevice(); + + await app.speculos.signSendTransaction(transaction.transaction); + await app.send.expectTxSent(); + await app.account.navigateToViewDetails(); + await app.sendDrawer.addressValueIsVisible( + transaction.transaction.accountToCredit.address, + ); + await app.drawer.close(); + + await app.layout.goToAccounts(); + await app.accounts.clickSyncBtnForAccount( + transaction.transaction.accountToCredit.accountName, + ); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToCredit.accountName, + ); + await app.account.clickOnLastOperation(); + await app.sendDrawer.expectReceiverInfos(transaction.transaction); }, - ], + ); }); + } - test( - `Send from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}`, - { - annotation: { - type: "TMS", - description: transaction.xrayTicket, - }, - }, - async ({ app }) => { - await addTmsLink(getDescription(test.info().annotations).split(", ")); - - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName( - transaction.transaction.accountToDebit.accountName, - ); - - await app.account.clickSend(); - await app.send.craftTx(transaction.transaction); - await app.send.expectTxInfoValidity(transaction.transaction); - await app.send.clickContinueToDevice(); - - await app.speculos.signSendTransaction(transaction.transaction); - await app.send.expectTxSent(); - await app.account.navigateToViewDetails(); - await app.sendDrawer.addressValueIsVisible(transaction.transaction.accountToCredit.address); - await app.drawer.close(); + test.describe("Send token (subAccount) - invalid address input", () => { + const tokenTransactionInvalid = { + transaction: new Transaction(Account.ALGO_USDT_1, Account.ALGO_USDT_2, "0.1", Fee.MEDIUM), + expectedErrorMessage: "Recipient account has not opted in the selected ASA.", + }; - await app.layout.goToAccounts(); - await app.accounts.clickSyncBtnForAccount( - transaction.transaction.accountToCredit.accountName, - ); - await app.accounts.navigateToAccountByName( - transaction.transaction.accountToCredit.accountName, - ); - await app.account.clickOnLastOperation(); - await app.sendDrawer.expectReceiverInfos(transaction.transaction); - }, - ); - }); -} - -test.describe("Send token (subAccount) - invalid address input", () => { - const tokenTransactionInvalid = { - transaction: new Transaction(Account.ALGO_USDT_1, Account.ALGO_USDT_2, "0.1", Fee.MEDIUM), - expectedErrorMessage: "Recipient account has not opted in the selected ASA.", - }; - - test.use({ - userdata: "skip-onboarding", - speculosApp: tokenTransactionInvalid.transaction.accountToDebit.currency.speculosApp, - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: tokenTransactionInvalid.transaction.accountToDebit.currency.currencyId, - index: tokenTransactionInvalid.transaction.accountToDebit.index, - add: true, - appjson: "", - }, - }, - ], - }); - - test( - `Send from ${tokenTransactionInvalid.transaction.accountToDebit.accountName} to ${tokenTransactionInvalid.transaction.accountToCredit.accountName} - invalid address input`, - { - annotation: { - type: "TMS", - description: "B2CQA-2702", - }, - }, - async ({ app }) => { - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName( - tokenTransactionInvalid.transaction.accountToDebit.accountName, - ); - await app.account.navigateToTokenInAccount( - tokenTransactionInvalid.transaction.accountToDebit, - ); - await app.account.clickSend(); - await app.send.fillRecipient(tokenTransactionInvalid.transaction.accountToCredit.address); - await app.send.checkContinueButtonDisabled(); - await app.layout.checkErrorMessage(tokenTransactionInvalid.expectedErrorMessage); - }, - ); -}); - -for (const transaction of tokenTransactionInvalid) { - test.describe("Send token (subAccount) - invalid amount input", () => { test.use({ userdata: "skip-onboarding", - speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + speculosApp: tokenTransactionInvalid.transaction.accountToDebit.currency.speculosApp, cliCommands: [ { command: commandCLI.liveData, args: { - currency: transaction.transaction.accountToDebit.currency.currencyId, - index: transaction.transaction.accountToDebit.index, + currency: tokenTransactionInvalid.transaction.accountToDebit.currency.currencyId, + index: tokenTransactionInvalid.transaction.accountToDebit.index, add: true, appjson: "", }, }, ], }); + test( - `Send from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName} - invalid amount input`, + `Send from ${tokenTransactionInvalid.transaction.accountToDebit.accountName} to ${tokenTransactionInvalid.transaction.accountToCredit.accountName} - invalid address input`, { annotation: { type: "TMS", - description: transaction.xrayTicket, + description: "B2CQA-2702", }, }, async ({ app }) => { await app.layout.goToAccounts(); await app.accounts.navigateToAccountByName( - transaction.transaction.accountToDebit.accountName, + tokenTransactionInvalid.transaction.accountToDebit.accountName, + ); + await app.account.navigateToTokenInAccount( + tokenTransactionInvalid.transaction.accountToDebit, ); - await app.account.navigateToTokenInAccount(transaction.transaction.accountToDebit); await app.account.clickSend(); - await app.send.fillRecipient(transaction.transaction.accountToCredit.address); - await app.send.clickContinue(); - await app.send.fillAmount(transaction.transaction.amount); + await app.send.fillRecipient(tokenTransactionInvalid.transaction.accountToCredit.address); await app.send.checkContinueButtonDisabled(); - await app.layout.checkAmoutWarningMessage(transaction.expectedWarningMessage); + await app.layout.checkErrorMessage(tokenTransactionInvalid.expectedErrorMessage); }, ); }); -} - -test.describe("Send token (subAccount) - valid address & amount input", () => { - const tokenTransactionValid = new Transaction( - Account.ETH_USDT_1, - Account.ETH_USDT_2, - "1", - Fee.MEDIUM, - ); - test.use({ - userdata: "skip-onboarding", - speculosApp: tokenTransactionValid.accountToDebit.currency.speculosApp, - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: tokenTransactionValid.accountToDebit.currency.currencyId, - index: tokenTransactionValid.accountToDebit.index, - add: true, - appjson: "", - }, - }, - ], - }); - test( - `Send from ${tokenTransactionValid.accountToDebit.accountName} to ${tokenTransactionValid.accountToCredit.accountName} - valid address & amount input`, - { - annotation: { - type: "TMS", - description: "B2CQA-2703, B2CQA-475", - }, - }, - async ({ app }) => { - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName(tokenTransactionValid.accountToDebit.accountName); - await app.account.navigateToTokenInAccount(tokenTransactionValid.accountToDebit); - await app.account.clickSend(); - await app.send.fillRecipient(tokenTransactionValid.accountToCredit.address); - await app.send.checkContinueButtonEnable(); - await app.layout.checkInputErrorVisibibility("hidden"); - await app.send.clickContinue(); - await app.send.fillAmount(tokenTransactionValid.amount); - await app.send.checkContinueButtonEnable(); - }, - ); -}); + for (const transaction of tokenTransactionInvalid) { + test.describe("Send token (subAccount) - invalid amount input", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToDebit.currency.currencyId, + index: transaction.transaction.accountToDebit.index, + add: true, + appjson: "", + }, + }, + ], + }); + test( + `Send from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName} - invalid amount input`, + { + annotation: { + type: "TMS", + description: transaction.xrayTicket, + }, + }, + async ({ app }) => { + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToDebit.accountName, + ); + await app.account.navigateToTokenInAccount(transaction.transaction.accountToDebit); + await app.account.clickSend(); + await app.send.fillRecipient(transaction.transaction.accountToCredit.address); + await app.send.clickContinue(); + await app.send.fillAmount(transaction.transaction.amount); + await app.send.checkContinueButtonDisabled(); + await app.layout.checkAmoutWarningMessage(transaction.expectedWarningMessage); + }, + ); + }); + } -for (const transaction of transactionsAmountInvalid) { - test.describe("Check invalid amount input error", () => { + test.describe("Send token (subAccount) - valid address & amount input", () => { + const tokenTransactionValid = new Transaction( + Account.ETH_USDT_1, + Account.ETH_USDT_2, + "1", + Fee.MEDIUM, + ); test.use({ userdata: "skip-onboarding", - speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + speculosApp: tokenTransactionValid.accountToDebit.currency.speculosApp, cliCommands: [ { command: commandCLI.liveData, args: { - currency: transaction.transaction.accountToDebit.currency.currencyId, - index: transaction.transaction.accountToDebit.index, + currency: tokenTransactionValid.accountToDebit.currency.currencyId, + index: tokenTransactionValid.accountToDebit.index, add: true, appjson: "", }, @@ -433,89 +400,90 @@ for (const transaction of transactionsAmountInvalid) { }); test( - `Check "${transaction.expectedErrorMessage}" for ${transaction.transaction.accountToDebit.currency.name} - invalid amount ${transaction.transaction.amount} input error`, + `Send from ${tokenTransactionValid.accountToDebit.accountName} to ${tokenTransactionValid.accountToCredit.accountName} - valid address & amount input`, { annotation: { type: "TMS", - description: transaction.xrayTicket, + description: "B2CQA-2703, B2CQA-475", }, }, async ({ app }) => { await app.layout.goToAccounts(); await app.accounts.navigateToAccountByName( - transaction.transaction.accountToDebit.accountName, + tokenTransactionValid.accountToDebit.accountName, ); - + await app.account.navigateToTokenInAccount(tokenTransactionValid.accountToDebit); await app.account.clickSend(); - await app.send.fillRecipient(transaction.transaction.accountToCredit.address); + await app.send.fillRecipient(tokenTransactionValid.accountToCredit.address); + await app.send.checkContinueButtonEnable(); + await app.layout.checkInputErrorVisibibility("hidden"); await app.send.clickContinue(); - await app.send.fillAmount(transaction.transaction.amount); - await app.send.checkContinueButtonDisabled(); - await app.layout.checkErrorMessage(transaction.expectedErrorMessage); + await app.send.fillAmount(tokenTransactionValid.amount); + await app.send.checkContinueButtonEnable(); }, ); }); -} - -test.describe("Verify send max user flow", () => { - const transactionInputValid = new Transaction( - Account.ETH_1, - Account.ETH_2, - "send max", - Fee.MEDIUM, - ); - - test.use({ - userdata: "skip-onboarding", - speculosApp: transactionInputValid.accountToDebit.currency.speculosApp, - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: transactionInputValid.accountToDebit.currency.currencyId, - index: transactionInputValid.accountToDebit.index, - add: true, - appjson: "", + + for (const transaction of transactionsAmountInvalid) { + test.describe("Check invalid amount input error", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToDebit.currency.currencyId, + index: transaction.transaction.accountToDebit.index, + add: true, + appjson: "", + }, + }, + ], + }); + + test( + `Check "${transaction.expectedErrorMessage}" for ${transaction.transaction.accountToDebit.currency.name} - invalid amount ${transaction.transaction.amount} input error`, + { + annotation: { + type: "TMS", + description: transaction.xrayTicket, + }, }, - }, - ], - }); + async ({ app }) => { + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToDebit.accountName, + ); + + await app.account.clickSend(); + await app.send.fillRecipient(transaction.transaction.accountToCredit.address); + await app.send.clickContinue(); + await app.send.fillAmount(transaction.transaction.amount); + await app.send.checkContinueButtonDisabled(); + await app.layout.checkErrorMessage(transaction.expectedErrorMessage); + }, + ); + }); + } - test( - `Check Valid amount input (${transactionInputValid.amount})`, - { - annotation: { - type: "TMS", - description: "B2CQA-473", - }, - }, - async ({ app }) => { - await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName(transactionInputValid.accountToDebit.accountName); - - await app.account.clickSend(); - await app.send.fillRecipient(transactionInputValid.accountToCredit.address); - await app.send.clickContinue(); - await app.send.fillAmount(transactionInputValid.amount); - await app.send.checkContinueButtonEnable(); - await app.layout.checkInputErrorVisibibility("hidden"); - }, - ); -}); + test.describe("Verify send max user flow", () => { + const transactionInputValid = new Transaction( + Account.ETH_1, + Account.ETH_2, + "send max", + Fee.MEDIUM, + ); -for (const transaction of transactionAddressValid) { - test.describe("Send funds step 1 (Recipient) - positive cases (Button enabled)", () => { test.use({ userdata: "skip-onboarding", - speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + speculosApp: transactionInputValid.accountToDebit.currency.speculosApp, cliCommands: [ { command: commandCLI.liveData, args: { - currency: transaction.transaction.accountToDebit.currency.currencyId, - index: transaction.transaction.accountToDebit.index, - scheme: transaction.transaction.accountToDebit.derivationMode, + currency: transactionInputValid.accountToDebit.currency.currencyId, + index: transactionInputValid.accountToDebit.index, add: true, appjson: "", }, @@ -524,119 +492,164 @@ for (const transaction of transactionAddressValid) { }); test( - `Check button enabled (${transaction.transaction.amount} from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}) - valid address input (${transaction.transaction.accountToDebit.address})`, + `Check Valid amount input (${transactionInputValid.amount})`, { annotation: { type: "TMS", - description: transaction.xrayTicket, + description: "B2CQA-473", }, }, async ({ app }) => { await addTmsLink(getDescription(test.info().annotations).split(", ")); await app.layout.goToAccounts(); await app.accounts.navigateToAccountByName( - transaction.transaction.accountToDebit.accountName, + transactionInputValid.accountToDebit.accountName, ); await app.account.clickSend(); - await app.send.fillRecipientInfo(transaction.transaction); - await app.layout.checkInputWarningMessage(transaction.expectedWarningMessage); + await app.send.fillRecipient(transactionInputValid.accountToCredit.address); + await app.send.clickContinue(); + await app.send.fillAmount(transactionInputValid.amount); await app.send.checkContinueButtonEnable(); + await app.layout.checkInputErrorVisibibility("hidden"); }, ); }); -} -for (const transaction of transactionsAddressInvalid) { - test.describe("Send funds step 1 (Recipient) - negative cases (Button disabled)", () => { + for (const transaction of transactionAddressValid) { + test.describe("Send funds step 1 (Recipient) - positive cases (Button enabled)", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToDebit.currency.currencyId, + index: transaction.transaction.accountToDebit.index, + scheme: transaction.transaction.accountToDebit.derivationMode, + add: true, + appjson: "", + }, + }, + ], + }); + + test( + `Check button enabled (${transaction.transaction.amount} from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}) - valid address input (${transaction.transaction.accountToDebit.address})`, + { + annotation: { + type: "TMS", + description: transaction.xrayTicket, + }, + }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToDebit.accountName, + ); + + await app.account.clickSend(); + await app.send.fillRecipientInfo(transaction.transaction); + await app.layout.checkInputWarningMessage(transaction.expectedWarningMessage); + await app.send.checkContinueButtonEnable(); + }, + ); + }); + } + + for (const transaction of transactionsAddressInvalid) { + test.describe("Send funds step 1 (Recipient) - negative cases (Button disabled)", () => { + test.use({ + userdata: "skip-onboarding", + speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, + cliCommands: [ + { + command: commandCLI.liveData, + args: { + currency: transaction.transaction.accountToDebit.currency.currencyId, + index: transaction.transaction.accountToDebit.index, + add: true, + appjson: "", + }, + }, + ], + }); + + test( + `Check "${transaction.expectedErrorMessage}" (from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}) - invalid address input error`, + { + annotation: { + type: "TMS", + description: transaction.xrayTicket, + }, + }, + async ({ app }) => { + await addTmsLink(getDescription(test.info().annotations).split(", ")); + await app.layout.goToAccounts(); + await app.accounts.navigateToAccountByName( + transaction.transaction.accountToDebit.accountName, + ); + + await app.account.clickSend(); + await app.send.fillRecipientInfo(transaction.transaction); + await app.layout.checkErrorMessage(transaction.expectedErrorMessage); + await app.send.checkContinueButtonDisabled(); + }, + ); + }); + } + + test.describe("send NFT to ENS address", () => { + const transaction = new NFTTransaction(Account.ETH_1, Account.ETH_MC, "NY la muse", Fee.SLOW); + test.beforeAll(async () => { + process.env.DISABLE_TRANSACTION_BROADCAST = "true"; + }); + test.afterAll(async () => { + delete process.env.DISABLE_TRANSACTION_BROADCAST; + }); test.use({ userdata: "skip-onboarding", - speculosApp: transaction.transaction.accountToDebit.currency.speculosApp, cliCommands: [ { command: commandCLI.liveData, args: { - currency: transaction.transaction.accountToDebit.currency.currencyId, - index: transaction.transaction.accountToDebit.index, - add: true, + currency: transaction.accountToDebit.currency.currencyId, + index: transaction.accountToDebit.index, appjson: "", + add: true, }, }, ], + speculosApp: transaction.accountToDebit.currency.speculosApp, }); test( - `Check "${transaction.expectedErrorMessage}" (from ${transaction.transaction.accountToDebit.accountName} to ${transaction.transaction.accountToCredit.accountName}) - invalid address input error`, + "Send NFT to ENS address", { annotation: { type: "TMS", - description: transaction.xrayTicket, + description: "B2CQA-2203", }, }, async ({ app }) => { await addTmsLink(getDescription(test.info().annotations).split(", ")); await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName( - transaction.transaction.accountToDebit.accountName, - ); - - await app.account.clickSend(); - await app.send.fillRecipientInfo(transaction.transaction); - await app.layout.checkErrorMessage(transaction.expectedErrorMessage); - await app.send.checkContinueButtonDisabled(); + await app.accounts.navigateToAccountByName(transaction.accountToDebit.accountName); + await app.account.navigateToNFTGallery(); + await app.account.selectNFT(transaction.nftName); + await app.nftDrawer.expectNftNameIsVisible(transaction.nftName); + await app.nftDrawer.clickSend(); + await app.send.craftNFTTx(transaction); + await app.send.expectNFTTxInfoValidity(transaction); + await app.speculos.signSendNFTTransaction(transaction); + await app.send.expectTxSent(); + await app.account.navigateToViewDetails(); + await app.drawer.close(); + await app.account.navigateToNFTOperation(); + await app.sendDrawer.expectNftInfos(transaction); }, ); }); -} - -test.describe("send NFT to ENS address", () => { - const transaction = new NFTTransaction(Account.ETH_1, Account.ETH_MC, "NY la muse", Fee.SLOW); - test.beforeAll(async () => { - process.env.DISABLE_TRANSACTION_BROADCAST = "true"; - }); - test.afterAll(async () => { - delete process.env.DISABLE_TRANSACTION_BROADCAST; - }); - test.use({ - userdata: "skip-onboarding", - cliCommands: [ - { - command: commandCLI.liveData, - args: { - currency: transaction.accountToDebit.currency.currencyId, - index: transaction.accountToDebit.index, - appjson: "", - add: true, - }, - }, - ], - speculosApp: transaction.accountToDebit.currency.speculosApp, - }); - - test( - "Send NFT to ENS address", - { - annotation: { - type: "TMS", - description: "B2CQA-2203", - }, - }, - async ({ app }) => { - await addTmsLink(getDescription(test.info().annotations).split(", ")); - await app.layout.goToAccounts(); - await app.accounts.navigateToAccountByName(transaction.accountToDebit.accountName); - await app.account.navigateToNFTGallery(); - await app.account.selectNFT(transaction.nftName); - await app.nftDrawer.expectNftNameIsVisible(transaction.nftName); - await app.nftDrawer.clickSend(); - await app.send.craftNFTTx(transaction); - await app.send.expectNFTTxInfoValidity(transaction); - await app.speculos.signSendNFTTransaction(transaction); - await app.send.expectTxSent(); - await app.account.navigateToViewDetails(); - await app.drawer.close(); - await app.account.navigateToNFTOperation(); - await app.sendDrawer.expectNftInfos(transaction); - }, - ); }); diff --git a/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts index 5781d1fb3c08..0551ea979b63 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/settings.spec.ts @@ -1,7 +1,7 @@ import { test } from "../../fixtures/common"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; -import { Account } from "tests/enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { commandCLI } from "tests/utils/cliUtils"; test.describe("Settings", () => { diff --git a/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts index c351fe0aa532..329b8bee73c3 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/subAccount.spec.ts @@ -1,5 +1,5 @@ import { test } from "../../fixtures/common"; -import { Account } from "../../enum/Account"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "../../utils/customJsonReporter"; diff --git a/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts b/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts index 95519f630c25..d550fa49172e 100644 --- a/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts +++ b/apps/ledger-live-desktop/tests/specs/speculos/swap.spec.ts @@ -1,10 +1,10 @@ import test from "../../fixtures/common"; -import { Account } from "tests/enum/Account"; -import { AppInfos } from "tests/enum/AppInfos"; +import { Account } from "@ledgerhq/live-common/e2e/enum/Account"; +import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos"; import { setExchangeDependencies } from "@ledgerhq/live-common/e2e/speculos"; -import { Fee } from "tests/enum/Fee"; +import { Fee } from "@ledgerhq/live-common/e2e/enum/Fee"; import { Swap } from "tests/models/Swap"; -import { Provider, Rate } from "tests/enum/Swap"; +import { Provider, Rate } from "@ledgerhq/live-common/e2e/enum/Swap"; import { addTmsLink } from "tests/utils/allureUtils"; import { getDescription } from "tests/utils/customJsonReporter"; import { Application } from "tests/page"; diff --git a/apps/ledger-live-desktop/tests/utils/githubUtils.ts b/apps/ledger-live-desktop/tests/utils/githubUtils.ts new file mode 100644 index 000000000000..89703fe0bb56 --- /dev/null +++ b/apps/ledger-live-desktop/tests/utils/githubUtils.ts @@ -0,0 +1,3 @@ +export function isRunningInScheduledWorkflow(): boolean { + return process.env.GITHUB_ACTIONS === "true" && process.env.GITHUB_EVENT_NAME === "schedule"; +} diff --git a/apps/ledger-live-mobile/.env.mock b/apps/ledger-live-mobile/.env.mock index f243d3f1eb60..e5688b9c296e 100644 --- a/apps/ledger-live-mobile/.env.mock +++ b/apps/ledger-live-mobile/.env.mock @@ -1,6 +1,7 @@ APP_NAME="LLmock" MOCK=1 MOCK_COUNTERVALUES=1 +DETOX=1 DISABLE_YELLOW_BOX=1 GOOGLE_SERVICE_INFO_NAME="GoogleService-Info-Testing" MOCK_SCAN_RECIPIENT=bitcoin:3HX3Q4wgYi8nKakxv7kmdCgLWJFrFgcqEt?amount=0.001 diff --git a/apps/ledger-live-mobile/e2e/bridge/client.ts b/apps/ledger-live-mobile/e2e/bridge/client.ts index 84d9312fec7a..3a8586614751 100644 --- a/apps/ledger-live-mobile/e2e/bridge/client.ts +++ b/apps/ledger-live-mobile/e2e/bridge/client.ts @@ -24,7 +24,10 @@ const retryDelay = 500; // Initial retry delay in milliseconds export function init() { const wsPort = LaunchArguments.value()["wsPort"] || "8099"; + const mock = LaunchArguments.value()["mock"]; + log(`[E2E Bridge Client]: wsPort=${wsPort}, mock=${mock}`); + if (mock == "0") setEnv("MOCK", ""); if (ws) { ws.close(); } diff --git a/apps/ledger-live-mobile/e2e/helpers.ts b/apps/ledger-live-mobile/e2e/helpers.ts index 566e16db7022..7eb6f1562a6c 100644 --- a/apps/ledger-live-mobile/e2e/helpers.ts +++ b/apps/ledger-live-mobile/e2e/helpers.ts @@ -5,7 +5,7 @@ import { findFreePort, close as closeBridge, init as initBridge } from "./bridge import { startSpeculos, stopSpeculos, specs } from "@ledgerhq/live-common/e2e/speculos"; import { SpeculosDevice } from "@ledgerhq/speculos-transport"; import invariant from "invariant"; -import { setEnv } from "@ledgerhq/live-env"; +import { getEnv, setEnv } from "@ledgerhq/live-env"; import { startProxy, closeProxy } from "./bridge/proxy"; const DEFAULT_TIMEOUT = 60000; // 60s !! @@ -152,6 +152,7 @@ export async function launchApp() { wsPort: port, detoxURLBlacklistRegex: '\\(".*sdk.*.braze.*",".*.googleapis.com/.*",".*clients3.google.com.*"\\)', + mock: getEnv("MOCK") ? getEnv("MOCK") : "0", }, languageAndLocale: { language: "en-US", @@ -171,11 +172,11 @@ export async function launchSpeculos(appName: string, proxyPort: number) { } const speculosPort = portCounter++; const speculosPidOffset = - (speculosPort - BASE_PORT) * 1000 + parseInt(process.env.TEST_WORKER_INDEX || "0") * 100; + (speculosPort - BASE_PORT) * 1000 + parseInt(process.env.JEST_WORKER_ID || "0") * 100; setEnv("SPECULOS_PID_OFFSET", speculosPidOffset); const testName = expect.getState().testPath || "unknown"; - const speculosDevice = await startSpeculos(testName, specs[appName]); + const speculosDevice = await startSpeculos(testName, specs[appName.replace(/ /g, "_")]); invariant(speculosDevice, "[E2E Setup] Speculos not started"); const speculosApiPort = speculosDevice.ports.apiPort; diff --git a/apps/ledger-live-mobile/e2e/jest.globalTeardown.ts b/apps/ledger-live-mobile/e2e/jest.globalTeardown.ts index 51b579b0e060..6843276b5904 100644 --- a/apps/ledger-live-mobile/e2e/jest.globalTeardown.ts +++ b/apps/ledger-live-mobile/e2e/jest.globalTeardown.ts @@ -1,10 +1,9 @@ const detoxGlobalTeardown = require("detox/runners/jest/globalTeardown"); import { promises as fs } from "fs"; -import { getEnvs, getFlags } from "./bridge/server"; +import { getEnvs, getFlags, loadConfig } from "./bridge/server"; import { formatFlagsData, formatEnvData } from "@ledgerhq/live-common/e2e/index"; -import { launchApp } from "./helpers"; +import { launchApp, waitForElementById } from "./helpers"; import detox from "detox/internals"; -import { Application } from "./page"; import { close as closeBridge } from "./bridge/server"; const environmentFilePath = "artifacts/environment.properties"; @@ -15,8 +14,8 @@ export default async () => { try { await initDetox(); await launchApp(); - const app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); - await app.portfolio.waitForPortfolioPageToLoad(); + await loadConfig("1AccountBTC1AccountETHReadOnlyFalse", true); + await waitForElementById("settings-icon", 120000); const flagsData = formatFlagsData(JSON.parse(await getFlags())); const envsData = formatEnvData(JSON.parse(await getEnvs())); await fs.appendFile(environmentFilePath, flagsData + envsData); diff --git a/apps/ledger-live-mobile/e2e/page/common.page.ts b/apps/ledger-live-mobile/e2e/page/common.page.ts index f9593ac177e9..89ef37a2710c 100644 --- a/apps/ledger-live-mobile/e2e/page/common.page.ts +++ b/apps/ledger-live-mobile/e2e/page/common.page.ts @@ -27,6 +27,7 @@ export default class CommonPage { scannedDeviceRow = (id: string) => `device-scanned-${id}`; pluggedDeviceRow = (nano: DeviceUSB) => `device-item-usb|${JSON.stringify(nano)}`; + @Step("Perform search") async performSearch(text: string) { await waitForElementById(this.searchBarId); await typeTextByElement(this.searchBar(), text, false); @@ -83,8 +84,8 @@ export default class CommonPage { return proxyPort; } - async removeSpeculos(proxyPort: number) { + async removeSpeculos(proxyPort?: number) { await deleteSpeculos(proxyPort); - await bridge.removeKnownSpeculos(`${proxyAddress}:${proxyPort}`); + proxyPort && (await bridge.removeKnownSpeculos(`${proxyAddress}:${proxyPort}`)); } } diff --git a/apps/ledger-live-mobile/e2e/page/index.ts b/apps/ledger-live-mobile/e2e/page/index.ts index 67b420e9d432..a7a71163ac23 100644 --- a/apps/ledger-live-mobile/e2e/page/index.ts +++ b/apps/ledger-live-mobile/e2e/page/index.ts @@ -28,6 +28,14 @@ import WalletTabNavigatorPage from "./wallet/walletTabNavigator.page"; import type { Account } from "@ledgerhq/types-live"; import { DeviceLike } from "~/reducers/types"; import { loadAccounts, loadBleState, loadConfig } from "../bridge/server"; +import { AppInfos } from "@ledgerhq/live-common/e2e/enum/AppInfos"; + +type ApplicationOptions = { + speculosApp?: AppInfos; + userdata?: string; + knownDevices?: DeviceLike[]; + testAccounts?: Account[]; +}; export class Application { public account = new AccountPage(); @@ -57,11 +65,12 @@ export class Application { public transfertMenu = new TransfertMenuDrawer(); public walletTabNavigator = new WalletTabNavigatorPage(); - static async init(userdata?: string, knownDevices?: DeviceLike[], testAccounts?: Account[]) { + static async init({ speculosApp, userdata, knownDevices, testAccounts }: ApplicationOptions) { const app = new Application(); - if (userdata) await loadConfig(userdata, true); - if (knownDevices) await loadBleState({ knownDevices: knownDevices }); - if (testAccounts) await loadAccounts(testAccounts); + userdata && (await loadConfig(userdata, true)); + knownDevices && (await loadBleState({ knownDevices })); + testAccounts && (await loadAccounts(testAccounts)); + speculosApp && (await app.common.addSpeculos(speculosApp.name)); return app; } diff --git a/apps/ledger-live-mobile/e2e/setup.ts b/apps/ledger-live-mobile/e2e/setup.ts index 1f760136968f..92575443871a 100644 --- a/apps/ledger-live-mobile/e2e/setup.ts +++ b/apps/ledger-live-mobile/e2e/setup.ts @@ -11,6 +11,7 @@ import { setEnv } from "@ledgerhq/live-env"; const currentDate = new Date(); const date = format(currentDate, "MM-dd"); const directoryPath = `artifacts/${date}_LLM`; +setEnv("MOCK", process.env.MOCK == "0" ? "" : "1"); beforeAll( async () => { diff --git a/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts b/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts index 5c77a1314f19..844f0b7dbafb 100644 --- a/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/addAccounts/addAccount.spec.ts @@ -11,7 +11,10 @@ const knownDevice = knownDevices.nanoX; describe("Add account from modal", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted", [knownDevice]); + app = await Application.init({ + userdata: "onboardingcompleted", + knownDevices: [knownDevice], + }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts b/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts index 9fb095c879b6..2e34f96e2d24 100644 --- a/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/deeplinks.spec.ts @@ -11,7 +11,10 @@ const bobaLong = "boba"; $TmsLink("B2CQA-1837"); describe("DeepLinks Tests", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse", [knownDevices.nanoX]); + app = await Application.init({ + userdata: "1AccountBTC1AccountETHReadOnlyFalse", + knownDevices: [knownDevices.nanoX], + }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts b/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts index 9cbd8ed1d96b..38d0872c75bb 100644 --- a/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/delegate/cosmos.spec.ts @@ -20,7 +20,11 @@ const knownDevice = knownDevices.nanoX; describe("Cosmos delegate flow", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted", [knownDevice], [testAccount]); + app = await Application.init({ + userdata: "onboardingcompleted", + knownDevices: [knownDevice], + testAccounts: [testAccount], + }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts b/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts index b73d50486e09..b3f70435fe50 100644 --- a/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/languageChange.spec.ts @@ -26,7 +26,7 @@ const verifyLanguageCanBeChanged = (l10n: { lang: string; localization: string } $TmsLink("B2CQA-2344"); describe("Change Language", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); + app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/manager.spec.ts b/apps/ledger-live-mobile/e2e/specs/manager.spec.ts index aa2136228c24..c250a9854992 100644 --- a/apps/ledger-live-mobile/e2e/specs/manager.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/manager.spec.ts @@ -12,7 +12,7 @@ const knownDevice = knownDevices.nanoX; describe("Test My Ledger", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted"); + app = await Application.init({ userdata: "onboardingcompleted" }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/market.spec.ts b/apps/ledger-live-mobile/e2e/specs/market.spec.ts index e98d91bfd164..6fdece52b615 100644 --- a/apps/ledger-live-mobile/e2e/specs/market.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/market.spec.ts @@ -5,7 +5,7 @@ const asset = "Ethereum (ETH)"; describe("Market page for user with no device", () => { beforeAll(async () => { - app = await Application.init("1accountEth"); + app = await Application.init({ userdata: "1accountEth" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts b/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts index e54c94890a97..e30d7ee847f3 100644 --- a/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/nftGallery.spec.ts @@ -7,7 +7,7 @@ const accountCurrency = "ethereum"; // To-Do Fix NFT not available in account describe.skip("NFT Gallery screen", () => { beforeAll(async () => { - app = await Application.init("1Account1NFTNotSpam"); + app = await Application.init({ userdata: "1Account1NFTNotSpam" }); await app.portfolio.waitForPortfolioPageToLoad(); await app.nftGallery.openViaDeeplink(); diff --git a/apps/ledger-live-mobile/e2e/specs/password.spec.ts b/apps/ledger-live-mobile/e2e/specs/password.spec.ts index cce8b2d78e7d..01a35a9d9aeb 100644 --- a/apps/ledger-live-mobile/e2e/specs/password.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/password.spec.ts @@ -7,7 +7,7 @@ const CORRECT_PASSWORD = "passWORD$123!"; describe("Password Lock Screen", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); + app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts b/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts index 3a163c142643..edd1ad3e23fc 100644 --- a/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/receive/currencies.spec.ts @@ -12,7 +12,10 @@ $TmsLink("B2CQA-651"); $TmsLink("B2CQA-1854"); describe("Receive different currency", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted", [knownDevice]); + app = await Application.init({ + userdata: "onboardingcompleted", + knownDevices: [knownDevice], + }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts b/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts index d53df9941973..5c2f4d78ce15 100644 --- a/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/receive/receiveFlow.spec.ts @@ -10,7 +10,10 @@ const knownDevice = knownDevices.nanoX; describe("Receive Flow", () => { beforeAll(async () => { - app = await Application.init("EthAccountXrpAccountReadOnlyFalse", [knownDevice]); + app = await Application.init({ + userdata: "EthAccountXrpAccountReadOnlyFalse", + knownDevices: [knownDevice], + }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts b/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts index 557f6929096f..33e16cf26f3e 100644 --- a/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/send/currencies.spec.ts @@ -35,7 +35,11 @@ const knownDevice = knownDevices.nanoX; $TmsLink("B2CQA-1823"); describe("Send flow", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted", [knownDevice], testAccounts); + app = await Application.init({ + userdata: "onboardingcompleted", + knownDevices: [knownDevice], + testAccounts: testAccounts, + }); deviceAction = new DeviceAction(knownDevice); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts b/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts index 4465e86e6826..1fa55596fc27 100644 --- a/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/speculos/addAccount.spec.ts @@ -9,7 +9,7 @@ const currencies = [ describe("Add accounts", () => { beforeAll(async () => { - app = await Application.init("onboardingcompleted"); + app = await Application.init({ userdata: "onboardingcompleted" }); await app.portfolio.waitForPortfolioPageToLoad(); }); @@ -24,7 +24,7 @@ describe("Add accounts", () => { deviceNumber = await app.common.addSpeculos(nanoApp); await app.addAccount.startAccountsDiscovery(); - await app.addAccount.expectAccountDiscovery(currency, 1); + //await app.addAccount.expectAccountDiscovery(currency, 1); To be fixed in a separate PR await app.addAccount.finishAccountsDiscovery(); await app.addAccount.tapSuccessCta(); await app.account.waitForAccountPageToLoad(currency); diff --git a/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts b/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts index e0766bbddd88..7b6498feaf13 100644 --- a/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/swap/dexSwap.spec.ts @@ -4,7 +4,7 @@ let app: Application; describe("DEX Swap", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); + app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); await app.swap.openViaDeeplink(); diff --git a/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts b/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts index f3a75867e7a1..000658e9f72d 100644 --- a/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/swap/swap.spec.ts @@ -4,7 +4,7 @@ let app: Application; describe("Swap", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); + app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.portfolio.waitForPortfolioPageToLoad(); }); diff --git a/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts b/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts index dc5a88431fb9..382dd923f7b5 100644 --- a/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/unknown-currency-resilience.spec.ts @@ -22,7 +22,7 @@ describe("Portfolio to load with unknown currency data in accounts", () => { { data: badAccount2, version: 0 }, ]); - app = await Application.init("onboardingcompleted"); + app = await Application.init({ userdata: "onboardingcompleted" }); }); it("opens to empty state", async () => { diff --git a/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts b/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts index ad2c9e9ba93b..fb4b1d3ae642 100644 --- a/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts +++ b/apps/ledger-live-mobile/e2e/specs/wallet-api.spec.ts @@ -4,7 +4,7 @@ let app: Application; describe("Wallet API methods", () => { beforeAll(async () => { - app = await Application.init("1AccountBTC1AccountETHReadOnlyFalse"); + app = await Application.init({ userdata: "1AccountBTC1AccountETHReadOnlyFalse" }); await app.dummyWalletApp.startApp(); await app.portfolio.waitForPortfolioPageToLoad(); diff --git a/apps/ledger-live-mobile/e2e/tsconfig.test.json b/apps/ledger-live-mobile/e2e/tsconfig.test.json index 2f10c52d6d80..df42095480e2 100644 --- a/apps/ledger-live-mobile/e2e/tsconfig.test.json +++ b/apps/ledger-live-mobile/e2e/tsconfig.test.json @@ -1,6 +1,7 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "allowJs": true + "allowJs": true, + "experimentalDecorators": true } } diff --git a/apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj b/apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj index 9cc6536b5a72..bf405f88eb54 100644 --- a/apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj +++ b/apps/ledger-live-mobile/ios/ledgerlivemobile.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 2EA091AF2C3FBD5900B6181E /* GoogleService-Info-Testing.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2EA091AE2C3FBD5900B6181E /* GoogleService-Info-Testing.plist */; }; 3407D5D9215D2AB800C9D40B /* NeededForBLE.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3407D5D8215D2AB800C9D40B /* NeededForBLE.swift */; }; 515E9C2C8C0049EC992210D9 /* Inter-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3B6982A2E67F482A8069215B /* Inter-Medium.otf */; }; - 53E10EBE8D058B0E732DD09B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B2ADF826B67305807029EFEE /* PrivacyInfo.xcprivacy */; }; + 9DB523402249BD405124BA05 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3FF1B576B23156C611F7B818 /* PrivacyInfo.xcprivacy */; }; AD6EE26071FA4673B5C89936 /* FontAwesome5_Pro_Brands.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4BD106EA37CA467F9525D699 /* FontAwesome5_Pro_Brands.ttf */; }; AD7A77B84DF3487C812B091B /* FontAwesome5_Pro_Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 668E26194DD94B6D8F10D450 /* FontAwesome5_Pro_Regular.ttf */; }; B116B48438CB416C980DD0E7 /* Inter-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = F3993D7FF61549FE9270BC06 /* Inter-SemiBold.otf */; }; @@ -52,17 +52,20 @@ 148B039A3EDE47A19A6BC6AE /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = ""; }; 17F58471269C64670070C475 /* RCTBluetoothHelperModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTBluetoothHelperModule.m; path = ledgerlivemobile/RCTBluetoothHelperModule.m; sourceTree = ""; }; 17F58473269C64870070C475 /* RCTBluetoothHelperModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTBluetoothHelperModule.h; path = ledgerlivemobile/RCTBluetoothHelperModule.h; sourceTree = ""; }; + 1C5AEEE0CC5135F31C3BEDA3 /* Pods-ledgerlivemobile.nightly.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobile.nightly.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile.nightly.xcconfig"; sourceTree = ""; }; 1EA470840B7C44A3BF38FA4A /* HMAlphaMono-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "HMAlphaMono-Medium.otf"; path = "../node_modules/@ledgerhq/native-ui/lib/assets/fonts/alpha/HMAlphaMono-Medium.otf"; sourceTree = ""; }; 2402D074219C2E6600276138 /* ledgerlivemobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ledgerlivemobile.entitlements; path = ledgerlivemobile/ledgerlivemobile.entitlements; sourceTree = ""; }; 2433F86A66DB455E803650A5 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; 2B8A443FFF9942B295210CA2 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = ""; }; 2EA091AE2C3FBD5900B6181E /* GoogleService-Info-Testing.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info-Testing.plist"; sourceTree = ""; }; + 31305912D029BD43F91EC27C /* Pods-ledgerlivemobile.prerelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobile.prerelease.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile.prerelease.xcconfig"; sourceTree = ""; }; 31C4672E151A9F9D4A18DB00 /* libPods-ledgerlivemobile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ledgerlivemobile.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3263CCC7104E4B86AC2ADDB4 /* MuseoSans-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "MuseoSans-Regular.otf"; path = "../assets/fonts/MuseoSans-Regular.otf"; sourceTree = ""; }; 3407D5D7215D2AB800C9D40B /* ledgerlivemobile-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ledgerlivemobile-Bridging-Header.h"; sourceTree = ""; }; 3407D5D8215D2AB800C9D40B /* NeededForBLE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeededForBLE.swift; sourceTree = ""; }; 3B6982A2E67F482A8069215B /* Inter-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Medium.otf"; path = "../node_modules/@ledgerhq/native-ui/lib/assets/fonts/inter/Inter-Medium.otf"; sourceTree = ""; }; 3E71666B2C4291351C2BA23C /* Pods-ledgerlivemobileTests.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobileTests.staging.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobileTests/Pods-ledgerlivemobileTests.staging.xcconfig"; sourceTree = ""; }; + 3FF1B576B23156C611F7B818 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = ledgerlivemobile/PrivacyInfo.xcprivacy; sourceTree = ""; }; 44387CB2EE84464C83A75FD7 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Regular.ttf"; path = "../assets/fonts/OpenSans-Regular.ttf"; sourceTree = ""; }; 4BD106EA37CA467F9525D699 /* FontAwesome5_Pro_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Pro_Brands.ttf; path = ../assets/fonts/FontAwesome5_Pro_Brands.ttf; sourceTree = ""; }; 4C2397DC873B4F8E91B750A8 /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../assets/fonts/Inter-Regular.otf"; sourceTree = ""; }; @@ -79,12 +82,9 @@ 6D891D99F1084D459DBF667F /* FontAwesome5_Pro_Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Pro_Light.ttf; path = ../assets/fonts/FontAwesome5_Pro_Light.ttf; sourceTree = ""; }; 793F2C3B8DC0475194262928 /* libRCTCamera.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTCamera.a; sourceTree = ""; }; 9390D938BCB148F2A34703E3 /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = "../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf"; sourceTree = ""; }; - 97FD0A4F7C8CED04EEB0A176 /* Pods-ledgerlivemobile.prerelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobile.prerelease.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile.prerelease.xcconfig"; sourceTree = ""; }; 991AA9919E4840DBB799E117 /* FontAwesome5_Pro_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Pro_Solid.ttf; path = ../assets/fonts/FontAwesome5_Pro_Solid.ttf; sourceTree = ""; }; 99A82013C77445B4B2B54AB5 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; }; A80B735599C416373F147DED /* Pods-ledgerlivemobile-ledgerlivemobileTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobile-ledgerlivemobileTests.release.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobile-ledgerlivemobileTests/Pods-ledgerlivemobile-ledgerlivemobileTests.release.xcconfig"; sourceTree = ""; }; - B2ADF826B67305807029EFEE /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = ledgerlivemobile/PrivacyInfo.xcprivacy; sourceTree = ""; }; - B3F983E6F88EBD69A6725FF4 /* Pods-ledgerlivemobile.nightly.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ledgerlivemobile.nightly.xcconfig"; path = "Target Support Files/Pods-ledgerlivemobile/Pods-ledgerlivemobile.nightly.xcconfig"; sourceTree = ""; }; BA451DE627CE516700AAB209 /* GoogleService-Info-Production.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info-Production.plist"; sourceTree = ""; }; BA451DE727CE516700AAB209 /* GoogleService-Info-Staging.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info-Staging.plist"; sourceTree = ""; }; BAE7948F27D7C46A00C465F5 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -164,8 +164,8 @@ 68139B1F4BF967461F30D471 /* Pods-ledgerlivemobile-ledgerlivemobileTests.debug.xcconfig */, A80B735599C416373F147DED /* Pods-ledgerlivemobile-ledgerlivemobileTests.release.xcconfig */, C630F76F0E1C857DA405027E /* Pods-ledgerlivemobile-ledgerlivemobileTests.staging.xcconfig */, - B3F983E6F88EBD69A6725FF4 /* Pods-ledgerlivemobile.nightly.xcconfig */, - 97FD0A4F7C8CED04EEB0A176 /* Pods-ledgerlivemobile.prerelease.xcconfig */, + 1C5AEEE0CC5135F31C3BEDA3 /* Pods-ledgerlivemobile.nightly.xcconfig */, + 31305912D029BD43F91EC27C /* Pods-ledgerlivemobile.prerelease.xcconfig */, ); path = Pods; sourceTree = ""; @@ -185,7 +185,7 @@ 13B07FB71A68108700A75B9A /* main.m */, E9558F012AF93CD200BBEB55 /* InfoPlist.strings */, E85A22C52B17E835005A8E6D /* LaunchScreen.storyboard */, - B2ADF826B67305807029EFEE /* PrivacyInfo.xcprivacy */, + 3FF1B576B23156C611F7B818 /* PrivacyInfo.xcprivacy */, ); name = ledgerlivemobile; sourceTree = ""; @@ -409,7 +409,7 @@ BC26C23ED1C649E7849FF99A /* HMAlphaMono-Medium.otf in Resources */, 515E9C2C8C0049EC992210D9 /* Inter-Medium.otf in Resources */, BAE7949027D7C46A00C465F5 /* GoogleService-Info.plist in Resources */, - 53E10EBE8D058B0E732DD09B /* PrivacyInfo.xcprivacy in Resources */, + 9DB523402249BD405124BA05 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -709,7 +709,6 @@ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VALID_ARCHS = "$(ARCHS_STANDARD)"; - "VALID_ARCHS[arch=*]" = "$(ARCHS_STANDARD)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -1130,7 +1129,7 @@ }; BB0B80022CAAB47600AF2B0C /* Nightly */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B3F983E6F88EBD69A6725FF4 /* Pods-ledgerlivemobile.nightly.xcconfig */; + baseConfigurationReference = 1C5AEEE0CC5135F31C3BEDA3 /* Pods-ledgerlivemobile.nightly.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = NightlyAppIcon; CLANG_ENABLE_MODULES = YES; @@ -1257,7 +1256,7 @@ }; BB2FFDA22CAD600D00AB17D8 /* Prerelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 97FD0A4F7C8CED04EEB0A176 /* Pods-ledgerlivemobile.prerelease.xcconfig */; + baseConfigurationReference = 31305912D029BD43F91EC27C /* Pods-ledgerlivemobile.prerelease.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = PrereleaseAppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/apps/ledger-live-mobile/package.json b/apps/ledger-live-mobile/package.json index b5185b9076bd..5a423b5c7e46 100644 --- a/apps/ledger-live-mobile/package.json +++ b/apps/ledger-live-mobile/package.json @@ -19,8 +19,8 @@ "gen-metafile": "zx ./scripts/gen-metafile.mjs", "e2e:build": "pnpm detox build", "e2e:ci": "zx ./scripts/e2e-ci.mjs", - "e2e:test": "pnpm detox test", - "e2e:test:speculos": "pnpm detox test --testMatch $(pwd)/e2e/specs/speculos/**/*.spec.ts", + "e2e:test": "export MOCK=1 && pnpm detox test", + "e2e:test:speculos": "export MOCK=0 && pnpm detox test --testMatch $(pwd)/e2e/specs/speculos/**/**/*.spec.ts", "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", diff --git a/apps/ledger-live-mobile/src/actions/dynamicContent.ts b/apps/ledger-live-mobile/src/actions/dynamicContent.ts index 2be7ebeb92c7..03510c805f2a 100755 --- a/apps/ledger-live-mobile/src/actions/dynamicContent.ts +++ b/apps/ledger-live-mobile/src/actions/dynamicContent.ts @@ -15,6 +15,7 @@ import { DynamicContentSetNotificationCardsPayload, DynamicContentSetCategoriesCardsPayload, DynamicContentSetMobileCardsPayload, + DynamicContentSetLandingStickyCtaCardsPayload, } from "./types"; const setDynamicContentWalletCardsAction = createAction( @@ -58,6 +59,11 @@ const setDynamicContentNotificationCardsAction = DynamicContentActionTypes.DYNAMIC_CONTENT_SET_NOTIFICATION_CARDS, ); +export const setDynamicContentLandingPageStickyCtaCards = + createAction( + DynamicContentActionTypes.DYNAMIC_CONTENT_SET_LANDING_STICKY_CTA_CARDS, + ); + export const setDynamicContentNotificationCards = (notificationCards: NotificationContentCard[]) => setDynamicContentNotificationCardsAction(notificationCards); diff --git a/apps/ledger-live-mobile/src/actions/types.ts b/apps/ledger-live-mobile/src/actions/types.ts index a351875d625e..862298861625 100644 --- a/apps/ledger-live-mobile/src/actions/types.ts +++ b/apps/ledger-live-mobile/src/actions/types.ts @@ -165,6 +165,7 @@ export enum DynamicContentActionTypes { DYNAMIC_CONTENT_SET_LEARN_CARDS = "DYNAMIC_CONTENT_SET_LEARN_CARDS", DYNAMIC_CONTENT_SET_NOTIFICATION_CARDS = "DYNAMIC_CONTENT_SET_NOTIFICATION_CARDS", DYNAMIC_CONTENT_SET_CATEGORIES_CARDS = "DYNAMIC_CONTENT_SET_CATEGORIES_CARDS", + DYNAMIC_CONTENT_SET_LANDING_STICKY_CTA_CARDS = "DYNAMIC_CONTENT_SET_LANDING_STICKY_CTA_CARDS", DYNAMIC_CONTENT_SET_MOBILE_CARDS = "DYNAMIC_CONTENT_SET_MOBILE_CARDS", DYNAMIC_CONTENT_IS_LOADING = "DYNAMIC_CONTENT_IS_LOADING", } @@ -178,6 +179,8 @@ export type DynamicContentSetLearnCardsPayload = DynamicContentState["learnCards export type DynamicContentSetNotificationCardsPayload = DynamicContentState["notificationCards"]; export type DynamicContentSetCategoriesCardsPayload = DynamicContentState["categoriesCards"]; +export type DynamicContentSetLandingStickyCtaCardsPayload = + DynamicContentState["landingPageStickyCtaCards"]; export type DynamicContentSetMobileCardsPayload = DynamicContentState["mobileCards"]; @@ -187,6 +190,7 @@ export type DynamicContentPayload = | DynamicContentSetLearnCardsPayload | DynamicContentSetNotificationCardsPayload | DynamicContentSetCategoriesCardsPayload + | DynamicContentSetLandingStickyCtaCardsPayload | DynamicContentSetMobileCardsPayload; // === RATINGS ACTIONS === diff --git a/apps/ledger-live-mobile/src/analytics/segment.ts b/apps/ledger-live-mobile/src/analytics/segment.ts index cdb395e99023..ec34d59a7d72 100644 --- a/apps/ledger-live-mobile/src/analytics/segment.ts +++ b/apps/ledger-live-mobile/src/analytics/segment.ts @@ -39,6 +39,7 @@ import { userNpsSelector, personalizedRecommendationsEnabledSelector, hasSeenAnalyticsOptInPromptSelector, + mevProtectionSelector, } from "../reducers/settings"; import { knownDevicesSelector } from "../reducers/ble"; import { DeviceLike, State } from "../reducers/types"; @@ -117,6 +118,17 @@ const getRebornAttributes = () => { }; }; +const getMEVAttributes = (state: State) => { + if (!analyticsFeatureFlagMethod) return false; + const mevProtection = analyticsFeatureFlagMethod("llMevProtection"); + + const hasMEVActivated = mevProtectionSelector(state); + + return { + MEVProtectionActivated: !mevProtection?.enabled ? "Null" : hasMEVActivated ? "Yes" : "No", + }; +}; + const getMandatoryProperties = async (store: AppStore) => { const state: State = store.getState(); const { user } = await getOrCreateUser(); @@ -197,6 +209,7 @@ const extraProperties = async (store: AppStore) => { const ledgerSyncAtributes = getLedgerSyncAttributes(state); const rebornAttributes = getRebornAttributes(); + const mevProtectionAtributes = getMEVAttributes(state); return { ...mandatoryProperties, @@ -234,6 +247,7 @@ const extraProperties = async (store: AppStore) => { stakingProvidersEnabled: stakingProvidersCount || "flag not loaded", ...ledgerSyncAtributes, ...rebornAttributes, + ...mevProtectionAtributes, }; }; diff --git a/apps/ledger-live-mobile/src/components/Animation.tsx b/apps/ledger-live-mobile/src/components/Animation.tsx index 30016e081fdb..c226e39dd850 100644 --- a/apps/ledger-live-mobile/src/components/Animation.tsx +++ b/apps/ledger-live-mobile/src/components/Animation.tsx @@ -45,7 +45,7 @@ export default function Animation({ {...lottieProps} style={[styles.default, { aspectRatio }, style]} loop={lottieProps.loop ?? true} - autoPlay={Config.MOCK ? false : lottieProps.autoPlay ?? true} + autoPlay={Config.DETOX ? false : lottieProps.autoPlay ?? true} /> ); diff --git a/apps/ledger-live-mobile/src/components/BleDevicePairingFlow/BleDevicePairing.tsx b/apps/ledger-live-mobile/src/components/BleDevicePairingFlow/BleDevicePairing.tsx index 5c8c3f2cf99c..3955f5859aa1 100644 --- a/apps/ledger-live-mobile/src/components/BleDevicePairingFlow/BleDevicePairing.tsx +++ b/apps/ledger-live-mobile/src/components/BleDevicePairingFlow/BleDevicePairing.tsx @@ -169,7 +169,7 @@ const BleDevicePairing = ({ deviceToPair, onPaired, onRetry }: BleDevicePairingP } + Icon={} backgroundColor={colors.opacityDefault.c05} size={64} variant="circle" diff --git a/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx b/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx index 29d99f1f8904..3acc3942d885 100644 --- a/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx +++ b/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx @@ -883,7 +883,7 @@ export function renderLoading({ return ( - + {description ?? t("DeviceAction.loading")} diff --git a/apps/ledger-live-mobile/src/components/KeyboardView.tsx b/apps/ledger-live-mobile/src/components/KeyboardView.tsx index 9e6960a8bc5f..8c407273b0a5 100644 --- a/apps/ledger-live-mobile/src/components/KeyboardView.tsx +++ b/apps/ledger-live-mobile/src/components/KeyboardView.tsx @@ -21,7 +21,7 @@ const KeyboardView = React.memo( const isExperimental = useExperimental(); const headerHeight = React.useContext(HeaderHeightContext) || 0; let behaviorParam: KeyboardAvoidingViewProps["behavior"] | undefined; - const keyboardVerticalOffset = isExperimental || Config.MOCK ? ExperimentalHeaderHeight : 0; + const keyboardVerticalOffset = isExperimental || Config.DETOX ? ExperimentalHeaderHeight : 0; if (Platform.OS === "ios") { behaviorParam = behavior || "height"; diff --git a/apps/ledger-live-mobile/src/components/LoadingFooter.tsx b/apps/ledger-live-mobile/src/components/LoadingFooter.tsx index 3099265b22d4..0798bd5a782c 100644 --- a/apps/ledger-live-mobile/src/components/LoadingFooter.tsx +++ b/apps/ledger-live-mobile/src/components/LoadingFooter.tsx @@ -11,7 +11,7 @@ export default () => { margin: 40, }} color={colors.live} - animating={!Config.MOCK} + animating={!Config.DETOX} /> ); }; diff --git a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx index 619a02e4f1c8..9ac51b523b72 100644 --- a/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx +++ b/apps/ledger-live-mobile/src/components/Nft/NftGallery/NftList.tsx @@ -81,8 +81,8 @@ const NftList = ({ data, fetchNextPage, isLoading }: Props) => { ], }; - const Fade_In_Down = Config.MOCK ? undefined : FadeInDown; - const Fade_Out_Down = Config.MOCK ? undefined : FadeOutDown; + const Fade_In_Down = Config.DETOX ? undefined : FadeInDown; + const Fade_Out_Down = Config.DETOX ? undefined : FadeOutDown; const renderItem = useCallback( ({ item, index }: { item: ProtoNFT; index: number; count?: number }) => ( diff --git a/apps/ledger-live-mobile/src/components/RequiresBLE/hooks/useEnableBluetooth.ts b/apps/ledger-live-mobile/src/components/RequiresBLE/hooks/useEnableBluetooth.ts index c54f0972629e..ecaa2ca62e05 100644 --- a/apps/ledger-live-mobile/src/components/RequiresBLE/hooks/useEnableBluetooth.ts +++ b/apps/ledger-live-mobile/src/components/RequiresBLE/hooks/useEnableBluetooth.ts @@ -98,7 +98,7 @@ export function useEnableBluetooth( const checkAndRequestAgain = useCallback(async () => { // Early return when mocking, because when running LLM in an iOS simulator // prompting the user to enable bluetooth services will randomly crash the app - if (!isHookEnabled || Config.MOCK) return; + if (!isHookEnabled || Config.MOCK || Config.DETOX) return; // We actually can't do anything with the result, as on iOS it will always be BLE_UNKNOWN_STATE await promptBluetoothCallback(); diff --git a/apps/ledger-live-mobile/src/components/RootDrawer/InitialDrawers/PTXServicesAppleWarning.tsx b/apps/ledger-live-mobile/src/components/RootDrawer/InitialDrawers/PTXServicesAppleWarning.tsx index 4b6012c7762a..f55e9d28b42d 100644 --- a/apps/ledger-live-mobile/src/components/RootDrawer/InitialDrawers/PTXServicesAppleWarning.tsx +++ b/apps/ledger-live-mobile/src/components/RootDrawer/InitialDrawers/PTXServicesAppleWarning.tsx @@ -44,7 +44,7 @@ export function PTXServicesAppleWarning() { ); useEffect(() => { - if (!exchangeDrawerEnabled && !ctaScreensEnabled && !Config.MOCK) { + if (!exchangeDrawerEnabled && !ctaScreensEnabled && !Config.DETOX) { openDrawer(); } else { _onClose(); diff --git a/apps/ledger-live-mobile/src/components/Skeleton.tsx b/apps/ledger-live-mobile/src/components/Skeleton.tsx index 4bd12fd2d473..1a2ac52b4f40 100644 --- a/apps/ledger-live-mobile/src/components/Skeleton.tsx +++ b/apps/ledger-live-mobile/src/components/Skeleton.tsx @@ -27,7 +27,7 @@ const Skeleton: React.FC = ({ useEffect(() => { // Disable animation when mock env because it was blocking Detox tests - if (animated && !Config.MOCK) { + if (animated && !Config.DETOX) { const duration = 1000; const values = { min: 0.5, max: 1 }; diff --git a/apps/ledger-live-mobile/src/components/TabBar/Transfer.tsx b/apps/ledger-live-mobile/src/components/TabBar/Transfer.tsx index be35d5e07376..b381dd9a8080 100644 --- a/apps/ledger-live-mobile/src/components/TabBar/Transfer.tsx +++ b/apps/ledger-live-mobile/src/components/TabBar/Transfer.tsx @@ -77,7 +77,7 @@ const BackdropPressable = Animated.createAnimatedComponent(styled(Pressable)` background-color: rgba(0, 0, 0, 0.7); `); -const DURATION_MS = Config.MOCK ? 50 : 400; +const DURATION_MS = Config.DETOX ? 50 : 400; const Y_AMPLITUDE = 90; const animParams = { duration: DURATION_MS }; @@ -199,7 +199,7 @@ export function TransferTabIcon() { screenHeight - bottomInset - topInset - - (isExperimental || Config.MOCK ? ExperimentalHeaderHeight : 0); + (isExperimental || Config.DETOX ? ExperimentalHeaderHeight : 0); return ( <> @@ -213,8 +213,8 @@ export function TransferTabIcon() { maxHeight: drawerHeight, paddingBottom: bottomInset + 16 + MAIN_BUTTON_SIZE + MAIN_BUTTON_BOTTOM, }, - Config.MOCK ? {} : opacityStyle, - Config.MOCK ? {} : translateYStyle, + Config.DETOX ? {} : opacityStyle, + Config.DETOX ? {} : translateYStyle, ]} > diff --git a/apps/ledger-live-mobile/src/dynamicContent/ContentCardsLocation.tsx b/apps/ledger-live-mobile/src/dynamicContent/ContentCardsLocation.tsx index 195798f16186..a1cdb15e66b7 100644 --- a/apps/ledger-live-mobile/src/dynamicContent/ContentCardsLocation.tsx +++ b/apps/ledger-live-mobile/src/dynamicContent/ContentCardsLocation.tsx @@ -14,6 +14,7 @@ const Category: ListRenderItem = ({ item }) => ( type Props = FlexBoxProps & { locationId: AllLocations; + hasStickyCta?: boolean; }; type CategoriesWithCards = { @@ -21,9 +22,8 @@ type CategoriesWithCards = { cards: BrazeContentCard[]; }; -const ContentCardsLocationComponent = ({ locationId, ...containerProps }: Props) => { +const ContentCardsLocationComponent = ({ locationId, hasStickyCta, ...containerProps }: Props) => { const { categoriesCards, mobileCards } = useDynamicContent(); - const categoriesToDisplay = filterCategoriesByLocation(categoriesCards, locationId); const categoriesFormatted = formatCategories(categoriesToDisplay, mobileCards); @@ -32,10 +32,12 @@ const ContentCardsLocationComponent = ({ locationId, ...containerProps }: Props) return ( item.category.id} ItemSeparatorComponent={() => } + ListFooterComponent={hasStickyCta ? : null} /> ); diff --git a/apps/ledger-live-mobile/src/dynamicContent/types.ts b/apps/ledger-live-mobile/src/dynamicContent/types.ts index 253cfce41ac0..367e0e292259 100644 --- a/apps/ledger-live-mobile/src/dynamicContent/types.ts +++ b/apps/ledger-live-mobile/src/dynamicContent/types.ts @@ -33,6 +33,8 @@ enum LandingPageUseCase { LP_Wallet_Connect = "LP_Wallet_Connect", LP_Security_Key = "LP_Security_Key", LP_Generic = "LP_Generic", + LP_Reborn1 = "LP_Reborn1", + LP_Reborn2 = "LP_Reborn2", } enum ContentCardLocation { @@ -42,6 +44,7 @@ enum ContentCardLocation { Learn = "learn", MyLedger = "my_ledger", NotificationCenter = "notification_center", + LandingPageStickyCta = "landing_page_sticky_cta", } type AllLocations = ContentCardLocation | LandingPageUseCase; @@ -108,6 +111,12 @@ type NotificationContentCard = ContentCardCommonProperties & { cta?: string; }; +type LandingPageStickyCtaContentCard = ContentCardCommonProperties & { + cta: string; + link: string; + landingPage: LandingPageUseCase; +}; + type HorizontalContentCard = ContentCardCommonProperties & { tag?: string; title?: string; @@ -160,6 +169,7 @@ export type { BrazeContentCard, AnyContentCard, AllLocations, + LandingPageStickyCtaContentCard, }; export { ContentCardLocation, diff --git a/apps/ledger-live-mobile/src/dynamicContent/useDynamicContent.tsx b/apps/ledger-live-mobile/src/dynamicContent/useDynamicContent.tsx index 52cd13096c08..452c584042d5 100644 --- a/apps/ledger-live-mobile/src/dynamicContent/useDynamicContent.tsx +++ b/apps/ledger-live-mobile/src/dynamicContent/useDynamicContent.tsx @@ -9,9 +9,15 @@ import { learnCardsSelector, notificationsCardsSelector, walletCardsSelector, + landingPageStickyCtaCardsSelector, } from "../reducers/dynamicContent"; import { dismissedDynamicCardsSelector } from "../reducers/settings"; -import { AssetContentCard, WalletContentCard } from "./types"; +import { + AssetContentCard, + LandingPageStickyCtaContentCard, + LandingPageUseCase, + WalletContentCard, +} from "./types"; import { track } from "../analytics"; import { setDismissedDynamicCards } from "../actions/settings"; import { setDynamicContentMobileCards } from "~/actions/dynamicContent"; @@ -25,6 +31,7 @@ const useDynamicContent = () => { const walletCards = useSelector(walletCardsSelector); const learnCards = useSelector(learnCardsSelector); const categoriesCards = useSelector(categoriesCardsSelector); + const landingPageStickyCtaCards = useSelector(landingPageStickyCtaCardsSelector); const mobileCards = useSelector(mobileCardsSelector); const hiddenCards: string[] = useSelector(dismissedDynamicCardsSelector); @@ -57,6 +64,11 @@ const useDynamicContent = () => { [assetsCardsDisplayed], ); + const getStickyCtaCardByLandingPage = (landingPage: LandingPageUseCase) => + landingPageStickyCtaCards.find( + (card: LandingPageStickyCtaContentCard) => card.landingPage === landingPage, + ); + const dismissCard = useCallback( (cardId: string) => { dispatch(setDismissedDynamicCards([...hiddenCards, cardId])); @@ -78,6 +90,7 @@ const useDynamicContent = () => { type?: string; layout?: string; location?: string; + landingPage?: string; }, ) => { track(event, params); @@ -94,6 +107,7 @@ const useDynamicContent = () => { categoriesCards, mobileCards, getAssetCardByIdOrTicker, + getStickyCtaCardByLandingPage, logClickCard, logDismissCard, logImpressionCard, diff --git a/apps/ledger-live-mobile/src/dynamicContent/useDynamicContentLogic.ts b/apps/ledger-live-mobile/src/dynamicContent/useDynamicContentLogic.ts index d5bd4f57815e..9c86ce516fb0 100644 --- a/apps/ledger-live-mobile/src/dynamicContent/useDynamicContentLogic.ts +++ b/apps/ledger-live-mobile/src/dynamicContent/useDynamicContentLogic.ts @@ -8,6 +8,7 @@ import { setDynamicContentCategoriesCards, setDynamicContentMobileCards, setIsDynamicContentLoading, + setDynamicContentLandingPageStickyCtaCards, } from "../actions/dynamicContent"; import { useBrazeContentCard } from "./brazeContentCard"; import { @@ -19,6 +20,7 @@ import { mapAsNotificationContentCard, mapAsLearnContentCard, mapAsCategoryContentCard, + mapAsLandingPageStickyCtaContentCard, getMobileContentCards, compareCards, } from "./utils"; @@ -73,6 +75,13 @@ export const useDynamicContentLogic = () => { .map(card => mapAsCategoryContentCard(card)) .sort(compareCards); + const landingPageStickyCtaCards = filterByPage( + mobileContentCards, + ContentCardLocation.LandingPageStickyCta, + ) + .map(card => mapAsLandingPageStickyCtaContentCard(card)) + .sort(compareCards); + dispatch(setDynamicContentCategoriesCards(categoriesCards)); dispatch(setDynamicContentMobileCards(mobileContentCards)); dispatch(setDynamicContentWalletCards(walletCards)); @@ -80,6 +89,7 @@ export const useDynamicContentLogic = () => { dispatch(setDynamicContentNotificationCards(notificationCards)); dispatch(setDynamicContentLearnCards(learnCards)); dispatch(setIsDynamicContentLoading(false)); + dispatch(setDynamicContentLandingPageStickyCtaCards(landingPageStickyCtaCards)); }, [Braze, dismissedContentCardsIds, dispatch]); const clearOldDismissedContentCards = () => { diff --git a/apps/ledger-live-mobile/src/dynamicContent/utils.tsx b/apps/ledger-live-mobile/src/dynamicContent/utils.tsx index 7bb1072c0b56..55fbda15472a 100644 --- a/apps/ledger-live-mobile/src/dynamicContent/utils.tsx +++ b/apps/ledger-live-mobile/src/dynamicContent/utils.tsx @@ -16,6 +16,8 @@ import { VerticalContentCard, HeroContentCard, AllLocations, + LandingPageStickyCtaContentCard, + LandingPageUseCase, } from "~/dynamicContent/types"; export const getMobileContentCards = (array: BrazeContentCard[]) => @@ -217,3 +219,14 @@ export const mapAsMediumSquareContentCard = (card: BrazeContentCard): VerticalCo export const mapAsBigSquareContentCard = (card: BrazeContentCard): VerticalContentCard => mapAsSquareContentCard(card, "L", ContentCardsType.bigSquare, WidthFactor.Full, WidthFactor.Full); + +export const mapAsLandingPageStickyCtaContentCard = ( + card: BrazeContentCard, +): LandingPageStickyCtaContentCard => ({ + id: card.id, + cta: card.extras.cta, + link: card.extras.link, + createdAt: card.created, + viewed: card.viewed, + landingPage: card.extras.landingPage as LandingPageUseCase, +}); diff --git a/apps/ledger-live-mobile/src/families/cosmos/DelegationFlow/02-Summary.tsx b/apps/ledger-live-mobile/src/families/cosmos/DelegationFlow/02-Summary.tsx index 2dcd50572893..b279b5da71ce 100644 --- a/apps/ledger-live-mobile/src/families/cosmos/DelegationFlow/02-Summary.tsx +++ b/apps/ledger-live-mobile/src/families/cosmos/DelegationFlow/02-Summary.tsx @@ -106,7 +106,7 @@ export default function DelegationSummary({ navigation, route }: Props) { const [rotateAnim] = useState(() => new Animated.Value(0)); useEffect(() => { - if (!Config.MOCK) { + if (!Config.DETOX) { Animated.loop( Animated.sequence([ Animated.timing(rotateAnim, { diff --git a/apps/ledger-live-mobile/src/index.tsx b/apps/ledger-live-mobile/src/index.tsx index 2cfc962a7b25..c0ce26ac9395 100644 --- a/apps/ledger-live-mobile/src/index.tsx +++ b/apps/ledger-live-mobile/src/index.tsx @@ -314,7 +314,7 @@ export default class Root extends Component { } onInitFinished = () => { - if (Config.MOCK) { + if (Config.DETOX) { init(); } }; diff --git a/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/genericLandingPage.integration.test.tsx b/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/genericLandingPage.integration.test.tsx new file mode 100644 index 000000000000..daa30a1bd0de --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/genericLandingPage.integration.test.tsx @@ -0,0 +1,70 @@ +import { render, screen } from "@tests/test-renderer"; +import React from "react"; +import { fakeCategoryContentCards, landingPageStickyCtaCard, classicCards } from "./shared"; +import { LandingPageUseCase } from "~/dynamicContent/types"; +import { GenericView } from "../screens/GenericLandingPage"; +import { State } from "~/reducers/types"; + +const openLinkMock = jest.fn(); + +jest.mock("~/dynamicContent/useDynamicContent", () => ({ + __esModule: true, + default: () => ({ + categoriesCards: fakeCategoryContentCards, + mobileCards: classicCards, + logImpressionCard: jest.fn(), + }), +})); + +describe("GenericLandingPage", () => { + test("Display Content Cards on Landing Page, Scroll to bottom and clicks Sticky CTA", async () => { + const { user } = render( + , + { + overrideInitialState: (state: State) => ({ + ...state, + settings: { + ...state.settings, + readOnlyModeEnabled: false, + overriddenFeatureFlags: { + flexibleContentCards: { + enabled: true, + }, + }, + }, + dynamicContent: { + ...state.dynamicContent, + mobileCards: classicCards, + }, + }), + }, + ); + const firstCard = fakeCategoryContentCards[0]; + const secondCard = fakeCategoryContentCards[1]; + + expect(await screen.findByText(String(firstCard.cta))).toBeOnTheScreen(); + expect(await screen.findByText(String(firstCard.title))).toBeOnTheScreen(); + + const scrollContainer = screen.getByTestId("flat-list-container"); + + // Scroll to bottom + await user.scrollTo(scrollContainer, { + y: 200, + }); + + expect(await screen.findByText(String(secondCard.cta))).toBeOnTheScreen(); + expect(await screen.findByText(String(secondCard.title))).toBeOnTheScreen(); + + // Click on Sticky CTA + expect(await screen.findByText(String(landingPageStickyCtaCard.cta))).toBeOnTheScreen(); + await user.press(screen.getByText(String(landingPageStickyCtaCard.cta))); + + expect(openLinkMock).toHaveBeenCalled(); + }); +}); diff --git a/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/shared.tsx b/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/shared.tsx new file mode 100644 index 000000000000..481270c34ea7 --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/LandingPages/__integrations__/shared.tsx @@ -0,0 +1,119 @@ +import { + CategoryContentCard, + ContentCardsLayout, + ContentCardsType, + LandingPageStickyCtaContentCard, + LandingPageUseCase, +} from "~/dynamicContent/types"; +import { WidthFactor } from "~/contentCards/layouts/types"; +import { ContentCard } from "@braze/react-native-sdk"; + +export const fakeCategoryContentCards: CategoryContentCard[] = [ + { + id: "category1", + categoryId: "offers", + location: "LP_Generic" as LandingPageUseCase, + createdAt: 1634310000, + viewed: true, + order: 1, + carouselWidthFactor: WidthFactor.Full, + gridWidthFactor: WidthFactor.Full, + type: ContentCardsType.category, + cardsLayout: ContentCardsLayout.unique, + cardsType: ContentCardsType.bigSquare, + title: "New Arrivals", + description: "Check out the latest arrivals in our store.", + cta: "Shop Now", + link: "https://example.com/new-arrivals", + isDismissable: true, + hasPagination: true, + }, + { + id: "category2", + categoryId: "offers", + location: "LP_Generic" as LandingPageUseCase, + createdAt: 1634310000, + viewed: true, + order: 2, + carouselWidthFactor: WidthFactor.Full, + gridWidthFactor: WidthFactor.Full, + type: ContentCardsType.category, + cardsLayout: ContentCardsLayout.unique, + cardsType: ContentCardsType.bigSquare, + title: "Nano X Accessories", + description: "Check out the latest Nanox.", + cta: "Get one", + link: "https://example.com/new-arrivals", + isDismissable: true, + hasPagination: true, + }, +]; + +export const landingPageStickyCtaCard: LandingPageStickyCtaContentCard = { + id: "stickyCta001", + createdAt: 1634310000, + viewed: false, + cta: "Sign Up Now", + link: "https://example.com/signup", + landingPage: "LP_Generic" as LandingPageUseCase, +}; + +export const classicCards: ContentCard[] = [ + { + id: "card1", + created: 1690112400, // Example UNIX timestamp + expiresAt: -1, // Never expires + viewed: false, + clicked: false, + pinned: false, + dismissed: false, + dismissible: true, + openURLInWebView: true, + isControl: false, + extras: { categoryId: "news", tag: "featured" }, + type: "Classic", + image: "https://example.com/images/card1.jpg", + title: "Breaking News", + cardDescription: "Stay updated with the latest news from around the globe.", + domain: "news.example.com", + url: "https://news.example.com/breaking-news", + }, + { + id: "card2", + created: 1690115400, + expiresAt: 1700115400, // Example expiration timestamp + viewed: true, + clicked: true, + pinned: false, + dismissed: false, + dismissible: false, + openURLInWebView: false, + isControl: false, + extras: { categoryId: "events", priority: "high" }, + type: "Classic", + image: "https://example.com/images/card2.jpg", + title: "Upcoming Event", + cardDescription: "Join us for the annual tech conference happening next week!", + domain: "events.example.com", + url: "https://events.example.com/conference", + }, + { + id: "card3", + created: 1690118400, + expiresAt: 1693123200, // Example expiration timestamp + viewed: false, + clicked: false, + pinned: true, + dismissed: false, + dismissible: true, + openURLInWebView: true, + isControl: false, + extras: { categoryId: "offers", discount: "20%" }, + type: "Classic", + image: "https://example.com/images/card3.jpg", + title: "Exclusive Offer", + cardDescription: "Get 20% off on your first purchase. Limited time only!", + domain: "shop.example.com", + url: "https://shop.example.com/offer", + }, +]; diff --git a/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/index.tsx b/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/index.tsx index d47238325aac..2c9b40af7417 100644 --- a/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/index.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/index.tsx @@ -1,45 +1,54 @@ -import React, { useEffect } from "react"; -import { Flex, InfiniteLoader } from "@ledgerhq/native-ui"; +import React from "react"; +import { Button, Flex, Text, InfiniteLoader } from "@ledgerhq/native-ui"; import { LandingPagesNavigatorParamList } from "~/components/RootNavigator/types/LandingPagesNavigator"; import { BaseComposite, StackNavigatorProps } from "~/components/RootNavigator/types/helpers"; import { ScreenName } from "~/const"; import ContentCardsLocation from "~/dynamicContent/ContentCardsLocation"; import { TrackScreen } from "~/analytics"; -import { LandingPageUseCase } from "~/dynamicContent/types"; -import useDynamicContent from "~/dynamicContent/useDynamicContent"; -import { filterCategoriesByLocation } from "~/dynamicContent/utils"; -import { useSelector } from "react-redux"; -import { isDynamicContentLoadingSelector } from "~/reducers/dynamicContent"; +import styled from "styled-components/native"; +import { HookResult, useGeneralLandingPage } from "./useGeneralLandingPageViewModel"; type NavigationProps = BaseComposite< StackNavigatorProps >; -const GenericLandingPage = (props: NavigationProps) => { - const useCase = props.route.params?.useCase; - const isLoading = useSelector(isDynamicContentLoadingSelector); - const { categoriesCards } = useDynamicContent(); - - useEffect(() => { - if (!useCase || !Object.values(LandingPageUseCase).includes(useCase)) { - props.navigation.goBack(); - } - const categoriesToDisplay = filterCategoriesByLocation(categoriesCards, useCase); - if (categoriesToDisplay.length === 0 && !isLoading) { - props.navigation.goBack(); - } - }, [categoriesCards, isLoading, props.navigation, useCase]); +export const GenericView = (props: HookResult) => { + const { useCase, isLoading, landingStickyCTA, openLink } = props; return ( - + {isLoading ? ( ) : ( - + <> + + {!!landingStickyCTA && ( + + + + )} + )} - + ); }; +export function GenericLandingPage(props: NavigationProps) { + return ; +} + export default GenericLandingPage; + +const Container = styled(Flex)` + position: relative; +`; + +const StickyContainer = styled(Flex)` + position: absolute; + bottom: 35px; +`; diff --git a/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/useGeneralLandingPageViewModel.ts b/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/useGeneralLandingPageViewModel.ts new file mode 100644 index 000000000000..2b072a9ff906 --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/LandingPages/screens/GenericLandingPage/useGeneralLandingPageViewModel.ts @@ -0,0 +1,63 @@ +import { useEffect } from "react"; +import { Linking } from "react-native"; +import { useSelector } from "react-redux"; +import { BaseComposite, StackNavigatorProps } from "~/components/RootNavigator/types/helpers"; +import { LandingPagesNavigatorParamList } from "~/components/RootNavigator/types/LandingPagesNavigator"; +import { ScreenName } from "~/const"; +import { + CategoryContentCard, + LandingPageStickyCtaContentCard, + LandingPageUseCase, +} from "~/dynamicContent/types"; +import useDynamicContent from "~/dynamicContent/useDynamicContent"; +import { filterCategoriesByLocation } from "~/dynamicContent/utils"; +import { isDynamicContentLoadingSelector } from "~/reducers/dynamicContent"; + +export type NavigationProps = BaseComposite< + StackNavigatorProps +>; + +export type HookResult = { + isLoading: boolean; + openLink: (card: LandingPageStickyCtaContentCard) => void; + categoriesCards: CategoryContentCard[]; + landingStickyCTA?: LandingPageStickyCtaContentCard; + useCase: LandingPageUseCase; +}; + +export const useGeneralLandingPage = (props: NavigationProps) => { + const useCase = props.route.params?.useCase; + const isLoading = useSelector(isDynamicContentLoadingSelector); + const { categoriesCards, getStickyCtaCardByLandingPage, trackContentCardEvent } = + useDynamicContent(); + + const landingStickyCTA = getStickyCtaCardByLandingPage(useCase); + + const openLink = (card: LandingPageStickyCtaContentCard) => { + trackContentCardEvent("contentcard_clicked", { + campaign: card.id, + link: card.link, + contentcard: card.cta, + landingPage: useCase, + }); + Linking.openURL(card.link); + }; + + useEffect(() => { + if (!useCase || !Object.values(LandingPageUseCase).includes(useCase)) { + props.navigation.goBack(); + } + const categoriesToDisplay = filterCategoriesByLocation(categoriesCards, useCase); + if (categoriesToDisplay.length === 0 && !isLoading) { + props.navigation.goBack(); + } + }, [categoriesCards, isLoading, props.navigation, useCase]); + + return { + isLoading, + openLink, + categoriesCards, + landingStickyCTA, + useCase, + }; +}; diff --git a/apps/ledger-live-mobile/src/reducers/dynamicContent.ts b/apps/ledger-live-mobile/src/reducers/dynamicContent.ts index c2ba58436799..829d63e98fc3 100644 --- a/apps/ledger-live-mobile/src/reducers/dynamicContent.ts +++ b/apps/ledger-live-mobile/src/reducers/dynamicContent.ts @@ -10,6 +10,7 @@ import { DynamicContentSetNotificationCardsPayload, DynamicContentSetCategoriesCardsPayload, DynamicContentSetMobileCardsPayload, + DynamicContentSetLandingStickyCtaCardsPayload, } from "../actions/types"; export const INITIAL_STATE: DynamicContentState = { @@ -17,6 +18,7 @@ export const INITIAL_STATE: DynamicContentState = { walletCards: [], learnCards: [], notificationCards: [], + landingPageStickyCtaCards: [], categoriesCards: [], mobileCards: [], isLoading: true, @@ -43,6 +45,11 @@ const handlers: ReducerMap = { ...state, categoriesCards: (action as Action).payload, }), + [DynamicContentActionTypes.DYNAMIC_CONTENT_SET_LANDING_STICKY_CTA_CARDS]: (state, action) => ({ + ...state, + landingPageStickyCtaCards: (action as Action) + .payload, + }), [DynamicContentActionTypes.DYNAMIC_CONTENT_SET_MOBILE_CARDS]: (state, action) => ({ ...state, mobileCards: (action as Action).payload, @@ -64,6 +71,9 @@ export const notificationsCardsSelector = (s: State) => s.dynamicContent.notific export const categoriesCardsSelector = (s: State) => s.dynamicContent.categoriesCards; +export const landingPageStickyCtaCardsSelector = (s: State) => + s.dynamicContent.landingPageStickyCtaCards; + export const mobileCardsSelector = (s: State) => s.dynamicContent.mobileCards; export const isDynamicContentLoadingSelector: (s: State) => boolean = (s: State) => diff --git a/apps/ledger-live-mobile/src/reducers/types.ts b/apps/ledger-live-mobile/src/reducers/types.ts index 06226fff8e01..74c9956d07b4 100644 --- a/apps/ledger-live-mobile/src/reducers/types.ts +++ b/apps/ledger-live-mobile/src/reducers/types.ts @@ -23,6 +23,7 @@ import { NotificationContentCard, CategoryContentCard, BrazeContentCard, + LandingPageStickyCtaContentCard, } from "../dynamicContent/types"; import { ProtectStateNumberEnum } from "../components/ServicesWidget/types"; import { ImageType } from "../components/CustomImage/types"; @@ -127,6 +128,8 @@ export type DynamicContentState = { notificationCards: NotificationContentCard[]; /** Dynamic content cards handling flexible categories throughout the app */ categoriesCards: CategoryContentCard[]; + /** Dynamic content cards displayed in the landing page as sticky CTA */ + landingPageStickyCtaCards: LandingPageStickyCtaContentCard[]; /** Dynamic content cards for Ledger Live Mobile */ mobileCards: BrazeContentCard[]; /** Check if CC are loading */ diff --git a/apps/ledger-live-mobile/src/screens/AddAccounts/03-Accounts.tsx b/apps/ledger-live-mobile/src/screens/AddAccounts/03-Accounts.tsx index 7bc4695a5a7a..570aece13b10 100644 --- a/apps/ledger-live-mobile/src/screens/AddAccounts/03-Accounts.tsx +++ b/apps/ledger-live-mobile/src/screens/AddAccounts/03-Accounts.tsx @@ -350,7 +350,7 @@ function AddAccountsAccounts({ item.id} ListHeaderComponent={ScanningHeader} - ListEmptyComponent={} + ListEmptyComponent={} /> diff --git a/apps/ledger-live-mobile/src/screens/ReceiveFunds/ReceiveSecurityModal/index.tsx b/apps/ledger-live-mobile/src/screens/ReceiveFunds/ReceiveSecurityModal/index.tsx index 5df10b5c5ba9..4aa398b06245 100644 --- a/apps/ledger-live-mobile/src/screens/ReceiveFunds/ReceiveSecurityModal/index.tsx +++ b/apps/ledger-live-mobile/src/screens/ReceiveFunds/ReceiveSecurityModal/index.tsx @@ -91,7 +91,7 @@ const ReceiveSecurityModal = ({ noCloseButton preventBackdropClick > - + {component} diff --git a/apps/ledger-live-mobile/src/sentry.ts b/apps/ledger-live-mobile/src/sentry.ts index 2e8d5474bc46..e1bf1a29e8ec 100644 --- a/apps/ledger-live-mobile/src/sentry.ts +++ b/apps/ledger-live-mobile/src/sentry.ts @@ -25,8 +25,6 @@ const excludedErrorName = [ "EthAppPleaseEnableContractData", "VechainAppPleaseEnableContractDataAndMultiClause", "CantOpenDevice", - "DisconnectedDevice", - "DisconnectedDeviceDuringOperation", "DeviceOnDashboardExpected", "PairingFailed", "GetAppAndVersionUnsupportedFormat", @@ -61,7 +59,6 @@ const excludedErrorDescription = [ "Unexpected '<'", "Service Unvailable", // base usage of device - /Device .* was disconnected/, "Invalid channel", /Ledger Device is busy/, "Ledger device: UNKNOWN_ERROR", @@ -82,7 +79,8 @@ const excludedErrorDescription = [ "Bad status on response: 503", // cryptoorg node ]; -const sentryEnabled = Config.SENTRY_DSN && (!__DEV__ || Config.FORCE_SENTRY) && !Config.MOCK; +const sentryEnabled = + Config.SENTRY_DSN && (!__DEV__ || Config.FORCE_SENTRY) && !(Config.MOCK || Config.DETOX); export function withSentry(App: React.ComponentType) { if (sentryEnabled) { diff --git a/apps/ledger-live-mobile/src/utils/constants.ts b/apps/ledger-live-mobile/src/utils/constants.ts index 21855c86e586..77740f77e277 100644 --- a/apps/ledger-live-mobile/src/utils/constants.ts +++ b/apps/ledger-live-mobile/src/utils/constants.ts @@ -1,7 +1,7 @@ import Config from "react-native-config"; export const SYNC_DELAY = 2500; -export const BLE_SCANNING_NOTHING_TIMEOUT = (Config.MOCK ? 60 : 30) * 1000; +export const BLE_SCANNING_NOTHING_TIMEOUT = (Config.DETOX ? 60 : 30) * 1000; export const GENUINE_CHECK_TIMEOUT = 120 * 1000; export const VIBRATION_PATTERN_ERROR = [0, 150]; export const LEDGER_APPLE_WARNING_EXPLAINER_LINK = diff --git a/libs/coin-framework/src/api/errors.ts b/libs/coin-framework/src/api/errors.ts new file mode 100644 index 000000000000..24912924e312 --- /dev/null +++ b/libs/coin-framework/src/api/errors.ts @@ -0,0 +1,5 @@ +export class IncorrectTypeError extends Error { + constructor(message?: string) { + super(`IncorrectType: ${message}`); + } +} diff --git a/libs/coin-framework/src/api/index.ts b/libs/coin-framework/src/api/index.ts index 78b6395f7e30..69fee69f8f96 100644 --- a/libs/coin-framework/src/api/index.ts +++ b/libs/coin-framework/src/api/index.ts @@ -3,4 +3,5 @@ * One consumer of this API is Alpaca. */ +export * from "./errors"; export * from "./types"; diff --git a/libs/coin-framework/src/api/types.ts b/libs/coin-framework/src/api/types.ts index 89586d554f14..cff36d366b16 100644 --- a/libs/coin-framework/src/api/types.ts +++ b/libs/coin-framework/src/api/types.ts @@ -20,7 +20,7 @@ export type Operation = { }; export type Transaction = { - mode: string; + type: string; recipient: string; amount: bigint; fee: bigint; diff --git a/libs/coin-modules/coin-polkadot/src/api/index.integ.test.ts b/libs/coin-modules/coin-polkadot/src/api/index.integ.test.ts index 2872486b0143..e399c8955baf 100644 --- a/libs/coin-modules/coin-polkadot/src/api/index.integ.test.ts +++ b/libs/coin-modules/coin-polkadot/src/api/index.integ.test.ts @@ -81,7 +81,7 @@ describe("Polkadot Api", () => { it("returns a raw transaction", async () => { // When const result = await module.craftTransaction(address, { - mode: "send", + type: "send", recipient: "16YreVmGhM8mNMqnsvK7rn7b1e4SKYsTfFUn4UfCZ65BgDjh", amount: BigInt(10), fee: BigInt(1), diff --git a/libs/coin-modules/coin-polkadot/src/api/index.ts b/libs/coin-modules/coin-polkadot/src/api/index.ts index 3ed38a624353..fcdc3d4d6f0f 100644 --- a/libs/coin-modules/coin-polkadot/src/api/index.ts +++ b/libs/coin-modules/coin-polkadot/src/api/index.ts @@ -1,4 +1,4 @@ -import type { Api } from "@ledgerhq/coin-framework/api/index"; +import type { Api, Transaction as ApiTransaction } from "@ledgerhq/coin-framework/api/index"; import coinConfig, { type PolkadotConfig } from "../config"; import { broadcast, @@ -27,16 +27,7 @@ export function createApi(config: PolkadotConfig): Api { }; } -async function craft( - address: string, - transaction: { - mode: string; - recipient: string; - amount: bigint; - fee: bigint; - supplement?: unknown; - }, -): Promise { +async function craft(address: string, transaction: ApiTransaction): Promise { const extrinsicArg = defaultExtrinsicArg(transaction.amount, transaction.recipient); //TODO: Retrieve correctly the nonce via a call to the node `await api.rpc.system.accountNextIndex(address)` const nonce = 0; diff --git a/libs/coin-modules/coin-stellar/src/api/index.integ.test.ts b/libs/coin-modules/coin-stellar/src/api/index.integ.test.ts index 865efffba888..87023840ae85 100644 --- a/libs/coin-modules/coin-stellar/src/api/index.integ.test.ts +++ b/libs/coin-modules/coin-stellar/src/api/index.integ.test.ts @@ -68,7 +68,7 @@ describe("Stellar Api", () => { it("returns a raw transaction", async () => { // When const result = await module.craftTransaction(address, { - mode: "send", + type: "send", recipient: "GD6QELUZPSKPRWVXOQ3F6GBF4OBRMCHO5PHREXH4ZRTPJAG7V5MD7JGX", amount: BigInt(1_000_000), fee: BigInt(100), diff --git a/libs/coin-modules/coin-stellar/src/api/index.ts b/libs/coin-modules/coin-stellar/src/api/index.ts index df3d896a8458..f13df4107a22 100644 --- a/libs/coin-modules/coin-stellar/src/api/index.ts +++ b/libs/coin-modules/coin-stellar/src/api/index.ts @@ -1,4 +1,4 @@ -import type { Api } from "@ledgerhq/coin-framework/api/index"; +import type { Api, Transaction as ApiTransaction } from "@ledgerhq/coin-framework/api/index"; import coinConfig, { type StellarConfig } from "../config"; import { broadcast, @@ -33,16 +33,7 @@ type Supplement = { function isSupplement(supplement: unknown): supplement is Supplement { return typeof supplement === "object"; } -async function craft( - address: string, - transaction: { - mode: string; - recipient: string; - amount: bigint; - fee: bigint; - supplement?: unknown; - }, -): Promise { +async function craft(address: string, transaction: ApiTransaction): Promise { const supplement = isSupplement(transaction.supplement) ? { assetCode: transaction.supplement?.assetCode, diff --git a/libs/coin-modules/coin-stellar/src/bridge/buildTransaction.ts b/libs/coin-modules/coin-stellar/src/bridge/buildTransaction.ts index b825430e97c5..45f77a17c8d7 100644 --- a/libs/coin-modules/coin-stellar/src/bridge/buildTransaction.ts +++ b/libs/coin-modules/coin-stellar/src/bridge/buildTransaction.ts @@ -28,7 +28,7 @@ export async function buildTransaction(account: Account, transaction: Transactio const { transaction: built } = await craftTransaction( { address: account.freshAddress }, { - mode, + type: mode, recipient, amount: BigInt(amount.toString()), fee: BigInt(fees.toString()), diff --git a/libs/coin-modules/coin-stellar/src/logic/craftTransaction.ts b/libs/coin-modules/coin-stellar/src/logic/craftTransaction.ts index c37785967f72..b8e5f25618ac 100644 --- a/libs/coin-modules/coin-stellar/src/logic/craftTransaction.ts +++ b/libs/coin-modules/coin-stellar/src/logic/craftTransaction.ts @@ -19,7 +19,7 @@ export async function craftTransaction( address: string; }, transaction: { - mode: string; + type: string; recipient: string; amount: bigint; fee: bigint; @@ -29,7 +29,7 @@ export async function craftTransaction( memoValue?: string | null | undefined; }, ): Promise<{ transaction: StellarSdkTransaction; xdr: string }> { - const { amount, recipient, fee, memoType, memoValue, mode, assetCode, assetIssuer } = transaction; + const { amount, recipient, fee, memoType, memoValue, type, assetCode, assetIssuer } = transaction; const source = await loadAccount(account.address); @@ -40,7 +40,7 @@ export async function craftTransaction( const transactionBuilder = buildTransactionBuilder(source, fee); let operation: xdr.Operation | null = null; - if (mode === "changeTrust") { + if (type === "changeTrust") { if (!assetCode || !assetIssuer) { throw new StellarAssetRequired(""); } diff --git a/libs/coin-modules/coin-tezos/src/api/index.integ.test.ts b/libs/coin-modules/coin-tezos/src/api/index.integ.test.ts index e42bd57df02e..179cf21ebaf8 100644 --- a/libs/coin-modules/coin-tezos/src/api/index.integ.test.ts +++ b/libs/coin-modules/coin-tezos/src/api/index.integ.test.ts @@ -1,4 +1,4 @@ -import type { Api } from "@ledgerhq/coin-framework/api/index"; +import { IncorrectTypeError, type Api } from "@ledgerhq/coin-framework/api/index"; import { createApi } from "."; /** * https://teztnets.com/ghostnet-about @@ -82,19 +82,44 @@ describe("Tezos Api", () => { }); describe("craftTransaction", () => { - it("returns a raw transaction", async () => { + it.each([ + { + type: "send", + rawTx: + "6c0053ddb3b3a89ed5c8d8326066032beac6de225c9e010300000a0000a31e81ac3425310e3274a4698a793b2839dc0afa00", + }, + { + type: "delegate", + rawTx: + "6e0053ddb3b3a89ed5c8d8326066032beac6de225c9e01030000ff00a31e81ac3425310e3274a4698a793b2839dc0afa", + }, + { + type: "undelegate", + rawTx: "6e0053ddb3b3a89ed5c8d8326066032beac6de225c9e0103000000", + }, + ])("returns a raw transaction with $type", async ({ type, rawTx }) => { // When const result = await module.craftTransaction(address, { - mode: "send", + type, recipient: "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9", amount: BigInt(10), fee: BigInt(1), }); // Then - expect(result.slice(64)).toEqual( - "6c0053ddb3b3a89ed5c8d8326066032beac6de225c9e010300000a0000a31e81ac3425310e3274a4698a793b2839dc0afa00", - ); + expect(result.slice(64)).toEqual(rawTx); + }); + + it("throws an error if type in 'send' or 'delegate' or 'undelegate'", async () => { + // When + await expect( + module.craftTransaction(address, { + type: "WHATEVERTYPE", + recipient: "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9", + amount: BigInt(10), + fee: BigInt(1), + }), + ).rejects.toThrow(IncorrectTypeError); }); }); }); diff --git a/libs/coin-modules/coin-tezos/src/api/index.ts b/libs/coin-modules/coin-tezos/src/api/index.ts index df61edaf54c9..4d5a5805af14 100644 --- a/libs/coin-modules/coin-tezos/src/api/index.ts +++ b/libs/coin-modules/coin-tezos/src/api/index.ts @@ -1,4 +1,8 @@ -import type { Api } from "@ledgerhq/coin-framework/api/index"; +import { + IncorrectTypeError, + type Api, + type Transaction as ApiTransaction, +} from "@ledgerhq/coin-framework/api/index"; import coinConfig, { type TezosConfig } from "../config"; import { broadcast, @@ -26,17 +30,20 @@ export function createApi(config: TezosConfig): Api { }; } +function isTezosTransactionType(type: string): type is "send" | "delegate" | "undelegate" { + return ["send", "delegate", "undelegate"].includes(type); +} async function craft( address: string, - transaction: { - recipient: string; - amount: bigint; - fee: bigint; - }, + { type, recipient, amount, fee }: ApiTransaction, ): Promise { + if (!isTezosTransactionType(type)) { + throw new IncorrectTypeError(type); + } + const { contents } = await craftTransaction( { address }, - { ...transaction, type: "send", fee: { fees: transaction.fee.toString() } }, + { recipient, amount, type, fee: { fees: fee.toString() } }, ); return rawEncode(contents); } diff --git a/libs/coin-modules/coin-vechain/.eslintrc.js b/libs/coin-modules/coin-vechain/.eslintrc.js new file mode 100644 index 000000000000..8f6848a860b9 --- /dev/null +++ b/libs/coin-modules/coin-vechain/.eslintrc.js @@ -0,0 +1,20 @@ +module.exports = { + env: { + browser: true, + es6: true, + }, + overrides: [ + { + files: ["src/**/*.test.{ts,tsx}"], + env: { + "jest/globals": true, + }, + plugins: ["jest"], + }, + ], + rules: { + "no-console": ["error", { allow: ["warn", "error"] }], + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "warn", + }, +}; diff --git a/libs/coin-modules/coin-vechain/.unimportedrc.json b/libs/coin-modules/coin-vechain/.unimportedrc.json new file mode 100644 index 000000000000..eae49dffeabc --- /dev/null +++ b/libs/coin-modules/coin-vechain/.unimportedrc.json @@ -0,0 +1,74 @@ +{ + "entry": [ + "src/deviceTransactionConfig.ts", + "src/errors.ts", + "src/hw-getAddress.ts", + "src/serialization.ts", + "src/specs.ts", + "src/transaction.ts" + ], + "ignorePatterns": [ + "**/node_modules/**", + "**/*.fixture.ts", + "**/*.mock.ts", + "**/*.test.{js,jsx,ts,tsx}" + ], + "ignoreUnresolved": [], + "ignoreUnimported": [ + "src/account.ts", + "src/bridge/broadcast.ts", + "src/bridge/buildOptimisticOperatioin.ts", + "src/bridge/createTransaction.ts", + "src/bridge/estimateMaxSpendable.ts", + "src/bridge/getTransactionStatus.ts", + "src/bridge/index.ts", + "src/bridge/prepareTransaction.ts", + "src/bridge/signOperation.ts", + "src/bridge/synchronisation.ts", + "src/bridge/transaction.ts", + "src/common-logic/address-utils.ts", + "src/common-logic/hex-utils.ts", + "src/common-logic/index.ts", + "src/common-logic/logic.ts", + "src/common-logic/mapping-utils.ts", + "src/common-logic/pad-address.ts", + "src/common-logic/transaction-utils.ts", + "src/config.ts", + "src/contracts/abis/VIP180.ts", + "src/contracts/abis/params.ts", + "src/contracts/constants.ts", + "src/datasets/index.ts", + "src/datasets/vechain.scanAccounts.1.ts", + "src/datasets/vechain.ts", + "src/index.ts", + "src/mock.ts", + "src/network/index.ts", + "src/network/sdk.ts", + "src/signer/getAddress.ts", + "src/signer/index.ts", + "src/signer/signMessage.ts", + "src/test/bot-deviceActions.ts", + "src/test/bot-specs.ts", + "src/test/bridgeDatasetTest.ts", + "src/test/cli.ts", + "src/test/index.ts", + "src/types/bridge.ts", + "src/types/constants.ts", + "src/types/index.ts", + "src/types/network.ts", + "src/types/signer.ts" + ], + "ignoreUnused": [ + "@ledgerhq/coin-framework", + "@ledgerhq/cryptoassets", + "@ledgerhq/devices", + "@ledgerhq/live-env", + "@ledgerhq/live-network", + "bignumber.js", + "eip55", + "invariant", + "lodash", + "rxjs", + "thor-devkit" + ] +} \ No newline at end of file diff --git a/libs/coin-modules/coin-vechain/CHANGELOG.md b/libs/coin-modules/coin-vechain/CHANGELOG.md new file mode 100644 index 000000000000..959e9741d07f --- /dev/null +++ b/libs/coin-modules/coin-vechain/CHANGELOG.md @@ -0,0 +1,1175 @@ +# @ledgerhq/coin-evm + +## 2.1.3 + +### Patch Changes + +- Updated dependencies [[`0b12c90`](https://github.com/LedgerHQ/ledger-live/commit/0b12c9040d6ee0a326b1d5effd261ddee2db452f)]: + - @ledgerhq/devices@8.4.2 + - @ledgerhq/coin-framework@0.16.1 + +## 2.1.3-hotfix.0 + +### Patch Changes + +- Updated dependencies [[`5d508e5`](https://github.com/LedgerHQ/ledger-live/commit/5d508e5cfd296e458746adf176dd292aa884f7ea)]: + - @ledgerhq/devices@8.4.2-hotfix.0 + - @ledgerhq/coin-framework@0.16.1-hotfix.0 + +## 2.1.2 + +### Patch Changes + +- Updated dependencies [[`ef2d53d`](https://github.com/LedgerHQ/ledger-live/commit/ef2d53d514f1f4e6f18fc79fa3423bd9b0208a04), [`b77ab8e`](https://github.com/LedgerHQ/ledger-live/commit/b77ab8e718ee8e10b74dc15370e8a19d2597d39e), [`fe8a26b`](https://github.com/LedgerHQ/ledger-live/commit/fe8a26b04206df64e50220c3e9249c9a1bd057a6), [`e78f3b7`](https://github.com/LedgerHQ/ledger-live/commit/e78f3b75296c7a063f6cddbeae44c36d236055f3), [`f979216`](https://github.com/LedgerHQ/ledger-live/commit/f9792160293fc8215c6d099f02e1b136c6655f9b), [`c1d2bb0`](https://github.com/LedgerHQ/ledger-live/commit/c1d2bb0866723c10d6e2899d40ddd9b9801189f4), [`c59adf2`](https://github.com/LedgerHQ/ledger-live/commit/c59adf2b0d49ea3c72b94fcb356eb72bcbfc4a6b)]: + - @ledgerhq/cryptoassets@13.2.0 + - @ledgerhq/coin-framework@0.16.0 + - @ledgerhq/errors@6.18.0 + - @ledgerhq/domain-service@1.2.2 + - @ledgerhq/evm-tools@1.1.2 + - @ledgerhq/devices@8.4.1 + - @ledgerhq/live-network@1.3.1 + +## 2.1.2-next.0 + +### Patch Changes + +- Updated dependencies [[`ef2d53d`](https://github.com/LedgerHQ/ledger-live/commit/ef2d53d514f1f4e6f18fc79fa3423bd9b0208a04), [`b77ab8e`](https://github.com/LedgerHQ/ledger-live/commit/b77ab8e718ee8e10b74dc15370e8a19d2597d39e), [`fe8a26b`](https://github.com/LedgerHQ/ledger-live/commit/fe8a26b04206df64e50220c3e9249c9a1bd057a6), [`e78f3b7`](https://github.com/LedgerHQ/ledger-live/commit/e78f3b75296c7a063f6cddbeae44c36d236055f3), [`f979216`](https://github.com/LedgerHQ/ledger-live/commit/f9792160293fc8215c6d099f02e1b136c6655f9b), [`c1d2bb0`](https://github.com/LedgerHQ/ledger-live/commit/c1d2bb0866723c10d6e2899d40ddd9b9801189f4), [`c59adf2`](https://github.com/LedgerHQ/ledger-live/commit/c59adf2b0d49ea3c72b94fcb356eb72bcbfc4a6b)]: + - @ledgerhq/cryptoassets@13.2.0-next.0 + - @ledgerhq/coin-framework@0.16.0-next.0 + - @ledgerhq/errors@6.18.0-next.0 + - @ledgerhq/domain-service@1.2.2-next.0 + - @ledgerhq/evm-tools@1.1.2-next.0 + - @ledgerhq/devices@8.4.1-next.0 + - @ledgerhq/live-network@1.3.1-next.0 + +## 2.1.1 + +### Patch Changes + +- [#7078](https://github.com/LedgerHQ/ledger-live/pull/7078) [`993c5f2`](https://github.com/LedgerHQ/ledger-live/commit/993c5f25b8a3ef3bb1f96dd93883e430e61f9fac) Thanks [@lvndry](https://github.com/lvndry)! - [evm] Improve error message if could not get list of operations + +- [#7206](https://github.com/LedgerHQ/ledger-live/pull/7206) [`81e5b8b`](https://github.com/LedgerHQ/ledger-live/commit/81e5b8bf4830dcb9d666436f2cc4367d92e93e78) Thanks [@kallen-ledger](https://github.com/kallen-ledger)! - chore: resolve merge conflicts + +- Updated dependencies [[`cde94b9`](https://github.com/LedgerHQ/ledger-live/commit/cde94b9584d6889849fb097813a5fc11ea19d069), [`b478096`](https://github.com/LedgerHQ/ledger-live/commit/b478096537a0f86a9e39acc8c6cf17b1184e0849), [`81e5b8b`](https://github.com/LedgerHQ/ledger-live/commit/81e5b8bf4830dcb9d666436f2cc4367d92e93e78)]: + - @ledgerhq/coin-framework@0.15.0 + - @ledgerhq/cryptoassets@13.1.1 + - @ledgerhq/domain-service@1.2.1 + - @ledgerhq/evm-tools@1.1.1 + +## 2.1.1-next.2 + +### Patch Changes + +- [#7206](https://github.com/LedgerHQ/ledger-live/pull/7206) [`81e5b8b`](https://github.com/LedgerHQ/ledger-live/commit/81e5b8bf4830dcb9d666436f2cc4367d92e93e78) Thanks [@kallen-ledger](https://github.com/kallen-ledger)! - chore: resolve merge conflicts + +- Updated dependencies [[`81e5b8b`](https://github.com/LedgerHQ/ledger-live/commit/81e5b8bf4830dcb9d666436f2cc4367d92e93e78)]: + - @ledgerhq/cryptoassets@13.1.1-next.1 + - @ledgerhq/coin-framework@0.15.0-next.2 + - @ledgerhq/domain-service@1.2.1-next.1 + - @ledgerhq/evm-tools@1.1.1-next.1 + +## 2.1.1-next.1 + +### Patch Changes + +- Updated dependencies [[`b478096`](https://github.com/LedgerHQ/ledger-live/commit/b478096537a0f86a9e39acc8c6cf17b1184e0849)]: + - @ledgerhq/cryptoassets@13.1.1-next.0 + - @ledgerhq/coin-framework@0.15.0-next.1 + - @ledgerhq/evm-tools@1.1.1-next.0 + +## 2.1.1-next.0 + +### Patch Changes + +- [#7078](https://github.com/LedgerHQ/ledger-live/pull/7078) [`993c5f2`](https://github.com/LedgerHQ/ledger-live/commit/993c5f25b8a3ef3bb1f96dd93883e430e61f9fac) Thanks [@lvndry](https://github.com/lvndry)! - [evm] Improve error message if could not get list of operations + +- Updated dependencies [[`cde94b9`](https://github.com/LedgerHQ/ledger-live/commit/cde94b9584d6889849fb097813a5fc11ea19d069)]: + - @ledgerhq/coin-framework@0.15.0-next.0 + - @ledgerhq/domain-service@1.2.1-next.0 + - @ledgerhq/evm-tools@1.1.0 + +## 2.1.0 + +### Minor Changes + +- [#6596](https://github.com/LedgerHQ/ledger-live/pull/6596) [`77fa530`](https://github.com/LedgerHQ/ledger-live/commit/77fa530c8626df94fa7f9c0a8b3a99f2efa7cb11) Thanks [@KVNLS](https://github.com/KVNLS)! - Upgrade React Native to version 0.73.6 + +- [#7030](https://github.com/LedgerHQ/ledger-live/pull/7030) [`12a74b9`](https://github.com/LedgerHQ/ledger-live/commit/12a74b9f2f27285e44a5dca665422b3b8ecd4028) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update evm coin-tester indexer now supporting Ledger & Etherscan-like explorers + +- [#6876](https://github.com/LedgerHQ/ledger-live/pull/6876) [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update coin implementations to use new account bridge types & implement cleaner architecture + +- [#6977](https://github.com/LedgerHQ/ledger-live/pull/6977) [`2f2b754`](https://github.com/LedgerHQ/ledger-live/commit/2f2b754b1350360ca0d9f761ca6e4a8cbaff141b) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Scroll & Scroll Sepolia + +### Patch Changes + +- [#6663](https://github.com/LedgerHQ/ledger-live/pull/6663) [`de5de2d`](https://github.com/LedgerHQ/ledger-live/commit/de5de2d273ed6966c82bde2c3a95b98ba594204f) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Reorganize coin serializaiton code + +- [#6754](https://github.com/LedgerHQ/ledger-live/pull/6754) [`4c01029`](https://github.com/LedgerHQ/ledger-live/commit/4c01029b4d4feb32dab2f9e77da1126050d8c1bc) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Move Tezos in its own package + +- [#6752](https://github.com/LedgerHQ/ledger-live/pull/6752) [`434262d`](https://github.com/LedgerHQ/ledger-live/commit/434262db4560f62113002fbb607bd1a8da0712b4) Thanks [@CremaFR](https://github.com/CremaFR)! - bugfix, keep swap history for token when deep cleaning + +- [#6844](https://github.com/LedgerHQ/ledger-live/pull/6844) [`f19960f`](https://github.com/LedgerHQ/ledger-live/commit/f19960f2e7104e5bdf332269fa92fda47455e17d) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Simplify SignerContext generic signature + +- [#6796](https://github.com/LedgerHQ/ledger-live/pull/6796) [`6552679`](https://github.com/LedgerHQ/ledger-live/commit/65526794bb4d1fbc7e286c0e1c0b6d021413fc8c) Thanks [@gre](https://github.com/gre)! - Drop technical Account#name and Account#starred fields and replace it with a new architecture: a wallet store that contains all user's data. + +- [#7030](https://github.com/LedgerHQ/ledger-live/pull/7030) [`12a74b9`](https://github.com/LedgerHQ/ledger-live/commit/12a74b9f2f27285e44a5dca665422b3b8ecd4028) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Make `gasTracker` optional in `EvmConfig` + +- [#6816](https://github.com/LedgerHQ/ledger-live/pull/6816) [`60cd799`](https://github.com/LedgerHQ/ledger-live/commit/60cd799e693e3ae0712a5a9e88206b5304bbc214) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Split currencies utils between CoinFmk and LLC + +- Updated dependencies [[`77fa530`](https://github.com/LedgerHQ/ledger-live/commit/77fa530c8626df94fa7f9c0a8b3a99f2efa7cb11), [`6c35cc5`](https://github.com/LedgerHQ/ledger-live/commit/6c35cc564cb050614ee571907f628ecf15ec4584), [`b9f1f71`](https://github.com/LedgerHQ/ledger-live/commit/b9f1f715355752d8c57c24ecd6a6d166b80f689d), [`815ae3d`](https://github.com/LedgerHQ/ledger-live/commit/815ae3dae8027823854ada837df3dc983d09b10f), [`de5de2d`](https://github.com/LedgerHQ/ledger-live/commit/de5de2d273ed6966c82bde2c3a95b98ba594204f), [`83e5690`](https://github.com/LedgerHQ/ledger-live/commit/83e5690429e41ecd1c508b3398904ae747085cf7), [`4c01029`](https://github.com/LedgerHQ/ledger-live/commit/4c01029b4d4feb32dab2f9e77da1126050d8c1bc), [`326cae0`](https://github.com/LedgerHQ/ledger-live/commit/326cae088cc33795536deb1d868c86e8dbeb6a13), [`6c35cc5`](https://github.com/LedgerHQ/ledger-live/commit/6c35cc564cb050614ee571907f628ecf15ec4584), [`4499990`](https://github.com/LedgerHQ/ledger-live/commit/449999066c58ae5df371dfb92a7230f9b5e90a60), [`a18c28e`](https://github.com/LedgerHQ/ledger-live/commit/a18c28e3f6a6132bd5e53d5b61721084b3aa19e8), [`cec1599`](https://github.com/LedgerHQ/ledger-live/commit/cec1599a41aa1a18a249e34312164bc93b63972f), [`801265b`](https://github.com/LedgerHQ/ledger-live/commit/801265b7ff3ed7ebd0012eb50f70898557a2dd52), [`d5a1300`](https://github.com/LedgerHQ/ledger-live/commit/d5a130034c18c7ac8b1fd3d4c5271423b4f7639d), [`6d44f25`](https://github.com/LedgerHQ/ledger-live/commit/6d44f255c5b2f453c61d0b754807db1f76d7174e), [`f19960f`](https://github.com/LedgerHQ/ledger-live/commit/f19960f2e7104e5bdf332269fa92fda47455e17d), [`3b9c93c`](https://github.com/LedgerHQ/ledger-live/commit/3b9c93c0de8ceff2af96a6ee8e42b8d9c2ab7af0), [`6623cd1`](https://github.com/LedgerHQ/ledger-live/commit/6623cd13102bd8340bd7d4dfdd469934527985c3), [`f7e7881`](https://github.com/LedgerHQ/ledger-live/commit/f7e7881a820880143c2b011d6a92b5a36156b2c1), [`2f2b754`](https://github.com/LedgerHQ/ledger-live/commit/2f2b754b1350360ca0d9f761ca6e4a8cbaff141b), [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4), [`6552679`](https://github.com/LedgerHQ/ledger-live/commit/65526794bb4d1fbc7e286c0e1c0b6d021413fc8c), [`fda6a81`](https://github.com/LedgerHQ/ledger-live/commit/fda6a814544b3a1debceab22f69485911e76cadc), [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4), [`60cd799`](https://github.com/LedgerHQ/ledger-live/commit/60cd799e693e3ae0712a5a9e88206b5304bbc214), [`84274a6`](https://github.com/LedgerHQ/ledger-live/commit/84274a6e764a385f707bc811ead7a7e92a02ed6a)]: + - @ledgerhq/cryptoassets@13.1.0 + - @ledgerhq/devices@8.4.0 + - @ledgerhq/errors@6.17.0 + - @ledgerhq/coin-framework@0.14.0 + - @ledgerhq/domain-service@1.2.0 + - @ledgerhq/live-network@1.3.0 + - @ledgerhq/evm-tools@1.1.0 + - @ledgerhq/live-promise@0.1.0 + - @ledgerhq/live-env@2.1.0 + +## 2.1.0-next.2 + +### Patch Changes + +- Updated dependencies [[`d5a1300`](https://github.com/LedgerHQ/ledger-live/commit/d5a130034c18c7ac8b1fd3d4c5271423b4f7639d)]: + - @ledgerhq/cryptoassets@13.1.0-next.2 + - @ledgerhq/coin-framework@0.14.0-next.2 + - @ledgerhq/evm-tools@1.1.0-next.2 + +## 2.1.0-next.1 + +### Patch Changes + +- Updated dependencies [[`f7e7881`](https://github.com/LedgerHQ/ledger-live/commit/f7e7881a820880143c2b011d6a92b5a36156b2c1)]: + - @ledgerhq/cryptoassets@13.1.0-next.1 + - @ledgerhq/coin-framework@0.14.0-next.1 + - @ledgerhq/evm-tools@1.1.0-next.1 + +## 2.1.0-next.0 + +### Minor Changes + +- [#6596](https://github.com/LedgerHQ/ledger-live/pull/6596) [`77fa530`](https://github.com/LedgerHQ/ledger-live/commit/77fa530c8626df94fa7f9c0a8b3a99f2efa7cb11) Thanks [@KVNLS](https://github.com/KVNLS)! - Upgrade React Native to version 0.73.6 + +- [#7030](https://github.com/LedgerHQ/ledger-live/pull/7030) [`12a74b9`](https://github.com/LedgerHQ/ledger-live/commit/12a74b9f2f27285e44a5dca665422b3b8ecd4028) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update evm coin-tester indexer now supporting Ledger & Etherscan-like explorers + +- [#6876](https://github.com/LedgerHQ/ledger-live/pull/6876) [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update coin implementations to use new account bridge types & implement cleaner architecture + +- [#6977](https://github.com/LedgerHQ/ledger-live/pull/6977) [`2f2b754`](https://github.com/LedgerHQ/ledger-live/commit/2f2b754b1350360ca0d9f761ca6e4a8cbaff141b) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Scroll & Scroll Sepolia + +### Patch Changes + +- [#6663](https://github.com/LedgerHQ/ledger-live/pull/6663) [`de5de2d`](https://github.com/LedgerHQ/ledger-live/commit/de5de2d273ed6966c82bde2c3a95b98ba594204f) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Reorganize coin serializaiton code + +- [#6754](https://github.com/LedgerHQ/ledger-live/pull/6754) [`4c01029`](https://github.com/LedgerHQ/ledger-live/commit/4c01029b4d4feb32dab2f9e77da1126050d8c1bc) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Move Tezos in its own package + +- [#6752](https://github.com/LedgerHQ/ledger-live/pull/6752) [`434262d`](https://github.com/LedgerHQ/ledger-live/commit/434262db4560f62113002fbb607bd1a8da0712b4) Thanks [@CremaFR](https://github.com/CremaFR)! - bugfix, keep swap history for token when deep cleaning + +- [#6844](https://github.com/LedgerHQ/ledger-live/pull/6844) [`f19960f`](https://github.com/LedgerHQ/ledger-live/commit/f19960f2e7104e5bdf332269fa92fda47455e17d) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Simplify SignerContext generic signature + +- [#6796](https://github.com/LedgerHQ/ledger-live/pull/6796) [`6552679`](https://github.com/LedgerHQ/ledger-live/commit/65526794bb4d1fbc7e286c0e1c0b6d021413fc8c) Thanks [@gre](https://github.com/gre)! - Drop technical Account#name and Account#starred fields and replace it with a new architecture: a wallet store that contains all user's data. + +- [#7030](https://github.com/LedgerHQ/ledger-live/pull/7030) [`12a74b9`](https://github.com/LedgerHQ/ledger-live/commit/12a74b9f2f27285e44a5dca665422b3b8ecd4028) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Make `gasTracker` optional in `EvmConfig` + +- [#6816](https://github.com/LedgerHQ/ledger-live/pull/6816) [`60cd799`](https://github.com/LedgerHQ/ledger-live/commit/60cd799e693e3ae0712a5a9e88206b5304bbc214) Thanks [@sprohaszka-ledger](https://github.com/sprohaszka-ledger)! - Split currencies utils between CoinFmk and LLC + +- Updated dependencies [[`77fa530`](https://github.com/LedgerHQ/ledger-live/commit/77fa530c8626df94fa7f9c0a8b3a99f2efa7cb11), [`6c35cc5`](https://github.com/LedgerHQ/ledger-live/commit/6c35cc564cb050614ee571907f628ecf15ec4584), [`b9f1f71`](https://github.com/LedgerHQ/ledger-live/commit/b9f1f715355752d8c57c24ecd6a6d166b80f689d), [`815ae3d`](https://github.com/LedgerHQ/ledger-live/commit/815ae3dae8027823854ada837df3dc983d09b10f), [`de5de2d`](https://github.com/LedgerHQ/ledger-live/commit/de5de2d273ed6966c82bde2c3a95b98ba594204f), [`83e5690`](https://github.com/LedgerHQ/ledger-live/commit/83e5690429e41ecd1c508b3398904ae747085cf7), [`4c01029`](https://github.com/LedgerHQ/ledger-live/commit/4c01029b4d4feb32dab2f9e77da1126050d8c1bc), [`326cae0`](https://github.com/LedgerHQ/ledger-live/commit/326cae088cc33795536deb1d868c86e8dbeb6a13), [`6c35cc5`](https://github.com/LedgerHQ/ledger-live/commit/6c35cc564cb050614ee571907f628ecf15ec4584), [`4499990`](https://github.com/LedgerHQ/ledger-live/commit/449999066c58ae5df371dfb92a7230f9b5e90a60), [`a18c28e`](https://github.com/LedgerHQ/ledger-live/commit/a18c28e3f6a6132bd5e53d5b61721084b3aa19e8), [`cec1599`](https://github.com/LedgerHQ/ledger-live/commit/cec1599a41aa1a18a249e34312164bc93b63972f), [`801265b`](https://github.com/LedgerHQ/ledger-live/commit/801265b7ff3ed7ebd0012eb50f70898557a2dd52), [`6d44f25`](https://github.com/LedgerHQ/ledger-live/commit/6d44f255c5b2f453c61d0b754807db1f76d7174e), [`f19960f`](https://github.com/LedgerHQ/ledger-live/commit/f19960f2e7104e5bdf332269fa92fda47455e17d), [`3b9c93c`](https://github.com/LedgerHQ/ledger-live/commit/3b9c93c0de8ceff2af96a6ee8e42b8d9c2ab7af0), [`6623cd1`](https://github.com/LedgerHQ/ledger-live/commit/6623cd13102bd8340bd7d4dfdd469934527985c3), [`2f2b754`](https://github.com/LedgerHQ/ledger-live/commit/2f2b754b1350360ca0d9f761ca6e4a8cbaff141b), [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4), [`6552679`](https://github.com/LedgerHQ/ledger-live/commit/65526794bb4d1fbc7e286c0e1c0b6d021413fc8c), [`fda6a81`](https://github.com/LedgerHQ/ledger-live/commit/fda6a814544b3a1debceab22f69485911e76cadc), [`689e6e5`](https://github.com/LedgerHQ/ledger-live/commit/689e6e5a443170b8e6c2b404cc99af2e67d8e8e4), [`60cd799`](https://github.com/LedgerHQ/ledger-live/commit/60cd799e693e3ae0712a5a9e88206b5304bbc214), [`84274a6`](https://github.com/LedgerHQ/ledger-live/commit/84274a6e764a385f707bc811ead7a7e92a02ed6a)]: + - @ledgerhq/cryptoassets@13.1.0-next.0 + - @ledgerhq/devices@8.4.0-next.0 + - @ledgerhq/errors@6.17.0-next.0 + - @ledgerhq/coin-framework@0.14.0-next.0 + - @ledgerhq/domain-service@1.2.0-next.0 + - @ledgerhq/live-network@1.3.0-next.0 + - @ledgerhq/evm-tools@1.1.0-next.0 + - @ledgerhq/live-promise@0.1.0-next.0 + - @ledgerhq/live-env@2.1.0-next.0 + +## 2.0.0 + +### Major Changes + +- [#6669](https://github.com/LedgerHQ/ledger-live/pull/6669) [`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Removing support for Goerli & Ropsten networks and their Layer 2 variants (Linea Goerli & Optimism Goerli) and replace them by Linea Sepolia & Optimism Sepolia + +### Minor Changes + +- [#6567](https://github.com/LedgerHQ/ledger-live/pull/6567) [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `getSyncHash` method to use new hash files provided by token importers instead of manually serializing each token. This greatly improve performances of that method. + +### Patch Changes + +- [#6684](https://github.com/LedgerHQ/ledger-live/pull/6684) [`96029e1`](https://github.com/LedgerHQ/ledger-live/commit/96029e1396be2f283f0345a59e08009b0a6a96db) Thanks [@CremaFR](https://github.com/CremaFR)! - Allow additional fees when using maxButton + +- Updated dependencies [[`5552ca0`](https://github.com/LedgerHQ/ledger-live/commit/5552ca0542d5734b845ed23dae2f02c6d1b8ba2d), [`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd), [`df1dcbf`](https://github.com/LedgerHQ/ledger-live/commit/df1dcbffe901d7c4baddb46a06b08a4ed5b7a17e), [`3896648`](https://github.com/LedgerHQ/ledger-live/commit/389664874b98074905a7f8f8e5a845bb76908f13), [`45a53bc`](https://github.com/LedgerHQ/ledger-live/commit/45a53bc227ab2f42b1e839aacbb8c251d0a4a5d2), [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167), [`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd), [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167), [`cfb97f7`](https://github.com/LedgerHQ/ledger-live/commit/cfb97f7d5c81824815522e8699b7469047b1513a), [`2f2ef00`](https://github.com/LedgerHQ/ledger-live/commit/2f2ef001145469870ac703b6af28fdf8f0d70945)]: + - @ledgerhq/live-promise@0.0.4 + - @ledgerhq/coin-framework@0.13.0 + - @ledgerhq/live-env@2.0.2 + - @ledgerhq/cryptoassets@13.0.0 + - @ledgerhq/live-network@1.2.2 + - @ledgerhq/domain-service@1.1.21 + - @ledgerhq/evm-tools@1.0.19 + +## 2.0.0-next.1 + +### Patch Changes + +- Updated dependencies [[`5552ca0`](https://github.com/LedgerHQ/ledger-live/commit/5552ca0542d5734b845ed23dae2f02c6d1b8ba2d)]: + - @ledgerhq/live-promise@0.0.4-next.1 + - @ledgerhq/live-network@1.2.2-next.1 + +## 2.0.0-next.0 + +### Major Changes + +- [#6669](https://github.com/LedgerHQ/ledger-live/pull/6669) [`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Removing support for Goerli & Ropsten networks and their Layer 2 variants (Linea Goerli & Optimism Goerli) and replace them by Linea Sepolia & Optimism Sepolia + +### Minor Changes + +- [#6567](https://github.com/LedgerHQ/ledger-live/pull/6567) [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `getSyncHash` method to use new hash files provided by token importers instead of manually serializing each token. This greatly improve performances of that method. + +### Patch Changes + +- [#6684](https://github.com/LedgerHQ/ledger-live/pull/6684) [`96029e1`](https://github.com/LedgerHQ/ledger-live/commit/96029e1396be2f283f0345a59e08009b0a6a96db) Thanks [@CremaFR](https://github.com/CremaFR)! - Allow additional fees when using maxButton + +- Updated dependencies [[`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd), [`df1dcbf`](https://github.com/LedgerHQ/ledger-live/commit/df1dcbffe901d7c4baddb46a06b08a4ed5b7a17e), [`3896648`](https://github.com/LedgerHQ/ledger-live/commit/389664874b98074905a7f8f8e5a845bb76908f13), [`45a53bc`](https://github.com/LedgerHQ/ledger-live/commit/45a53bc227ab2f42b1e839aacbb8c251d0a4a5d2), [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167), [`fdb76a7`](https://github.com/LedgerHQ/ledger-live/commit/fdb76a7c3a8459a50b22b3e5a5a3002932805bcd), [`0dae8e5`](https://github.com/LedgerHQ/ledger-live/commit/0dae8e5a33704eaee5976e8ae2cbe29c6f458167), [`cfb97f7`](https://github.com/LedgerHQ/ledger-live/commit/cfb97f7d5c81824815522e8699b7469047b1513a), [`2f2ef00`](https://github.com/LedgerHQ/ledger-live/commit/2f2ef001145469870ac703b6af28fdf8f0d70945)]: + - @ledgerhq/coin-framework@0.13.0-next.0 + - @ledgerhq/live-env@2.0.2-next.0 + - @ledgerhq/cryptoassets@13.0.0-next.0 + - @ledgerhq/live-network@1.2.2-next.0 + - @ledgerhq/live-promise@0.0.4-next.0 + - @ledgerhq/domain-service@1.1.21-next.0 + - @ledgerhq/evm-tools@1.0.19-next.0 + +## 1.1.0 + +### Minor Changes + +- [#6309](https://github.com/LedgerHQ/ledger-live/pull/6309) [`5848f9e`](https://github.com/LedgerHQ/ledger-live/commit/5848f9e247f169eb7a4aff322253937214b9efdd) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Removes never publicly exposed Evmos & Kava currencies. Also fixes multiple Etherscan based explorers URI (Lukso, RSK, Astar & Boba). + +- [#6290](https://github.com/LedgerHQ/ledger-live/pull/6290) [`08c9779`](https://github.com/LedgerHQ/ledger-live/commit/08c9779659628e4e22ac99a152049ac3fa2745fa) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add `chainId` while using the `hw-getAddress` method to display the network name and logo on a Stax device + +- [#6422](https://github.com/LedgerHQ/ledger-live/pull/6422) [`381023d`](https://github.com/LedgerHQ/ledger-live/commit/381023de2617aa09829a8b5dad7b0ba2c846328e) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix Operations' amount depending if failure and remove internal operations from a failed coin operation + +- [#6482](https://github.com/LedgerHQ/ledger-live/pull/6482) [`83d0bc6`](https://github.com/LedgerHQ/ledger-live/commit/83d0bc67979159044a7785b5cb4cbda8ed78ebf4) Thanks [@vbergeron-ledger](https://github.com/vbergeron-ledger)! - EVM coin synchronozation is now optimized to start from the latest sync rather than from the latest operation + +### Patch Changes + +- [#6501](https://github.com/LedgerHQ/ledger-live/pull/6501) [`5e939e0`](https://github.com/LedgerHQ/ledger-live/commit/5e939e0540cabb8d9931794b79909fe0a353a179) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add missing index to Ledger ERC20 operations' ids, leading to missing token ops in history + +- [#6341](https://github.com/LedgerHQ/ledger-live/pull/6341) [`92e9d19`](https://github.com/LedgerHQ/ledger-live/commit/92e9d194313ffd1542b676c59ae2d34e861f698f) Thanks [@sarneijim](https://github.com/sarneijim)! - Fix swap history + +- [#6370](https://github.com/LedgerHQ/ledger-live/pull/6370) [`3c15515`](https://github.com/LedgerHQ/ledger-live/commit/3c155155f2d45fb85f8900e7e77c1b5ab1c7ad67) Thanks [@lvndry](https://github.com/lvndry)! - Get evm node, explorer and gasTracker information from liveconfig + +- Updated dependencies [[`1aa8ef4`](https://github.com/LedgerHQ/ledger-live/commit/1aa8ef404411c31f6ac4cf09fba453042db8b955), [`3c15515`](https://github.com/LedgerHQ/ledger-live/commit/3c155155f2d45fb85f8900e7e77c1b5ab1c7ad67), [`762dea1`](https://github.com/LedgerHQ/ledger-live/commit/762dea1c52ef0537961d058f7ba81fa399663ac1), [`fc4f83e`](https://github.com/LedgerHQ/ledger-live/commit/fc4f83e26d9f00b7c518f28157e8d9da55ce3685), [`dd1d17f`](https://github.com/LedgerHQ/ledger-live/commit/dd1d17fd3ce7ed42558204b2f93707fb9b1599de), [`26b3a5d`](https://github.com/LedgerHQ/ledger-live/commit/26b3a5d7d6e11efc226403707d683f3d0098a1c1), [`5848f9e`](https://github.com/LedgerHQ/ledger-live/commit/5848f9e247f169eb7a4aff322253937214b9efdd), [`a8138f9`](https://github.com/LedgerHQ/ledger-live/commit/a8138f9ec0cff714d9745012eb91a09713ffbbd2), [`ebb45be`](https://github.com/LedgerHQ/ledger-live/commit/ebb45be56c6b1fdb3c36a8c20a16b41600baa264), [`53da330`](https://github.com/LedgerHQ/ledger-live/commit/53da3301aaceeb16e6b1f96b1ea44428fbeb4483), [`abb1bbb`](https://github.com/LedgerHQ/ledger-live/commit/abb1bbb09c52a3d08577ba622c6cb0f44aab36c1)]: + - @ledgerhq/coin-framework@0.12.0 + - @ledgerhq/cryptoassets@12.1.0 + - @ledgerhq/live-env@2.0.1 + - @ledgerhq/errors@6.16.4 + - @ledgerhq/devices@8.3.0 + - @ledgerhq/domain-service@1.1.20 + - @ledgerhq/evm-tools@1.0.18 + - @ledgerhq/live-network@1.2.1 + +## 1.1.0-next.1 + +### Patch Changes + +- Updated dependencies [[`762dea1`](https://github.com/LedgerHQ/ledger-live/commit/762dea1c52ef0537961d058f7ba81fa399663ac1)]: + - @ledgerhq/live-env@2.0.1-next.0 + - @ledgerhq/coin-framework@0.12.0-next.1 + - @ledgerhq/evm-tools@1.0.18-next.1 + - @ledgerhq/live-network@1.2.1-next.1 + +## 1.1.0-next.0 + +### Minor Changes + +- [#6309](https://github.com/LedgerHQ/ledger-live/pull/6309) [`5848f9e`](https://github.com/LedgerHQ/ledger-live/commit/5848f9e247f169eb7a4aff322253937214b9efdd) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Removes never publicly exposed Evmos & Kava currencies. Also fixes multiple Etherscan based explorers URI (Lukso, RSK, Astar & Boba). + +- [#6290](https://github.com/LedgerHQ/ledger-live/pull/6290) [`08c9779`](https://github.com/LedgerHQ/ledger-live/commit/08c9779659628e4e22ac99a152049ac3fa2745fa) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add `chainId` while using the `hw-getAddress` method to display the network name and logo on a Stax device + +- [#6422](https://github.com/LedgerHQ/ledger-live/pull/6422) [`381023d`](https://github.com/LedgerHQ/ledger-live/commit/381023de2617aa09829a8b5dad7b0ba2c846328e) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix Operations' amount depending if failure and remove internal operations from a failed coin operation + +- [#6482](https://github.com/LedgerHQ/ledger-live/pull/6482) [`83d0bc6`](https://github.com/LedgerHQ/ledger-live/commit/83d0bc67979159044a7785b5cb4cbda8ed78ebf4) Thanks [@vbergeron-ledger](https://github.com/vbergeron-ledger)! - EVM coin synchronozation is now optimized to start from the latest sync rather than from the latest operation + +### Patch Changes + +- [#6501](https://github.com/LedgerHQ/ledger-live/pull/6501) [`5e939e0`](https://github.com/LedgerHQ/ledger-live/commit/5e939e0540cabb8d9931794b79909fe0a353a179) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add missing index to Ledger ERC20 operations' ids, leading to missing token ops in history + +- [#6341](https://github.com/LedgerHQ/ledger-live/pull/6341) [`92e9d19`](https://github.com/LedgerHQ/ledger-live/commit/92e9d194313ffd1542b676c59ae2d34e861f698f) Thanks [@sarneijim](https://github.com/sarneijim)! - Fix swap history + +- [#6370](https://github.com/LedgerHQ/ledger-live/pull/6370) [`3c15515`](https://github.com/LedgerHQ/ledger-live/commit/3c155155f2d45fb85f8900e7e77c1b5ab1c7ad67) Thanks [@lvndry](https://github.com/lvndry)! - Get evm node, explorer and gasTracker information from liveconfig + +- Updated dependencies [[`1aa8ef4`](https://github.com/LedgerHQ/ledger-live/commit/1aa8ef404411c31f6ac4cf09fba453042db8b955), [`3c15515`](https://github.com/LedgerHQ/ledger-live/commit/3c155155f2d45fb85f8900e7e77c1b5ab1c7ad67), [`fc4f83e`](https://github.com/LedgerHQ/ledger-live/commit/fc4f83e26d9f00b7c518f28157e8d9da55ce3685), [`dd1d17f`](https://github.com/LedgerHQ/ledger-live/commit/dd1d17fd3ce7ed42558204b2f93707fb9b1599de), [`26b3a5d`](https://github.com/LedgerHQ/ledger-live/commit/26b3a5d7d6e11efc226403707d683f3d0098a1c1), [`5848f9e`](https://github.com/LedgerHQ/ledger-live/commit/5848f9e247f169eb7a4aff322253937214b9efdd), [`a8138f9`](https://github.com/LedgerHQ/ledger-live/commit/a8138f9ec0cff714d9745012eb91a09713ffbbd2), [`ebb45be`](https://github.com/LedgerHQ/ledger-live/commit/ebb45be56c6b1fdb3c36a8c20a16b41600baa264), [`53da330`](https://github.com/LedgerHQ/ledger-live/commit/53da3301aaceeb16e6b1f96b1ea44428fbeb4483), [`abb1bbb`](https://github.com/LedgerHQ/ledger-live/commit/abb1bbb09c52a3d08577ba622c6cb0f44aab36c1)]: + - @ledgerhq/coin-framework@0.12.0-next.0 + - @ledgerhq/cryptoassets@12.1.0-next.0 + - @ledgerhq/errors@6.16.4-next.0 + - @ledgerhq/devices@8.3.0-next.0 + - @ledgerhq/domain-service@1.1.20-next.0 + - @ledgerhq/evm-tools@1.0.18-next.0 + - @ledgerhq/live-network@1.2.1-next.0 + +## 1.0.0 + +### Major Changes + +- [#6195](https://github.com/LedgerHQ/ledger-live/pull/6195) [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Deprecating Arbitrum goerli & Base goerli + +### Minor Changes + +- [#6179](https://github.com/LedgerHQ/ledger-live/pull/6179) [`25fe5c4`](https://github.com/LedgerHQ/ledger-live/commit/25fe5c48d44d3d1b11e35b81bb4bf31d30fa1268) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `DEFAULT_NONCE` (-1) behaviour when converting a Ledger Live transaction to an `ethers` transaction, because using an invalid nonce (like a negative value here) will make `ethers` throw with some of its methods, like `serializeTransaction` + +- [#6196](https://github.com/LedgerHQ/ledger-live/pull/6196) [`255476b`](https://github.com/LedgerHQ/ledger-live/commit/255476bd65b15971eb523807fe9795c84882f198) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add suppport of `blacklistedTokenIds` to coin-evm synchronization + +- [#6195](https://github.com/LedgerHQ/ledger-live/pull/6195) [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Base Sepolia & Arbitrum Sepolia + +### Patch Changes + +- [#6041](https://github.com/LedgerHQ/ledger-live/pull/6041) [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Remove unnecessary logs + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Make `hw-app-eth` a devDep by relying on `clearSignTransaction` instead of importing the `ledgerService` + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add documentation + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Move clear signed selectors to evm-tools lib + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `NotEnoughBalance` error for token transactions + +- Updated dependencies [[`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`0dd1546`](https://github.com/LedgerHQ/ledger-live/commit/0dd15467070cbf7fcbb9d9055a4535f6a25b2ad0), [`f456d69`](https://github.com/LedgerHQ/ledger-live/commit/f456d69a2f64b6a217d3c1d9c6a531f31c2817a8), [`4715e4c`](https://github.com/LedgerHQ/ledger-live/commit/4715e4c411fa2396330ebcb810aeb6bfc9892e88), [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f), [`74ef384`](https://github.com/LedgerHQ/ledger-live/commit/74ef3840c17181fa779035f190f829e9537e1539), [`2fd465e`](https://github.com/LedgerHQ/ledger-live/commit/2fd465ee730b11594d231503cfb940b984fa2f5a), [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6), [`7fb3eb2`](https://github.com/LedgerHQ/ledger-live/commit/7fb3eb266acdca143c94d2fce74329809ebfbb79), [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`bd4ee6c`](https://github.com/LedgerHQ/ledger-live/commit/bd4ee6c938c27102c2d0529c2aab07ac000f7424), [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6), [`2e5185b`](https://github.com/LedgerHQ/ledger-live/commit/2e5185b3dba497c956272068128e49db72e8af2a)]: + - @ledgerhq/live-env@2.0.0 + - @ledgerhq/errors@6.16.3 + - @ledgerhq/cryptoassets@12.0.0 + - @ledgerhq/coin-framework@0.11.3 + - @ledgerhq/evm-tools@1.0.17 + - @ledgerhq/live-network@1.2.0 + - @ledgerhq/domain-service@1.1.19 + - @ledgerhq/devices@8.2.2 + +## 1.0.0-next.1 + +### Patch Changes + +- [#6375](https://github.com/LedgerHQ/ledger-live/pull/6375) [`09128f3`](https://github.com/LedgerHQ/ledger-live/commit/09128f3fd41285199122115324964d83befe9237) Thanks [@CremaFR](https://github.com/CremaFR)! - Allow additional fees when using maxButton + +## 1.0.0-next.0 + +### Major Changes + +- [#6195](https://github.com/LedgerHQ/ledger-live/pull/6195) [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Deprecating Arbitrum goerli & Base goerli + +### Minor Changes + +- [#6179](https://github.com/LedgerHQ/ledger-live/pull/6179) [`25fe5c4`](https://github.com/LedgerHQ/ledger-live/commit/25fe5c48d44d3d1b11e35b81bb4bf31d30fa1268) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `DEFAULT_NONCE` (-1) behaviour when converting a Ledger Live transaction to an `ethers` transaction, because using an invalid nonce (like a negative value here) will make `ethers` throw with some of its methods, like `serializeTransaction` + +- [#6196](https://github.com/LedgerHQ/ledger-live/pull/6196) [`255476b`](https://github.com/LedgerHQ/ledger-live/commit/255476bd65b15971eb523807fe9795c84882f198) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add suppport of `blacklistedTokenIds` to coin-evm synchronization + +- [#6195](https://github.com/LedgerHQ/ledger-live/pull/6195) [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Base Sepolia & Arbitrum Sepolia + +### Patch Changes + +- [#6041](https://github.com/LedgerHQ/ledger-live/pull/6041) [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Remove unnecessary logs + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Make `hw-app-eth` a devDep by relying on `clearSignTransaction` instead of importing the `ledgerService` + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add documentation + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Move clear signed selectors to evm-tools lib + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `NotEnoughBalance` error for token transactions + +- Updated dependencies [[`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`0dd1546`](https://github.com/LedgerHQ/ledger-live/commit/0dd15467070cbf7fcbb9d9055a4535f6a25b2ad0), [`f456d69`](https://github.com/LedgerHQ/ledger-live/commit/f456d69a2f64b6a217d3c1d9c6a531f31c2817a8), [`4715e4c`](https://github.com/LedgerHQ/ledger-live/commit/4715e4c411fa2396330ebcb810aeb6bfc9892e88), [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f), [`74ef384`](https://github.com/LedgerHQ/ledger-live/commit/74ef3840c17181fa779035f190f829e9537e1539), [`2fd465e`](https://github.com/LedgerHQ/ledger-live/commit/2fd465ee730b11594d231503cfb940b984fa2f5a), [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6), [`7fb3eb2`](https://github.com/LedgerHQ/ledger-live/commit/7fb3eb266acdca143c94d2fce74329809ebfbb79), [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`bd4ee6c`](https://github.com/LedgerHQ/ledger-live/commit/bd4ee6c938c27102c2d0529c2aab07ac000f7424), [`dfac39b`](https://github.com/LedgerHQ/ledger-live/commit/dfac39b2086f0475d1bc8065032bfe27cbf424f6), [`2e5185b`](https://github.com/LedgerHQ/ledger-live/commit/2e5185b3dba497c956272068128e49db72e8af2a)]: + - @ledgerhq/live-env@2.0.0-next.0 + - @ledgerhq/errors@6.16.3-next.0 + - @ledgerhq/cryptoassets@12.0.0-next.0 + - @ledgerhq/coin-framework@0.11.3-next.0 + - @ledgerhq/evm-tools@1.0.17-next.0 + - @ledgerhq/live-network@1.2.0-next.0 + - @ledgerhq/domain-service@1.1.19-next.0 + - @ledgerhq/devices@8.2.2-next.0 + +## 0.12.3 + +### Patch Changes + +- Updated dependencies [[`884cfd6`](https://github.com/LedgerHQ/ledger-live/commit/884cfd64a1440d393fb983dfe361be9c78f3b81c), [`3e28615`](https://github.com/LedgerHQ/ledger-live/commit/3e28615a8d5edbec3eff1e93207bf0e9d017666a)]: + - @ledgerhq/cryptoassets@11.4.1 + - @ledgerhq/live-env@1.0.1 + - @ledgerhq/coin-framework@0.11.2 + - @ledgerhq/evm-tools@1.0.16 + - @ledgerhq/live-network@1.1.13 + +## 0.12.3-hotfix.1 + +### Patch Changes + +- Updated dependencies [[`884cfd6`](https://github.com/LedgerHQ/ledger-live/commit/884cfd64a1440d393fb983dfe361be9c78f3b81c)]: + - @ledgerhq/cryptoassets@11.4.1-hotfix.0 + - @ledgerhq/coin-framework@0.11.2-hotfix.1 + - @ledgerhq/evm-tools@1.0.16-hotfix.1 + +## 0.12.3-hotfix.0 + +### Patch Changes + +- Updated dependencies [[`3e28615`](https://github.com/LedgerHQ/ledger-live/commit/3e28615a8d5edbec3eff1e93207bf0e9d017666a)]: + - @ledgerhq/live-env@1.0.1-hotfix.0 + - @ledgerhq/coin-framework@0.11.2-hotfix.0 + - @ledgerhq/evm-tools@1.0.16-hotfix.0 + - @ledgerhq/live-network@1.1.13-hotfix.0 + +## 0.12.2 + +### Patch Changes + +- [#6165](https://github.com/LedgerHQ/ledger-live/pull/6165) [`8d99b81`](https://github.com/LedgerHQ/ledger-live/commit/8d99b81feaf5e8d46e0c26f34bc70b709a7e3c14) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Remove unnecessary logs + +- [#6165](https://github.com/LedgerHQ/ledger-live/pull/6165) [`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Make `hw-app-eth` a devDep by relying on `clearSignTransaction` instead of importing the `ledgerService` + +- [#6165](https://github.com/LedgerHQ/ledger-live/pull/6165) [`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Add documentation + +- [#6165](https://github.com/LedgerHQ/ledger-live/pull/6165) [`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Move clear signed selectors to evm-tools lib + +- [#6165](https://github.com/LedgerHQ/ledger-live/pull/6165) [`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Update `NotEnoughBalance` error for token transactions + +- Updated dependencies [[`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa), [`ee88785`](https://github.com/LedgerHQ/ledger-live/commit/ee8878515671241ce1037362af5e8f7799b3673a), [`8d99b81`](https://github.com/LedgerHQ/ledger-live/commit/8d99b81feaf5e8d46e0c26f34bc70b709a7e3c14), [`628fa73`](https://github.com/LedgerHQ/ledger-live/commit/628fa732866a6018287ca7bc3d463acb3f5cd6b9), [`43eea9e`](https://github.com/LedgerHQ/ledger-live/commit/43eea9e8076f2c9d5aeb0f8a3b0738e97b3152c8), [`c18a0cf`](https://github.com/LedgerHQ/ledger-live/commit/c18a0cfdce5d1e44faf8d8bd5659ebdae38533fa), [`b444092`](https://github.com/LedgerHQ/ledger-live/commit/b444092040af249ae45e5ee18d75be420f9f26f8)]: + - @ledgerhq/live-env@1.0.0 + - @ledgerhq/errors@6.16.2 + - @ledgerhq/coin-framework@0.11.1 + - @ledgerhq/evm-tools@1.0.15 + - @ledgerhq/domain-service@1.1.18 + - @ledgerhq/live-network@1.1.12 + - @ledgerhq/devices@8.2.1 + +## 0.12.2-next.0 + +### Patch Changes + +- [#6041](https://github.com/LedgerHQ/ledger-live/pull/6041) [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Remove unnecessary logs + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Make `hw-app-eth` a devDep by relying on `clearSignTransaction` instead of importing the `ledgerService` + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add documentation + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Move clear signed selectors to evm-tools lib + +- [#5682](https://github.com/LedgerHQ/ledger-live/pull/5682) [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `NotEnoughBalance` error for token transactions + +- Updated dependencies [[`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`f456d69`](https://github.com/LedgerHQ/ledger-live/commit/f456d69a2f64b6a217d3c1d9c6a531f31c2817a8), [`9c83695`](https://github.com/LedgerHQ/ledger-live/commit/9c8369580b91d82021d4ec28ad7a49dc4ba42e4f), [`74ef384`](https://github.com/LedgerHQ/ledger-live/commit/74ef3840c17181fa779035f190f829e9537e1539), [`2fd465e`](https://github.com/LedgerHQ/ledger-live/commit/2fd465ee730b11594d231503cfb940b984fa2f5a), [`4744c31`](https://github.com/LedgerHQ/ledger-live/commit/4744c3136021f1f47ad1617f2c84f47ac0647370), [`bd4ee6c`](https://github.com/LedgerHQ/ledger-live/commit/bd4ee6c938c27102c2d0529c2aab07ac000f7424)]: + - @ledgerhq/live-env@1.0.0-next.0 + - @ledgerhq/errors@6.16.2-next.0 + - @ledgerhq/coin-framework@0.11.1-next.0 + - @ledgerhq/evm-tools@1.0.15-next.0 + - @ledgerhq/domain-service@1.1.18-next.0 + - @ledgerhq/live-network@1.1.12-next.0 + - @ledgerhq/devices@8.2.1-next.0 + +## 0.12.1 + +### Patch Changes + +- Updated dependencies []: + - @ledgerhq/hw-app-eth@6.35.4 + - @ledgerhq/coin-framework@0.11.0 + +## 0.12.1-next.0 + +### Patch Changes + +- Updated dependencies []: + - @ledgerhq/hw-app-eth@6.35.4-next.0 + - @ledgerhq/coin-framework@0.11.0 + +## 0.12.0 + +### Minor Changes + +- [#5722](https://github.com/LedgerHQ/ledger-live/pull/5722) [`2358e87`](https://github.com/LedgerHQ/ledger-live/commit/2358e8748d9ae9398cfc05a0ec20a6b191fc7324) Thanks [@chabroA](https://github.com/chabroA)! - Add Ethereum Sepolia and Holesky + +- [#5744](https://github.com/LedgerHQ/ledger-live/pull/5744) [`ed23f46`](https://github.com/LedgerHQ/ledger-live/commit/ed23f4680d4ed1020bf34ac05b064ff659a282f5) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for internal transactions in transactions' history + +### Patch Changes + +- [#5743](https://github.com/LedgerHQ/ledger-live/pull/5743) [`e494a2b`](https://github.com/LedgerHQ/ledger-live/commit/e494a2b984fb0406fe9225bb4eccde3d9585efe1) Thanks [@chabroA](https://github.com/chabroA)! - remove unreachable statement + +- [#5780](https://github.com/LedgerHQ/ledger-live/pull/5780) [`2b627ae`](https://github.com/LedgerHQ/ledger-live/commit/2b627aebddef859b9cb62467353e7d868bfbc4f9) Thanks [@mle-gall](https://github.com/mle-gall)! - Parent Account Error on gas fees LLD + +- [#5780](https://github.com/LedgerHQ/ledger-live/pull/5780) [`17d1f86`](https://github.com/LedgerHQ/ledger-live/commit/17d1f86022f0122ac85ca6489eb4698c7d9045fb) Thanks [@mle-gall](https://github.com/mle-gall)! - New LLM gas fees parent account error + +- Updated dependencies [[`fc2cf04`](https://github.com/LedgerHQ/ledger-live/commit/fc2cf04c8d3cd55503ea19aeb21fd12ee55046f6), [`dd5d930`](https://github.com/LedgerHQ/ledger-live/commit/dd5d9308e0e3ef8ca78f879c15bc07313ef3c8c4), [`a4a72da`](https://github.com/LedgerHQ/ledger-live/commit/a4a72da33ddfefd5ba69ac4d9ecb33d7775583f1), [`acc0605`](https://github.com/LedgerHQ/ledger-live/commit/acc06050b622f8d4265be9f962c6c83b1fbaefd5), [`2358e87`](https://github.com/LedgerHQ/ledger-live/commit/2358e8748d9ae9398cfc05a0ec20a6b191fc7324), [`65772fb`](https://github.com/LedgerHQ/ledger-live/commit/65772fbcc1e6887d60ca585147123d356914ba56), [`69bbdce`](https://github.com/LedgerHQ/ledger-live/commit/69bbdce5c88d69248cbddb94ac4627334c1df626), [`b74faea`](https://github.com/LedgerHQ/ledger-live/commit/b74faea05f856860a253c5b94a9333810a3446ca), [`0375de1`](https://github.com/LedgerHQ/ledger-live/commit/0375de19ca909b0b013992c114b0fa2ead2a08f3)]: + - @ledgerhq/cryptoassets@11.4.0 + - @ledgerhq/live-network@1.1.11 + - @ledgerhq/types-live@6.44.0 + - @ledgerhq/coin-framework@0.11.0 + - @ledgerhq/types-cryptoassets@7.9.0 + - @ledgerhq/live-env@0.9.0 + - @ledgerhq/evm-tools@1.0.14 + - @ledgerhq/hw-app-eth@6.35.3 + - @ledgerhq/domain-service@1.1.17 + +## 0.12.0-next.0 + +### Minor Changes + +- [#5722](https://github.com/LedgerHQ/ledger-live/pull/5722) [`2358e87`](https://github.com/LedgerHQ/ledger-live/commit/2358e8748d9ae9398cfc05a0ec20a6b191fc7324) Thanks [@chabroA](https://github.com/chabroA)! - Add Ethereum Sepolia and Holesky + +- [#5744](https://github.com/LedgerHQ/ledger-live/pull/5744) [`ed23f46`](https://github.com/LedgerHQ/ledger-live/commit/ed23f4680d4ed1020bf34ac05b064ff659a282f5) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for internal transactions in transactions' history + +### Patch Changes + +- [#5743](https://github.com/LedgerHQ/ledger-live/pull/5743) [`e494a2b`](https://github.com/LedgerHQ/ledger-live/commit/e494a2b984fb0406fe9225bb4eccde3d9585efe1) Thanks [@chabroA](https://github.com/chabroA)! - remove unreachable statement + +- [#5780](https://github.com/LedgerHQ/ledger-live/pull/5780) [`2b627ae`](https://github.com/LedgerHQ/ledger-live/commit/2b627aebddef859b9cb62467353e7d868bfbc4f9) Thanks [@mle-gall](https://github.com/mle-gall)! - Parent Account Error on gas fees LLD + +- [#5780](https://github.com/LedgerHQ/ledger-live/pull/5780) [`17d1f86`](https://github.com/LedgerHQ/ledger-live/commit/17d1f86022f0122ac85ca6489eb4698c7d9045fb) Thanks [@mle-gall](https://github.com/mle-gall)! - New LLM gas fees parent account error + +- Updated dependencies [[`fc2cf04`](https://github.com/LedgerHQ/ledger-live/commit/fc2cf04c8d3cd55503ea19aeb21fd12ee55046f6), [`dd5d930`](https://github.com/LedgerHQ/ledger-live/commit/dd5d9308e0e3ef8ca78f879c15bc07313ef3c8c4), [`a4a72da`](https://github.com/LedgerHQ/ledger-live/commit/a4a72da33ddfefd5ba69ac4d9ecb33d7775583f1), [`acc0605`](https://github.com/LedgerHQ/ledger-live/commit/acc06050b622f8d4265be9f962c6c83b1fbaefd5), [`2358e87`](https://github.com/LedgerHQ/ledger-live/commit/2358e8748d9ae9398cfc05a0ec20a6b191fc7324), [`65772fb`](https://github.com/LedgerHQ/ledger-live/commit/65772fbcc1e6887d60ca585147123d356914ba56), [`69bbdce`](https://github.com/LedgerHQ/ledger-live/commit/69bbdce5c88d69248cbddb94ac4627334c1df626), [`b74faea`](https://github.com/LedgerHQ/ledger-live/commit/b74faea05f856860a253c5b94a9333810a3446ca), [`0375de1`](https://github.com/LedgerHQ/ledger-live/commit/0375de19ca909b0b013992c114b0fa2ead2a08f3)]: + - @ledgerhq/cryptoassets@11.4.0-next.0 + - @ledgerhq/live-network@1.1.11-next.0 + - @ledgerhq/types-live@6.44.0-next.0 + - @ledgerhq/coin-framework@0.11.0-next.0 + - @ledgerhq/types-cryptoassets@7.9.0-next.0 + - @ledgerhq/live-env@0.9.0-next.0 + - @ledgerhq/evm-tools@1.0.14-next.0 + - @ledgerhq/hw-app-eth@6.35.3-next.0 + - @ledgerhq/domain-service@1.1.17-next.0 + +## 0.11.2 + +### Patch Changes + +- Updated dependencies [[`d49f444`](https://github.com/LedgerHQ/ledger-live/commit/d49f44417fd175affe71da589c0ca380e88fbb35)]: + - @ledgerhq/cryptoassets@11.3.1 + - @ledgerhq/coin-framework@0.10.1 + - @ledgerhq/evm-tools@1.0.13 + - @ledgerhq/hw-app-eth@6.35.2 + +## 0.11.2-next.0 + +### Patch Changes + +- Updated dependencies [[`d49f444`](https://github.com/LedgerHQ/ledger-live/commit/d49f44417fd175affe71da589c0ca380e88fbb35)]: + - @ledgerhq/cryptoassets@11.3.1-next.0 + - @ledgerhq/coin-framework@0.10.1-next.0 + - @ledgerhq/evm-tools@1.0.13-next.0 + - @ledgerhq/hw-app-eth@6.35.2-next.0 + +## 0.11.1 + +### Patch Changes + +- [#5709](https://github.com/LedgerHQ/ledger-live/pull/5709) [`0fb6cb3`](https://github.com/LedgerHQ/ledger-live/commit/0fb6cb3cb0085b71dfadfd3a92602511cb7e9928) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix improper filtering for logging of invalid dates + +- [#5546](https://github.com/LedgerHQ/ledger-live/pull/5546) [`6dc1007`](https://github.com/LedgerHQ/ledger-live/commit/6dc100774010ad674001d04b531239f5adfdce7b) Thanks [@lvndry](https://github.com/lvndry)! - safeEncode senders and recipient addresses + +- [#5524](https://github.com/LedgerHQ/ledger-live/pull/5524) [`be22d72`](https://github.com/LedgerHQ/ledger-live/commit/be22d724cf5499fe4958bfb3b5f763ffaf0d0446) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Addings logs to detect date issue resulting with a RangeError + +- Updated dependencies [[`1cb527b`](https://github.com/LedgerHQ/ledger-live/commit/1cb527b9a0b03f23a921a446c64f71ab5c9e9013), [`b7d58b4`](https://github.com/LedgerHQ/ledger-live/commit/b7d58b4cf3aa041b7b794d9af6f0b89bbc0df633), [`44ee889`](https://github.com/LedgerHQ/ledger-live/commit/44ee88944571c73afb105349f5f28b82e8be262d), [`13d9cbe`](https://github.com/LedgerHQ/ledger-live/commit/13d9cbe9a4afbf3ccd532a33e4ada3685d9d646a), [`618307f`](https://github.com/LedgerHQ/ledger-live/commit/618307f92899af07f4c8ad97c67df483492e3d9d), [`0f5292a`](https://github.com/LedgerHQ/ledger-live/commit/0f5292af8feaa517f36ec35155d813b17c4f66e9), [`52a3732`](https://github.com/LedgerHQ/ledger-live/commit/52a373273dee3b2cb5a3e8d2d4b05f90616d71a2), [`4d1aade`](https://github.com/LedgerHQ/ledger-live/commit/4d1aade53cd33f8e7548ce340f54fbb834bdcdcb), [`eb5ac4d`](https://github.com/LedgerHQ/ledger-live/commit/eb5ac4dca430654f5f86854025fddddab4261a29), [`c8172ab`](https://github.com/LedgerHQ/ledger-live/commit/c8172abc5c052a753b93be8b6c9cfd88ce0dd64a), [`5d03bf5`](https://github.com/LedgerHQ/ledger-live/commit/5d03bf514fcf7aea91dc8beae0cd503ed6b4ab3c), [`9d35080`](https://github.com/LedgerHQ/ledger-live/commit/9d35080944a6a63c78f54a545734f4cf3cbded63), [`3adea7a`](https://github.com/LedgerHQ/ledger-live/commit/3adea7a7ad66080b5e6e4407071a976644158d04), [`2edfa53`](https://github.com/LedgerHQ/ledger-live/commit/2edfa533bccafbfd8a61aea0f5422c0db79825ea), [`be22d72`](https://github.com/LedgerHQ/ledger-live/commit/be22d724cf5499fe4958bfb3b5f763ffaf0d0446), [`52a3732`](https://github.com/LedgerHQ/ledger-live/commit/52a373273dee3b2cb5a3e8d2d4b05f90616d71a2), [`6dea540`](https://github.com/LedgerHQ/ledger-live/commit/6dea54057f67162a1f556661afae16e0422f7ac3), [`e70e345`](https://github.com/LedgerHQ/ledger-live/commit/e70e345bd21d4f5c82fbedfd4447aec0e866be5a)]: + - @ledgerhq/types-live@6.43.1 + - @ledgerhq/cryptoassets@11.3.0 + - @ledgerhq/coin-framework@0.10.0 + - @ledgerhq/live-env@0.8.0 + - @ledgerhq/errors@6.16.1 + - @ledgerhq/devices@8.2.0 + - @ledgerhq/domain-service@1.1.16 + - @ledgerhq/evm-tools@1.0.12 + - @ledgerhq/hw-app-eth@6.35.1 + - @ledgerhq/live-network@1.1.10 + +## 0.11.1-next.1 + +### Patch Changes + +- [#5709](https://github.com/LedgerHQ/ledger-live/pull/5709) [`0fb6cb3`](https://github.com/LedgerHQ/ledger-live/commit/0fb6cb3cb0085b71dfadfd3a92602511cb7e9928) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix improper filtering for logging of invalid dates + +## 0.11.1-next.0 + +### Patch Changes + +- [#5546](https://github.com/LedgerHQ/ledger-live/pull/5546) [`6dc1007`](https://github.com/LedgerHQ/ledger-live/commit/6dc100774010ad674001d04b531239f5adfdce7b) Thanks [@lvndry](https://github.com/lvndry)! - safeEncode senders and recipient addresses + +- [#5524](https://github.com/LedgerHQ/ledger-live/pull/5524) [`be22d72`](https://github.com/LedgerHQ/ledger-live/commit/be22d724cf5499fe4958bfb3b5f763ffaf0d0446) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Addings logs to detect date issue resulting with a RangeError + +- Updated dependencies [[`1cb527b`](https://github.com/LedgerHQ/ledger-live/commit/1cb527b9a0b03f23a921a446c64f71ab5c9e9013), [`b7d58b4`](https://github.com/LedgerHQ/ledger-live/commit/b7d58b4cf3aa041b7b794d9af6f0b89bbc0df633), [`44ee889`](https://github.com/LedgerHQ/ledger-live/commit/44ee88944571c73afb105349f5f28b82e8be262d), [`13d9cbe`](https://github.com/LedgerHQ/ledger-live/commit/13d9cbe9a4afbf3ccd532a33e4ada3685d9d646a), [`618307f`](https://github.com/LedgerHQ/ledger-live/commit/618307f92899af07f4c8ad97c67df483492e3d9d), [`0f5292a`](https://github.com/LedgerHQ/ledger-live/commit/0f5292af8feaa517f36ec35155d813b17c4f66e9), [`52a3732`](https://github.com/LedgerHQ/ledger-live/commit/52a373273dee3b2cb5a3e8d2d4b05f90616d71a2), [`4d1aade`](https://github.com/LedgerHQ/ledger-live/commit/4d1aade53cd33f8e7548ce340f54fbb834bdcdcb), [`eb5ac4d`](https://github.com/LedgerHQ/ledger-live/commit/eb5ac4dca430654f5f86854025fddddab4261a29), [`c8172ab`](https://github.com/LedgerHQ/ledger-live/commit/c8172abc5c052a753b93be8b6c9cfd88ce0dd64a), [`5d03bf5`](https://github.com/LedgerHQ/ledger-live/commit/5d03bf514fcf7aea91dc8beae0cd503ed6b4ab3c), [`9d35080`](https://github.com/LedgerHQ/ledger-live/commit/9d35080944a6a63c78f54a545734f4cf3cbded63), [`3adea7a`](https://github.com/LedgerHQ/ledger-live/commit/3adea7a7ad66080b5e6e4407071a976644158d04), [`2edfa53`](https://github.com/LedgerHQ/ledger-live/commit/2edfa533bccafbfd8a61aea0f5422c0db79825ea), [`be22d72`](https://github.com/LedgerHQ/ledger-live/commit/be22d724cf5499fe4958bfb3b5f763ffaf0d0446), [`52a3732`](https://github.com/LedgerHQ/ledger-live/commit/52a373273dee3b2cb5a3e8d2d4b05f90616d71a2), [`6dea540`](https://github.com/LedgerHQ/ledger-live/commit/6dea54057f67162a1f556661afae16e0422f7ac3), [`e70e345`](https://github.com/LedgerHQ/ledger-live/commit/e70e345bd21d4f5c82fbedfd4447aec0e866be5a)]: + - @ledgerhq/types-live@6.43.1-next.0 + - @ledgerhq/cryptoassets@11.3.0-next.0 + - @ledgerhq/coin-framework@0.10.0-next.0 + - @ledgerhq/live-env@0.8.0-next.0 + - @ledgerhq/errors@6.16.1-next.0 + - @ledgerhq/devices@8.2.0-next.0 + - @ledgerhq/domain-service@1.1.16-next.0 + - @ledgerhq/evm-tools@1.0.12-next.0 + - @ledgerhq/hw-app-eth@6.35.1-next.0 + - @ledgerhq/live-network@1.1.10-next.0 + +## 0.11.0 + +### Minor Changes + +- [#4886](https://github.com/LedgerHQ/ledger-live/pull/4886) [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b) Thanks [@chabroA](https://github.com/chabroA)! - Add speedup / cancel tx feature for evm + +### Patch Changes + +- [#5364](https://github.com/LedgerHQ/ledger-live/pull/5364) [`743e1ede3e`](https://github.com/LedgerHQ/ledger-live/commit/743e1ede3eebf806e1e22c8627191b419870a476) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Updating the hashing algorithm from SHA256 to MurmurHashV3 for the `getSyncHash` method in order to drastically increase performances on a React Native environment. + +- [#4886](https://github.com/LedgerHQ/ledger-live/pull/4886) [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b) Thanks [@chabroA](https://github.com/chabroA)! - Fix wrong usage of explorer block endpoint in coin evm + +- [#4987](https://github.com/LedgerHQ/ledger-live/pull/4987) [`e63205b850`](https://github.com/LedgerHQ/ledger-live/commit/e63205b85071538ed2431157a12818d7a8f0ffa9) Thanks [@kallen-ledger](https://github.com/kallen-ledger)! - add 10s timeout to estimate gas + +- Updated dependencies [[`48487abd29`](https://github.com/LedgerHQ/ledger-live/commit/48487abd297e41629c6725bc0ac9d69bfeaa74d3), [`08dde174fd`](https://github.com/LedgerHQ/ledger-live/commit/08dde174fdeaadbce85dcd914383839f788f21dd), [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b), [`c5981ae341`](https://github.com/LedgerHQ/ledger-live/commit/c5981ae3411abc4c8594adf2efcb52aacddac143), [`317685e696`](https://github.com/LedgerHQ/ledger-live/commit/317685e69678e6fe1f489f0c071e7613d329d389), [`a4299c5d62`](https://github.com/LedgerHQ/ledger-live/commit/a4299c5d629cd56e6e6795adaa14978ae2b90f42), [`b4e7201b0b`](https://github.com/LedgerHQ/ledger-live/commit/b4e7201b0b70d146de7d936ff2c9e9e443164243), [`e63205b850`](https://github.com/LedgerHQ/ledger-live/commit/e63205b85071538ed2431157a12818d7a8f0ffa9), [`5964e30bed`](https://github.com/LedgerHQ/ledger-live/commit/5964e30bed11d64a3b7401c6ab51ffc1ad4c427c), [`4a283060bf`](https://github.com/LedgerHQ/ledger-live/commit/4a283060bf2e837d73c6c1cb5d89f890a4e4b931)]: + - @ledgerhq/types-live@6.43.0 + - @ledgerhq/types-cryptoassets@7.8.0 + - @ledgerhq/cryptoassets@11.2.0 + - @ledgerhq/errors@6.16.0 + - @ledgerhq/coin-framework@0.9.0 + - @ledgerhq/live-env@0.7.0 + - @ledgerhq/hw-app-eth@6.35.0 + - @ledgerhq/devices@8.1.0 + - @ledgerhq/logs@6.12.0 + - @ledgerhq/domain-service@1.1.15 + - @ledgerhq/evm-tools@1.0.11 + - @ledgerhq/live-network@1.1.9 + - @ledgerhq/live-promise@0.0.3 + +## 0.11.0-next.1 + +### Patch Changes + +- Updated dependencies [[`4a283060bf`](https://github.com/LedgerHQ/ledger-live/commit/4a283060bf2e837d73c6c1cb5d89f890a4e4b931)]: + - @ledgerhq/cryptoassets@11.2.0-next.1 + - @ledgerhq/coin-framework@0.9.0-next.1 + - @ledgerhq/evm-tools@1.0.11-next.1 + - @ledgerhq/hw-app-eth@6.35.0-next.1 + +## 0.11.0-next.0 + +### Minor Changes + +- [#4886](https://github.com/LedgerHQ/ledger-live/pull/4886) [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b) Thanks [@chabroA](https://github.com/chabroA)! - Add speedup / cancel tx feature for evm + +### Patch Changes + +- [#5364](https://github.com/LedgerHQ/ledger-live/pull/5364) [`743e1ede3e`](https://github.com/LedgerHQ/ledger-live/commit/743e1ede3eebf806e1e22c8627191b419870a476) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Updating the hashing algorithm from SHA256 to MurmurHashV3 for the `getSyncHash` method in order to drastically increase performances on a React Native environment. + +- [#4886](https://github.com/LedgerHQ/ledger-live/pull/4886) [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b) Thanks [@chabroA](https://github.com/chabroA)! - Fix wrong usage of explorer block endpoint in coin evm + +- [#4987](https://github.com/LedgerHQ/ledger-live/pull/4987) [`e63205b850`](https://github.com/LedgerHQ/ledger-live/commit/e63205b85071538ed2431157a12818d7a8f0ffa9) Thanks [@kallen-ledger](https://github.com/kallen-ledger)! - add 10s timeout to estimate gas + +- Updated dependencies [[`48487abd29`](https://github.com/LedgerHQ/ledger-live/commit/48487abd297e41629c6725bc0ac9d69bfeaa74d3), [`08dde174fd`](https://github.com/LedgerHQ/ledger-live/commit/08dde174fdeaadbce85dcd914383839f788f21dd), [`771c9d3c1d`](https://github.com/LedgerHQ/ledger-live/commit/771c9d3c1d138ddd68da2e4f9738e2c41ecaf81b), [`c5981ae341`](https://github.com/LedgerHQ/ledger-live/commit/c5981ae3411abc4c8594adf2efcb52aacddac143), [`317685e696`](https://github.com/LedgerHQ/ledger-live/commit/317685e69678e6fe1f489f0c071e7613d329d389), [`a4299c5d62`](https://github.com/LedgerHQ/ledger-live/commit/a4299c5d629cd56e6e6795adaa14978ae2b90f42), [`b4e7201b0b`](https://github.com/LedgerHQ/ledger-live/commit/b4e7201b0b70d146de7d936ff2c9e9e443164243), [`e63205b850`](https://github.com/LedgerHQ/ledger-live/commit/e63205b85071538ed2431157a12818d7a8f0ffa9), [`5964e30bed`](https://github.com/LedgerHQ/ledger-live/commit/5964e30bed11d64a3b7401c6ab51ffc1ad4c427c)]: + - @ledgerhq/types-live@6.43.0-next.0 + - @ledgerhq/types-cryptoassets@7.8.0-next.0 + - @ledgerhq/cryptoassets@11.2.0-next.0 + - @ledgerhq/errors@6.16.0-next.0 + - @ledgerhq/coin-framework@0.9.0-next.0 + - @ledgerhq/live-env@0.7.0-next.0 + - @ledgerhq/hw-app-eth@6.35.0-next.0 + - @ledgerhq/devices@8.1.0-next.0 + - @ledgerhq/logs@6.12.0-next.0 + - @ledgerhq/domain-service@1.1.15-next.0 + - @ledgerhq/evm-tools@1.0.11-next.0 + - @ledgerhq/live-network@1.1.9-next.0 + - @ledgerhq/live-promise@0.0.3-next.0 + +## 0.10.0 + +### Minor Changes + +- [#5173](https://github.com/LedgerHQ/ledger-live/pull/5173) [`17ba334e47`](https://github.com/LedgerHQ/ledger-live/commit/17ba334e47b901e34fbb083396aa3f9952e5233e) Thanks [@chabroA](https://github.com/chabroA)! - Add neon_evm support + +### Patch Changes + +- [#4856](https://github.com/LedgerHQ/ledger-live/pull/4856) [`173d7d6d22`](https://github.com/LedgerHQ/ledger-live/commit/173d7d6d224bcf1cecf364062b6571f52792e371) Thanks [@chabroA](https://github.com/chabroA)! - return error when tx from tokenAccount has no amount + +- [#5088](https://github.com/LedgerHQ/ledger-live/pull/5088) [`2fc6d1efa0`](https://github.com/LedgerHQ/ledger-live/commit/2fc6d1efa0233a90b0fa273782cff1dd6344d52c) Thanks [@sarneijim](https://github.com/sarneijim)! - Fix swap-web-app fees + +- Updated dependencies [[`3dc4937cc0`](https://github.com/LedgerHQ/ledger-live/commit/3dc4937cc0c77f6dc40ac7c628e9ab165dfb899f), [`fc121ce96d`](https://github.com/LedgerHQ/ledger-live/commit/fc121ce96dbcc4f30cfd9836644f778b85f997b7), [`95cf52eb66`](https://github.com/LedgerHQ/ledger-live/commit/95cf52eb66769228feb45dd5e799c444e80c5072), [`f5a5c315ea`](https://github.com/LedgerHQ/ledger-live/commit/f5a5c315ea2200cd5b52ef3a0b377d1327b1144e), [`17ba334e47`](https://github.com/LedgerHQ/ledger-live/commit/17ba334e47b901e34fbb083396aa3f9952e5233e), [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac), [`f83e060bf4`](https://github.com/LedgerHQ/ledger-live/commit/f83e060bf474a6b6133406eff49cb054e813046f), [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac), [`df5c9ae02a`](https://github.com/LedgerHQ/ledger-live/commit/df5c9ae02a604ddba13ddc64caf8d9ad079c303d), [`54b1d185c9`](https://github.com/LedgerHQ/ledger-live/commit/54b1d185c9df5ae84dc7e85d58249c06550df5f1), [`9b49ff233c`](https://github.com/LedgerHQ/ledger-live/commit/9b49ff233ccfad68c98d15cd648927dee12a8b0b), [`4d6fa0772e`](https://github.com/LedgerHQ/ledger-live/commit/4d6fa0772e19cdbd4b432fafa43621c42e2a5fdd), [`b259781b72`](https://github.com/LedgerHQ/ledger-live/commit/b259781b7212aa7758437640e7c48c5d17b0fa79)]: + - @ledgerhq/types-live@6.42.0 + - @ledgerhq/domain-service@1.1.14 + - @ledgerhq/types-cryptoassets@7.7.0 + - @ledgerhq/cryptoassets@11.1.0 + - @ledgerhq/logs@6.11.0 + - @ledgerhq/coin-framework@0.8.1 + - @ledgerhq/live-env@0.6.1 + - @ledgerhq/errors@6.15.0 + - @ledgerhq/evm-tools@1.0.10 + - @ledgerhq/hw-app-eth@6.34.9 + - @ledgerhq/devices@8.0.8 + - @ledgerhq/live-network@1.1.8 + - @ledgerhq/live-promise@0.0.2 + +## 0.10.0-next.0 + +### Minor Changes + +- [#5173](https://github.com/LedgerHQ/ledger-live/pull/5173) [`17ba334e47`](https://github.com/LedgerHQ/ledger-live/commit/17ba334e47b901e34fbb083396aa3f9952e5233e) Thanks [@chabroA](https://github.com/chabroA)! - Add neon_evm support + +### Patch Changes + +- [#4856](https://github.com/LedgerHQ/ledger-live/pull/4856) [`173d7d6d22`](https://github.com/LedgerHQ/ledger-live/commit/173d7d6d224bcf1cecf364062b6571f52792e371) Thanks [@chabroA](https://github.com/chabroA)! - return error when tx from tokenAccount has no amount + +- [#5088](https://github.com/LedgerHQ/ledger-live/pull/5088) [`2fc6d1efa0`](https://github.com/LedgerHQ/ledger-live/commit/2fc6d1efa0233a90b0fa273782cff1dd6344d52c) Thanks [@sarneijim](https://github.com/sarneijim)! - Fix swap-web-app fees + +- Updated dependencies [[`3dc4937cc0`](https://github.com/LedgerHQ/ledger-live/commit/3dc4937cc0c77f6dc40ac7c628e9ab165dfb899f), [`fc121ce96d`](https://github.com/LedgerHQ/ledger-live/commit/fc121ce96dbcc4f30cfd9836644f778b85f997b7), [`95cf52eb66`](https://github.com/LedgerHQ/ledger-live/commit/95cf52eb66769228feb45dd5e799c444e80c5072), [`f5a5c315ea`](https://github.com/LedgerHQ/ledger-live/commit/f5a5c315ea2200cd5b52ef3a0b377d1327b1144e), [`17ba334e47`](https://github.com/LedgerHQ/ledger-live/commit/17ba334e47b901e34fbb083396aa3f9952e5233e), [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac), [`f83e060bf4`](https://github.com/LedgerHQ/ledger-live/commit/f83e060bf474a6b6133406eff49cb054e813046f), [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac), [`df5c9ae02a`](https://github.com/LedgerHQ/ledger-live/commit/df5c9ae02a604ddba13ddc64caf8d9ad079c303d), [`54b1d185c9`](https://github.com/LedgerHQ/ledger-live/commit/54b1d185c9df5ae84dc7e85d58249c06550df5f1), [`9b49ff233c`](https://github.com/LedgerHQ/ledger-live/commit/9b49ff233ccfad68c98d15cd648927dee12a8b0b), [`4d6fa0772e`](https://github.com/LedgerHQ/ledger-live/commit/4d6fa0772e19cdbd4b432fafa43621c42e2a5fdd), [`b259781b72`](https://github.com/LedgerHQ/ledger-live/commit/b259781b7212aa7758437640e7c48c5d17b0fa79)]: + - @ledgerhq/types-live@6.42.0-next.0 + - @ledgerhq/domain-service@1.1.14-next.0 + - @ledgerhq/types-cryptoassets@7.7.0-next.0 + - @ledgerhq/cryptoassets@11.1.0-next.0 + - @ledgerhq/logs@6.11.0-next.0 + - @ledgerhq/coin-framework@0.8.1-next.0 + - @ledgerhq/live-env@0.6.1-next.0 + - @ledgerhq/errors@6.15.0-next.0 + - @ledgerhq/evm-tools@1.0.10-next.0 + - @ledgerhq/hw-app-eth@6.34.9-next.0 + - @ledgerhq/devices@8.0.8-next.0 + - @ledgerhq/live-network@1.1.8-next.0 + - @ledgerhq/live-promise@0.0.2-next.0 + +## 0.9.0 + +### Minor Changes + +- [#5042](https://github.com/LedgerHQ/ledger-live/pull/5042) [`3b4f7501cc`](https://github.com/LedgerHQ/ledger-live/commit/3b4f7501cc5f09be94a2994f20f9998898682975) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Ensure compatiblity with @ledgerhq/coin-framework change regarding `TokenAccounts` ids & update `preload` & `hydrate` method to use the `convertBEP20` method instead of the `convertERC20` method when dealing with the bsc chain. This last fix is technically useless as BEP20 = ERC20, it's only here in order to prevent breaking changes with the different backends at Ledger. As soon as those backends have the possibility of changing the "bsc/bep20/XYZ" token ids into "bsc/erc20/XYZ", this fix should be removed in order to avoid useless complexity. + +### Patch Changes + +- Updated dependencies [[`ce18546c0a`](https://github.com/LedgerHQ/ledger-live/commit/ce18546c0a0b9dd5ed78b1745cac19b7eef7b5eb), [`3b4f7501cc`](https://github.com/LedgerHQ/ledger-live/commit/3b4f7501cc5f09be94a2994f20f9998898682975), [`fbeebfe04b`](https://github.com/LedgerHQ/ledger-live/commit/fbeebfe04b297b33ec258440b694cdfb6213af24)]: + - @ledgerhq/types-live@6.41.1 + - @ledgerhq/coin-framework@0.8.0 + - @ledgerhq/cryptoassets@11.0.1 + - @ledgerhq/domain-service@1.1.13 + - @ledgerhq/evm-tools@1.0.9 + - @ledgerhq/hw-app-eth@6.34.8 + +## 0.9.0-hotfix.2 + +### Patch Changes + +- Updated dependencies [[`fbeebfe04b`](https://github.com/LedgerHQ/ledger-live/commit/fbeebfe04b297b33ec258440b694cdfb6213af24)]: + - @ledgerhq/cryptoassets@11.0.1-hotfix.0 + - @ledgerhq/coin-framework@0.8.0-hotfix.2 + - @ledgerhq/domain-service@1.1.13-hotfix.1 + - @ledgerhq/evm-tools@1.0.9-hotfix.0 + - @ledgerhq/hw-app-eth@6.34.8-hotfix.1 + +## 0.9.0-hotfix.1 + +### Minor Changes + +- [#5042](https://github.com/LedgerHQ/ledger-live/pull/5042) [`3b4f7501cc`](https://github.com/LedgerHQ/ledger-live/commit/3b4f7501cc5f09be94a2994f20f9998898682975) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Ensure compatiblity with @ledgerhq/coin-framework change regarding `TokenAccounts` ids & update `preload` & `hydrate` method to use the `convertBEP20` method instead of the `convertERC20` method when dealing with the bsc chain. This last fix is technically useless as BEP20 = ERC20, it's only here in order to prevent breaking changes with the different backends at Ledger. As soon as those backends have the possibility of changing the "bsc/bep20/XYZ" token ids into "bsc/erc20/XYZ", this fix should be removed in order to avoid useless complexity. + +### Patch Changes + +- Updated dependencies [[`3b4f7501cc`](https://github.com/LedgerHQ/ledger-live/commit/3b4f7501cc5f09be94a2994f20f9998898682975)]: + - @ledgerhq/coin-framework@0.8.0-hotfix.1 + +## 0.8.1-hotfix.0 + +### Patch Changes + +- Updated dependencies [[`ce18546c0a`](https://github.com/LedgerHQ/ledger-live/commit/ce18546c0a0b9dd5ed78b1745cac19b7eef7b5eb)]: + - @ledgerhq/types-live@6.41.1-hotfix.0 + - @ledgerhq/coin-framework@0.7.1-hotfix.0 + - @ledgerhq/domain-service@1.1.13-hotfix.0 + - @ledgerhq/evm-tools@1.0.8 + - @ledgerhq/hw-app-eth@6.34.8-hotfix.0 + +## 0.8.0 + +### Minor Changes + +- [#4741](https://github.com/LedgerHQ/ledger-live/pull/4741) [`a134f28e9d`](https://github.com/LedgerHQ/ledger-live/commit/a134f28e9d220d172148619ed281d4ca897d5532) Thanks [@chabroA](https://github.com/chabroA)! - Add gasOption serialisation and deserialisation to evm transactions + +- [#4791](https://github.com/LedgerHQ/ledger-live/pull/4791) [`b779f6c964`](https://github.com/LedgerHQ/ledger-live/commit/b779f6c964079b9cd9a4ee985cd5cdbb8c49406e) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update `getDeviceTransactionConfig` to return correctly nano fields when the transaction has been crafted by a third party (like the Wallet API) + +- [#4285](https://github.com/LedgerHQ/ledger-live/pull/4285) [`533278e2c4`](https://github.com/LedgerHQ/ledger-live/commit/533278e2c40ee764ecb87d4430fa6650f251ff0c) Thanks [@chabroA](https://github.com/chabroA)! - Migrate Ethereum family implementation to EVM family + + Replace the legcay Ethereum familly implementation that was present in ledger-live-common by the coin-evm lib implementation. + This change was made in order to improve scalabillity and maintainability of the evm coins, as well as more easilly integrate new evm based chains in the future. + +### Patch Changes + +- [#4804](https://github.com/LedgerHQ/ledger-live/pull/4804) [`4cb507a52b`](https://github.com/LedgerHQ/ledger-live/commit/4cb507a52bf336d395b08b4c1a429bd4956ab22d) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add cache to CDN requests during preload + +- Updated dependencies [[`c86637f6e5`](https://github.com/LedgerHQ/ledger-live/commit/c86637f6e57845716a791854dd8f686807152e73), [`72288402ec`](https://github.com/LedgerHQ/ledger-live/commit/72288402ec70f9159022505cb3187e63b24df450), [`f527d1bb5a`](https://github.com/LedgerHQ/ledger-live/commit/f527d1bb5a2888a916f761d43d2ba5093eaa3e3f), [`a134f28e9d`](https://github.com/LedgerHQ/ledger-live/commit/a134f28e9d220d172148619ed281d4ca897d5532), [`49ea3fd98b`](https://github.com/LedgerHQ/ledger-live/commit/49ea3fd98ba1e1e0ed54d29ab5fdc71c4918183f), [`533278e2c4`](https://github.com/LedgerHQ/ledger-live/commit/533278e2c40ee764ecb87d4430fa6650f251ff0c), [`70e4277bc9`](https://github.com/LedgerHQ/ledger-live/commit/70e4277bc9dda253b894bdae5f2c8a5f43a9a64e)]: + - @ledgerhq/hw-app-eth@6.34.7 + - @ledgerhq/cryptoassets@11.0.0 + - @ledgerhq/types-cryptoassets@7.6.0 + - @ledgerhq/types-live@6.41.0 + - @ledgerhq/coin-framework@0.7.0 + - @ledgerhq/live-env@0.6.0 + - @ledgerhq/domain-service@1.1.12 + - @ledgerhq/evm-tools@1.0.8 + - @ledgerhq/live-network@1.1.7 + +## 0.6.2 + +### Patch Changes + +- Updated dependencies [[`6c83521fee`](https://github.com/LedgerHQ/ledger-live/commit/6c83521fee8da656858630c1cb37a5af95df3362)]: + - @ledgerhq/types-cryptoassets@7.5.0 + - @ledgerhq/cryptoassets@9.13.0 + - @ledgerhq/types-live@6.40.0 + - @ledgerhq/coin-framework@0.5.4 + - @ledgerhq/domain-service@1.1.11 + - @ledgerhq/evm-tools@1.0.7 + - @ledgerhq/hw-app-eth@6.34.6 + +## 0.6.1 + +### Patch Changes + +- Updated dependencies [[`e0cc3a0841`](https://github.com/LedgerHQ/ledger-live/commit/e0cc3a08415de84b9d3ce828444248a043a9d699), [`18b4a47b48`](https://github.com/LedgerHQ/ledger-live/commit/18b4a47b4878a23695a50096b7770134883b8a2e)]: + - @ledgerhq/coin-framework@0.5.3 + - @ledgerhq/cryptoassets@9.12.1 + - @ledgerhq/domain-service@1.1.10 + - @ledgerhq/evm-tools@1.0.6 + - @ledgerhq/hw-app-eth@6.34.5 + +## 0.6.0 + +### Minor Changes + +- [#4235](https://github.com/LedgerHQ/ledger-live/pull/4235) [`8e9df43a0c`](https://github.com/LedgerHQ/ledger-live/commit/8e9df43a0cd00a2065b494439f300f96724b8eb8) Thanks [@haammar-ledger](https://github.com/haammar-ledger)! - Better typing for the Operation.extra field + +### Patch Changes + +- [#4391](https://github.com/LedgerHQ/ledger-live/pull/4391) [`fde2fe79f1`](https://github.com/LedgerHQ/ledger-live/commit/fde2fe79f1df69fffe80763cd6d9792fe9de1262) Thanks [@valpinkman](https://github.com/valpinkman)! - Rework some env typings + +- [#4452](https://github.com/LedgerHQ/ledger-live/pull/4452) [`1020f27632`](https://github.com/LedgerHQ/ledger-live/commit/1020f276322fe361585a56573091ec647fbd901e) Thanks [@hzheng-ledger](https://github.com/hzheng-ledger)! - fix evm integration tests + +- [#4268](https://github.com/LedgerHQ/ledger-live/pull/4268) [`707e59f8b5`](https://github.com/LedgerHQ/ledger-live/commit/707e59f8b516448e6f2845288ad4cb3f5488e688) Thanks [@hzheng-ledger](https://github.com/hzheng-ledger)! - fix pending transaction bug in evm family + +- Updated dependencies [[`8e9df43a0c`](https://github.com/LedgerHQ/ledger-live/commit/8e9df43a0cd00a2065b494439f300f96724b8eb8), [`fde2fe79f1`](https://github.com/LedgerHQ/ledger-live/commit/fde2fe79f1df69fffe80763cd6d9792fe9de1262), [`f6f70ba0e8`](https://github.com/LedgerHQ/ledger-live/commit/f6f70ba0e85c7898cdeec19402b1eadfde6a2206), [`45be23c776`](https://github.com/LedgerHQ/ledger-live/commit/45be23c77666697dbe395f836ab592062173d5cb), [`6375c250a9`](https://github.com/LedgerHQ/ledger-live/commit/6375c250a9a58b33e3dd1d6c96a96c7e46150298), [`0d9ad3599b`](https://github.com/LedgerHQ/ledger-live/commit/0d9ad3599bce8872fde97d27c977ab24445afc3a)]: + - @ledgerhq/types-live@6.39.0 + - @ledgerhq/live-env@0.5.0 + - @ledgerhq/coin-framework@0.5.2 + - @ledgerhq/cryptoassets@9.12.0 + - @ledgerhq/domain-service@1.1.9 + - @ledgerhq/evm-tools@1.0.5 + - @ledgerhq/hw-app-eth@6.34.4 + - @ledgerhq/live-network@1.1.6 + +## 0.6.0-next.0 + +### Minor Changes + +- [#4235](https://github.com/LedgerHQ/ledger-live/pull/4235) [`8e9df43a0c`](https://github.com/LedgerHQ/ledger-live/commit/8e9df43a0cd00a2065b494439f300f96724b8eb8) Thanks [@haammar-ledger](https://github.com/haammar-ledger)! - Better typing for the Operation.extra field + +### Patch Changes + +- [#4391](https://github.com/LedgerHQ/ledger-live/pull/4391) [`fde2fe79f1`](https://github.com/LedgerHQ/ledger-live/commit/fde2fe79f1df69fffe80763cd6d9792fe9de1262) Thanks [@valpinkman](https://github.com/valpinkman)! - Rework some env typings + +- [#4452](https://github.com/LedgerHQ/ledger-live/pull/4452) [`1020f27632`](https://github.com/LedgerHQ/ledger-live/commit/1020f276322fe361585a56573091ec647fbd901e) Thanks [@hzheng-ledger](https://github.com/hzheng-ledger)! - fix evm integration tests + +- [#4268](https://github.com/LedgerHQ/ledger-live/pull/4268) [`707e59f8b5`](https://github.com/LedgerHQ/ledger-live/commit/707e59f8b516448e6f2845288ad4cb3f5488e688) Thanks [@hzheng-ledger](https://github.com/hzheng-ledger)! - fix pending transaction bug in evm family + +- Updated dependencies [[`8e9df43a0c`](https://github.com/LedgerHQ/ledger-live/commit/8e9df43a0cd00a2065b494439f300f96724b8eb8), [`fde2fe79f1`](https://github.com/LedgerHQ/ledger-live/commit/fde2fe79f1df69fffe80763cd6d9792fe9de1262), [`f6f70ba0e8`](https://github.com/LedgerHQ/ledger-live/commit/f6f70ba0e85c7898cdeec19402b1eadfde6a2206), [`45be23c776`](https://github.com/LedgerHQ/ledger-live/commit/45be23c77666697dbe395f836ab592062173d5cb), [`6375c250a9`](https://github.com/LedgerHQ/ledger-live/commit/6375c250a9a58b33e3dd1d6c96a96c7e46150298), [`0d9ad3599b`](https://github.com/LedgerHQ/ledger-live/commit/0d9ad3599bce8872fde97d27c977ab24445afc3a)]: + - @ledgerhq/types-live@6.39.0-next.0 + - @ledgerhq/live-env@0.5.0-next.0 + - @ledgerhq/coin-framework@0.5.2-next.0 + - @ledgerhq/cryptoassets@9.12.0-next.0 + - @ledgerhq/domain-service@1.1.9-next.0 + - @ledgerhq/evm-tools@1.0.5-next.0 + - @ledgerhq/hw-app-eth@6.34.4-next.0 + - @ledgerhq/live-network@1.1.6-next.0 + +## 0.5.1 + +### Patch Changes + +- Updated dependencies [[`5bbcea12f9`](https://github.com/LedgerHQ/ledger-live/commit/5bbcea12f93e3cda41705a4d61d50845628a6de6), [`95088eab45`](https://github.com/LedgerHQ/ledger-live/commit/95088eab45f6af919e347a605cefefb6d7705808), [`a61a43fc47`](https://github.com/LedgerHQ/ledger-live/commit/a61a43fc47399e969fa68539de6af51bfa41e921), [`4c2539a1d5`](https://github.com/LedgerHQ/ledger-live/commit/4c2539a1d5c9c01c0f9fa7cd1daf5a5a63c02996), [`229cf62304`](https://github.com/LedgerHQ/ledger-live/commit/229cf623043b29eefed3e8e37a102325fa6e0387), [`3455944496`](https://github.com/LedgerHQ/ledger-live/commit/34559444969ce1571ff4c54f33feb7f3fb59a33a)]: + - @ledgerhq/types-live@6.38.1 + - @ledgerhq/live-env@0.4.2 + - @ledgerhq/errors@6.14.0 + - @ledgerhq/cryptoassets@9.11.1 + - @ledgerhq/coin-framework@0.5.1 + - @ledgerhq/domain-service@1.1.8 + - @ledgerhq/evm-tools@1.0.4 + - @ledgerhq/hw-app-eth@6.34.3 + - @ledgerhq/live-network@1.1.5 + - @ledgerhq/devices@8.0.7 + +## 0.5.1-next.0 + +### Patch Changes + +- Updated dependencies [[`5bbcea12f9`](https://github.com/LedgerHQ/ledger-live/commit/5bbcea12f93e3cda41705a4d61d50845628a6de6), [`95088eab45`](https://github.com/LedgerHQ/ledger-live/commit/95088eab45f6af919e347a605cefefb6d7705808), [`a61a43fc47`](https://github.com/LedgerHQ/ledger-live/commit/a61a43fc47399e969fa68539de6af51bfa41e921), [`4c2539a1d5`](https://github.com/LedgerHQ/ledger-live/commit/4c2539a1d5c9c01c0f9fa7cd1daf5a5a63c02996), [`229cf62304`](https://github.com/LedgerHQ/ledger-live/commit/229cf623043b29eefed3e8e37a102325fa6e0387), [`3455944496`](https://github.com/LedgerHQ/ledger-live/commit/34559444969ce1571ff4c54f33feb7f3fb59a33a)]: + - @ledgerhq/types-live@6.38.1-next.0 + - @ledgerhq/live-env@0.4.2-next.0 + - @ledgerhq/errors@6.14.0-next.0 + - @ledgerhq/cryptoassets@9.11.1-next.0 + - @ledgerhq/coin-framework@0.5.1-next.0 + - @ledgerhq/domain-service@1.1.8-next.0 + - @ledgerhq/evm-tools@1.0.4-next.0 + - @ledgerhq/hw-app-eth@6.34.3-next.0 + - @ledgerhq/live-network@1.1.5-next.0 + - @ledgerhq/devices@8.0.7-next.0 + +## 0.5.0 + +### Minor Changes + +- [#4021](https://github.com/LedgerHQ/ledger-live/pull/4021) [`e5f9cc46d6`](https://github.com/LedgerHQ/ledger-live/commit/e5f9cc46d69b82ad7267296b350e9d97a47f9e86) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add telos evm currency + +- [#3704](https://github.com/LedgerHQ/ledger-live/pull/3704) [`b6e50932af`](https://github.com/LedgerHQ/ledger-live/commit/b6e50932afac6acc2d2f9fa9ed10b77a62378e03) Thanks [@chabroA](https://github.com/chabroA)! - Create EVM send flow + +- [#3827](https://github.com/LedgerHQ/ledger-live/pull/3827) [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Ledger infra as node and/or explorer + +- [#4015](https://github.com/LedgerHQ/ledger-live/pull/4015) [`374e339c27`](https://github.com/LedgerHQ/ledger-live/commit/374e339c27e317656d01463a822898ad3a60df85) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Polygon zkEVM, Base Goerli, Klaytn + +### Patch Changes + +- [#4090](https://github.com/LedgerHQ/ledger-live/pull/4090) [`7675787398`](https://github.com/LedgerHQ/ledger-live/commit/767578739822597768f877f94fd8f7f35441395a) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix building & bundling of `evm-tools` & `domain-service` libs due to .gitignore(s) + +- [#4143](https://github.com/LedgerHQ/ledger-live/pull/4143) [`c2fd7e2e3d`](https://github.com/LedgerHQ/ledger-live/commit/c2fd7e2e3d684da831a7eafe6b22b5e2c96a3722) Thanks [@chabroA](https://github.com/chabroA)! - Add missing teloscan in type guard + +- Updated dependencies [[`1263b7a9c1`](https://github.com/LedgerHQ/ledger-live/commit/1263b7a9c1916da81ad55bb2ca1e804cff5f89e2), [`770842cdbe`](https://github.com/LedgerHQ/ledger-live/commit/770842cdbe94c629b6844f93d1b5d94d381931b1), [`e5f9cc46d6`](https://github.com/LedgerHQ/ledger-live/commit/e5f9cc46d69b82ad7267296b350e9d97a47f9e86), [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1), [`cfbff52724`](https://github.com/LedgerHQ/ledger-live/commit/cfbff527241534aba69bff3d86733b50a14eb4ce), [`b6e50932af`](https://github.com/LedgerHQ/ledger-live/commit/b6e50932afac6acc2d2f9fa9ed10b77a62378e03), [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1), [`7675787398`](https://github.com/LedgerHQ/ledger-live/commit/767578739822597768f877f94fd8f7f35441395a), [`95ac67a5e0`](https://github.com/LedgerHQ/ledger-live/commit/95ac67a5e0359b03c7d82c34fd1f2f3b6eb7df22), [`c7c484acf0`](https://github.com/LedgerHQ/ledger-live/commit/c7c484acf01e9db8dc5a5507b62ffcb863c77ca4), [`374e339c27`](https://github.com/LedgerHQ/ledger-live/commit/374e339c27e317656d01463a822898ad3a60df85), [`66769a98e6`](https://github.com/LedgerHQ/ledger-live/commit/66769a98e69f2b8156417e464e90d9162272b470)]: + - @ledgerhq/cryptoassets@9.11.0 + - @ledgerhq/live-env@0.4.1 + - @ledgerhq/types-cryptoassets@7.4.0 + - @ledgerhq/types-live@6.38.0 + - @ledgerhq/coin-framework@0.5.0 + - @ledgerhq/evm-tools@1.0.3 + - @ledgerhq/hw-app-eth@6.34.2 + - @ledgerhq/errors@6.13.1 + - @ledgerhq/domain-service@1.1.7 + - @ledgerhq/live-network@1.1.4 + - @ledgerhq/devices@8.0.6 + +## 0.5.0-next.0 + +### Minor Changes + +- [#4021](https://github.com/LedgerHQ/ledger-live/pull/4021) [`e5f9cc46d6`](https://github.com/LedgerHQ/ledger-live/commit/e5f9cc46d69b82ad7267296b350e9d97a47f9e86) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add telos evm currency + +- [#3704](https://github.com/LedgerHQ/ledger-live/pull/3704) [`b6e50932af`](https://github.com/LedgerHQ/ledger-live/commit/b6e50932afac6acc2d2f9fa9ed10b77a62378e03) Thanks [@chabroA](https://github.com/chabroA)! - Create EVM send flow + +- [#3827](https://github.com/LedgerHQ/ledger-live/pull/3827) [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Ledger infra as node and/or explorer + +- [#4015](https://github.com/LedgerHQ/ledger-live/pull/4015) [`374e339c27`](https://github.com/LedgerHQ/ledger-live/commit/374e339c27e317656d01463a822898ad3a60df85) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for Polygon zkEVM, Base Goerli, Klaytn + +### Patch Changes + +- [#4090](https://github.com/LedgerHQ/ledger-live/pull/4090) [`7675787398`](https://github.com/LedgerHQ/ledger-live/commit/767578739822597768f877f94fd8f7f35441395a) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Fix building & bundling of `evm-tools` & `domain-service` libs due to .gitignore(s) + +- [#4143](https://github.com/LedgerHQ/ledger-live/pull/4143) [`c2fd7e2e3d`](https://github.com/LedgerHQ/ledger-live/commit/c2fd7e2e3d684da831a7eafe6b22b5e2c96a3722) Thanks [@chabroA](https://github.com/chabroA)! - Add missing teloscan in type guard + +- Updated dependencies [[`1263b7a9c1`](https://github.com/LedgerHQ/ledger-live/commit/1263b7a9c1916da81ad55bb2ca1e804cff5f89e2), [`770842cdbe`](https://github.com/LedgerHQ/ledger-live/commit/770842cdbe94c629b6844f93d1b5d94d381931b1), [`e5f9cc46d6`](https://github.com/LedgerHQ/ledger-live/commit/e5f9cc46d69b82ad7267296b350e9d97a47f9e86), [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1), [`cfbff52724`](https://github.com/LedgerHQ/ledger-live/commit/cfbff527241534aba69bff3d86733b50a14eb4ce), [`b6e50932af`](https://github.com/LedgerHQ/ledger-live/commit/b6e50932afac6acc2d2f9fa9ed10b77a62378e03), [`6a88b7f8a6`](https://github.com/LedgerHQ/ledger-live/commit/6a88b7f8a6b7c732be0c945131b6c1d9b3937cc1), [`7675787398`](https://github.com/LedgerHQ/ledger-live/commit/767578739822597768f877f94fd8f7f35441395a), [`95ac67a5e0`](https://github.com/LedgerHQ/ledger-live/commit/95ac67a5e0359b03c7d82c34fd1f2f3b6eb7df22), [`c7c484acf0`](https://github.com/LedgerHQ/ledger-live/commit/c7c484acf01e9db8dc5a5507b62ffcb863c77ca4), [`374e339c27`](https://github.com/LedgerHQ/ledger-live/commit/374e339c27e317656d01463a822898ad3a60df85), [`66769a98e6`](https://github.com/LedgerHQ/ledger-live/commit/66769a98e69f2b8156417e464e90d9162272b470)]: + - @ledgerhq/cryptoassets@9.11.0-next.0 + - @ledgerhq/live-env@0.4.1-next.0 + - @ledgerhq/types-cryptoassets@7.4.0-next.0 + - @ledgerhq/types-live@6.38.0-next.0 + - @ledgerhq/coin-framework@0.5.0-next.0 + - @ledgerhq/evm-tools@1.0.3-next.0 + - @ledgerhq/hw-app-eth@6.34.2-next.0 + - @ledgerhq/errors@6.13.1-next.0 + - @ledgerhq/domain-service@1.1.7-next.0 + - @ledgerhq/live-network@1.1.4-next.0 + - @ledgerhq/devices@8.0.6-next.0 + +## 0.4.1 + +### Patch Changes + +- [#4103](https://github.com/LedgerHQ/ledger-live/pull/4103) [`2317fccb67`](https://github.com/LedgerHQ/ledger-live/commit/2317fccb6776a077eaca8828da8371d402323be4) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Fix building & bundling of `evm-tools` & `domain-service` libs due to .gitignore(s) + +- Updated dependencies [[`2317fccb67`](https://github.com/LedgerHQ/ledger-live/commit/2317fccb6776a077eaca8828da8371d402323be4)]: + - @ledgerhq/evm-tools@1.0.2 + - @ledgerhq/hw-app-eth@6.34.1 + +## 0.4.1-hotfix.0 + +### Patch Changes + +- [#4103](https://github.com/LedgerHQ/ledger-live/pull/4103) [`2317fccb67`](https://github.com/LedgerHQ/ledger-live/commit/2317fccb6776a077eaca8828da8371d402323be4) Thanks [@live-github-bot](https://github.com/apps/live-github-bot)! - Fix building & bundling of `evm-tools` & `domain-service` libs due to .gitignore(s) + +- Updated dependencies [[`2317fccb67`](https://github.com/LedgerHQ/ledger-live/commit/2317fccb6776a077eaca8828da8371d402323be4)]: + - @ledgerhq/evm-tools@1.0.2-hotfix.0 + - @ledgerhq/hw-app-eth@6.34.1-hotfix.0 + +## 0.4.0 + +### Minor Changes + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Adding support for NFT transactions + +- [#3786](https://github.com/LedgerHQ/ledger-live/pull/3786) [`11e62b1e1e`](https://github.com/LedgerHQ/ledger-live/commit/11e62b1e1e3773eeaad748453973e0b3bcd3e3bf) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Adds support for the `setLoadConfig` during the SignOperation step and adds the usage of environment variables to set the backends URIs + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for non finite quantity w/ NFT transaction data crafting + +- [#3924](https://github.com/LedgerHQ/ledger-live/pull/3924) [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Use of the `evm-tools` new library to bring support for SignMessage + +### Patch Changes + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Prevent duplicated sub & nft operations with rate limited explorers & make explorerless implementation also patch sub & nft operations after transaction finalization + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Rename rpc file that prevented shims to be applied for React Native + +- Updated dependencies [[`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`49182846de`](https://github.com/LedgerHQ/ledger-live/commit/49182846dee35ae9b3535c0c120e17d0eaecde70), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`c660c4e389`](https://github.com/LedgerHQ/ledger-live/commit/c660c4e389ac200ef308cbc3882930d392375de3), [`2c28d5aab3`](https://github.com/LedgerHQ/ledger-live/commit/2c28d5aab36b8b0cf2cb2a50e02eac4c5a588e41), [`0f4293e9bf`](https://github.com/LedgerHQ/ledger-live/commit/0f4293e9bf9cac4c2a195efeb0831aab3d51933d), [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1), [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`bae3b64dd2`](https://github.com/LedgerHQ/ledger-live/commit/bae3b64dd2710a3743552600166be986e93d9099), [`9692adc2a6`](https://github.com/LedgerHQ/ledger-live/commit/9692adc2a6774feb4424fc7a984810918c946b1b), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec)]: + - @ledgerhq/live-env@0.4.0 + - @ledgerhq/coin-framework@0.4.0 + - @ledgerhq/cryptoassets@9.10.0 + - @ledgerhq/errors@6.13.0 + - @ledgerhq/types-live@6.37.0 + - @ledgerhq/hw-app-eth@6.34.0 + - @ledgerhq/types-cryptoassets@7.3.1 + - @ledgerhq/evm-tools@1.0.1 + - @ledgerhq/live-network@1.1.3 + - @ledgerhq/domain-service@1.1.6 + - @ledgerhq/devices@8.0.5 + +## 0.4.0-next.0 + +### Minor Changes + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Adding support for NFT transactions + +- [#3786](https://github.com/LedgerHQ/ledger-live/pull/3786) [`11e62b1e1e`](https://github.com/LedgerHQ/ledger-live/commit/11e62b1e1e3773eeaad748453973e0b3bcd3e3bf) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Adds support for the `setLoadConfig` during the SignOperation step and adds the usage of environment variables to set the backends URIs + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Add support for non finite quantity w/ NFT transaction data crafting + +- [#3924](https://github.com/LedgerHQ/ledger-live/pull/3924) [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Use of the `evm-tools` new library to bring support for SignMessage + +### Patch Changes + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Prevent duplicated sub & nft operations with rate limited explorers & make explorerless implementation also patch sub & nft operations after transaction finalization + +- [#3714](https://github.com/LedgerHQ/ledger-live/pull/3714) [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Rename rpc file that prevented shims to be applied for React Native + +- Updated dependencies [[`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`49182846de`](https://github.com/LedgerHQ/ledger-live/commit/49182846dee35ae9b3535c0c120e17d0eaecde70), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`c660c4e389`](https://github.com/LedgerHQ/ledger-live/commit/c660c4e389ac200ef308cbc3882930d392375de3), [`2c28d5aab3`](https://github.com/LedgerHQ/ledger-live/commit/2c28d5aab36b8b0cf2cb2a50e02eac4c5a588e41), [`0f4293e9bf`](https://github.com/LedgerHQ/ledger-live/commit/0f4293e9bf9cac4c2a195efeb0831aab3d51933d), [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1), [`14cce73003`](https://github.com/LedgerHQ/ledger-live/commit/14cce7300333c51cbcdbd5a7e290ddc600c9f3a1), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec), [`bae3b64dd2`](https://github.com/LedgerHQ/ledger-live/commit/bae3b64dd2710a3743552600166be986e93d9099), [`9692adc2a6`](https://github.com/LedgerHQ/ledger-live/commit/9692adc2a6774feb4424fc7a984810918c946b1b), [`15e8abc482`](https://github.com/LedgerHQ/ledger-live/commit/15e8abc482b2b38e4808890f556097cf693359ec)]: + - @ledgerhq/live-env@0.4.0-next.0 + - @ledgerhq/coin-framework@0.4.0-next.0 + - @ledgerhq/cryptoassets@9.10.0-next.0 + - @ledgerhq/errors@6.13.0-next.0 + - @ledgerhq/types-live@6.37.0-next.0 + - @ledgerhq/hw-app-eth@6.34.0-next.0 + - @ledgerhq/types-cryptoassets@7.3.1-next.0 + - @ledgerhq/evm-tools@1.0.1-next.0 + - @ledgerhq/live-network@1.1.3-next.0 + - @ledgerhq/domain-service@1.1.6-next.0 + - @ledgerhq/devices@8.0.5-next.0 + +## 0.3.0 + +### Minor Changes + +- [#3611](https://github.com/LedgerHQ/ledger-live/pull/3611) [`092cb8d317`](https://github.com/LedgerHQ/ledger-live/commit/092cb8d317fa7971e0f790b77f900ae3864d96c2) Thanks [@chabroA](https://github.com/chabroA)! - Create GasTracker abstraction for evm familly + +### Patch Changes + +- [#3741](https://github.com/LedgerHQ/ledger-live/pull/3741) [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update eip55 dependency + +- [#3741](https://github.com/LedgerHQ/ledger-live/pull/3741) [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update eip55 dependency to 2.1.1 fixing browser context usage + +- [#3872](https://github.com/LedgerHQ/ledger-live/pull/3872) [`d1d1578ab5`](https://github.com/LedgerHQ/ledger-live/commit/d1d1578ab5b351544c98d56b67c68f18640f2d20) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Rename rpc file that prevented shims to be applied for React Native + +- Updated dependencies [[`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc), [`44192f2ab2`](https://github.com/LedgerHQ/ledger-live/commit/44192f2ab2857cbae2ef4a81ee9608d395dcd2b9), [`cb95f72c24`](https://github.com/LedgerHQ/ledger-live/commit/cb95f72c2415876ef88ca83fd2c4363a57669b92), [`be5f56b233`](https://github.com/LedgerHQ/ledger-live/commit/be5f56b2330c166323914b79fef37a3c05e0e13a), [`092cb8d317`](https://github.com/LedgerHQ/ledger-live/commit/092cb8d317fa7971e0f790b77f900ae3864d96c2), [`5af41b6fa1`](https://github.com/LedgerHQ/ledger-live/commit/5af41b6fa1e43037ccdb2df279c82e12ef3d2b1a), [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc)]: + - @ledgerhq/domain-service@1.1.5 + - @ledgerhq/types-live@6.36.0 + - @ledgerhq/cryptoassets@9.9.0 + - @ledgerhq/types-cryptoassets@7.3.0 + - @ledgerhq/live-env@0.3.1 + - @ledgerhq/hw-app-eth@6.33.7 + - @ledgerhq/coin-framework@0.3.7 + - @ledgerhq/live-network@1.1.2 + +## 0.3.0-next.1 + +### Patch Changes + +- [#3872](https://github.com/LedgerHQ/ledger-live/pull/3872) [`d1d1578ab5`](https://github.com/LedgerHQ/ledger-live/commit/d1d1578ab5b351544c98d56b67c68f18640f2d20) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Rename rpc file that prevented shims to be applied for React Native + +## 0.3.0-next.0 + +### Minor Changes + +- [#3611](https://github.com/LedgerHQ/ledger-live/pull/3611) [`092cb8d317`](https://github.com/LedgerHQ/ledger-live/commit/092cb8d317fa7971e0f790b77f900ae3864d96c2) Thanks [@chabroA](https://github.com/chabroA)! - Create GasTracker abstraction for evm familly + +### Patch Changes + +- [#3741](https://github.com/LedgerHQ/ledger-live/pull/3741) [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update eip55 dependency + +- [#3741](https://github.com/LedgerHQ/ledger-live/pull/3741) [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Update eip55 dependency to 2.1.1 fixing browser context usage + +- Updated dependencies [[`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc), [`44192f2ab2`](https://github.com/LedgerHQ/ledger-live/commit/44192f2ab2857cbae2ef4a81ee9608d395dcd2b9), [`cb95f72c24`](https://github.com/LedgerHQ/ledger-live/commit/cb95f72c2415876ef88ca83fd2c4363a57669b92), [`be5f56b233`](https://github.com/LedgerHQ/ledger-live/commit/be5f56b2330c166323914b79fef37a3c05e0e13a), [`092cb8d317`](https://github.com/LedgerHQ/ledger-live/commit/092cb8d317fa7971e0f790b77f900ae3864d96c2), [`5af41b6fa1`](https://github.com/LedgerHQ/ledger-live/commit/5af41b6fa1e43037ccdb2df279c82e12ef3d2b1a), [`6194db3178`](https://github.com/LedgerHQ/ledger-live/commit/6194db3178cf90b26f4f6c7f049b7eafafdf7bfc)]: + - @ledgerhq/domain-service@1.1.5-next.0 + - @ledgerhq/types-live@6.36.0-next.0 + - @ledgerhq/cryptoassets@9.9.0-next.0 + - @ledgerhq/types-cryptoassets@7.3.0-next.0 + - @ledgerhq/live-env@0.3.1-next.0 + - @ledgerhq/hw-app-eth@6.33.7-next.0 + - @ledgerhq/coin-framework@0.3.7-next.0 + - @ledgerhq/live-network@1.1.2-next.0 + +## 0.2.1 + +### Patch Changes + +- Updated dependencies [[`9adc1862dd`](https://github.com/LedgerHQ/ledger-live/commit/9adc1862dda605a722d19f3b6895bd324834c914), [`4a1454beb3`](https://github.com/LedgerHQ/ledger-live/commit/4a1454beb3f86405ba2686e07879c12a7d35ad8e), [`809065c571`](https://github.com/LedgerHQ/ledger-live/commit/809065c57198646a49adea112b9d799e35a57d25), [`d1aa522db7`](https://github.com/LedgerHQ/ledger-live/commit/d1aa522db75f7ea850efe412abaa4dc7d37af6b7), [`ebe5b07afe`](https://github.com/LedgerHQ/ledger-live/commit/ebe5b07afec441ea3e2d9103da9e1175972add47)]: + - @ledgerhq/errors@6.12.7 + - @ledgerhq/cryptoassets@9.8.0 + - @ledgerhq/types-cryptoassets@7.2.1 + - @ledgerhq/types-live@6.35.1 + - @ledgerhq/coin-framework@0.3.6 + - @ledgerhq/domain-service@1.1.4 + - @ledgerhq/devices@8.0.4 + - @ledgerhq/hw-app-eth@6.33.6 + - @ledgerhq/live-network@1.1.1 + - @ledgerhq/live-portfolio@0.0.8 + +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies [[`9adc1862dd`](https://github.com/LedgerHQ/ledger-live/commit/9adc1862dda605a722d19f3b6895bd324834c914), [`4a1454beb3`](https://github.com/LedgerHQ/ledger-live/commit/4a1454beb3f86405ba2686e07879c12a7d35ad8e), [`809065c571`](https://github.com/LedgerHQ/ledger-live/commit/809065c57198646a49adea112b9d799e35a57d25), [`d1aa522db7`](https://github.com/LedgerHQ/ledger-live/commit/d1aa522db75f7ea850efe412abaa4dc7d37af6b7), [`ebe5b07afe`](https://github.com/LedgerHQ/ledger-live/commit/ebe5b07afec441ea3e2d9103da9e1175972add47)]: + - @ledgerhq/errors@6.12.7-next.0 + - @ledgerhq/cryptoassets@9.8.0-next.0 + - @ledgerhq/types-cryptoassets@7.2.1-next.0 + - @ledgerhq/types-live@6.35.1-next.0 + - @ledgerhq/coin-framework@0.3.6-next.0 + - @ledgerhq/domain-service@1.1.4-next.0 + - @ledgerhq/devices@8.0.4-next.0 + - @ledgerhq/hw-app-eth@6.33.6-next.0 + - @ledgerhq/live-network@1.1.1-next.0 + - @ledgerhq/live-portfolio@0.0.8-next.0 + +## 0.2.0 + +### Minor Changes + +- [#3536](https://github.com/LedgerHQ/ledger-live/pull/3536) [`a380bfc53a`](https://github.com/LedgerHQ/ledger-live/commit/a380bfc53a25bf196031337cd7ab8bc459731e16) Thanks [@chabroA](https://github.com/chabroA)! - Move evm familly logic in own package + +### Patch Changes + +- Updated dependencies [[`5cce6e3593`](https://github.com/LedgerHQ/ledger-live/commit/5cce6e359309110df53e16ef989c5b8b94492dfd), [`30bf4d92c7`](https://github.com/LedgerHQ/ledger-live/commit/30bf4d92c7d79cb81b1e4ad014857459739c33be), [`b30ead9d22`](https://github.com/LedgerHQ/ledger-live/commit/b30ead9d22a4bce5f8ee27febf0190fccd2ca25b), [`ce675302c7`](https://github.com/LedgerHQ/ledger-live/commit/ce675302c78311571e1087cfa35ee67580263796), [`43cdd2624c`](https://github.com/LedgerHQ/ledger-live/commit/43cdd2624cd2965ddb6e346e9a77a3cc12476500)]: + - @ledgerhq/cryptoassets@9.7.0 + - @ledgerhq/live-network@1.1.0 + - @ledgerhq/types-live@6.35.0 + - @ledgerhq/coin-framework@0.3.5 + - @ledgerhq/domain-service@1.1.3 + - @ledgerhq/hw-app-eth@6.33.5 + - @ledgerhq/live-portfolio@0.0.7 + +## 0.2.0-next.1 + +### Patch Changes + +- Updated dependencies [[`30bf4d92c7`](https://github.com/LedgerHQ/ledger-live/commit/30bf4d92c7d79cb81b1e4ad014857459739c33be)]: + - @ledgerhq/cryptoassets@9.7.0-next.1 + - @ledgerhq/coin-framework@0.3.5-next.1 + - @ledgerhq/domain-service@1.1.3-next.1 + - @ledgerhq/hw-app-eth@6.33.5-next.1 + +## 0.2.0-next.0 + +### Minor Changes + +- [#3536](https://github.com/LedgerHQ/ledger-live/pull/3536) [`a380bfc53a`](https://github.com/LedgerHQ/ledger-live/commit/a380bfc53a25bf196031337cd7ab8bc459731e16) Thanks [@chabroA](https://github.com/chabroA)! - Move evm familly logic in own package + +### Patch Changes + +- Updated dependencies [[`5cce6e3593`](https://github.com/LedgerHQ/ledger-live/commit/5cce6e359309110df53e16ef989c5b8b94492dfd), [`b30ead9d22`](https://github.com/LedgerHQ/ledger-live/commit/b30ead9d22a4bce5f8ee27febf0190fccd2ca25b), [`7439b63325`](https://github.com/LedgerHQ/ledger-live/commit/7439b63325a9b0181a3af4310ba787f00faa80c9), [`ce675302c7`](https://github.com/LedgerHQ/ledger-live/commit/ce675302c78311571e1087cfa35ee67580263796), [`43cdd2624c`](https://github.com/LedgerHQ/ledger-live/commit/43cdd2624cd2965ddb6e346e9a77a3cc12476500)]: + - @ledgerhq/cryptoassets@9.7.0-next.0 + - @ledgerhq/live-network@1.1.0-next.0 + - @ledgerhq/types-live@6.35.0-next.0 + - @ledgerhq/coin-framework@0.3.5-next.0 + - @ledgerhq/domain-service@1.1.3-next.0 + - @ledgerhq/hw-app-eth@6.33.5-next.0 + - @ledgerhq/live-portfolio@0.0.7-next.0 diff --git a/libs/coin-modules/coin-vechain/jest.config.js b/libs/coin-modules/coin-vechain/jest.config.js new file mode 100644 index 000000000000..256cf95233c1 --- /dev/null +++ b/libs/coin-modules/coin-vechain/jest.config.js @@ -0,0 +1,8 @@ +/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ +module.exports = { + collectCoverageFrom: ["src/**/*.ts"], + coverageDirectory: "coverage", + preset: "ts-jest", + testEnvironment: "node", + testPathIgnorePatterns: ["lib/", "lib-es/"], +}; diff --git a/libs/coin-modules/coin-vechain/package.json b/libs/coin-modules/coin-vechain/package.json new file mode 100644 index 000000000000..ed4cd459faec --- /dev/null +++ b/libs/coin-modules/coin-vechain/package.json @@ -0,0 +1,120 @@ +{ + "name": "@ledgerhq/coin-vechain", + "version": "2.1.3", + "description": "Ledger VeChain Coin integration", + "keywords": [ + "Ledger", + "LedgerWallet", + "VeChain", + "vet", + "vtho", + "Hardware Wallet" + ], + "repository": { + "type": "git", + "url": "https://github.com/LedgerHQ/ledger-live.git" + }, + "bugs": { + "url": "https://github.com/LedgerHQ/ledger-live/issues" + }, + "homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/coin-modules/coin-vechain", + "publishConfig": { + "access": "public" + }, + "typesVersions": { + "*": { + "lib/*": [ + "lib/*" + ], + "lib-es/*": [ + "lib-es/*" + ], + "specs": [ + "lib/test/bot-specs" + ], + "transaction": [ + "lib/bridge/transaction" + ], + "*": [ + "lib/*" + ] + } + }, + "exports": { + "./lib/*": "./lib/*.js", + "./lib-es/*": "./lib-es/*.js", + "./logic": { + "require": "./lib/common-logic/index.js", + "default": "./lib-es/common-logic/index.js" + }, + "./network": { + "require": "./lib/network/index.js", + "default": "./lib-es/network/index.js" + }, + "./signer": { + "require": "./lib/signer/index.js", + "default": "./lib-es/signer/index.js" + }, + "./specs": { + "require": "./lib/test/bot-specs.js", + "default": "./lib-es/test/bot-specs.js" + }, + "./transaction": { + "require": "./lib/bridge/transaction.js", + "default": "./lib-es/bridge/transaction.js" + }, + "./types": { + "require": "./lib/types/index.js", + "default": "./lib-es/types/index.js" + }, + "./*": { + "require": "./lib/*.js", + "default": "./lib-es/*.js" + }, + ".": { + "require": "./lib/index.js", + "default": "./lib-es/index.js" + }, + "./package.json": "./package.json" + }, + "license": "Apache-2.0", + "scripts": { + "clean": "rimraf lib lib-es", + "build": "tsc && tsc -m ES6 --outDir lib-es", + "coverage": "jest --coverage --testPathIgnorePatterns='/bridge.integration.test.ts|node_modules|lib-es|lib/' --passWithNoTests && mv coverage/coverage-final.json coverage/coverage-vechain.json", + "prewatch": "pnpm build", + "watch": "tsc --watch", + "doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts", + "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache", + "lint:fix": "pnpm lint --fix", + "typecheck": "tsc --noEmit", + "test": "jest --passWithNoTests", + "test-integ": "DOTENV_CONFIG_PATH=.env.integ.test jest --config=jest.integ.config.js", + "unimported": "unimported" + }, + "dependencies": { + "@ledgerhq/coin-framework": "workspace:^", + "@ledgerhq/cryptoassets": "workspace:^", + "@ledgerhq/devices": "workspace:^", + "@ledgerhq/errors": "workspace:^", + "@ledgerhq/live-env": "workspace:^", + "@ledgerhq/live-network": "workspace:^", + "bignumber.js": "^9.1.2", + "eip55": "^2.1.1", + "invariant": "^2.2.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "thor-devkit": "^2.0.6" + }, + "devDependencies": { + "@ledgerhq/coin-tester": "workspace:^", + "@ledgerhq/types-cryptoassets": "workspace:^", + "@ledgerhq/types-live": "workspace:^", + "@types/invariant": "^2.2.2", + "@types/jest": "^29.5.10", + "@types/lodash": "^4.14.191", + "dotenv": "^16.4.5", + "jest": "^29.7.0", + "ts-jest": "^29.1.1" + } +} diff --git a/libs/coin-modules/coin-vechain/src/__snapshots__/bridge.integration.test.ts.snap b/libs/coin-modules/coin-vechain/src/__snapshots__/bridge.integration.test.ts.snap new file mode 100644 index 000000000000..0c0bbaa55115 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/__snapshots__/bridge.integration.test.ts.snap @@ -0,0 +1,146 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`vechain currency bridge scanAccounts vechain seed 1 1`] = ` +[ + { + "currencyId": "vechain", + "derivationMode": "vechain", + "feesCurrencyId": "vechain/vip180/vtho", + "freshAddress": "0x0fe6688548f0C303932bB197B0A96034f1d74dba", + "freshAddressPath": "44'/818'/0'/0/0", + "id": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain", + "index": 0, + "operationsCount": 1, + "pendingOperations": [], + "seedIdentifier": "04de5a8f11cc426ff5617aeffd397c5dd77b58424662f368f2cd539a8c42fd2e7d0c6245c9c3a4306f70d7f292e95642651a6832d66fd9823fa6a0af575113e94e", + "subAccounts": [], + "swapHistory": [], + "syncHash": undefined, + "used": true, + }, + { + "id": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", + "operationsCount": 1, + "parentId": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain", + "pendingOperations": [], + "swapHistory": [], + "tokenId": "vechain/vip180/vtho", + "type": "TokenAccountRaw", + }, + { + "currencyId": "vechain", + "derivationMode": "vechain", + "feesCurrencyId": "vechain/vip180/vtho", + "freshAddress": "0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86", + "freshAddressPath": "44'/818'/0'/0/1", + "id": "js:2:vechain:0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86:vechain", + "index": 1, + "operationsCount": 1, + "pendingOperations": [], + "seedIdentifier": "04de5a8f11cc426ff5617aeffd397c5dd77b58424662f368f2cd539a8c42fd2e7d0c6245c9c3a4306f70d7f292e95642651a6832d66fd9823fa6a0af575113e94e", + "subAccounts": [], + "swapHistory": [], + "syncHash": undefined, + "used": true, + }, + { + "id": "js:2:vechain:0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86:vechain+vechain%2Fvip180%2Fvtho", + "operationsCount": 0, + "parentId": "js:2:vechain:0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86:vechain", + "pendingOperations": [], + "swapHistory": [], + "tokenId": "vechain/vip180/vtho", + "type": "TokenAccountRaw", + }, + { + "currencyId": "vechain", + "derivationMode": "vechain", + "feesCurrencyId": "vechain/vip180/vtho", + "freshAddress": "0xFbC8653C0b842dd33361CE8938B24e407dd4838C", + "freshAddressPath": "44'/818'/0'/0/2", + "id": "js:2:vechain:0xFbC8653C0b842dd33361CE8938B24e407dd4838C:vechain", + "index": 2, + "operationsCount": 0, + "pendingOperations": [], + "seedIdentifier": "04de5a8f11cc426ff5617aeffd397c5dd77b58424662f368f2cd539a8c42fd2e7d0c6245c9c3a4306f70d7f292e95642651a6832d66fd9823fa6a0af575113e94e", + "subAccounts": [], + "swapHistory": [], + "syncHash": undefined, + "used": false, + }, + { + "id": "js:2:vechain:0xFbC8653C0b842dd33361CE8938B24e407dd4838C:vechain+vechain%2Fvip180%2Fvtho", + "operationsCount": 0, + "parentId": "js:2:vechain:0xFbC8653C0b842dd33361CE8938B24e407dd4838C:vechain", + "pendingOperations": [], + "swapHistory": [], + "tokenId": "vechain/vip180/vtho", + "type": "TokenAccountRaw", + }, +] +`; + +exports[`vechain currency bridge scanAccounts vechain seed 1 2`] = ` +[ + [ + { + "accountId": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain", + "blockHash": "0x00fa5b35f158cee280b6be35b4ada7669951035a79806244aaa11e5d2764d5bd", + "blockHeight": 16407349, + "extra": {}, + "fee": "210000000000000000", + "hash": "0xe113f82af98a24c6f2473802f8673f0d69eed1c0f51a5a87d3cc6b8cf96ccfd6", + "id": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain-0xe113f82af98a24c6f2473802f8673f0d69eed1c0f51a5a87d3cc6b8cf96ccfd6-IN", + "recipients": [ + "0x0fe6688548f0c303932bb197b0a96034f1d74dba", + ], + "senders": [ + "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + ], + "type": "IN", + "value": "10000000000000000000", + }, + ], + [ + { + "accountId": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", + "blockHash": "0x00fa5b4ee2eca5cf65907e3695bbea044cd1f78224534dc0ba02526890055ecc", + "blockHeight": 16407374, + "extra": {}, + "fee": "365180000000000000", + "hash": "0x5fdd7191c4d476a8e86060d516366e87421f65667b9b3c14c33a740c04921b10", + "id": "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho-0x5fdd7191c4d476a8e86060d516366e87421f65667b9b3c14c33a740c04921b10-IN", + "recipients": [ + "0x0fe6688548f0c303932bb197b0a96034f1d74dba", + ], + "senders": [ + "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + ], + "type": "IN", + "value": "10000000000000000000", + }, + ], + [ + { + "accountId": "js:2:vechain:0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86:vechain", + "blockHash": "0x00fa5b547b0d542ba8e62a85aa99cf355f1b2a70bd34e3949f889b0856776e05", + "blockHeight": 16407380, + "extra": {}, + "fee": "210000000000000000", + "hash": "0xa4096186f2d58ecc68e6ea11c9757ef5bd78b21b87d73b4618eb6fd3508431ec", + "id": "js:2:vechain:0x02961B92B8D20A4ea12f1f1CeFA74Dd7B4355A86:vechain-0xa4096186f2d58ecc68e6ea11c9757ef5bd78b21b87d73b4618eb6fd3508431ec-IN", + "recipients": [ + "0x02961b92b8d20a4ea12f1f1cefa74dd7b4355a86", + ], + "senders": [ + "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + ], + "type": "IN", + "value": "10000000000000000000", + }, + ], + [], + [], + [], +] +`; diff --git a/libs/ledger-live-common/src/families/vechain/account.ts b/libs/coin-modules/coin-vechain/src/account.ts similarity index 73% rename from libs/ledger-live-common/src/families/vechain/account.ts rename to libs/coin-modules/coin-vechain/src/account.ts index 6ce5b5dbc58e..87fa54e88f98 100644 --- a/libs/ledger-live-common/src/families/vechain/account.ts +++ b/libs/coin-modules/coin-vechain/src/account.ts @@ -1,6 +1,6 @@ +import { getAccountCurrency } from "@ledgerhq/coin-framework/account/index"; +import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/index"; import type { Account } from "@ledgerhq/types-live"; -import { getAccountCurrency } from "../../account"; -import { formatCurrencyUnit } from "../../currencies"; function formatAccountSpecifics(account: Account): string { const unit = getAccountCurrency(account).units[0]; diff --git a/libs/ledger-live-common/src/families/vechain/broadcast.ts b/libs/coin-modules/coin-vechain/src/bridge/broadcast.ts similarity index 79% rename from libs/ledger-live-common/src/families/vechain/broadcast.ts rename to libs/coin-modules/coin-vechain/src/bridge/broadcast.ts index 708d2fa95615..3909ff4863e6 100644 --- a/libs/ledger-live-common/src/families/vechain/broadcast.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/broadcast.ts @@ -1,8 +1,9 @@ import { Transaction as VeChainThorTransaction } from "thor-devkit"; import type { AccountBridge } from "@ledgerhq/types-live"; -import { patchOperationWithHash } from "../../operation"; -import { Transaction } from "./types"; -import { submit } from "./api"; +import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation"; + +import { Transaction } from "../types"; +import { submit } from "../network"; /** * Broadcast the signed transaction diff --git a/libs/ledger-live-common/src/families/vechain/buildOptimisticOperatioin.ts b/libs/coin-modules/coin-vechain/src/bridge/buildOptimisticOperatioin.ts similarity index 92% rename from libs/ledger-live-common/src/families/vechain/buildOptimisticOperatioin.ts rename to libs/coin-modules/coin-vechain/src/bridge/buildOptimisticOperatioin.ts index f14b6d6476e6..44ba5fcfd68d 100644 --- a/libs/ledger-live-common/src/families/vechain/buildOptimisticOperatioin.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/buildOptimisticOperatioin.ts @@ -1,7 +1,7 @@ -import { Account, Operation } from "@ledgerhq/types-live"; -import { Transaction } from "./types"; -import { encodeOperationId } from "../../operation"; import BigNumber from "bignumber.js"; +import { Account, Operation } from "@ledgerhq/types-live"; +import { Transaction } from "../types"; +import { encodeOperationId } from "@ledgerhq/coin-framework/operation"; export const buildOptimisticOperation = async ( account: Account, diff --git a/libs/ledger-live-common/src/families/vechain/createTransaction.ts b/libs/coin-modules/coin-vechain/src/bridge/createTransaction.ts similarity index 79% rename from libs/ledger-live-common/src/families/vechain/createTransaction.ts rename to libs/coin-modules/coin-vechain/src/bridge/createTransaction.ts index 785a096fa017..898aedb8c958 100644 --- a/libs/ledger-live-common/src/families/vechain/createTransaction.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/createTransaction.ts @@ -1,8 +1,7 @@ import BigNumber from "bignumber.js"; import { AccountBridge } from "@ledgerhq/types-live"; -import { DEFAULT_GAS_COEFFICIENT, MAINNET_CHAIN_TAG } from "./constants"; -import { generateNonce } from "./utils/transaction-utils"; -import { Transaction } from "./types"; +import { generateNonce } from "../common-logic"; +import { Transaction, DEFAULT_GAS_COEFFICIENT, MAINNET_CHAIN_TAG } from "../types"; /** * Create an empty VET or VTHO transaction diff --git a/libs/ledger-live-common/src/families/vechain/estimateMaxSpendable.ts b/libs/coin-modules/coin-vechain/src/bridge/estimateMaxSpendable.ts similarity index 84% rename from libs/ledger-live-common/src/families/vechain/estimateMaxSpendable.ts rename to libs/coin-modules/coin-vechain/src/bridge/estimateMaxSpendable.ts index bf6eb66d9b14..afe3c5cd7c30 100644 --- a/libs/ledger-live-common/src/families/vechain/estimateMaxSpendable.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/estimateMaxSpendable.ts @@ -1,7 +1,7 @@ import BigNumber from "bignumber.js"; import { AccountBridge } from "@ledgerhq/types-live"; -import { calculateGasFees } from "./utils/transaction-utils"; -import type { Transaction } from "./types"; +import { calculateGasFees } from "../common-logic"; +import type { Transaction } from "../types"; export const estimateMaxSpendable: AccountBridge["estimateMaxSpendable"] = async ({ account, diff --git a/libs/ledger-live-common/src/families/vechain/getTransactionStatus.ts b/libs/coin-modules/coin-vechain/src/bridge/getTransactionStatus.ts similarity index 90% rename from libs/ledger-live-common/src/families/vechain/getTransactionStatus.ts rename to libs/coin-modules/coin-vechain/src/bridge/getTransactionStatus.ts index 0b3f20280f13..f77f8969ad66 100644 --- a/libs/ledger-live-common/src/families/vechain/getTransactionStatus.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/getTransactionStatus.ts @@ -1,3 +1,4 @@ +import BigNumber from "bignumber.js"; import { AmountRequired, FeeNotLoaded, @@ -6,12 +7,10 @@ import { NotEnoughBalance, RecipientRequired, } from "@ledgerhq/errors"; -import BigNumber from "bignumber.js"; import { AccountBridge } from "@ledgerhq/types-live"; -import { calculateTransactionInfo } from "./utils/transaction-utils"; -import { isValid } from "./utils/address-utils"; -import type { Transaction } from "./types"; -import { NotEnoughVTHO } from "./errors"; +import { calculateTransactionInfo, isValid } from "../common-logic"; +import type { Transaction } from "../types"; +import { NotEnoughVTHO } from "../errors"; export const getTransactionStatus: AccountBridge["getTransactionStatus"] = async ( account, diff --git a/libs/coin-modules/coin-vechain/src/bridge/index.ts b/libs/coin-modules/coin-vechain/src/bridge/index.ts new file mode 100644 index 000000000000..cc8a581daa36 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/bridge/index.ts @@ -0,0 +1,63 @@ +import { AccountBridge, CurrencyBridge } from "@ledgerhq/types-live"; +import { + defaultUpdateTransaction, + makeAccountBridgeReceive, + makeScanAccounts, + makeSync, +} from "@ledgerhq/coin-framework/bridge/jsHelpers"; +import { SignerContext } from "@ledgerhq/coin-framework/signer"; +import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper"; +import { getTransactionStatus } from "./getTransactionStatus"; +import { estimateMaxSpendable } from "./estimateMaxSpendable"; +import { prepareTransaction } from "./prepareTransaction"; +import { createTransaction } from "./createTransaction"; +import { getAccountShape } from "./synchronisation"; +import { buildSignOperation } from "./signOperation"; +import { broadcast } from "./broadcast"; +import resolver from "../signer"; +import type { Transaction, VechainSigner } from "../types"; + +export function buildCurrencyBridge(signerContext: SignerContext): CurrencyBridge { + const getAddress = resolver(signerContext); + + const scanAccounts = makeScanAccounts({ + getAccountShape, + getAddressFn: getAddressWrapper(getAddress), + }); + + return { + preload: async () => Promise.resolve({}), + hydrate: () => {}, + scanAccounts, + }; +} + +const sync = makeSync({ getAccountShape }); + +export function buildAccountBridge( + signerContext: SignerContext, +): AccountBridge { + const getAddress = resolver(signerContext); + + const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress)); + const signOperation = buildSignOperation(signerContext); + + return { + estimateMaxSpendable, + createTransaction, + updateTransaction: defaultUpdateTransaction, + getTransactionStatus, + prepareTransaction, + sync, + receive, + signOperation, + broadcast, + }; +} + +export function createBridges(signerContext: SignerContext) { + return { + currencyBridge: buildCurrencyBridge(signerContext), + accountBridge: buildAccountBridge(signerContext), + }; +} diff --git a/libs/ledger-live-common/src/families/vechain/prepareTransaction.ts b/libs/coin-modules/coin-vechain/src/bridge/prepareTransaction.ts similarity index 79% rename from libs/ledger-live-common/src/families/vechain/prepareTransaction.ts rename to libs/coin-modules/coin-vechain/src/bridge/prepareTransaction.ts index 3458dc32002a..31600ec0104b 100644 --- a/libs/ledger-live-common/src/families/vechain/prepareTransaction.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/prepareTransaction.ts @@ -1,10 +1,13 @@ import { Account } from "@ledgerhq/types-live"; import { Transaction as VeChainThorTransaction } from "thor-devkit"; -import { calculateTransactionInfo } from "./utils/transaction-utils"; -import { isValid } from "./utils/address-utils"; -import { Transaction } from "./types"; -import { getBlockRef } from "./api"; -import { calculateClausesVet, calculateClausesVtho } from "./logic"; +import { + calculateTransactionInfo, + isValid, + calculateClausesVet, + calculateClausesVtho, +} from "../common-logic"; +import { Transaction } from "../types"; +import { getBlockRef } from "../network"; /** * Prepare transaction before checking status diff --git a/libs/coin-modules/coin-vechain/src/bridge/signOperation.ts b/libs/coin-modules/coin-vechain/src/bridge/signOperation.ts new file mode 100644 index 000000000000..9c1d68adf308 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/bridge/signOperation.ts @@ -0,0 +1,53 @@ +import { Observable } from "rxjs"; +import { Transaction as ThorTransaction } from "thor-devkit"; +import type { Account, AccountBridge, DeviceId, SignOperationEvent } from "@ledgerhq/types-live"; +import { SignerContext } from "@ledgerhq/coin-framework/signer"; +import { buildOptimisticOperation } from "./buildOptimisticOperatioin"; +import type { Transaction, VechainSigner } from "../types"; + +/** + * Sign Transaction with Ledger hardware + */ +export const buildSignOperation = + (signerContext: SignerContext): AccountBridge["signOperation"] => + ({ + account, + transaction, + deviceId, + }: { + account: Account; + transaction: Transaction; + deviceId: DeviceId; + }): Observable => + new Observable(o => { + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + async function main() { + const unsigned = new ThorTransaction(transaction.body); + + o.next({ + type: "device-signature-requested", + }); + + const signature = await signerContext(deviceId, signer => + signer.signTransaction(account.freshAddressPath, unsigned.encode().toString("hex")), + ); + + o.next({ type: "device-signature-granted" }); + + const operation = await buildOptimisticOperation(account, transaction); + + o.next({ + type: "signed", + signedOperation: { + operation, + signature: signature.toString("hex"), + rawData: transaction, + }, + }); + } + + main().then( + () => o.complete(), + e => o.error(e), + ); + }); diff --git a/libs/ledger-live-common/src/families/vechain/synchronisation.ts b/libs/coin-modules/coin-vechain/src/bridge/synchronisation.ts similarity index 87% rename from libs/ledger-live-common/src/families/vechain/synchronisation.ts rename to libs/coin-modules/coin-vechain/src/bridge/synchronisation.ts index e5a4f052e313..75602ec77e60 100644 --- a/libs/ledger-live-common/src/families/vechain/synchronisation.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/synchronisation.ts @@ -1,6 +1,5 @@ -import type { GetAccountShape } from "../../bridge/jsHelpers"; import { BigNumber } from "bignumber.js"; -import { makeSync, makeScanAccounts, mergeOps } from "../../bridge/jsHelpers"; + import eip55 from "eip55"; import { emptyHistoryCache, @@ -8,11 +7,13 @@ import { encodeTokenAccountId, } from "@ledgerhq/coin-framework/account/index"; -import { getAccount, getLastBlockHeight, getOperations, getTokenOperations } from "./api"; +import { getAccount, getLastBlockHeight, getOperations, getTokenOperations } from "../network"; import { findTokenById, getTokenById } from "@ledgerhq/cryptoassets/tokens"; -import { VTHO_ADDRESS } from "./contracts/constants"; +import { VTHO_ADDRESS } from "../contracts/constants"; +import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers"; +import { Account } from "@ledgerhq/types-live"; -const getAccountShape: GetAccountShape = async info => { +export const getAccountShape: GetAccountShape = async info => { const { initialAccount, currency, derivationMode } = info; const address = eip55.encode(info.address); @@ -83,6 +84,3 @@ const getAccountShape: GetAccountShape = async info => { return shape; }; - -export const scanAccounts = makeScanAccounts({ getAccountShape }); -export const sync = makeSync({ getAccountShape }); diff --git a/libs/ledger-live-common/src/families/vechain/transaction.ts b/libs/coin-modules/coin-vechain/src/bridge/transaction.ts similarity index 86% rename from libs/ledger-live-common/src/families/vechain/transaction.ts rename to libs/coin-modules/coin-vechain/src/bridge/transaction.ts index 834fa18c142b..d99e6b842e8a 100644 --- a/libs/ledger-live-common/src/families/vechain/transaction.ts +++ b/libs/coin-modules/coin-vechain/src/bridge/transaction.ts @@ -1,5 +1,12 @@ -import type { Transaction, TransactionRaw, TransactionStatus, TransactionStatusRaw } from "./types"; +import { getAccountCurrency } from "@ledgerhq/coin-framework/account/index"; +import type { + Transaction, + TransactionRaw, + TransactionStatus, + TransactionStatusRaw, +} from "../types"; import { formatTransactionStatus } from "@ledgerhq/coin-framework/formatters"; +import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/index"; import { fromTransactionCommonRaw, fromTransactionStatusRawCommon, @@ -7,8 +14,6 @@ import { toTransactionStatusRawCommon, } from "@ledgerhq/coin-framework/serialization"; import type { Account } from "@ledgerhq/types-live"; -import { getAccountCurrency } from "../../account"; -import { formatCurrencyUnit } from "../../currencies"; export const formatTransaction = (t: Transaction, account: Account): string => { const { amount, recipient, useAllAmount } = t; diff --git a/libs/ledger-live-common/src/families/vechain/utils/address-utils.ts b/libs/coin-modules/coin-vechain/src/common-logic/address-utils.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/utils/address-utils.ts rename to libs/coin-modules/coin-vechain/src/common-logic/address-utils.ts diff --git a/libs/ledger-live-common/src/families/vechain/utils/hex-utils.ts b/libs/coin-modules/coin-vechain/src/common-logic/hex-utils.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/utils/hex-utils.ts rename to libs/coin-modules/coin-vechain/src/common-logic/hex-utils.ts diff --git a/libs/coin-modules/coin-vechain/src/common-logic/index.ts b/libs/coin-modules/coin-vechain/src/common-logic/index.ts new file mode 100644 index 000000000000..72d4939ff517 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/common-logic/index.ts @@ -0,0 +1,6 @@ +export * from "./address-utils"; +export * from "./hex-utils"; +export * from "./logic"; +export * from "./mapping-utils"; +export * from "./pad-address"; +export * from "./transaction-utils"; diff --git a/libs/ledger-live-common/src/families/vechain/logic.ts b/libs/coin-modules/coin-vechain/src/common-logic/logic.ts similarity index 88% rename from libs/ledger-live-common/src/families/vechain/logic.ts rename to libs/coin-modules/coin-vechain/src/common-logic/logic.ts index 4326ca2972d5..36f63c10a882 100644 --- a/libs/ledger-live-common/src/families/vechain/logic.ts +++ b/libs/coin-modules/coin-vechain/src/common-logic/logic.ts @@ -1,8 +1,8 @@ import BigNumber from "bignumber.js"; import { Transaction as VeChainThorTransaction } from "thor-devkit"; -import { VTHO_ADDRESS } from "./contracts/constants"; -import VIP180 from "./contracts/abis/VIP180"; -import { HEX_PREFIX } from "./constants"; +import { VTHO_ADDRESS } from "../contracts/constants"; +import VIP180 from "../contracts/abis/VIP180"; +import { HEX_PREFIX } from "../types"; export const calculateClausesVtho = async ( recipient: string, diff --git a/libs/ledger-live-common/src/families/vechain/utils/mapping-utils.ts b/libs/coin-modules/coin-vechain/src/common-logic/mapping-utils.ts similarity index 95% rename from libs/ledger-live-common/src/families/vechain/utils/mapping-utils.ts rename to libs/coin-modules/coin-vechain/src/common-logic/mapping-utils.ts index 70a242922ce8..5fcd78dcffd4 100644 --- a/libs/ledger-live-common/src/families/vechain/utils/mapping-utils.ts +++ b/libs/coin-modules/coin-vechain/src/common-logic/mapping-utils.ts @@ -1,9 +1,9 @@ +import BigNumber from "bignumber.js"; import vip180 from "../contracts/abis/VIP180"; import { Operation } from "@ledgerhq/types-live"; -import BigNumber from "bignumber.js"; -import { EventLog, TransferLog } from "../api/types"; +import { EventLog, TransferLog } from "../types"; import { encodeOperationId } from "@ledgerhq/coin-framework/operation"; -import { getFees } from "../api"; +import { getFees } from "../network"; export const mapVetTransfersToOperations = async ( txs: TransferLog[], diff --git a/libs/ledger-live-common/src/families/vechain/utils/pad-address.ts b/libs/coin-modules/coin-vechain/src/common-logic/pad-address.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/utils/pad-address.ts rename to libs/coin-modules/coin-vechain/src/common-logic/pad-address.ts diff --git a/libs/ledger-live-common/src/families/vechain/utils/transaction-utils.ts b/libs/coin-modules/coin-vechain/src/common-logic/transaction-utils.ts similarity index 95% rename from libs/ledger-live-common/src/families/vechain/utils/transaction-utils.ts rename to libs/coin-modules/coin-vechain/src/common-logic/transaction-utils.ts index 4533d8c0bd5f..f44c49b4dc77 100644 --- a/libs/ledger-live-common/src/families/vechain/utils/transaction-utils.ts +++ b/libs/coin-modules/coin-vechain/src/common-logic/transaction-utils.ts @@ -1,15 +1,14 @@ -import { DEFAULT_GAS_COEFFICIENT, HEX_PREFIX } from "../constants"; -import crypto from "crypto"; import BigNumber from "bignumber.js"; +import { DEFAULT_GAS_COEFFICIENT, HEX_PREFIX } from "../types"; +import crypto from "crypto"; import { Transaction as ThorTransaction } from "thor-devkit"; import params from "../contracts/abis/params"; import { BASE_GAS_PRICE_KEY, PARAMS_ADDRESS } from "../contracts/constants"; -import { Query } from "../api/types"; -import { query } from "../api/sdk"; +import { query } from "../network"; import { Account, TokenAccount } from "@ledgerhq/types-live"; -import { Transaction, TransactionInfo } from "../types"; +import { Transaction, TransactionInfo, Query } from "../types"; import { isValid } from "./address-utils"; -import { calculateClausesVet, calculateClausesVtho } from "../logic"; +import { calculateClausesVet, calculateClausesVtho } from "./logic"; import { ImpossibleToCalculateAmountAndFees } from "../errors"; const GAS_COEFFICIENT = 15000; diff --git a/libs/coin-modules/coin-vechain/src/config.ts b/libs/coin-modules/coin-vechain/src/config.ts new file mode 100644 index 000000000000..3b975cf4245f --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/config.ts @@ -0,0 +1,18 @@ +import { CurrencyConfig, CoinConfig } from "@ledgerhq/coin-framework/config"; +import { MissingCoinConfig } from "@ledgerhq/coin-framework/errors"; + +export type VechainCoinConfig = () => CurrencyConfig; + +let coinConfig: CoinConfig | undefined; + +export function setCoinConfig(config: CoinConfig): void { + coinConfig = config; +} + +export function getCoinConfig(): CurrencyConfig { + if (!coinConfig) { + throw new MissingCoinConfig(); + } + + return coinConfig(); +} diff --git a/libs/ledger-live-common/src/families/vechain/contracts/abis/VIP180.ts b/libs/coin-modules/coin-vechain/src/contracts/abis/VIP180.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/contracts/abis/VIP180.ts rename to libs/coin-modules/coin-vechain/src/contracts/abis/VIP180.ts diff --git a/libs/ledger-live-common/src/families/vechain/contracts/abis/params.ts b/libs/coin-modules/coin-vechain/src/contracts/abis/params.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/contracts/abis/params.ts rename to libs/coin-modules/coin-vechain/src/contracts/abis/params.ts diff --git a/libs/ledger-live-common/src/families/vechain/contracts/constants.ts b/libs/coin-modules/coin-vechain/src/contracts/constants.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/contracts/constants.ts rename to libs/coin-modules/coin-vechain/src/contracts/constants.ts diff --git a/libs/coin-modules/coin-vechain/src/datasets/index.ts b/libs/coin-modules/coin-vechain/src/datasets/index.ts new file mode 100644 index 000000000000..e1f780299a02 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/datasets/index.ts @@ -0,0 +1,2 @@ +export * from "./vechain.scanAccounts.1"; +export { vechain1, vechain2, vechain3 } from "./vechain"; diff --git a/libs/ledger-live-common/src/families/vechain/datasets/vechain.scanAccounts.1.ts b/libs/coin-modules/coin-vechain/src/datasets/vechain.scanAccounts.1.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/datasets/vechain.scanAccounts.1.ts rename to libs/coin-modules/coin-vechain/src/datasets/vechain.scanAccounts.1.ts diff --git a/libs/ledger-live-common/src/families/vechain/datasets/vechain.ts b/libs/coin-modules/coin-vechain/src/datasets/vechain.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/datasets/vechain.ts rename to libs/coin-modules/coin-vechain/src/datasets/vechain.ts diff --git a/libs/ledger-live-common/src/families/vechain/errors.ts b/libs/coin-modules/coin-vechain/src/errors.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/errors.ts rename to libs/coin-modules/coin-vechain/src/errors.ts diff --git a/libs/coin-modules/coin-vechain/src/index.ts b/libs/coin-modules/coin-vechain/src/index.ts new file mode 100644 index 000000000000..b6952a1f1150 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/index.ts @@ -0,0 +1 @@ +export { createBridges } from "./bridge/index"; diff --git a/libs/ledger-live-common/src/families/vechain/mock.ts b/libs/coin-modules/coin-vechain/src/mock.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/mock.ts rename to libs/coin-modules/coin-vechain/src/mock.ts diff --git a/libs/ledger-live-common/src/families/vechain/api/index.ts b/libs/coin-modules/coin-vechain/src/network/index.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/api/index.ts rename to libs/coin-modules/coin-vechain/src/network/index.ts diff --git a/libs/ledger-live-common/src/families/vechain/api/sdk.ts b/libs/coin-modules/coin-vechain/src/network/sdk.ts similarity index 94% rename from libs/ledger-live-common/src/families/vechain/api/sdk.ts rename to libs/coin-modules/coin-vechain/src/network/sdk.ts index 046233433d01..617f16318bac 100644 --- a/libs/ledger-live-common/src/families/vechain/api/sdk.ts +++ b/libs/coin-modules/coin-vechain/src/network/sdk.ts @@ -1,13 +1,16 @@ +import BigNumber from "bignumber.js"; import network from "@ledgerhq/live-network/network"; -import { AccountResponse, VetTxsQuery, TokenTxsQuery, Query, QueryResponse } from "./types"; +import { AccountResponse, VetTxsQuery, TokenTxsQuery, Query, QueryResponse } from "../types"; import type { Operation } from "@ledgerhq/types-live"; -import { mapVetTransfersToOperations, mapTokenTransfersToOperations } from "../utils/mapping-utils"; -import { padAddress } from "../utils/pad-address"; +import { + mapVetTransfersToOperations, + mapTokenTransfersToOperations, + padAddress, +} from "../common-logic"; import { TransferEventSignature } from "../contracts/constants"; import { Transaction } from "thor-devkit"; -import { HEX_PREFIX } from "../constants"; +import { HEX_PREFIX } from "../types"; import { getEnv } from "@ledgerhq/live-env"; -import BigNumber from "bignumber.js"; const BASE_URL = getEnv("API_VECHAIN_THOREST"); diff --git a/libs/coin-modules/coin-vechain/src/signer/getAddress.ts b/libs/coin-modules/coin-vechain/src/signer/getAddress.ts new file mode 100644 index 000000000000..dfccaeff4858 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/signer/getAddress.ts @@ -0,0 +1,25 @@ +import { SignerContext } from "@ledgerhq/coin-framework/signer"; +import eip55 from "eip55"; +import { VechainSigner } from "../types"; +import { GetAddressFn } from "@ledgerhq/coin-framework/bridge/getAddressWrapper"; +import { GetAddressOptions } from "@ledgerhq/coin-framework/derivation"; + +const resolver = (signerContext: SignerContext): GetAddressFn => { + return async (deviceId: string, { path, verify }: GetAddressOptions) => { + const sig = await signerContext(deviceId, async signer => { + return await signer.getAddress(path, verify, false); // Note: Do we need to check askChainCode or false? + }); + + if (!sig.address || !sig.publicKey.length) + throw Error(`[vechain] Response is empty ${sig.address} ${sig.publicKey}`); + + const address = eip55.encode(sig.address); + return { + address, + publicKey: sig.publicKey, + path, + }; + }; +}; + +export default resolver; diff --git a/libs/coin-modules/coin-vechain/src/signer/index.ts b/libs/coin-modules/coin-vechain/src/signer/index.ts new file mode 100644 index 000000000000..dfe294ec89ba --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/signer/index.ts @@ -0,0 +1,4 @@ +import resolver from "./getAddress"; + +export * from "./signMessage"; +export default resolver; diff --git a/libs/coin-modules/coin-vechain/src/signer/signMessage.ts b/libs/coin-modules/coin-vechain/src/signer/signMessage.ts new file mode 100644 index 000000000000..cc2641f77080 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/signer/signMessage.ts @@ -0,0 +1,22 @@ +import { Transaction as ThorTransaction } from "thor-devkit"; +import { SignerContext } from "@ledgerhq/coin-framework/signer"; +import { VechainSigner } from "../types"; + +export const signMessage = + (signerContext: SignerContext) => + async (deviceId: string, path: string, message: string, rawMessage: string) => { + let messageObj; + let unsigned: ThorTransaction; + try { + if (message) messageObj = JSON.parse(message); + else messageObj = JSON.parse(rawMessage); + unsigned = new ThorTransaction(messageObj); + } catch (e) { + throw new Error("Message is not a valid JSON object"); + } + const result = await signerContext(deviceId, signer => + signer.signTransaction(path, unsigned.encode().toString("hex")), + ); + + return result.toString("hex"); + }; diff --git a/libs/ledger-live-common/src/families/vechain/speculos-deviceActions.ts b/libs/coin-modules/coin-vechain/src/test/bot-deviceActions.ts similarity index 70% rename from libs/ledger-live-common/src/families/vechain/speculos-deviceActions.ts rename to libs/coin-modules/coin-vechain/src/test/bot-deviceActions.ts index 6edac20389e2..1e026e72cc38 100644 --- a/libs/ledger-live-common/src/families/vechain/speculos-deviceActions.ts +++ b/libs/coin-modules/coin-vechain/src/test/bot-deviceActions.ts @@ -1,6 +1,6 @@ -import type { DeviceAction } from "../../bot/types"; -import type { Transaction } from "./types"; -import { deviceActionFlow, SpeculosButton } from "../../bot/specs"; +import { SpeculosButton, deviceActionFlow } from "@ledgerhq/coin-framework/bot/specs"; +import type { Transaction } from "../types"; +import { DeviceAction } from "@ledgerhq/coin-framework/bot/types"; const acceptTransaction: DeviceAction = deviceActionFlow({ steps: [ diff --git a/libs/ledger-live-common/src/families/vechain/specs.ts b/libs/coin-modules/coin-vechain/src/test/bot-specs.ts similarity index 94% rename from libs/ledger-live-common/src/families/vechain/specs.ts rename to libs/coin-modules/coin-vechain/src/test/bot-specs.ts index 754bacb53101..18f3165fc6f6 100644 --- a/libs/ledger-live-common/src/families/vechain/specs.ts +++ b/libs/coin-modules/coin-vechain/src/test/bot-specs.ts @@ -1,17 +1,17 @@ +import BigNumber from "bignumber.js"; import invariant from "invariant"; -import expect from "expect"; import type { AppSpec, TransactionArg, TransactionRes, TransactionTestInput, -} from "../../bot/types"; -import type { Transaction } from "./types"; -import { pickSiblings, botTest, SpeculosButton } from "../../bot/specs"; + SpeculosTransport, +} from "@ledgerhq/coin-framework/bot/types"; +import type { Transaction } from "../types"; +import { pickSiblings, botTest, SpeculosButton } from "@ledgerhq/coin-framework/bot/specs"; import { DeviceModelId } from "@ledgerhq/devices"; import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies"; -import deviceAction from "../vechain/speculos-deviceActions"; -import BigNumber from "bignumber.js"; +import speculosDeviceActions from "./bot-deviceActions"; const MIN_VET_TRANSACTION_AMOUNT = 1000000000000000000; const MAX_VTHO_FEE_FOR_VTHO_TRANSACTION = 1040000000000000000; @@ -26,8 +26,8 @@ const vechainTest = { }, allowEmptyAccounts: true, testTimeout: 60 * 1000, // 1 minute - genericDeviceAction: deviceAction.acceptTransaction, - onSpeculosDeviceCreated: async ({ transport }) => { + genericDeviceAction: speculosDeviceActions.acceptTransaction, + onSpeculosDeviceCreated: async ({ transport }: { transport: SpeculosTransport }) => { // enable contract data await transport.button(SpeculosButton.RIGHT); await transport.button(SpeculosButton.BOTH); diff --git a/libs/coin-modules/coin-vechain/src/test/bridgeDatasetTest.ts b/libs/coin-modules/coin-vechain/src/test/bridgeDatasetTest.ts new file mode 100644 index 000000000000..a13e93e1b1a4 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/test/bridgeDatasetTest.ts @@ -0,0 +1,262 @@ +import BigNumber from "bignumber.js"; +import type { AccountRaw, CurrenciesData, DatasetTest } from "@ledgerhq/types-live"; +import type { Transaction } from "../types"; +import { fromTransactionRaw } from "../bridge/transaction"; +import { DEFAULT_GAS_COEFFICIENT, MAINNET_CHAIN_TAG } from "../types"; +import { vechain1, vechain3 } from "../datasets"; +import { generateNonce } from "../common-logic"; + +import vechainScanAccounts1 from "../datasets/vechain.scanAccounts.1"; +import { AmountRequired, NotEnoughBalance } from "@ledgerhq/errors"; +import VIP180 from "../contracts/abis/VIP180"; +import { CryptoCurrencyId } from "@ledgerhq/types-cryptoassets"; +import { NotEnoughVTHO } from "../errors"; +import { + listSupportedCurrencies, + setSupportedCurrencies, +} from "@ledgerhq/coin-framework/currencies/index"; +import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies"; + +const listSupported = listSupportedCurrencies(); +listSupported.push(getCryptoCurrencyById("vechain")); +setSupportedCurrencies(listSupported.map(c => c.id) as CryptoCurrencyId[]); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const vechain: CurrenciesData = { + FIXME_ignoreAccountFields: ["balance", "spendableBalance", "estimateMaxSpendable"], // the balance depends on VTHO and it's earned without operations + scanAccounts: vechainScanAccounts1, + + accounts: [ + { + raw: vechain1 as AccountRaw, + transactions: [ + { + name: "Send VET", + transaction: fromTransactionRaw({ + family: "vechain", + estimatedFees: "210000000000000000", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "1000000000000000000", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [ + { + to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + value: "1000000000000000000", + data: "0x", + }, + ], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + amount: new BigNumber("1000000000000000000"), + estimatedFees: new BigNumber("210000000000000000"), + totalSpent: new BigNumber("1000000000000000000"), + errors: {}, + warnings: {}, + }, + }, + { + name: "Send VTHO", + transaction: fromTransactionRaw({ + family: "vechain", + subAccountId: + "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", + estimatedFees: "515180000000000000", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "1000000000000000000", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [ + { + to: "0x0000000000000000000000000000456e65726779", + value: 0, + data: VIP180.transfer.encode( + "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + "9000000000000000000", + ), + }, + ], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + amount: new BigNumber("1000000000000000000"), + estimatedFees: new BigNumber("515180000000000000"), + totalSpent: new BigNumber("1515180000000000000"), + errors: {}, + warnings: {}, + }, + }, + { + name: "Amount required", + transaction: fromTransactionRaw({ + family: "vechain", + estimatedFees: "0", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [{ to: "", value: 0, data: "0x" }], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + errors: { + amount: new AmountRequired(), + }, + warnings: {}, + }, + }, + { + name: "VET balance not enough", + transaction: fromTransactionRaw({ + family: "vechain", + estimatedFees: "210000000000000000", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "20000000000000000000", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [ + { + to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + value: "20000000000000000000", + data: "0x", + }, + ], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + amount: new BigNumber("20000000000000000000"), + errors: { + amount: new NotEnoughBalance(), + }, + warnings: {}, + totalSpent: new BigNumber("20000000000000000000"), + estimatedFees: new BigNumber("210000000000000000"), + }, + }, + { + name: "VTHO balance not enough", + transaction: fromTransactionRaw({ + family: "vechain", + subAccountId: + "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", + estimatedFees: "515820000000000000", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "20000000000000000000", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [ + { + to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + value: "20000000000000000000", + data: "0x", + }, + ], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + amount: new BigNumber("20000000000000000000"), + errors: { + amount: new NotEnoughBalance(), + }, + warnings: {}, + totalSpent: new BigNumber("20515820000000000000"), + estimatedFees: new BigNumber("515820000000000000"), + }, + }, + ], + FIXME_tests: [ + "balance is sum of ops", // the balance depends on VTHO and it's earned without operations + "empty transaction is equals to itself", //nonce is not deterministic + "ref stability on self transaction", //blockref is not deterministic + "can be run in parallel and all yield same results", //blockref is not deterministic + ], + }, + { + raw: vechain3 as AccountRaw, + transactions: [ + { + name: "Not enough VTHO to pay fees", + transaction: fromTransactionRaw({ + family: "vechain", + estimatedFees: "210000000000000000", + recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + amount: "1000000000000000000", + body: { + chainTag: MAINNET_CHAIN_TAG, + blockRef: "0x00634a0c856ec1db", + expiration: 18, + clauses: [ + { + to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", + value: "1000000000000000000", + data: "0x", + }, + ], + gasPriceCoef: DEFAULT_GAS_COEFFICIENT, + gas: "0", + dependsOn: null, + nonce: generateNonce(), + }, + }), + expectedStatus: { + amount: new BigNumber("1000000000000000000"), + estimatedFees: new BigNumber("210000000000000000"), + totalSpent: new BigNumber("1000000000000000000"), + errors: { + amount: new NotEnoughVTHO(), + }, + warnings: {}, + }, + }, + ], + FIXME_tests: [ + "balance is sum of ops", // the balance depends on VTHO and it's earned without operations + "empty transaction is equals to itself", //nonce is not deterministic + "ref stability on self transaction", //blockref is not deterministic + "can be run in parallel and all yield same results", //blockref is not deterministic + ], + }, + ], +}; + +// describe("VeChain Bridge", () => { +// test.todo("sample test"); +// }); + +export const dataset: DatasetTest = { + implementations: ["js", "mock"], + currencies: { + vechain, + }, +}; diff --git a/libs/ledger-live-common/src/families/vechain/cli-transaction.ts b/libs/coin-modules/coin-vechain/src/test/cli.ts similarity index 71% rename from libs/ledger-live-common/src/families/vechain/cli-transaction.ts rename to libs/coin-modules/coin-vechain/src/test/cli.ts index 97c556250f5c..b1d716dbf9d8 100644 --- a/libs/ledger-live-common/src/families/vechain/cli-transaction.ts +++ b/libs/coin-modules/coin-vechain/src/test/cli.ts @@ -1,10 +1,25 @@ import flatMap from "lodash/flatMap"; -import type { Transaction } from "../../generated/types"; -import { Transaction as VechainTransaction } from "./types"; +import { Transaction, Transaction as VechainTransaction } from "../types"; import type { Account, AccountLike } from "@ledgerhq/types-live"; -import { VTHO_ADDRESS } from "./contracts/constants"; -import VIP180 from "./contracts/abis/VIP180"; -import { MustBeVechain } from "./errors"; +import { VTHO_ADDRESS } from "../contracts/constants"; +import VIP180 from "../contracts/abis/VIP180"; +import { MustBeVechain } from "../errors"; + +type CliTools = { + options: Array<{ + name: string; + type: any; + desc: string; + }>; + inferTransactions: ( + transactions: Array<{ + account: AccountLike; + transaction: Transaction; + mainAccount: Account; + }>, + opts: Record, + ) => Transaction[]; +}; type Clauses = { to: string; @@ -63,7 +78,9 @@ function inferTransactions( }); } -export default { - options, - inferTransactions, -}; +export default function makeCliTools(): CliTools { + return { + options, + inferTransactions, + }; +} diff --git a/libs/coin-modules/coin-vechain/src/test/index.ts b/libs/coin-modules/coin-vechain/src/test/index.ts new file mode 100644 index 000000000000..f54948a8413b --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/test/index.ts @@ -0,0 +1,6 @@ +import makeCliTools from "./cli"; + +export * from "./bridgeDatasetTest"; +export { makeCliTools }; +export * from "./bot-deviceActions"; +export * from "./bot-specs"; diff --git a/libs/coin-modules/coin-vechain/src/types/bridge.ts b/libs/coin-modules/coin-vechain/src/types/bridge.ts new file mode 100644 index 000000000000..aa65063b80fd --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/types/bridge.ts @@ -0,0 +1,35 @@ +import type { + TokenAccount, + TransactionCommon, + TransactionCommonRaw, + TransactionStatusCommon, + TransactionStatusCommonRaw, +} from "@ledgerhq/types-live"; +import BigNumber from "bignumber.js"; +import { Transaction as ThorTransaction } from "thor-devkit"; + +export type Transaction = TransactionCommon & { + family: "vechain"; + estimatedFees: string; + body: ThorTransaction.Body; +}; + +export type TransactionRaw = TransactionCommonRaw & { + family: "vechain"; + estimatedFees: string; + body: ThorTransaction.Body; +}; + +export type TransactionStatus = TransactionStatusCommon; + +export type TransactionStatusRaw = TransactionStatusCommonRaw; + +export type TransactionInfo = { + isTokenAccount: boolean; + amount: BigNumber; + balance: BigNumber; + spendableBalance: BigNumber; + tokenAccount: TokenAccount | undefined; + estimatedFees: string; + estimatedGas: number; +}; diff --git a/libs/ledger-live-common/src/families/vechain/constants.ts b/libs/coin-modules/coin-vechain/src/types/constants.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/constants.ts rename to libs/coin-modules/coin-vechain/src/types/constants.ts diff --git a/libs/coin-modules/coin-vechain/src/types/index.ts b/libs/coin-modules/coin-vechain/src/types/index.ts new file mode 100644 index 000000000000..3e980b0d6b00 --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/types/index.ts @@ -0,0 +1,4 @@ +export * from "./bridge"; +export * from "./signer"; +export * from "./constants"; +export * from "./network"; diff --git a/libs/ledger-live-common/src/families/vechain/api/types.ts b/libs/coin-modules/coin-vechain/src/types/network.ts similarity index 100% rename from libs/ledger-live-common/src/families/vechain/api/types.ts rename to libs/coin-modules/coin-vechain/src/types/network.ts diff --git a/libs/coin-modules/coin-vechain/src/types/signer.ts b/libs/coin-modules/coin-vechain/src/types/signer.ts new file mode 100644 index 000000000000..878cbf96a0ee --- /dev/null +++ b/libs/coin-modules/coin-vechain/src/types/signer.ts @@ -0,0 +1,10 @@ +export type VechainAddress = { + publicKey: string; + address: string; + chainCode?: string; +}; +export type VechainSignature = Buffer; +export interface VechainSigner { + getAddress(path: string, boolDisplay?: boolean, chainCode?: boolean): Promise; + signTransaction(path: string, rawTxHex: string): Promise; +} diff --git a/libs/coin-modules/coin-vechain/tsconfig.json b/libs/coin-modules/coin-vechain/tsconfig.json new file mode 100644 index 000000000000..f56b01ccd35e --- /dev/null +++ b/libs/coin-modules/coin-vechain/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../tsconfig.base", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "module": "commonjs", + "downlevelIteration": true, + "lib": ["es2020", "dom"], + "outDir": "lib", + "exactOptionalPropertyTypes": true + }, + "include": ["src/**/*"] +} diff --git a/libs/coin-modules/coin-xrp/src/api/index.integ.test.ts b/libs/coin-modules/coin-xrp/src/api/index.integ.test.ts index eeb6853d6409..883f6d0e3b13 100644 --- a/libs/coin-modules/coin-xrp/src/api/index.integ.test.ts +++ b/libs/coin-modules/coin-xrp/src/api/index.integ.test.ts @@ -77,7 +77,7 @@ describe("Xrp Api", () => { it("returns a raw transaction", async () => { // When const result = await module.craftTransaction(address, { - mode: "send", + type: "send", recipient: "rKRtUG15iBsCQRgrkeUEg5oX4Ae2zWZ89z", amount: BigInt(10), fee: BigInt(1), diff --git a/libs/coin-modules/coin-xrp/src/api/index.ts b/libs/coin-modules/coin-xrp/src/api/index.ts index b57ce2b187c9..37d0d58be6b5 100644 --- a/libs/coin-modules/coin-xrp/src/api/index.ts +++ b/libs/coin-modules/coin-xrp/src/api/index.ts @@ -1,4 +1,8 @@ -import type { Api, Operation } from "@ledgerhq/coin-framework/api/index"; +import type { + Api, + Operation, + Transaction as ApiTransaction, +} from "@ledgerhq/coin-framework/api/index"; import coinConfig, { type XrpConfig } from "../config"; import { broadcast, @@ -25,15 +29,7 @@ export function createApi(config: XrpConfig): Api { }; } -async function craft( - address: string, - transaction: { - mode: string; - recipient: string; - amount: bigint; - fee: bigint; - }, -): Promise { +async function craft(address: string, transaction: ApiTransaction): Promise { const nextSequenceNumber = await getNextValidSequence(address); const tx = await craftTransaction({ address, nextSequenceNumber }, transaction); return tx.serializedTransaction; diff --git a/libs/env/src/env.ts b/libs/env/src/env.ts index da0ef7318c6e..2b3d265ba6aa 100644 --- a/libs/env/src/env.ts +++ b/libs/env/src/env.ts @@ -327,6 +327,11 @@ const envDefinitions = { parser: boolParser, desc: "disable the version check for firmware update eligibility", }, + DETOX: { + def: "", + parser: stringParser, + desc: "switch the app into a DETOX mode for test purpose. Avoid falsy values.", + }, EIP1559_MINIMUM_FEES_GATE: { def: true, parser: boolParser, diff --git a/libs/ledger-live-common/.unimportedrc.json b/libs/ledger-live-common/.unimportedrc.json index 26ea041ee3b9..27a029333edb 100644 --- a/libs/ledger-live-common/.unimportedrc.json +++ b/libs/ledger-live-common/.unimportedrc.json @@ -132,6 +132,8 @@ "src/families/tezos/types.ts", "src/families/tron/react.ts", "src/families/tron/types.ts", + "src/families/vechain/logic.ts", + "src/families/vechain/types.ts", "src/families/xrp/types.ts", "src/featureFlags/FeatureFlagsContext.ts", "src/featureFlags/groupedFeatures.ts", @@ -308,6 +310,13 @@ "src/deviceSDK/commands/genuineCheck.ts", "src/deviceSDK/commands/getAppAndVersion.ts", "src/deviceSDK/tasks/genuineCheck.ts", + "src/e2e/enum/Account.ts", + "src/e2e/enum/AccountType.ts", + "src/e2e/enum/AppInfos.ts", + "src/e2e/enum/Currency.ts", + "src/e2e/enum/DeviceLabels.ts", + "src/e2e/enum/Fee.ts", + "src/e2e/enum/Swap.ts", "src/exchange/swap/const/blockchain.ts", "src/families/cardano/logic.ts", "src/families/cardano/staking.ts", diff --git a/libs/ledger-live-common/package.json b/libs/ledger-live-common/package.json index dbaee903bbd1..62b8d426d73a 100644 --- a/libs/ledger-live-common/package.json +++ b/libs/ledger-live-common/package.json @@ -64,6 +64,7 @@ "scripts": { "build": "zx ./scripts/build-ts.mjs", "watch": "zx ./scripts/watch-ts.mjs", + "watch:es": "zx ./scripts/watch-ts-es.mjs", "updateAppSupportsQuitApp": "node scripts/updateAppSupportsQuitApp.js", "prettier": "prettier --write 'src/**/*.?s'", "lint": "eslint src --cache", @@ -148,6 +149,7 @@ "@ledgerhq/coin-tezos": "workspace:^", "@ledgerhq/coin-ton": "workspace:^", "@ledgerhq/coin-tron": "workspace:^", + "@ledgerhq/coin-vechain": "workspace:^", "@ledgerhq/coin-xrp": "workspace:^", "@ledgerhq/crypto-icons-ui": "workspace:^", "@ledgerhq/cryptoassets": "workspace:^", @@ -216,7 +218,6 @@ "bs58": "^4.0.1", "casper-js-sdk": "^2.15.2", "date-fns": "^2.23.0", - "eip55": "^2.1.1", "expect": "^27.4.6", "fuse.js": "^6.6.2", "invariant": "^2.2.2", @@ -237,7 +238,6 @@ "semver": "^7.3.5", "sha.js": "^2.4.11", "simple-cbor": "^0.4.1", - "thor-devkit": "^2.0.6", "triple-beam": "^1.3.0", "tsx": "^4.7.1", "usehooks-ts": "^2.13.0", diff --git a/libs/ledger-live-common/scripts/sync-families-dispatch.mjs b/libs/ledger-live-common/scripts/sync-families-dispatch.mjs index 624c48a37036..b1ae4e03089a 100644 --- a/libs/ledger-live-common/scripts/sync-families-dispatch.mjs +++ b/libs/ledger-live-common/scripts/sync-families-dispatch.mjs @@ -39,6 +39,7 @@ const familiesWPackage = [ "tezos", "ton", "tron", + "vechain", "xrp", ]; diff --git a/libs/ledger-live-common/scripts/watch-ts-es.mjs b/libs/ledger-live-common/scripts/watch-ts-es.mjs new file mode 100644 index 000000000000..cd629b8cbed2 --- /dev/null +++ b/libs/ledger-live-common/scripts/watch-ts-es.mjs @@ -0,0 +1,13 @@ +#!/usr/bin/env zx +import "zx/globals"; + +try { + cd(path.join(__dirname, "..")); + + await $`zx ./scripts/sync-families-dispatch.mjs`; + + await $`pnpm tsc --project src/tsconfig.json -m ES6 --outDir lib-es --watch`; +} catch (error) { + console.log(chalk.red(error)); + process.exit(1); +} diff --git a/apps/ledger-live-desktop/tests/enum/Account.ts b/libs/ledger-live-common/src/e2e/enum/Account.ts similarity index 99% rename from apps/ledger-live-desktop/tests/enum/Account.ts rename to libs/ledger-live-common/src/e2e/enum/Account.ts index bcec2703a7b9..de72c872dd58 100644 --- a/apps/ledger-live-desktop/tests/enum/Account.ts +++ b/libs/ledger-live-common/src/e2e/enum/Account.ts @@ -1,5 +1,5 @@ import { Currency } from "./Currency"; -import { AccountType } from "tests/enum/AccountType"; +import { AccountType } from "./AccountType"; export class Account { constructor( diff --git a/apps/ledger-live-desktop/tests/enum/AccountType.ts b/libs/ledger-live-common/src/e2e/enum/AccountType.ts similarity index 100% rename from apps/ledger-live-desktop/tests/enum/AccountType.ts rename to libs/ledger-live-common/src/e2e/enum/AccountType.ts diff --git a/apps/ledger-live-desktop/tests/enum/AppInfos.ts b/libs/ledger-live-common/src/e2e/enum/AppInfos.ts similarity index 100% rename from apps/ledger-live-desktop/tests/enum/AppInfos.ts rename to libs/ledger-live-common/src/e2e/enum/AppInfos.ts diff --git a/apps/ledger-live-desktop/tests/enum/Currency.ts b/libs/ledger-live-common/src/e2e/enum/Currency.ts similarity index 98% rename from apps/ledger-live-desktop/tests/enum/Currency.ts rename to libs/ledger-live-common/src/e2e/enum/Currency.ts index 11a50b415729..fa11b4f14c69 100644 --- a/apps/ledger-live-desktop/tests/enum/Currency.ts +++ b/libs/ledger-live-common/src/e2e/enum/Currency.ts @@ -53,7 +53,7 @@ export class Currency { "bsc", AppInfos.BINANCE_SMART_CHAIN, ); - static readonly TON = new Currency("Ton", "TON", "ton", AppInfos.TON); + static readonly TON = new Currency("TON", "TON", "ton", AppInfos.TON); static readonly ETH_USDT = new Currency("Tether USD", "USDT", "ethereum", AppInfos.ETHEREUM); static readonly ETH_USDC = new Currency("USD Coin", "USDC", "ethereum", AppInfos.ETHEREUM); static readonly ETH_LIDO = new Currency( diff --git a/apps/ledger-live-desktop/tests/enum/DeviceLabels.ts b/libs/ledger-live-common/src/e2e/enum/DeviceLabels.ts similarity index 100% rename from apps/ledger-live-desktop/tests/enum/DeviceLabels.ts rename to libs/ledger-live-common/src/e2e/enum/DeviceLabels.ts diff --git a/apps/ledger-live-desktop/tests/enum/Fee.ts b/libs/ledger-live-common/src/e2e/enum/Fee.ts similarity index 100% rename from apps/ledger-live-desktop/tests/enum/Fee.ts rename to libs/ledger-live-common/src/e2e/enum/Fee.ts diff --git a/apps/ledger-live-desktop/tests/enum/Swap.ts b/libs/ledger-live-common/src/e2e/enum/Swap.ts similarity index 100% rename from apps/ledger-live-desktop/tests/enum/Swap.ts rename to libs/ledger-live-common/src/e2e/enum/Swap.ts diff --git a/libs/ledger-live-common/src/errors.ts b/libs/ledger-live-common/src/errors.ts index 7b2c583fd329..29ad131885f1 100644 --- a/libs/ledger-live-common/src/errors.ts +++ b/libs/ledger-live-common/src/errors.ts @@ -134,3 +134,4 @@ export * from "@ledgerhq/coin-solana/errors"; export * from "@ledgerhq/coin-stacks/errors"; export * from "@ledgerhq/coin-stellar/errors"; export * from "@ledgerhq/coin-tezos/errors"; +export * from "@ledgerhq/coin-vechain/errors"; diff --git a/libs/ledger-live-common/src/exchange/swap/updateAccountSwapStatus.ts b/libs/ledger-live-common/src/exchange/swap/updateAccountSwapStatus.ts index e5c86be4abd4..3db92c5723ae 100644 --- a/libs/ledger-live-common/src/exchange/swap/updateAccountSwapStatus.ts +++ b/libs/ledger-live-common/src/exchange/swap/updateAccountSwapStatus.ts @@ -1,7 +1,7 @@ import { isSwapOperationPending } from "./"; import { getMultipleStatus } from "./getStatus"; import type { SubAccount, Account, SwapOperation, Operation } from "@ledgerhq/types-live"; -import type { SwapStatusRequest, UpdateAccountSwapStatus } from "./types"; +import type { SwapStatus, SwapStatusRequest, UpdateAccountSwapStatus } from "./types"; import { log } from "@ledgerhq/logs"; const maybeGetUpdatedSwapHistory = async ( @@ -9,40 +9,60 @@ const maybeGetUpdatedSwapHistory = async ( operations: Operation[] | null | undefined, ): Promise => { const pendingSwapIds: SwapStatusRequest[] = []; + const atomicSwapIds: SwapStatus[] = []; let accountNeedsUpdating = false; let consolidatedSwapHistory: SwapOperation[] = []; if (swapHistory) { - for (const { provider, swapId, status, operationId } of swapHistory) { + for (const swap of swapHistory) { + const { provider, swapId, status, operationId } = swap; + const updatedSwap: SwapOperation = { ...swap }; + if (isSwapOperationPending(status)) { - const transactionId = - provider === "thorswap" - ? operations?.find(o => o.id.includes(operationId))?.hash - : undefined; - pendingSwapIds.push({ - provider, - swapId, - transactionId, - ...(provider === "thorswap" && { operationId }), // to be removed after Thorswap is fully migrated - }); + // if swapId is in operationId, then we can get the status from the operation + // it means DEX swap like Uniswap + if (operationId && swapId && operationId.includes(swapId)) { + const operation = operations?.find(o => o.id.includes(operationId)); + if (operation) { + let newStatus; + if (operation.blockHeight) { + newStatus = operation.hasFailed ? "refunded" : "finished"; + } else { + newStatus = "pending"; + } + if (newStatus !== swap.status) { + accountNeedsUpdating = true; + updatedSwap.status = newStatus; + atomicSwapIds.push({ provider, swapId, status: newStatus }); + } + } + } else { + // Collect all others swaps that need status update via getMultipleStatus + const transactionId = + provider === "thorswap" + ? operations?.find(o => o.id.includes(operationId))?.hash + : undefined; + pendingSwapIds.push({ + provider, + swapId, + transactionId, + ...(provider === "thorswap" && { operationId }), + }); + } } } - - if (pendingSwapIds.length) { + if (pendingSwapIds.length || atomicSwapIds.length) { const uniquePendingSwapIdsMap = new Map(); for (const item of pendingSwapIds) { const existingItem = uniquePendingSwapIdsMap.get(item.swapId); - if (!existingItem) { uniquePendingSwapIdsMap.set(item.swapId, item); - } else { - if (item.transactionId && !existingItem.transactionId) { - uniquePendingSwapIdsMap.set(item.swapId, item); - } + } else if (item.transactionId && !existingItem.transactionId) { + uniquePendingSwapIdsMap.set(item.swapId, item); } } - const uniquePendingSwapIds = Array.from(uniquePendingSwapIdsMap.values()); + if (uniquePendingSwapIds.length !== pendingSwapIds.length) { log( "error", @@ -50,7 +70,11 @@ const maybeGetUpdatedSwapHistory = async ( pendingSwapIds.length - uniquePendingSwapIds.length, ); } - const newStatusList = await getMultipleStatus(uniquePendingSwapIds); + + const newStatusList = pendingSwapIds.length + ? await getMultipleStatus(uniquePendingSwapIds) + : []; + newStatusList.push(...atomicSwapIds); consolidatedSwapHistory = swapHistory.map((swap: SwapOperation) => { const newStatus = newStatusList.find(s => s.swapId === swap.swapId); @@ -61,10 +85,10 @@ const maybeGetUpdatedSwapHistory = async ( return swap; }); + } - if (accountNeedsUpdating) { - return consolidatedSwapHistory; - } + if (accountNeedsUpdating) { + return consolidatedSwapHistory; } } }; diff --git a/libs/ledger-live-common/src/families/ton/setup.ts b/libs/ledger-live-common/src/families/ton/setup.ts index 2527d74f8196..bb45474ea947 100644 --- a/libs/ledger-live-common/src/families/ton/setup.ts +++ b/libs/ledger-live-common/src/families/ton/setup.ts @@ -2,7 +2,7 @@ import { createBridges } from "@ledgerhq/coin-ton/bridge/js"; import makeCliTools from "@ledgerhq/coin-ton/cli-transaction"; -import nearResolver from "@ledgerhq/coin-ton/hw-getAddress"; +import tonResolver from "@ledgerhq/coin-ton/hw-getAddress"; import { signMessage } from "@ledgerhq/coin-ton/hw-signMessage"; import { TonCoinConfig } from "@ledgerhq/coin-ton/lib/config"; import { TonSigner } from "@ledgerhq/coin-ton/lib/signer"; @@ -26,7 +26,7 @@ const messageSigner = { signMessage, }; -const resolver: Resolver = createResolver(createSigner, nearResolver); +const resolver: Resolver = createResolver(createSigner, tonResolver); const cliTools = makeCliTools(); diff --git a/libs/ledger-live-common/src/families/vechain/bridge.integration.test.ts b/libs/ledger-live-common/src/families/vechain/bridge.integration.test.ts index 45ad5d724549..50b1a786fba4 100644 --- a/libs/ledger-live-common/src/families/vechain/bridge.integration.test.ts +++ b/libs/ledger-live-common/src/families/vechain/bridge.integration.test.ts @@ -1,258 +1,5 @@ import "../../__tests__/test-helpers/setup"; import { testBridge } from "../../__tests__/test-helpers/bridge"; -import type { AccountRaw, DatasetTest } from "@ledgerhq/types-live"; -import type { Transaction } from "./types"; -import { fromTransactionRaw } from "./transaction"; -import { DEFAULT_GAS_COEFFICIENT, MAINNET_CHAIN_TAG } from "./constants"; -import { vechain1, vechain3 } from "./datasets/vechain"; -import { generateNonce } from "./utils/transaction-utils"; -import BigNumber from "bignumber.js"; -import { - setSupportedCurrencies, - listSupportedCurrencies, - getCryptoCurrencyById, -} from "../../currencies"; -import vechainScanAccounts1 from "./datasets/vechain.scanAccounts.1"; -import { AmountRequired, NotEnoughBalance } from "@ledgerhq/errors"; -import VIP180 from "./contracts/abis/VIP180"; -import { CryptoCurrencyId } from "@ledgerhq/types-cryptoassets"; -import { NotEnoughVTHO } from "./errors"; - -const listSupported = listSupportedCurrencies(); -listSupported.push(getCryptoCurrencyById("vechain")); -setSupportedCurrencies(listSupported.map(c => c.id) as CryptoCurrencyId[]); - -const dataset: DatasetTest = { - implementations: ["js", "mock"], - currencies: { - vechain: { - FIXME_ignoreAccountFields: ["balance", "spendableBalance", "estimateMaxSpendable"], // the balance depends on VTHO and it's earned without operations - scanAccounts: vechainScanAccounts1, - - accounts: [ - { - raw: vechain1 as AccountRaw, - transactions: [ - { - name: "Send VET", - transaction: fromTransactionRaw({ - family: "vechain", - estimatedFees: "210000000000000000", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "1000000000000000000", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [ - { - to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - value: "1000000000000000000", - data: "0x", - }, - ], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - amount: new BigNumber("1000000000000000000"), - estimatedFees: new BigNumber("210000000000000000"), - totalSpent: new BigNumber("1000000000000000000"), - errors: {}, - warnings: {}, - }, - }, - { - name: "Send VTHO", - transaction: fromTransactionRaw({ - family: "vechain", - subAccountId: - "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", - estimatedFees: "515180000000000000", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "1000000000000000000", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [ - { - to: "0x0000000000000000000000000000456e65726779", - value: 0, - data: VIP180.transfer.encode( - "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - "9000000000000000000", - ), - }, - ], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - amount: new BigNumber("1000000000000000000"), - estimatedFees: new BigNumber("515180000000000000"), - totalSpent: new BigNumber("1515180000000000000"), - errors: {}, - warnings: {}, - }, - }, - { - name: "Amount required", - transaction: fromTransactionRaw({ - family: "vechain", - estimatedFees: "0", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [{ to: "", value: 0, data: "0x" }], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - errors: { - amount: new AmountRequired(), - }, - warnings: {}, - }, - }, - { - name: "VET balance not enough", - transaction: fromTransactionRaw({ - family: "vechain", - estimatedFees: "210000000000000000", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "20000000000000000000", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [ - { - to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - value: "20000000000000000000", - data: "0x", - }, - ], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - amount: new BigNumber("20000000000000000000"), - errors: { - amount: new NotEnoughBalance(), - }, - warnings: {}, - totalSpent: new BigNumber("20000000000000000000"), - estimatedFees: new BigNumber("210000000000000000"), - }, - }, - { - name: "VTHO balance not enough", - transaction: fromTransactionRaw({ - family: "vechain", - subAccountId: - "js:2:vechain:0x0fe6688548f0C303932bB197B0A96034f1d74dba:vechain+vechain%2Fvip180%2Fvtho", - estimatedFees: "515820000000000000", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "20000000000000000000", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [ - { - to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - value: "20000000000000000000", - data: "0x", - }, - ], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - amount: new BigNumber("20000000000000000000"), - errors: { - amount: new NotEnoughBalance(), - }, - warnings: {}, - totalSpent: new BigNumber("20515820000000000000"), - estimatedFees: new BigNumber("515820000000000000"), - }, - }, - ], - FIXME_tests: [ - "balance is sum of ops", // the balance depends on VTHO and it's earned without operations - "empty transaction is equals to itself", //nonce is not deterministic - "ref stability on self transaction", //blockref is not deterministic - "can be run in parallel and all yield same results", //blockref is not deterministic - ], - }, - { - raw: vechain3 as AccountRaw, - transactions: [ - { - name: "Not enough VTHO to pay fees", - transaction: fromTransactionRaw({ - family: "vechain", - estimatedFees: "210000000000000000", - recipient: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - amount: "1000000000000000000", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "0x00634a0c856ec1db", - expiration: 18, - clauses: [ - { - to: "0xcf130b42ae31c4931298b4b1c0f1d974b8732957", - value: "1000000000000000000", - data: "0x", - }, - ], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, - }), - expectedStatus: { - amount: new BigNumber("1000000000000000000"), - estimatedFees: new BigNumber("210000000000000000"), - totalSpent: new BigNumber("1000000000000000000"), - errors: { - amount: new NotEnoughVTHO(), - }, - warnings: {}, - }, - }, - ], - FIXME_tests: [ - "balance is sum of ops", // the balance depends on VTHO and it's earned without operations - "empty transaction is equals to itself", //nonce is not deterministic - "ref stability on self transaction", //blockref is not deterministic - "can be run in parallel and all yield same results", //blockref is not deterministic - ], - }, - ], - }, - }, -}; +import { dataset } from "@ledgerhq/coin-vechain/test/index"; testBridge(dataset); diff --git a/libs/ledger-live-common/src/families/vechain/bridge/js.ts b/libs/ledger-live-common/src/families/vechain/bridge/js.ts deleted file mode 100644 index 517caff82686..000000000000 --- a/libs/ledger-live-common/src/families/vechain/bridge/js.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Account, AccountBridge, CurrencyBridge } from "@ledgerhq/types-live"; -import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers"; -import { makeAccountBridgeReceive } from "../../../bridge/jsHelpers"; -import { getTransactionStatus } from "../getTransactionStatus"; -import type { Transaction, TransactionStatus } from "../types"; -import { estimateMaxSpendable } from "../estimateMaxSpendable"; -import { prepareTransaction } from "../prepareTransaction"; -import { createTransaction } from "../createTransaction"; -import { sync, scanAccounts } from "../synchronisation"; -import { signOperation } from "../signOperation"; -import { broadcast } from "../broadcast"; - -const receive: AccountBridge["receive"] = makeAccountBridgeReceive(); - -const currencyBridge: CurrencyBridge = { - scanAccounts, - preload: async () => Promise.resolve({}), - hydrate: (): void => {}, -}; - -const accountBridge: AccountBridge = { - estimateMaxSpendable, - createTransaction, - updateTransaction: defaultUpdateTransaction, - getTransactionStatus, - prepareTransaction, - sync, - receive, - signOperation, - broadcast, -}; - -export default { currencyBridge, accountBridge }; diff --git a/libs/ledger-live-common/src/families/vechain/bridge/mock.ts b/libs/ledger-live-common/src/families/vechain/bridge/mock.ts deleted file mode 100644 index e3bc22524547..000000000000 --- a/libs/ledger-live-common/src/families/vechain/bridge/mock.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { AccountBridge, CurrencyBridge, TokenAccount } from "@ledgerhq/types-live"; -import type { Transaction, TransactionStatus } from "../types"; -import { scanAccounts, signOperation, broadcast, sync } from "../../../bridge/mockHelpers"; -import { makeAccountBridgeReceive } from "../../../bridge/mockHelpers"; -import BigNumber from "bignumber.js"; -import { DEFAULT_GAS_COEFFICIENT, MAINNET_CHAIN_TAG } from "../constants"; -import { calculateTransactionInfo, generateNonce } from "../utils/transaction-utils"; -import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers"; -import { Account } from "@ledgerhq/types-live"; -import { - AmountRequired, - FeeNotLoaded, - InvalidAddress, - InvalidAddressBecauseDestinationIsAlsoSource, - NotEnoughBalance, - RecipientRequired, -} from "@ledgerhq/errors"; -import { NotEnoughVTHO } from "../errors"; -import { isValid } from "../utils/address-utils"; - -const receive = makeAccountBridgeReceive(); - -const currencyBridge: CurrencyBridge = { - scanAccounts, - preload: async () => Promise.resolve({}), - hydrate: (): void => {}, -}; - -const estimateMaxSpendable = ({ account }) => { - return account.balance; -}; - -const createTransaction = (): Transaction => ({ - amount: new BigNumber(0), - useAllAmount: false, - family: "vechain", - estimatedFees: "0", - recipient: "", - body: { - chainTag: MAINNET_CHAIN_TAG, - blockRef: "", - expiration: 18, - clauses: [], - gasPriceCoef: DEFAULT_GAS_COEFFICIENT, - gas: "0", - dependsOn: null, - nonce: generateNonce(), - }, -}); - -const getTransactionStatus = async ( - account: Account, - transaction: Transaction, -): Promise => { - const { freshAddress, currency, subAccounts } = account; - const { body, recipient, subAccountId } = transaction; - const errors: Record = {}; - const warnings: Record = {}; - - const tokenAccount = - subAccountId && subAccounts - ? (subAccounts.find(subAccount => { - return subAccount.id === subAccountId; - }) as TokenAccount) - : undefined; - const isTokenAccount = !!tokenAccount; - const estimatedFees = new BigNumber(transaction.estimatedFees); - - const { amount, spendableBalance } = await calculateTransactionInfo(account, transaction, { - estimatedGas: body.gas as number, - estimatedGasFees: estimatedFees, - }); - - if (!body?.gas) { - errors.fees = new FeeNotLoaded(); - } - - if (!recipient) { - errors.recipient = new RecipientRequired(); - } else if (freshAddress.toLowerCase() === recipient.toLowerCase()) { - warnings.recipient = new InvalidAddressBecauseDestinationIsAlsoSource(); - } else if (!isValid(recipient)) { - errors.recipient = new InvalidAddress("", { - currencyName: currency.name, - }); - } - - if (!amount.gt(0)) { - if (!transaction.useAllAmount) errors.amount = new AmountRequired(); - else errors.amount = new NotEnoughBalance(); - } else { - if (amount.gt(spendableBalance)) { - errors.amount = new NotEnoughBalance(); - } - if (!isTokenAccount) { - // vet - const vthoBalance = subAccounts?.[0].balance; - if (estimatedFees.gt(vthoBalance || 0)) { - errors.amount = new NotEnoughVTHO(); - } - } - } - - let totalSpent = amount; - if (isTokenAccount) { - totalSpent = amount.plus(estimatedFees); - } - - return Promise.resolve({ - errors, - warnings, - estimatedFees, - amount, - totalSpent, - }); -}; - -export const prepareTransaction = async ( - account: Account, - transaction: Transaction, -): Promise => { - return transaction; -}; - -const accountBridge: AccountBridge = { - estimateMaxSpendable, - createTransaction, - updateTransaction: defaultUpdateTransaction, - getTransactionStatus, - prepareTransaction, - sync, - receive, - signOperation, - broadcast, -}; - -export default { currencyBridge, accountBridge }; diff --git a/libs/ledger-live-common/src/families/vechain/config.ts b/libs/ledger-live-common/src/families/vechain/config.ts index d7929120f64e..6c096f4a2f21 100644 --- a/libs/ledger-live-common/src/families/vechain/config.ts +++ b/libs/ledger-live-common/src/families/vechain/config.ts @@ -1,12 +1,15 @@ -import { ConfigInfo } from "@ledgerhq/live-config/LiveConfig"; +import { CurrencyLiveConfigDefinition } from "../../config"; -export const vechainConfig: Record = { +const vechainConfig: CurrencyLiveConfigDefinition = { config_currency_vechain: { type: "object", default: { - status: { - type: "active", + status: { type: "active" }, + infra: { + API_VECHAIN_THOREST: "https://vechain.coin.ledger.com", }, }, }, }; + +export { vechainConfig }; diff --git a/libs/ledger-live-common/src/families/vechain/hw-getAddress.ts b/libs/ledger-live-common/src/families/vechain/hw-getAddress.ts deleted file mode 100644 index 227074d00dfe..000000000000 --- a/libs/ledger-live-common/src/families/vechain/hw-getAddress.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Vet from "@ledgerhq/hw-app-vet"; -import eip55 from "eip55"; -import type { Resolver } from "../../hw/getAddress/types"; - -const resolver: Resolver = async (transport, { path, verify, askChainCode }) => { - const vet = new Vet(transport); - const r = await vet.getAddress(path, verify, askChainCode || false); - const address = eip55.encode(r.address); - return { - path, - address, - publicKey: r.publicKey, - chainCode: r.chainCode, - }; -}; - -export default resolver; diff --git a/libs/ledger-live-common/src/families/vechain/hw-signMessage.ts b/libs/ledger-live-common/src/families/vechain/hw-signMessage.ts deleted file mode 100644 index 1c4cffe956d7..000000000000 --- a/libs/ledger-live-common/src/families/vechain/hw-signMessage.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Transport from "@ledgerhq/hw-transport"; -import Vet from "@ledgerhq/hw-app-vet"; -import { Transaction as ThorTransaction } from "thor-devkit"; - -export const signMessage = async ( - transport: Transport, - { path, message, rawMessage }: { path: string; message: string; rawMessage: string }, -): Promise => { - let messageObj; - let unsigned; - try { - if (message) messageObj = JSON.parse(message); - else messageObj = JSON.parse(rawMessage); - unsigned = new ThorTransaction(messageObj); - } catch (e) { - console.error(e); - } - const vet = new Vet(transport); - - const result = await vet.signTransaction(path, unsigned.encode().toString("hex")); - - return result.toString("hex"); -}; - -export default { signMessage }; diff --git a/libs/ledger-live-common/src/families/vechain/setup.ts b/libs/ledger-live-common/src/families/vechain/setup.ts new file mode 100644 index 000000000000..6ba4e3f59a5d --- /dev/null +++ b/libs/ledger-live-common/src/families/vechain/setup.ts @@ -0,0 +1,25 @@ +// Goal of this file is to inject all necessary device/signer dependency to coin-modules + +import { createBridges } from "@ledgerhq/coin-vechain/index"; +import makeCliTools from "@ledgerhq/coin-vechain/test/cli"; +import vechainResolver, { signMessage } from "@ledgerhq/coin-vechain/signer/index"; +import { Transaction, VechainSigner } from "./types"; +import Transport from "@ledgerhq/hw-transport"; +import type { Bridge } from "@ledgerhq/types-live"; +import Vet from "@ledgerhq/hw-app-vet"; +import { CreateSigner, createResolver, executeWithSigner } from "../../bridge/setup"; +import type { Resolver } from "../../hw/getAddress/types"; + +const createSigner: CreateSigner = (transport: Transport) => new Vet(transport); + +const bridge: Bridge = createBridges(executeWithSigner(createSigner)); + +const messageSigner = { + signMessage, +}; + +const resolver: Resolver = createResolver(createSigner, vechainResolver); + +const cliTools = makeCliTools(); + +export { bridge, cliTools, messageSigner, resolver }; diff --git a/libs/ledger-live-common/src/families/vechain/signOperation.ts b/libs/ledger-live-common/src/families/vechain/signOperation.ts deleted file mode 100644 index abe9807e9822..000000000000 --- a/libs/ledger-live-common/src/families/vechain/signOperation.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Observable } from "rxjs"; -import Vet from "@ledgerhq/hw-app-vet"; -import { Transaction as ThorTransaction } from "thor-devkit"; -import type { AccountBridge } from "@ledgerhq/types-live"; -import { buildOptimisticOperation } from "./buildOptimisticOperatioin"; -import { withDevice } from "../../hw/deviceAccess"; -import type { Transaction } from "./types"; - -/** - * Sign Transaction with Ledger hardware - */ -export const signOperation: AccountBridge["signOperation"] = ({ - account, - deviceId, - transaction, -}) => - withDevice(deviceId)( - transport => - new Observable(o => { - async function main() { - const unsigned = new ThorTransaction(transaction.body); - - // Sign on device - const vechainApp = new Vet(transport); - o.next({ - type: "device-signature-requested", - }); - const signature = await vechainApp.signTransaction( - account.freshAddressPath, - unsigned.encode().toString("hex"), - ); - - o.next({ type: "device-signature-granted" }); - - const operation = await buildOptimisticOperation(account, transaction); - - o.next({ - type: "signed", - signedOperation: { - operation, - signature: signature.toString("hex"), - rawData: transaction, - }, - }); - } - - main().then( - () => o.complete(), - e => o.error(e), - ); - }), - ); - -export default signOperation; diff --git a/libs/ledger-live-common/src/families/vechain/types.ts b/libs/ledger-live-common/src/families/vechain/types.ts index f225426a9c9c..9eba7ede9a90 100644 --- a/libs/ledger-live-common/src/families/vechain/types.ts +++ b/libs/ledger-live-common/src/families/vechain/types.ts @@ -1,35 +1,2 @@ -import type { - TokenAccount, - TransactionCommon, - TransactionCommonRaw, - TransactionStatusCommon, - TransactionStatusCommonRaw, -} from "@ledgerhq/types-live"; -import BigNumber from "bignumber.js"; -import { Transaction as ThorTransaction } from "thor-devkit"; - -export type Transaction = TransactionCommon & { - family: "vechain"; - estimatedFees: string; - body: ThorTransaction.Body; -}; - -export type TransactionRaw = TransactionCommonRaw & { - family: "vechain"; - estimatedFees: string; - body: ThorTransaction.Body; -}; - -export type TransactionStatus = TransactionStatusCommon; - -export type TransactionStatusRaw = TransactionStatusCommonRaw; - -export type TransactionInfo = { - isTokenAccount: boolean; - amount: BigNumber; - balance: BigNumber; - spendableBalance: BigNumber; - tokenAccount?: TokenAccount; - estimatedFees: string; - estimatedGas: number; -}; +// Encapsulate for LLD and LLM +export * from "@ledgerhq/coin-vechain/types/index"; diff --git a/libs/ledger-live-common/src/generated/account.ts b/libs/ledger-live-common/src/generated/account.ts index 099824df7138..e4543f89d777 100644 --- a/libs/ledger-live-common/src/generated/account.ts +++ b/libs/ledger-live-common/src/generated/account.ts @@ -1,15 +1,15 @@ import crypto_org from "../families/crypto_org/account"; -import vechain from "../families/vechain/account"; import bitcoin from "@ledgerhq/coin-bitcoin/account"; import cardano from "@ledgerhq/coin-cardano/account"; import icon from "@ledgerhq/coin-icon/account"; import near from "@ledgerhq/coin-near/account"; +import vechain from "@ledgerhq/coin-vechain/account"; export default { crypto_org, - vechain, bitcoin, cardano, icon, near, + vechain, }; diff --git a/libs/ledger-live-common/src/generated/bridge/js.ts b/libs/ledger-live-common/src/generated/bridge/js.ts index 6e8177397694..38193f9f776f 100644 --- a/libs/ledger-live-common/src/generated/bridge/js.ts +++ b/libs/ledger-live-common/src/generated/bridge/js.ts @@ -2,7 +2,6 @@ import casper from "../../families/casper/bridge/js"; import celo from "../../families/celo/bridge/js"; import crypto_org from "../../families/crypto_org/bridge/js"; import internet_computer from "../../families/internet_computer/bridge/js"; -import vechain from "../../families/vechain/bridge/js"; import { bridge as algorand } from "../../families/algorand/setup"; import { bridge as bitcoin } from "../../families/bitcoin/setup"; import { bridge as cardano } from "../../families/cardano/setup"; @@ -20,6 +19,7 @@ import { bridge as stellar } from "../../families/stellar/setup"; import { bridge as tezos } from "../../families/tezos/setup"; import { bridge as ton } from "../../families/ton/setup"; import { bridge as tron } from "../../families/tron/setup"; +import { bridge as vechain } from "../../families/vechain/setup"; import { bridge as xrp } from "../../families/xrp/setup"; export default { @@ -27,7 +27,6 @@ export default { celo, crypto_org, internet_computer, - vechain, algorand, bitcoin, cardano, @@ -45,5 +44,6 @@ export default { tezos, ton, tron, + vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/bridge/mock.ts b/libs/ledger-live-common/src/generated/bridge/mock.ts index 51bc56c966ca..a4b5ae66cce5 100644 --- a/libs/ledger-live-common/src/generated/bridge/mock.ts +++ b/libs/ledger-live-common/src/generated/bridge/mock.ts @@ -11,7 +11,6 @@ import solana from "../../families/solana/bridge/mock"; import stellar from "../../families/stellar/bridge/mock"; import tezos from "../../families/tezos/bridge/mock"; import tron from "../../families/tron/bridge/mock"; -import vechain from "../../families/vechain/bridge/mock"; import xrp from "../../families/xrp/bridge/mock"; export default { @@ -28,6 +27,5 @@ export default { stellar, tezos, tron, - vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/cli-transaction.ts b/libs/ledger-live-common/src/generated/cli-transaction.ts index e4c57400406d..02d5f8eb1ff3 100644 --- a/libs/ledger-live-common/src/generated/cli-transaction.ts +++ b/libs/ledger-live-common/src/generated/cli-transaction.ts @@ -1,6 +1,5 @@ import celo from "../families/celo/cli-transaction"; import crypto_org from "../families/crypto_org/cli-transaction"; -import vechain from "../families/vechain/cli-transaction"; import { cliTools as algorand } from "../families/algorand/setup"; import { cliTools as bitcoin } from "../families/bitcoin/setup"; import { cliTools as cardano } from "../families/cardano/setup"; @@ -18,12 +17,12 @@ import { cliTools as stellar } from "../families/stellar/setup"; import { cliTools as tezos } from "../families/tezos/setup"; import { cliTools as ton } from "../families/ton/setup"; import { cliTools as tron } from "../families/tron/setup"; +import { cliTools as vechain } from "../families/vechain/setup"; import { cliTools as xrp } from "../families/xrp/setup"; export default { celo, crypto_org, - vechain, algorand, bitcoin, cardano, @@ -41,5 +40,6 @@ export default { tezos, ton, tron, + vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/hw-getAddress.ts b/libs/ledger-live-common/src/generated/hw-getAddress.ts index 1f7c750cc2c9..acc39f116e0d 100644 --- a/libs/ledger-live-common/src/generated/hw-getAddress.ts +++ b/libs/ledger-live-common/src/generated/hw-getAddress.ts @@ -2,7 +2,6 @@ import casper from "../families/casper/hw-getAddress"; import celo from "../families/celo/hw-getAddress"; import crypto_org from "../families/crypto_org/hw-getAddress"; import internet_computer from "../families/internet_computer/hw-getAddress"; -import vechain from "../families/vechain/hw-getAddress"; import { resolver as algorand } from "../families/algorand/setup"; import { resolver as bitcoin } from "../families/bitcoin/setup"; import { resolver as cardano } from "../families/cardano/setup"; @@ -20,6 +19,7 @@ import { resolver as stellar } from "../families/stellar/setup"; import { resolver as tezos } from "../families/tezos/setup"; import { resolver as ton } from "../families/ton/setup"; import { resolver as tron } from "../families/tron/setup"; +import { resolver as vechain } from "../families/vechain/setup"; import { resolver as xrp } from "../families/xrp/setup"; export default { @@ -27,7 +27,6 @@ export default { celo, crypto_org, internet_computer, - vechain, algorand, bitcoin, cardano, @@ -45,5 +44,6 @@ export default { tezos, ton, tron, + vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/hw-signMessage.ts b/libs/ledger-live-common/src/generated/hw-signMessage.ts index e062112bc823..c72976f5903c 100644 --- a/libs/ledger-live-common/src/generated/hw-signMessage.ts +++ b/libs/ledger-live-common/src/generated/hw-signMessage.ts @@ -1,6 +1,5 @@ import casper from "../families/casper/hw-signMessage"; import internet_computer from "../families/internet_computer/hw-signMessage"; -import vechain from "../families/vechain/hw-signMessage"; import { messageSigner as bitcoin } from "../families/bitcoin/setup"; import { messageSigner as evm } from "../families/evm/setup"; import { messageSigner as filecoin } from "../families/filecoin/setup"; @@ -9,7 +8,6 @@ import { messageSigner as ton } from "../families/ton/setup"; export default { casper, internet_computer, - vechain, bitcoin, evm, filecoin, diff --git a/libs/ledger-live-common/src/generated/mock.ts b/libs/ledger-live-common/src/generated/mock.ts index ce694fe66d4e..b1febbae1628 100644 --- a/libs/ledger-live-common/src/generated/mock.ts +++ b/libs/ledger-live-common/src/generated/mock.ts @@ -1,9 +1,9 @@ -import vechain from "../families/vechain/mock"; import algorand from "@ledgerhq/coin-algorand/mock"; import cosmos from "@ledgerhq/coin-cosmos/mock"; +import vechain from "@ledgerhq/coin-vechain/mock"; export default { - vechain, algorand, cosmos, + vechain, }; diff --git a/libs/ledger-live-common/src/generated/specs.ts b/libs/ledger-live-common/src/generated/specs.ts index 5c6868beb8c9..9a8b0dc12629 100644 --- a/libs/ledger-live-common/src/generated/specs.ts +++ b/libs/ledger-live-common/src/generated/specs.ts @@ -2,7 +2,6 @@ import casper from "../families/casper/specs"; import celo from "../families/celo/specs"; import crypto_org from "../families/crypto_org/specs"; import internet_computer from "../families/internet_computer/specs"; -import vechain from "../families/vechain/specs"; import algorand from "@ledgerhq/coin-algorand/specs"; import bitcoin from "@ledgerhq/coin-bitcoin/specs"; import cardano from "@ledgerhq/coin-cardano/specs"; @@ -20,6 +19,7 @@ import stellar from "@ledgerhq/coin-stellar/specs"; import tezos from "@ledgerhq/coin-tezos/specs"; import ton from "@ledgerhq/coin-ton/specs"; import tron from "@ledgerhq/coin-tron/specs"; +import vechain from "@ledgerhq/coin-vechain/specs"; import xrp from "@ledgerhq/coin-xrp/specs"; export default { @@ -27,7 +27,6 @@ export default { celo, crypto_org, internet_computer, - vechain, algorand, bitcoin, cardano, @@ -45,5 +44,6 @@ export default { tezos, ton, tron, + vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/transaction.ts b/libs/ledger-live-common/src/generated/transaction.ts index 1418d8f3bb93..766e2199131d 100644 --- a/libs/ledger-live-common/src/generated/transaction.ts +++ b/libs/ledger-live-common/src/generated/transaction.ts @@ -2,7 +2,6 @@ import casper from "../families/casper/transaction"; import celo from "../families/celo/transaction"; import crypto_org from "../families/crypto_org/transaction"; import internet_computer from "../families/internet_computer/transaction"; -import vechain from "../families/vechain/transaction"; import algorand from "@ledgerhq/coin-algorand/transaction"; import bitcoin from "@ledgerhq/coin-bitcoin/transaction"; import cardano from "@ledgerhq/coin-cardano/transaction"; @@ -20,6 +19,7 @@ import stellar from "@ledgerhq/coin-stellar/transaction"; import tezos from "@ledgerhq/coin-tezos/transaction"; import ton from "@ledgerhq/coin-ton/transaction"; import tron from "@ledgerhq/coin-tron/transaction"; +import vechain from "@ledgerhq/coin-vechain/transaction"; import xrp from "@ledgerhq/coin-xrp/transaction"; export default { @@ -27,7 +27,6 @@ export default { celo, crypto_org, internet_computer, - vechain, algorand, bitcoin, cardano, @@ -45,5 +44,6 @@ export default { tezos, ton, tron, + vechain, xrp, }; diff --git a/libs/ledger-live-common/src/generated/types.ts b/libs/ledger-live-common/src/generated/types.ts index 96e3edb9536d..a09d8e051e30 100644 --- a/libs/ledger-live-common/src/generated/types.ts +++ b/libs/ledger-live-common/src/generated/types.ts @@ -129,7 +129,7 @@ import type { TransactionRaw as vechainTransactionRaw, TransactionStatus as vechainTransactionStatus, TransactionStatusRaw as vechainTransactionStatusRaw, -} from "../families/vechain/types"; +} from "@ledgerhq/coin-vechain/types/index"; import type { Transaction as xrpTransaction, TransactionRaw as xrpTransactionRaw, diff --git a/libs/ledger-live-common/src/hw/actions/implementations.ts b/libs/ledger-live-common/src/hw/actions/implementations.ts index f2cca5571899..63470b675db5 100644 --- a/libs/ledger-live-common/src/hw/actions/implementations.ts +++ b/libs/ledger-live-common/src/hw/actions/implementations.ts @@ -63,7 +63,7 @@ export const defaultImplementationConfig: PollingImplementationConfig = { pollingFrequency: 2000, initialWaitTime: 5000, reconnectWaitTime: 5000, - connectionTimeout: getEnv("MOCK") ? 60000 : 20000, + connectionTimeout: getEnv("DETOX") ? 60000 : 20000, }; type Implementation = ( params: PollingImplementationParams, diff --git a/libs/ledger-live-common/src/platform/providers/RemoteLiveAppProvider/api/index.ts b/libs/ledger-live-common/src/platform/providers/RemoteLiveAppProvider/api/index.ts index ee5db24befe3..aee10c2172d1 100644 --- a/libs/ledger-live-common/src/platform/providers/RemoteLiveAppProvider/api/index.ts +++ b/libs/ledger-live-common/src/platform/providers/RemoteLiveAppProvider/api/index.ts @@ -7,7 +7,7 @@ import mockData from "./mock.json"; const api = { fetchLiveAppManifests: async (url: string, params?: FilterParams): Promise => { - if (getEnv("MOCK")) { + if (getEnv("MOCK") || getEnv("DETOX")) { if (getEnv("MOCK_REMOTE_LIVE_MANIFEST")) { return [ ...mockData, diff --git a/libs/speculos-transport/src/index.ts b/libs/speculos-transport/src/index.ts index d365acb56b46..16b33ff782b7 100644 --- a/libs/speculos-transport/src/index.ts +++ b/libs/speculos-transport/src/index.ts @@ -24,13 +24,13 @@ export type SpeculosDeviceInternal = buttonPort: number; automationPort: number; transport: SpeculosTransportWebsocket; - destroy: () => void; + destroy: () => Promise; } | { process: ChildProcessWithoutNullStreams; apiPort: string | undefined; transport: SpeculosTransportHttp; - destroy: () => void; + destroy: () => Promise; }; // FIXME we need to figure out a better system, using a filesystem file? @@ -235,10 +235,10 @@ export async function createSpeculosDevice( }); let destroyed = false; - const destroy = () => { + const destroy = async () => { if (destroyed) return; destroyed = true; - new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { if (!data[speculosID]) return; delete data[speculosID]; exec(`docker rm -f ${speculosID}`, (error, stdout, stderr) => { @@ -259,7 +259,7 @@ export async function createSpeculosDevice( } }); let latestStderr: string | undefined; - p.stderr.on("data", data => { + p.stderr.on("data", async data => { if (!data) return; latestStderr = data; @@ -276,16 +276,16 @@ export async function createSpeculosDevice( } else if (data.includes("address already in use")) { if (maxRetry > 0) { log("speculos", "retrying speculos connection"); - destroy(); + await destroy(); resolveReady(false); } } }); - p.on("close", () => { + p.on("close", async () => { log("speculos", `${speculosID} closed`); if (!destroyed) { - destroy(); + await destroy(); rejectReady(new Error(`speculos process failure. ${latestStderr || ""}`)); } }); diff --git a/package.json b/package.json index 21b28351c2f6..e728e6e24eb9 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "watch:ljs": "pnpm turbo run watch --filter=\"./libs/ledgerjs/**\" --concurrency 44", "watch:es:ljs": "pnpm turbo run watch:es --filter=\"./libs/ledgerjs/**\" --concurrency 44", "watch:common": "pnpm turbo run watch --filter=./libs/ledger-live-common", + "watch:es:common": "pnpm turbo run watch:es --filter=./libs/ledger-live-common", "dev:cli": "pnpm turbo run watch --filter=@ledgerhq/live-cli", "dev:lld": "pnpm turbo start --filter=ledger-live-desktop", "dev:lld:debug": "DEV_TOOLS=1 LEDGER_INTERNAL_ARGS=--inspect ELECTRON_ARGS=--remote-debugging-port=8315 pnpm turbo start --filter=ledger-live-desktop", @@ -84,6 +85,7 @@ "coin:stellar": "pnpm --filter coin-stellar", "coin:tezos": "pnpm --filter coin-tezos", "coin:tron": "pnpm --filter coin-tron", + "coin:vechain": "pnpm --filter coin-vechain", "coin:xrp": "pnpm --filter coin-xrp", "evm-tools": "pnpm --filter evm-tools", "domain": "pnpm --filter domain-service", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29a2c741804c..fe2f565d1319 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3224,6 +3224,73 @@ importers: specifier: ^5.4.5 version: 5.6.3 + libs/coin-modules/coin-vechain: + dependencies: + '@ledgerhq/coin-framework': + specifier: workspace:^ + version: link:../../coin-framework + '@ledgerhq/cryptoassets': + specifier: workspace:^ + version: link:../../ledgerjs/packages/cryptoassets + '@ledgerhq/devices': + specifier: workspace:* + version: link:../../ledgerjs/packages/devices + '@ledgerhq/errors': + specifier: workspace:^ + version: link:../../ledgerjs/packages/errors + '@ledgerhq/live-env': + specifier: workspace:^ + version: link:../../env + '@ledgerhq/live-network': + specifier: workspace:^ + version: link:../../live-network + bignumber.js: + specifier: ^9.1.2 + version: 9.1.2 + eip55: + specifier: ^2.1.1 + version: 2.1.1 + invariant: + specifier: ^2.2.2 + version: 2.2.4 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + rxjs: + specifier: ^7.8.1 + version: 7.8.1 + thor-devkit: + specifier: ^2.0.6 + version: 2.0.9 + devDependencies: + '@ledgerhq/coin-tester': + specifier: workspace:^ + version: link:../../coin-tester + '@ledgerhq/types-cryptoassets': + specifier: workspace:^ + version: link:../../ledgerjs/packages/types-cryptoassets + '@ledgerhq/types-live': + specifier: workspace:^ + version: link:../../ledgerjs/packages/types-live + '@types/invariant': + specifier: ^2.2.2 + version: 2.2.37 + '@types/jest': + specifier: ^29.5.10 + version: 29.5.12 + '@types/lodash': + specifier: ^4.14.191 + version: 4.17.7 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + jest: + specifier: ^29.7.0 + version: 29.7.0 + ts-jest: + specifier: ^29.1.1 + version: 29.1.5(jest@29.7.0)(typescript@5.4.3) + libs/coin-modules/coin-xrp: dependencies: '@ledgerhq/coin-framework': @@ -3774,6 +3841,9 @@ importers: '@ledgerhq/coin-tron': specifier: workspace:^ version: link:../coin-modules/coin-tron + '@ledgerhq/coin-vechain': + specifier: workspace:^ + version: link:../coin-modules/coin-vechain '@ledgerhq/coin-xrp': specifier: workspace:^ version: link:../coin-modules/coin-xrp @@ -3978,9 +4048,6 @@ importers: date-fns: specifier: ^2.23.0 version: 2.30.0 - eip55: - specifier: ^2.1.1 - version: 2.1.1 expect: specifier: ^27.4.6 version: 27.5.1 @@ -4041,9 +4108,6 @@ importers: simple-cbor: specifier: ^0.4.1 version: 0.4.1 - thor-devkit: - specifier: ^2.0.6 - version: 2.0.9 triple-beam: specifier: ^1.3.0 version: 1.4.1