Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5e7b094
add initial version of linearizing send flow
leofelix077 May 6, 2026
6a18093
update keyboard avoiding view behavior for android
leofelix077 May 7, 2026
ceaf935
adjust keyboard avoiding view behavior for android
leofelix077 May 7, 2026
18084bd
add recipient name passing to review flow
leofelix077 May 7, 2026
1c517e6
fix navigation, typigns and input handling from typing and pasting
leofelix077 May 8, 2026
134bf87
Merge branch 'main' into lf-linearize-send-flow
leofelix077 May 11, 2026
fc3ab77
fix typings and reset search state
leofelix077 May 11, 2026
8cd4860
Merge branch 'lf-linearize-send-flow' of github.com:stellar/freighter…
leofelix077 May 11, 2026
60dc585
add back caret and remove highlighted hidden input
leofelix077 May 11, 2026
af8e4cc
fix ui elements from figma design
leofelix077 May 11, 2026
293fb05
adjust CI for android
leofelix077 May 11, 2026
4573eae
test no-keyboard option for android CI
leofelix077 May 11, 2026
616aca2
revert android ci option
leofelix077 May 11, 2026
0dc713b
fix copilot comments for virtualization
leofelix077 May 11, 2026
077872a
remove limit 10 recent contacts and add virtualization back
leofelix077 May 12, 2026
e4abc7f
adjust UI for wallets and invalid message
leofelix077 May 12, 2026
05a868c
clean stale state on collectible close
leofelix077 May 12, 2026
2aa00f1
fix collectible send flow
leofelix077 May 12, 2026
a5f5181
fix send flows when coming from details screens
leofelix077 May 12, 2026
618e545
fix memoization for nav headers
leofelix077 May 12, 2026
a5fb723
replace navigate with push and add e2e test for send from details
leofelix077 May 18, 2026
c9357ce
fix merge conflicts and adapt code to handle federated address on new…
leofelix077 May 18, 2026
04446e0
adjust safeguards for address truncation and fix scroll for tokens in…
leofelix077 May 19, 2026
7b6f9a5
adjust ui tweaks from figma and keyboard dismiss
leofelix077 May 26, 2026
20b7838
Merge branch 'main' into lf-linearize-send-flow
leofelix077 May 26, 2026
ca57079
fix navigation, align ui with figma latest design
leofelix077 May 28, 2026
e1e542a
adjust logic to hide usd conversion and has no price
leofelix077 May 28, 2026
bc3d2a1
adjust logic to hide usd conversion and has no price
leofelix077 May 28, 2026
efafeca
Merge branch 'main' into lf-linearize-send-flow
leofelix077 May 29, 2026
7ec7a9d
adjust memo type clearing on transaction amount screen and remove unu…
leofelix077 May 29, 2026
887e27e
adjust comments on federation memo type tests
leofelix077 May 29, 2026
10803db
Merge branch 'lf-linearize-send-flow' of github.com:stellar/freighter…
leofelix077 May 29, 2026
9c51a3e
enhance transaction test for federation memo type
leofelix077 May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions .github/workflows/android-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ jobs:
# - ImportFundedWallet: Import wallet with funded account
# - SwitchToTestnet: Switch network to testnet
# - SendClassicTokenMainnet: Send XLM on mainnet (small amount: 0.000001 XLM)
# - SendClassicTokenMainnetFromDetails: Send XLM on mainnet starting from Token Details screen (small amount: 0.000001 XLM)
# - SwapClassicTokenMainnet: Swap tokens on mainnet (small amount: 0.000001 XLM)
# - ForgotPasswordWarning: Lock screen forgot password confirmation modal
# - SendFederatedAddress: Send XLM and USDC to a federated address on mainnet (small amount: 0.000001 each)
Expand All @@ -240,47 +241,51 @@ jobs:
matrix:
include:
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: LaunchAndInspect
requires-mock-server: false
- shard-index: 1
shard-total: 9
shard-total: 10
flow-name: CreateWallet
requires-mock-server: false
- shard-index: 2
shard-total: 9
shard-total: 10
flow-name: ImportWallet
requires-mock-server: false
- shard-index: 3
shard-total: 9
shard-total: 10
flow-name: ImportFundedWallet
requires-mock-server: false
- shard-index: 4
shard-total: 9
shard-total: 10
flow-name: SwitchToTestnet
requires-mock-server: false
- shard-index: 5
shard-total: 9
shard-total: 10
flow-name: SendClassicTokenMainnet
requires-mock-server: false
- shard-index: 6
shard-total: 9
shard-total: 10
flow-name: SwapClassicTokenMainnet
requires-mock-server: false
- shard-index: 7
shard-total: 9
shard-total: 10
flow-name: ForgotPasswordWarning
requires-mock-server: false
- shard-index: 8
shard-total: 9
shard-total: 10
flow-name: SendFederatedAddress
requires-mock-server: false
- shard-index: 9
shard-total: 10
flow-name: SendClassicTokenMainnetFromDetails
requires-mock-server: false
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: SignMessageMockDapp
requires-mock-server: true
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: SignAuthEntryMockDapp
requires-mock-server: true

Expand Down
27 changes: 16 additions & 11 deletions .github/workflows/ios-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ jobs:
# - ImportFundedWallet: Import wallet with funded account
# - SwitchToTestnet: Switch network to testnet
# - SendClassicTokenMainnet: Send XLM on mainnet (small amount: 0.000001 XLM)
# - SendClassicTokenMainnetFromDetails: Send XLM on mainnet starting from Token Details screen (small amount: 0.000001 XLM)
# - SwapClassicTokenMainnet: Swap tokens on mainnet (small amount: 0.000001 XLM)
# - ForgotPasswordWarning: Lock screen forgot password confirmation modal
# - SendFederatedAddress: Send XLM and USDC to a federated address on mainnet (small amount: 0.000001 each)
Expand All @@ -237,47 +238,51 @@ jobs:
matrix:
include:
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: LaunchAndInspect
requires-mock-server: false
- shard-index: 1
shard-total: 9
shard-total: 10
flow-name: CreateWallet
requires-mock-server: false
- shard-index: 2
shard-total: 9
shard-total: 10
flow-name: ImportWallet
requires-mock-server: false
- shard-index: 3
shard-total: 9
shard-total: 10
flow-name: ImportFundedWallet
requires-mock-server: false
- shard-index: 4
shard-total: 9
shard-total: 10
flow-name: SwitchToTestnet
requires-mock-server: false
- shard-index: 5
shard-total: 9
shard-total: 10
flow-name: SendClassicTokenMainnet
requires-mock-server: false
- shard-index: 6
shard-total: 9
shard-total: 10
flow-name: SwapClassicTokenMainnet
requires-mock-server: false
- shard-index: 7
shard-total: 9
shard-total: 10
flow-name: ForgotPasswordWarning
requires-mock-server: false
- shard-index: 8
shard-total: 9
shard-total: 10
flow-name: SendFederatedAddress
requires-mock-server: false
- shard-index: 9
shard-total: 10
flow-name: SendClassicTokenMainnetFromDetails
requires-mock-server: false
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: SignMessageMockDapp
requires-mock-server: true
- shard-index: 0
shard-total: 9
shard-total: 10
flow-name: SignAuthEntryMockDapp
requires-mock-server: true

Expand Down
14 changes: 9 additions & 5 deletions .github/workflows/prPreviewIos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ jobs:
runs-on: macos-26-xlarge
timeout-minutes: 45
permissions:
contents: write # draft release create/delete + tag operations
pull-requests: write # sticky preview-link comment
contents: write # draft release create/delete + tag operations
pull-requests: write # sticky preview-link comment
env:
NODE_VERSION: "20"
RUBY_VERSION: 3.1.4
Expand Down Expand Up @@ -97,13 +97,15 @@ jobs:
WALLET_KIT_MT_DESCRIPTION_PROD: ${{ vars.WALLET_KIT_MT_DESCRIPTION_DEV }}
WALLET_KIT_MT_URL_PROD: ${{ vars.WALLET_KIT_MT_URL_DEV }}
WALLET_KIT_MT_ICON_PROD: ${{ vars.WALLET_KIT_MT_ICON_DEV }}
WALLET_KIT_MT_REDIRECT_NATIVE_PROD: ${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_DEV }}
WALLET_KIT_MT_REDIRECT_NATIVE_PROD:
${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_DEV }}
WALLET_KIT_PROJECT_ID_DEV: ${{ secrets.WALLET_KIT_PROJECT_ID_DEV }}
WALLET_KIT_MT_NAME_DEV: ${{ vars.WALLET_KIT_MT_NAME_DEV }}
WALLET_KIT_MT_DESCRIPTION_DEV: ${{ vars.WALLET_KIT_MT_DESCRIPTION_DEV }}
WALLET_KIT_MT_URL_DEV: ${{ vars.WALLET_KIT_MT_URL_DEV }}
WALLET_KIT_MT_ICON_DEV: ${{ vars.WALLET_KIT_MT_ICON_DEV }}
WALLET_KIT_MT_REDIRECT_NATIVE_DEV: ${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_DEV }}
WALLET_KIT_MT_REDIRECT_NATIVE_DEV:
${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_DEV }}
MP_COLLECTIONS_ADDRESSES: ${{ vars.MP_COLLECTIONS_ADDRESSES }}
IS_E2E_TEST: "false"
E2E_TEST_RECOVERY_PHRASE: ""
Expand Down Expand Up @@ -190,7 +192,9 @@ jobs:
ios/Pods
~/Library/Caches/CocoaPods
~/.cocoapods
key: ${{ runner.os }}-pods-pr-${{ github.event.pull_request.number }}-${{ hashFiles('ios/Podfile.lock') }}
key:
${{ runner.os }}-pods-pr-${{ github.event.pull_request.number }}-${{
hashFiles('ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-pods-pr-${{ github.event.pull_request.number }}-

Expand Down
179 changes: 179 additions & 0 deletions __tests__/components/TokensCollectiblesInline.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { fireEvent, render, screen } from "@testing-library/react-native";
import { TokensCollectiblesInline } from "components/TokensCollectiblesInline";
import { NETWORKS, TransactionContext } from "config/constants";
import { useCollectiblesStore } from "ducks/collectibles";
import { useFilteredCollectibles } from "hooks/useFilteredCollectibles";
import React from "react";
import {
TouchableOpacity as mockTouchableOpacity,
View as mockView,
} from "react-native";

const MockTouchableOpacity = mockTouchableOpacity;
const MockView = mockView;

jest.mock("components/BalancesList", () => ({
BalancesList: ({
onTokenPress,
}: {
onTokenPress?: (tokenId: string) => void;
}) => (
<MockTouchableOpacity
testID="balances-list-token-row"
onPress={() => onTokenPress?.("native")}
>
<MockView />
</MockTouchableOpacity>
),
}));

jest.mock("components/CollectibleImage", () => ({
CollectibleImage: () => <MockView testID="collectible-image" />,
}));

jest.mock("components/Spinner", () => ({
__esModule: true,
default: ({ testID }: { testID?: string }) => <MockView testID={testID} />,
}));

jest.mock("hooks/useAppTranslation", () => ({
__esModule: true,
default: () => ({
t: (key: string) =>
({
"balancesList.title": "Tokens",
"collectiblesGrid.title": "Collectibles",
"collectiblesGrid.error": "Error loading collectibles",
"collectiblesGrid.empty": "No collectibles",
})[key] || key,
}),
}));

jest.mock("hooks/useColors", () => ({
__esModule: true,
default: () => ({
themeColors: {
secondary: "#000",
text: {
secondary: "#111",
},
},
}),
}));

jest.mock("ducks/collectibles", () => ({
useCollectiblesStore: jest.fn(),
}));

jest.mock("hooks/useFilteredCollectibles", () => ({
useFilteredCollectibles: jest.fn(),
}));

const mockUseCollectiblesStore =
useCollectiblesStore as unknown as jest.MockedFunction<any>;
const mockUseFilteredCollectibles =
useFilteredCollectibles as unknown as jest.MockedFunction<any>;

const setupCollectibleState = ({
isLoading = false,
error = null,
visibleCollectibles = [],
}: {
isLoading?: boolean;
error?: string | null;
visibleCollectibles?: any[];
}) => {
mockUseCollectiblesStore.mockImplementation((selector: any) =>
selector({ isLoading, error }),
);
mockUseFilteredCollectibles.mockReturnValue({ visibleCollectibles });
};

describe("TokensCollectiblesInline", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("shows loading spinner while collectibles are loading", () => {
setupCollectibleState({ isLoading: true, visibleCollectibles: [] });

render(
<TokensCollectiblesInline
publicKey="G..."
network={NETWORKS.TESTNET}
feeContext={TransactionContext.Send}
/>,
);

expect(screen.getByTestId("collectibles-inline-spinner")).toBeTruthy();
});

it("shows collectibles error state", () => {
setupCollectibleState({ error: "failed", visibleCollectibles: [] });

render(
<TokensCollectiblesInline
publicKey="G..."
network={NETWORKS.TESTNET}
feeContext={TransactionContext.Send}
/>,
);

expect(screen.getByText("Error loading collectibles")).toBeTruthy();
});

it("shows collectibles empty state", () => {
setupCollectibleState({ visibleCollectibles: [] });

render(
<TokensCollectiblesInline
publicKey="G..."
network={NETWORKS.TESTNET}
feeContext={TransactionContext.Send}
/>,
);

expect(screen.getByText("No collectibles")).toBeTruthy();
});

it("forwards token and collectible press handlers", () => {
const onTokenPress = jest.fn();
const onCollectiblePress = jest.fn();

setupCollectibleState({
visibleCollectibles: [
{
collectionAddress: "CABC",
collectionName: "Cool Collection",
items: [
{
collectionAddress: "CABC",
tokenId: "42",
image: "https://example.com/item.png",
name: "Collectible #42",
},
],
},
],
});

render(
<TokensCollectiblesInline
publicKey="G..."
network={NETWORKS.TESTNET}
onTokenPress={onTokenPress}
onCollectiblePress={onCollectiblePress}
feeContext={TransactionContext.Send}
/>,
);

fireEvent.press(screen.getByTestId("balances-list-token-row"));
expect(onTokenPress).toHaveBeenCalledWith("native");

fireEvent.press(screen.getByText("Collectible #42"));
expect(onCollectiblePress).toHaveBeenCalledWith({
collectionAddress: "CABC",
tokenId: "42",
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ describe("CollectibleDetailsScreen", () => {
"SendPaymentStack",
{
screen: "SendSearchContactsScreen",
params: {
dismissToPreviousScreen: true,
},
},
);
});
Expand Down
Loading
Loading