Skip to content
Open
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
- added: MoonPay Trade swap provider
- added: Per-provider swap asset disables from the info server
- added: Copy button for the master private key or seed, cleared from the clipboard after one minute
- added: `stealth` navigation param that presets the Stealth Swap and Stealth Send toggles
- added: `edge://send` deep link that opens Send, optionally with Stealth Send on
- changed: Re-enable Pirate Chain on Android, using the smaller binary that downloads its Sapling parameters
- changed: Standardize wallet list automation test IDs to use period separators.
- changed: Lock the send confirmation slider for the rest of the scene once a broadcast has been attempted, whether the broadcast reported success or failure, and replace the generic failure card with a message that the transaction may have gone through, pointing at the block explorer or confirmation email before trying again.
Expand All @@ -39,6 +41,8 @@
- changed: Replace the flat `ENV` singleton with separate `CONFIG`, `KEYS`/`globalKeys`, and `pluginMaps` accessors (no top-level globalKeys flatten)
- changed: WalletConnect Smart Contract Call warning restated in the solid UI4 card
- changed: WalletConnect Connect button pinned to the bottom of Confirm Connection
- changed: Stealth Swap toggle shows on the swap scene before assets are selected
- changed: Stealth Send and Stealth Swap toggles remember the last setting per account
- fixed: Paybis and Simplex going missing from buy and sell on the launch after a slow or retried device attestation
- fixed: Missing wrong-device-clock warning on a launch that runs no device attestation
- fixed: Missing exchange rates when the device clock is set ahead
Expand Down
10 changes: 9 additions & 1 deletion maestro/14-stealth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,19 @@ private quote on a pair the suite does not cover is five `runFlow` steps:
AMOUNT: '30'
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'on'
- runFlow:
file: ../common/stealth-await-quote.yaml
```

Two things bite when writing these by hand:
Three things bite when writing these by hand:

- **The Stealth toggles are remembered per account** (synced settings), so a
scene can open with Stealth already on from an earlier run or another
device. `stealth-toggle.yaml` takes `STATE: on|off` and taps only when the
card is in the other state, so call it with an explicit state rather than
assuming the scene opens off.

- **The confirm slider is a pan gesture.** A coordinate swipe across the track
does nothing at all. `stealth-slide-to-confirm.yaml` swipes from the thumb by
Expand Down
8 changes: 8 additions & 0 deletions maestro/14-stealth/stealth-below-private-minimum.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account; this walk needs it off.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'
- runFlow:
file: ../common/stealth-pick-myself.yaml
env:
Expand All @@ -37,7 +42,10 @@ tags:
- runFlow:
file: ../common/stealth-await-quote.yaml

# Asking for on taps, since the explainer is hidden, and the tap is refused.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'on'
- assertVisible: 'Private routing needs at least.*'
- takeScreenshot: maestro/screenshots/stealth-below-min-01-toggle-refused
5 changes: 5 additions & 0 deletions maestro/14-stealth/stealth-cross-asset-quote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account; this walk needs it off.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'
- runFlow:
file: ../common/stealth-pick-myself.yaml
env:
Expand Down
2 changes: 2 additions & 0 deletions maestro/14-stealth/stealth-execute-send.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ tags:
AMOUNT: ${AMOUNT}
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'on'
- runFlow:
file: ../common/stealth-await-quote.yaml
env:
Expand Down
1 change: 1 addition & 0 deletions maestro/14-stealth/stealth-execute-swap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ tags:
file: ../common/stealth-toggle.yaml
env:
TOGGLE: 'Stealth Swap'
STATE: 'on'
- tapOn:
text: 'Tap to edit'
index: 0
Expand Down
5 changes: 5 additions & 0 deletions maestro/14-stealth/stealth-myself-picker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account; this walk needs it off.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'
- tapOn:
id: 'addressTileMyself'
- waitForAnimationToEnd:
Expand Down
7 changes: 7 additions & 0 deletions maestro/14-stealth/stealth-private-quote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account; this walk needs it off.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'
- runFlow:
file: ../common/stealth-pick-myself.yaml
env:
Expand All @@ -40,6 +45,8 @@ tags:

- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'on'
- takeScreenshot: maestro/screenshots/stealth-private-01-requoting
- runFlow:
file: ../common/stealth-await-quote.yaml
Expand Down
5 changes: 5 additions & 0 deletions maestro/14-stealth/stealth-qr-payment-uri.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account; this walk needs it off.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'

# Cross-asset destination: the source wallet cannot parse this chain's URI.
- runFlow:
Expand Down
9 changes: 9 additions & 0 deletions maestro/14-stealth/stealth-send.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,26 @@ tags:
WALLET_CODE: ${SRC_CODE}

# Plain same-asset start: the recipient selector is available before an address.
# The toggle is remembered per account, so it is forced off first.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'
- assertVisible: 'Stealth Send'
- assertVisible: 'Recipient receives'
- takeScreenshot: maestro/screenshots/stealth-send-01-initial

# Stealth on: the toggle card expands with the explainer and Learn more link.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'on'
- assertVisible: 'Uses a route that helps obfuscate.*Learn more.*'
- takeScreenshot: maestro/screenshots/stealth-send-02-stealth-on
- runFlow:
file: ../common/stealth-toggle.yaml
env:
STATE: 'off'

# A memo-required destination chain adds its tag row.
- runFlow:
Expand Down
7 changes: 7 additions & 0 deletions maestro/14-stealth/stealth-swap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ tags:
env:
WALLET: ${SRC_WALLET}
WALLET_CODE: ${SRC_CODE}
# The toggle is remembered per account, so it is forced off for the start.
- runFlow:
file: ../common/stealth-toggle.yaml
env:
TOGGLE: 'Stealth Swap'
STATE: 'off'
- assertVisible: 'Stealth Swap'
- takeScreenshot: maestro/screenshots/stealth-swap-01-start

- runFlow:
file: ../common/stealth-toggle.yaml
env:
TOGGLE: 'Stealth Swap'
STATE: 'on'
- assertVisible: 'Routes your swap through multiple.*Learn more.*'
- takeScreenshot: maestro/screenshots/stealth-swap-02-stealth-on
39 changes: 32 additions & 7 deletions maestro/common/stealth-toggle.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
# Flips the Stealth toggle.
# Sets the Stealth toggle to a requested state.
#
# env TOGGLE "Stealth Send" on the Send scene, "Stealth Swap" on the Exchange
# scene. Defaults to the Send scene's label.
# env STATE "on" or "off". Defaults to "on".
#
# The toggles are remembered per account, so a scene can open with Stealth
# already on from an earlier run. The helper reads the current state from the
# explainer text the card shows only while armed, and taps only when that state
# differs from STATE. A tap the scene refuses (below the private floor, an
# asset with no private route) leaves the explainer hidden and shows the reason
# instead, which callers can assert.
#
# Toggling always invalidates any held quote and refetches, because the private
# and transparent routes are different requests, so callers that need a live
# quote afterwards should follow with stealth-await-quote.yaml.
appId: ${APP_ID}
env:
APP_ID: ${MAESTRO_APP_ID || 'co.edgesecure.app'}
# Declared under a different name than the one callers pass: a subflow env
# Declared under different names than the ones callers pass: a subflow env
# entry that reuses the caller's key overwrites what the caller passed, so
# `TOGGLE: ${TOGGLE || default}` would silently ignore the argument.
TOGGLE_LABEL: ${TOGGLE || 'Stealth Send'}
TARGET: ${STATE || 'on'}
# The explainer text each card shows only while armed:
INFO: "${(TOGGLE || 'Stealth Send') == 'Stealth Swap' ? 'Routes your swap through multiple.*' : 'Uses a route that helps obfuscate.*'}"
---
# Rows can sit above or below the fold depending on where the previous step
# left the scroll position, so the row is brought into view from either side
# before it is tapped. A `scrollUntilVisible` that is already satisfied is a
# no-op, and one that scrolls the wrong way is optional and warns.
# before it is read. A `scrollUntilVisible` that is already satisfied is a
# no-op, and one that scrolls the wrong way is optional and warns. Centering
# the row also brings the explainer below it into view.
- scrollUntilVisible:
element:
text: '${TOGGLE_LABEL}'
Expand All @@ -32,6 +44,19 @@ env:
timeout: 4000
centerElement: true
optional: true
- tapOn: '${TOGGLE_LABEL}'
- waitForAnimationToEnd:
timeout: 2500
- runFlow:
when:
notVisible: '${INFO}'
true: ${TARGET == 'on'}
commands:
- tapOn: '${TOGGLE_LABEL}'
- waitForAnimationToEnd:
timeout: 2500
- runFlow:
when:
visible: '${INFO}'
true: ${TARGET == 'off'}
commands:
- tapOn: '${TOGGLE_LABEL}'
- waitForAnimationToEnd:
timeout: 2500
40 changes: 40 additions & 0 deletions src/__tests__/DeepLink.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,45 @@ describe('parseDeepLink', function () {
})
})

describe('send', () => {
makeLinkTests({
'edge://send?stealth=true': {
type: 'send',
asset: undefined,
stealth: true
},
'edge://send?stealth=true&asset=bitcoin': {
type: 'send',
asset: { pluginId: 'bitcoin', tokenId: null },
stealth: true
},
'https://deep.edge.app/send?asset=ethereum_0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&stealth=true':
{
type: 'send',
asset: {
pluginId: 'ethereum',
tokenId: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
},
stealth: true
},
'edge://send': {
type: 'send',
asset: undefined,
stealth: false
},
'edge://send?stealth=1&asset=monero': {
type: 'send',
asset: { pluginId: 'monero', tokenId: null },
stealth: false
},
'edge://send?stealth=true&asset=ethereum_': {
type: 'send',
asset: undefined,
stealth: true
}
})
})

describe('swap', () => {
makeLinkTests({
'edge://swap': {
Expand Down Expand Up @@ -876,6 +915,7 @@ describe('getDeepLinkReadiness', function () {
'wallets'
],
[{ type: 'rewards', pluginId: 'bitcoin', tokenId: null }, 'wallets'],
[{ type: 'send', stealth: true }, 'wallets'],
[{ type: 'walletConnect', uri: 'wc:topic@2' }, 'wallets'],

// An `exchange` link that names an asset opens the wallet picker, so it
Expand Down
Loading
Loading