Skip to content

Linearize Send Flow#2764

Open
leofelix077 wants to merge 22 commits into
masterfrom
feature/linearize-send-flow
Open

Linearize Send Flow#2764
leofelix077 wants to merge 22 commits into
masterfrom
feature/linearize-send-flow

Conversation

@leofelix077
Copy link
Copy Markdown
Collaborator

@leofelix077 leofelix077 commented May 11, 2026

Closes #2686

This PR linearizes the extension Send flow so users move more consistently from recipient selection to amount entry to review, with cleaner state handoff between steps.
It improves recipient UX by keeping Recents and My Accounts visible while searching, making Suggestions pressable like other destination options, and debouncing validation/search feedback to avoid premature errors.
It also hardens amount handling by preserving the exact source value when switching between fiat and token views, improving numeric sanitization, and fixing edge cases like formatted thousands leading to invalid amount states.
Additionally, it includes reliability and polish updates across query-param handling, submit safeguards, collectible grouping/styling, locale cleanup, and Send flow test coverage.

initial.flow.and.navigation.mov
input-validation-and-preservation.mov
changing-address-and-token.mov
fullscreen-smoke-test.mov
sending-to-federated-p1.mov
sending-to-federated-p2-and-recents.mov

Adding back the memo and fee row that was missing from previous videos:

Screenshot 2026-05-14 at 15 28 48 Screenshot 2026-05-14 at 15 29 00

@leofelix077 leofelix077 self-assigned this May 11, 2026
@leofelix077 leofelix077 added wip not for merging yet don't review yet wip / tests in progress / missing videos or screenshots / pending self code-review labels May 11, 2026
Copilot AI review requested due to automatic review settings May 11, 2026 16:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an initial “linearized” Send flow in the popup, aligning with the desired UX of selecting a token first (unless pre-selected via query params), then choosing destination, then entering amount, with step transition animations and updated tests.

Changes:

  • Added a new initial Send step (SELECT_SOURCE_ASSET) and step transition animations (enter from bottom/right/left + dismiss/exit overlay).
  • Updated Send screens to support the new step order, including “My Accounts” recipient picking and persisting/displaying a recipientName.
  • Updated unit and e2e tests to reflect the new flow and added supporting selectors/testids.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
extension/src/popup/views/Send/styles.scss Adds CSS keyframes/classes for step transition animations and dismiss overlay behavior.
extension/src/popup/views/Send/index.tsx Implements the new step state machine (token picker first unless query param preselect) and animation wiring.
extension/src/popup/views/tests/SendPayment.test.tsx Re-enables Send tests, adds initial-step assertions, and skips legacy tests pending rewrite.
extension/src/popup/locales/pt/translation.json Adds new i18n keys used by the refreshed Send UI (currently with untranslated values).
extension/src/popup/locales/en/translation.json Adds new i18n keys used by the refreshed Send UI (including a new “don’t” variant key).
extension/src/popup/ducks/transactionSubmission.ts Persists recipientName in redux transaction data and exposes saveRecipientName.
extension/src/popup/constants/send-payment.ts Adds the SELECT_SOURCE_ASSET step to the send flow enum.
extension/src/popup/components/send/styles.scss Updates SendAmount styling for the new card layout, inline asset selector, and percentage buttons.
extension/src/popup/components/send/SendTo/index.tsx Updates destination step header and adds “My Accounts” list that can set recipientName.
extension/src/popup/components/send/SendDestinationAsset/styles.scss Adjusts destination-asset selector styling (collectibles heading/section).
extension/src/popup/components/send/SendDestinationAsset/index.tsx Removes token/collectibles tabs and renders tokens + collectibles section in one view; adds returnToAmount.
extension/src/popup/components/send/SendAmount/index.tsx Refactors amount screen layout (recipient at top, inline asset selector, pct buttons, settings button).
extension/src/popup/components/send/AddressTile/index.tsx Allows displaying recipientName as primary text with address/federation as secondary.
extension/src/popup/components/InternalTransaction/TokenList/index.tsx Adds data-testid="token-list" to support updated test assertions.
extension/src/popup/components/InternalTransaction/SubmitTransaction/index.tsx Displays recipientName (if set) in the transaction summary instead of only truncated address.
extension/src/popup/components/InternalTransaction/SubmitTransaction/hooks/useSubmitTxData.tsx Avoids adding self-owned destinations to recent addresses.
extension/e2e-tests/test-fixtures.ts Adds optional viewport sizing to the Playwright context fixture.
extension/e2e-tests/sendPayment.test.ts Updates existing e2e flows for the new step order and adds new flow-specific e2e cases.
Comments suppressed due to low confidence (1)

extension/src/popup/views/tests/SendPayment.test.tsx:31

  • The same module ("popup/helpers/blockaid") is imported twice under two different identifiers (BlockaidHelpers and BlockAidHelpers). This is redundant and makes the test harder to follow. Consolidate to a single import name and update references accordingly.
import * as ApiInternal from "@shared/api/internal";
import * as UseNetworkFees from "popup/helpers/useNetworkFees";
import * as BlockaidHelpers from "popup/helpers/blockaid";
import * as UseGetCollectibles from "helpers/hooks/useGetCollectibles";
import * as ExtensionMessaging from "@shared/api/helpers/extensionMessaging";
import * as TokenList from "@shared/api/helpers/token-list";
import {
  TESTNET_NETWORK_DETAILS,
  DEFAULT_NETWORKS,
  MAINNET_NETWORK_DETAILS,
} from "@shared/constants/stellar";

import { APPLICATION_STATE as ApplicationState } from "@shared/constants/applicationState";
import { ROUTES } from "popup/constants/routes";
import { Send } from "popup/views/Send";
import { initialState as transactionSubmissionInitialState } from "popup/ducks/transactionSubmission";
import * as CheckSuspiciousAsset from "popup/helpers/checkForSuspiciousAsset";
import * as tokenPaymentActions from "popup/ducks/token-payment";
import * as GetIconHelper from "@shared/api/helpers/getIconUrlFromIssuer";
import * as BlockAidHelpers from "popup/helpers/blockaid";

jest.mock("lodash/debounce", () => jest.fn((fn) => fn));

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread extension/src/popup/components/send/SendAmount/index.tsx Outdated
Comment thread extension/src/popup/components/send/SendAmount/index.tsx
Comment thread extension/src/popup/views/Send/index.tsx Outdated
Comment thread extension/src/popup/views/Send/index.tsx Outdated
Comment thread extension/src/popup/views/Send/index.tsx Outdated
Comment thread extension/src/popup/views/__tests__/SendPayment.test.tsx Outdated
Comment thread extension/src/popup/components/send/SendAmount/index.tsx
Comment thread extension/src/popup/locales/pt/translation.json
Comment thread extension/src/popup/locales/pt/translation.json Outdated
Comment thread extension/src/popup/locales/pt/translation.json Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

extension/src/popup/views/Send/hooks/useSendQueryParams.ts:119

  • When ?asset is missing, the hook still dispatches saveIsToken(false) / saveIsCollectible(false) even if transactionData.asset is already set to a token/collectible. That can desync asset vs isToken after navigation. Consider only resetting these flags when you also set the default asset, or derive them from the existing transactionData.asset.
    } else {
      // Set default asset to native if not already set
      if (!transactionData.asset) {
        dispatch(saveAsset("native"));
      }
      dispatch(saveIsCollectible(false));
      dispatch(saveIsToken(false));
    }

extension/src/popup/locales/pt/translation.json:728

  • The pt locale value for the smart-apostrophe key "You don’t have enough {{asset}} in your account" is currently English. This string is still referenced elsewhere (e.g., SwapAmount), so users will see English error text in Portuguese UI. Translate this value (or consolidate keys) to keep locale coverage consistent.
  "You can close this screen, your transaction should be complete in less than a minute.": "Você pode fechar esta tela, sua transação deve estar completa em menos de um minuto.",
  "You can define your own assets lists in Settings.": "Você pode definir suas próprias listas de ativos nas Configurações.",
  "You don't have enough {{asset}} in your account": "Você não tem {{asset}} suficiente em sua conta",
  "You don’t have enough {{asset}} in your account": "You don’t have enough {{asset}} in your account",
  "You have no assets added.": "Você não tem ativos adicionados.",

Comment thread extension/src/popup/views/Send/hooks/useSendQueryParams.ts
Comment thread extension/src/popup/components/send/SendTo/index.tsx Outdated
Comment thread extension/src/popup/locales/pt/translation.json
@leofelix077 leofelix077 changed the title add initial version of linearize send flow Linearize Send Flow May 13, 2026
@leofelix077 leofelix077 added enhancement New feature or request and removed wip not for merging yet don't review yet wip / tests in progress / missing videos or screenshots / pending self code-review labels May 13, 2026
@leofelix077 leofelix077 requested a review from Copilot May 13, 2026 20:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

extension/src/popup/views/tests/SendPayment.test.tsx:781

  • This new test is declared at the top level (outside the describe("Send", ...) block), so it won’t inherit the suite’s beforeEach mocks (e.g. BlockaidHelpers.useScanTx, etc.). That can cause it to run with real implementations and become flaky/fail. Move it into the existing describe("Send") suite (or add the necessary setup/mocks locally).

Comment thread extension/src/popup/views/Send/index.tsx Outdated
Comment thread extension/src/popup/views/__tests__/SendPayment.test.tsx
Comment thread extension/src/popup/locales/pt/translation.json Outdated
Comment thread extension/src/popup/components/send/SendAmount/index.tsx
@leofelix077 leofelix077 added don't review yet wip / tests in progress / missing videos or screenshots / pending self code-review and removed enhancement New feature or request labels May 14, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 38 out of 38 changed files in this pull request and generated 2 comments.

Comment on lines 215 to 218
const hasError = sendDataState.state === RequestState.ERROR;
const isLoading =
sendDataState.state === RequestState.IDLE ||
sendDataState.state === RequestState.LOADING;
@leofelix077 leofelix077 added enhancement New feature or request and removed don't review yet wip / tests in progress / missing videos or screenshots / pending self code-review labels May 14, 2026
@leofelix077 leofelix077 requested review from CassioMG and piyalbasu May 14, 2026 23:35
@piyalbasu
Copy link
Copy Markdown
Contributor

Code review

Found 1 issue:

  1. The Soroban "Account doesn't exist" warning gate from master commit d8ee94c8 (#2778, landed 2026-05-15) is not applied in the refactored SendTo. Master rendered <AccountDoesntExistWarning /> behind shouldShowAccountDoesntExistWarning({ assetCanonical: asset, destination, isCollectible, isFunded }) (from popup/helpers/sendWarnings.ts) so that pure-Soroban custom tokens sent to a contract or unfunded destination wouldn't display the misleading "Send at least 1 XLM to create account" notice. This PR reverts to an unconditional !isFunded check, which after a rebase will re-introduce the bug #2778 fixed.

    <>
    {resolvedSendData.destinationBalances &&
    !resolvedSendData.destinationBalances.isFunded && (
    <AccountDoesntExistWarning />
    )}
    <div className="SendTo__subheading">

    Suggest pulling shouldShowAccountDoesntExistWarning into the new flow (and re-selecting asset/isCollectible from transactionDataSelector) to preserve the fix.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

extensionId,
context,
}) => {
test.slow();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice we're using a lot of test.slow(). Why is this necessary? This isn't necessarily wrong, but it does triple the time a test has to run (15s vs 45s). If a test fails, you'll have to wait 45s for it terminate.

It's best to avoid this unless it's absolutely necessary to make sure our tests run and fail quickly

await expect(page.getByTestId("send-amount-fee-display")).toHaveText(
"0.00001 XLM",
"0.0093338 XLM",
{ timeout: 10000 },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10s is a pretty long timeout. Shouldn't this happen pretty quickly if the API calls are stubbed?

await page.getByTestId("nav-link-swap").click();
await expect(page.getByTestId("AppHeaderPageTitle")).toContainText("Swap");
await expect(page.getByTestId("swap-src-asset-tile")).toBeVisible({
timeout: 15000,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar comment about the timeouts here

["75%", 75],
] as const;

const normalizeNumericString = (value: string) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: it might be nice to move this helper and the 2 below this to the formatters helpers file so all the formatting utils are in 1 place

@piyalbasu
Copy link
Copy Markdown
Contributor

Occasionally, I'm seeing a loader briefly under the destination address bar that pushes everything down. It's not clear what it's loading:

Screen.Recording.2026-05-15.at.5.21.40.PM.mov

@piyalbasu
Copy link
Copy Markdown
Contributor

The number input in the Swap amount input isn't quite displaying correctly

Screen.Recording.2026-05-15.at.5.25.21.PM.mov

@piyalbasu
Copy link
Copy Markdown
Contributor

If you click Swap from the Asset Detail, pressing back goes back to the Account screen

But, if you click Send from the Asset Detail, pressing back goes back to the Asset Detail screen

Screen.Recording.2026-05-15.at.5.27.28.PM.mov

@CassioMG
Copy link
Copy Markdown
Contributor

Found a few issues:

1 - Weird double AQUA balances when entering fiat amount
Screenshot 2026-05-15 at 14 51 32

2 - When you start the Send flow from the Token Details screen it'll pre-select the token and it won't let you change the token using the picker. The picker opens, you tap to select a different token but nothing happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linearize Send flow from Home screen

4 participants