Skip to content

Linearize Send Flow#2764

Merged
leofelix077 merged 32 commits into
masterfrom
feature/linearize-send-flow
Jun 4, 2026
Merged

Linearize Send Flow#2764
leofelix077 merged 32 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
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

PR Preview build is ready: https://github.com/stellar/freighter/releases/tag/untagged-42be88ebe943573ef6d1 (SDF collaborators only — install instructions in the release description)

@leofelix077
Copy link
Copy Markdown
Collaborator Author

leofelix077 commented May 19, 2026

@piyalbasu -> The swap flow is untouched (except for the issue with the input. there were some overlapping classes on Swap and Send. both were using the SendAmount classes. Adjusted now

@CassioMG adjusted the token change when coming from details

and also the other minor parts added to the comments

also merged the last changes from main on both mobile and extension

Screen.Recording.2026-05-19.at.10.45.18.mov
Screen.Recording.2026-05-19.at.11.28.33.mov

@CassioMG
Copy link
Copy Markdown
Contributor

@leofelix077 I'm still seeing the double token balances issue when entering fiat amount, see video below.

I'll cross-post here my comment from the mobile PR which has the same issue so you know how to repro it:

What appears to happen here is that the "token available balance" value which usually appears aligned on the right side (right below the dropdown) is conflicting with the "token amount to send" value which usually appears aligned on the left side. This probably only happens for big string amounts. I'd suggest applying some UI constraints here to prevent this from happening, or keep things flexible, but ensure that:

  • the "token available balance" always appear below the dropdown in all cases instead of jumping to the other side
  • the "refresh-cw-03" icon always appear right next to the "amount to send" value instead of breaking the line which results in the icon being placed on the left side of the "token available balance"
double-amounts-issue.mov

@@ -1,4 +1,5 @@
export enum STEPS {
SELECT_SOURCE_ASSET = "select-source-asset",
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: should we name it as SET_SOURCE_ASSET for consistency with SET_DESTINATION_ASSET below or do they represent distinct things?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it can be SET. it leads to the same action

@leofelix077
Copy link
Copy Markdown
Collaborator Author

@CassioMG not sure I'm catching what you mean by double token balances

one of them is the conversion from USD to the token equivalent, and the second line is the total of the tokens

UI-wise I had already discussed with @sdfcharles for breaking it into two lines. one for the current and one for total spendable, just missing the refresh icon staying on the first line, instead of dropping down to the second line. He also gave the green light after I showed the mocks, but I think he didn't see this small tweak that it should stay on the first line as it converts back and forth to the typed amount equivalent

@CassioMG
Copy link
Copy Markdown
Contributor

@CassioMG not sure I'm catching what you mean by double token balances

one of them is the conversion from USD to the token equivalent, and the second line is the total of the tokens

Sorry I think the expression I used was indeed ambiguous, by "double token balances" I meant the 2 amounts stacked on top of each other as it appear on the video, which is basically just the result of the line break that happens when the 2 amounts get too big and don't fit in a single line. I think now that the refresh icon position is fixed on the last commit it is looking better. My initial thought was that the available token balance should always stay right below the token dropdown for consistency as jumping to the opposite side of the screen could be confusing for users. But I'm not super strong on it, I'll defer the UI treatment to @minkyeongshin. What do you think?

Screen.Recording.2026-05-26.at.17.43.41.mov

@leofelix077
Copy link
Copy Markdown
Collaborator Author

@CassioMG Ahh I see. Now I get what you meant, hadn't fully understood it before. but not sure as well how we could handle it. will leave it like this for now until we get feedback

if we keep it fixed below the token dropdown, then the first line needs to drop below it. might also get somewhat confusing

Screenshot 2026-05-27 at 12 57 38 Screenshot 2026-05-27 at 12 58 25

Another option could be to display above
Screenshot 2026-05-27 at 13 01 12
Screenshot 2026-05-27 at 13 03 27

For displaying below, long texts we probably would need some different UI I think, breaking into two lines on opposite sides doesn't look good imo. and not sure if we should ellipsize the amount values to make it fit into one line

or if we keep as is, as it's kind of an edge-case even for small token to USD conversion it needs a very long value

@minkyeongshin
Copy link
Copy Markdown

minkyeongshin commented May 27, 2026

Leo's suggestion could work. we can move the available balance above the dropdown, which gives more room to display the balance. (screen 1)

For cases where the typed amount gets long, we can reduce the text size up to a certain length to prevent it from being cut off. (screen 2) However, I think it would be better to set a maximum input length(screen 3).

What do you think? @CassioMG @leofelix077

Screenshot 2026-05-27 at 2 40 28 PM

design file here

@leofelix077
Copy link
Copy Markdown
Collaborator Author

Posting for both here so it's easier to keep track, but imo it looks good / doesn't look out of place. @minkyeongshin @CassioMG

Implemented with dynamic font size and in case it's still too big it ellipsizes, to avoid breaking the UI into two lines

what do you think?

Simulator Screenshot - iPhone 17 Pro - 2026-05-28 at 13 22 28 Simulator Screenshot - iPhone 17 Pro - 2026-05-28 at 13 22 48 Screenshot 2026-05-28 at 13 36 40 Screenshot 2026-05-28 at 13 37 24 Simulator Screenshot - iPhone 17 Pro - 2026-05-28 at 13 41 36

Also adjusted the logic to hide the fiat input when not supported (following extension logic)

Simulator Screenshot - iPhone 17 Pro - 2026-05-28 at 14 00 46

@minkyeongshin
Copy link
Copy Markdown

Looks good to me! 👍👍 @leofelix077

@CassioMG
Copy link
Copy Markdown
Contributor

Posting for both here so it's easier to keep track, but imo it looks good / doesn't look out of place. @minkyeongshin @CassioMG

Implemented with dynamic font size and in case it's still too big it ellipsizes, to avoid breaking the UI into two lines

what do you think?

@leofelix077 looks good to me 👍 thanks for making those changes. I think we could do the same on mobile for consistency 📱

@leofelix077
Copy link
Copy Markdown
Collaborator Author

@CassioMG I applied for both. I meant to keep the conversation only in one thread, but screenshots 1,2,5,6 are for mobile ✅ . will crosspost the thread there

Comment thread extension/src/popup/views/__tests__/Send.test.tsx
Comment thread extension/src/popup/locales/en/translation.json
Comment thread extension/src/popup/helpers/formatters.ts
@leofelix077 leofelix077 merged commit 92df09f into master Jun 4, 2026
11 checks passed
@leofelix077 leofelix077 deleted the feature/linearize-send-flow branch June 4, 2026 21:57
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

5 participants