diff --git a/CHANGELOG.md b/CHANGELOG.md index 12fe47fb7f1..c9a1f5f24f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased (develop) +- added: Houdini private-send prototype scene (Proposal A) reachable from a wallet's Send button, with hard-coded linked amounts, a recipient-asset picker, a Private send toggle, and modal vs swap-success completion paths. - added: Remote enable/disable of gift card providers via the info server's giftCardInfo config, supporting whole-provider disabling for Phaze and Bitrefill and per-brand disabling for Phaze. ## 4.49.0 (staging) diff --git a/maestro/14-houdini/houdini-send-a.yaml b/maestro/14-houdini/houdini-send-a.yaml new file mode 100644 index 00000000000..1de5d2c0502 --- /dev/null +++ b/maestro/14-houdini/houdini-send-a.yaml @@ -0,0 +1,85 @@ +# Houdini incognito-send prototype walk — Proposal A (From -> To grouping). +# +# Opens the Bitcoin wallet, taps Send (the wallet Send button is routed to the +# prototype scene), and walks every branch. Nothing talks to Houdini; every +# value is hard-coded by HoudiniSendScene. The reroute passes variant 'a1' (the +# "Recipient receives" row is visible before a selection); variant 'a2' hides +# that row until a selection is made. +# +# Screenshots captured (under ~/.maestro/tests// ): +# houdini-a-01-plain-initial same-asset start: add-recipient affordance, +# no amount / fee rows yet, "Recipient receives" +# visible (a1) +# houdini-a-02-after-address after a recipient is chosen: You send + Network +# Fee rows appear +# houdini-a-03-incognito incognito on: toggle tile expands with +# messaging, Recipient gets shows conversion % +# houdini-a-04-swap-xmr cross-asset XMR: conversion % + Destination Tag +appId: ${APP_ID} +env: + APP_ID: co.edgesecure.app + PIN_DIGIT: '0' +tags: + - houdini +--- +- launchApp +- runFlow: + when: + visible: 'Exit PIN' + commands: + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 1500 } +- runFlow: + when: + visible: 'Security is Our Priority' + commands: + - tapOn: 'Cancel' +# Dismiss the unrelated Stellar/Horizon plugin error toast if present. +- tapOn: + text: '.*Horizon.*' + optional: true + +# Open the Bitcoin wallet, then Send (routed to the prototype scene). Gate on +# the wallet tx-list "Receive" button so Send cannot misfire on the home Send. +- tapOn: 'Assets' +- waitForAnimationToEnd: + timeout: 2000 +- tapOn: 'My Bitcoin' +- assertVisible: 'Receive' +- tapOn: 'Send' +- waitForAnimationToEnd: + timeout: 3000 + +# Plain same-asset start: add-recipient affordance, no amount/fee rows yet. +- assertVisible: 'Incognito send' +- assertVisible: 'Send to Address' +- takeScreenshot: houdini-a-01-plain-initial + +# Choose a recipient via self-transfer -> reveals the amount + fee rows. +- tapOn: + text: '.*Myself' +- waitForAnimationToEnd: + timeout: 2000 +- tapOn: 'My Bitcoin 3' +- waitForAnimationToEnd: + timeout: 2500 +- assertVisible: 'You send' +- assertVisible: 'Network Fee' +- takeScreenshot: houdini-a-02-after-address + +# Incognito on: toggle tile expands, Recipient gets shows the conversion percent. +- tapOn: 'Incognito send' +- assertVisible: 'Incognito routes your send.*' +- assertVisible: 'Recipient gets' +- takeScreenshot: houdini-a-03-incognito + +# Cross-asset: pick XMR (asset mismatch routes through Houdini). +- tapOn: 'Incognito send' +- tapOn: 'Recipient receives' +- tapOn: + text: 'XMR Monero.*' +- assertVisible: 'Monero' +- assertVisible: 'Destination Tag' +- takeScreenshot: houdini-a-04-swap-xmr diff --git a/maestro/14-houdini/houdini-swap-a.yaml b/maestro/14-houdini/houdini-swap-a.yaml new file mode 100644 index 00000000000..6f04422ed93 --- /dev/null +++ b/maestro/14-houdini/houdini-swap-a.yaml @@ -0,0 +1,66 @@ +# Houdini incognito-swap prototype walk — Proposal A. +# +# Opens the Bitcoin wallet, taps Trade -> "Swap BTC to/from another crypto" (the +# wallet swap action is routed to the prototype HoudiniSwapScene), enters +# amounts with the incognito toggle in a card, then gets a mock quote +# ("Powered by Houdini", no chevron). Nothing talks to Houdini. +# +# Screenshots captured (under ~/.maestro/tests// ): +# houdini-swap-01-entry from/to amount entry, incognito toggle in a card +# houdini-swap-02-incognito incognito on: toggle card expands with messaging +# houdini-swap-03-quote mock quote scene, "Powered by Houdini" (no chevron) +appId: ${APP_ID} +env: + APP_ID: co.edgesecure.app + PIN_DIGIT: '0' +tags: + - houdini +--- +- launchApp +- runFlow: + when: + visible: 'Exit PIN' + commands: + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 900 } + - tapOn: { text: '${PIN_DIGIT}', waitToSettleTimeoutMs: 1500 } +- tapOn: + text: '.*Horizon.*' + optional: true + +# Open the Bitcoin wallet, then Trade -> Swap (routed to the prototype scene). +- tapOn: 'Assets' +- waitForAnimationToEnd: + timeout: 2000 +- tapOn: 'My Bitcoin' +- assertVisible: 'Receive' +- tapOn: 'Trade' +- waitForAnimationToEnd: + timeout: 2000 +- tapOn: 'Swap BTC to/from another crypto' +- waitForAnimationToEnd: + timeout: 3000 + +# Swap amount entry, incognito toggle in a card. +- assertVisible: 'You send' +- assertVisible: 'You receive' +- assertVisible: 'Incognito send' +- takeScreenshot: houdini-swap-01-entry + +# Incognito on: the toggle card expands with messaging. +- tapOn: 'Incognito send' +- assertVisible: 'Incognito routes your send.*' +- takeScreenshot: houdini-swap-02-incognito + +# Slide to get the mock quote -> "Powered by Houdini" (no chevron). +- scrollUntilVisible: + element: + text: 'Slide to get quote' + direction: DOWN +- swipe: + start: 77%, 80% + end: 16%, 80% + duration: 1900 +- assertVisible: 'Powered by Houdini' +- takeScreenshot: houdini-swap-03-quote diff --git a/src/components/Main.tsx b/src/components/Main.tsx index 1d67d8131e3..626301512c6 100644 --- a/src/components/Main.tsx +++ b/src/components/Main.tsx @@ -106,6 +106,9 @@ import { } from './scenes/GuiPluginListScene' import { GuiPluginViewScene as GuiPluginViewSceneComponent } from './scenes/GuiPluginViewScene' import { HomeScene as HomeSceneComponent } from './scenes/HomeScene' +import { HoudiniSendScene as HoudiniSendSceneComponent } from './scenes/HoudiniSendScene' +import { HoudiniSwapQuoteScene as HoudiniSwapQuoteSceneComponent } from './scenes/HoudiniSwapQuoteScene' +import { HoudiniSwapScene as HoudiniSwapSceneComponent } from './scenes/HoudiniSwapScene' import { LoanCloseScene as LoanCloseSceneComponent } from './scenes/Loans/LoanCloseScene' import { LoanCreateConfirmationScene as LoanCreateConfirmationSceneComponent } from './scenes/Loans/LoanCreateConfirmationScene' import { LoanCreateScene as LoanCreateSceneComponent } from './scenes/Loans/LoanCreateScene' @@ -242,6 +245,9 @@ const FioStakingChangeScene = ifLoggedIn(FioStakingChangeSceneComponent) const FioStakingOverviewScene = ifLoggedIn(FioStakingOverviewSceneComponent) const GuiPluginViewScene = ifLoggedIn(GuiPluginViewSceneComponent) const HomeScene = ifLoggedIn(HomeSceneComponent) +const HoudiniSendScene = ifLoggedIn(HoudiniSendSceneComponent) +const HoudiniSwapScene = ifLoggedIn(HoudiniSwapSceneComponent) +const HoudiniSwapQuoteScene = ifLoggedIn(HoudiniSwapQuoteSceneComponent) const GiftCardAccountInfoScene = ifLoggedIn(GiftCardAccountInfoSceneComponent) const GiftCardListScene = ifLoggedIn(GiftCardListSceneComponent) const GiftCardMarketScene = ifLoggedIn(GiftCardMarketSceneComponent) @@ -1087,6 +1093,12 @@ const EdgeAppStack: React.FC = () => { options={{ headerShown: false }} /> + + +