feat: integrate Freighter wallet provider - #445
Conversation
|
@jahrulezfrancis is attempting to deploy a commit to the luluameh's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughThe wallet provider now integrates Freighter for connection, network monitoring, cached restoration, and transaction signing. Wallet controls display connection state and network errors across desktop, mobile, and modal interfaces, while test mocks match the updated Freighter API responses. ChangesFreighter wallet integration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant CreateWalletModal
participant WalletProvider
participant Freighter
participant Navbar
User->>CreateWalletModal: Select Freighter
CreateWalletModal->>WalletProvider: connect()
WalletProvider->>Freighter: requestAccess()
Freighter-->>WalletProvider: address and network
WalletProvider-->>CreateWalletModal: connection result
WalletProvider-->>Navbar: wallet state and address
Navbar-->>User: Connected address or network alert
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (8)
tests/mocks/wallet.ts (1)
59-62: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
setAllowedmock is now unexercised.The provider moved to
requestAccess(), so nothing drives this mock; drop it unless another test still relies on it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/mocks/wallet.ts` around lines 59 - 62, Remove the unused setAllowed mock from the wallet test mock. Confirm no remaining tests reference setAllowed, while preserving the existing requestAccess-based mock behavior.src/providers/WalletProvider.tsx (4)
149-152: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a timeout to the Horizon request.
This call is triggered on every connect and on every watcher-detected account/network change with no deadline; a stalled Horizon leaves balance pending indefinitely.
♻️ Suggested change
try { - const response = await fetch(`${baseUrl}/accounts/${address}`); + const response = await fetch(`${baseUrl}/accounts/${address}`, { + signal: AbortSignal.timeout(10_000), + }); if (!response.ok) return null;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/WalletProvider.tsx` around lines 149 - 152, Add an abort timeout to the Horizon fetch in the account-loading flow, using an AbortController and passing its signal to the request; ensure the timeout is cleared after completion and existing null/error handling remains intact.
480-487: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueMemoize the context values.
Both objects are rebuilt on every provider render (watcher ticks, balance resolution, signing flags), forcing all
useWallet()consumers to re-render. Wrapping inuseMemokeyed onstateand the stable callbacks avoids that.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/WalletProvider.tsx` around lines 480 - 487, Memoize the WalletContextValue object in the provider using useMemo, with dependencies on state and the stable connect, disconnect, and signTransaction callbacks. Preserve the existing isWrongNetwork calculation and pass the memoized value to the context provider so watcher and state updates do not rebuild it unnecessarily.
25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake the expected network configurable.
EXPECTED_NETWORKis compile-time pinned toTESTNET, and it gates bothisWrongNetworkand signing. Reading it fromprocess.env.NEXT_PUBLIC_STELLAR_NETWORK(defaulting toTESTNET) avoids a code change for mainnet.♻️ Suggested change
-const EXPECTED_NETWORK = "TESTNET"; +const EXPECTED_NETWORK = + process.env.NEXT_PUBLIC_STELLAR_NETWORK ?? "TESTNET";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/WalletProvider.tsx` at line 25, Update EXPECTED_NETWORK in WalletProvider to read from process.env.NEXT_PUBLIC_STELLAR_NETWORK, falling back to "TESTNET" when unset, so the existing isWrongNetwork and signing logic uses the configured network without further code changes.
222-233: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse the real Testnet passphrase in mock mode.
networkPassphrase: ""(also insetMockProfileat Line 472) is a valid-looking but empty value that any consumer reading it outside the signing short-circuit will silently misuse.tests/mocks/wallet.tsalready exportsMOCK_NETWORK_PASSPHRASEwith the correct Testnet value.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/WalletProvider.tsx` around lines 222 - 233, Update the mock wallet state in the initialization flow to use the existing MOCK_NETWORK_PASSPHRASE instead of an empty networkPassphrase, and make the same change in setMockProfile. Reuse the exported Testnet passphrase constant from tests/mocks/wallet.ts without changing other mock state behavior.src/components/home/layout/navbar.tsx (2)
11-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate
shortenAddresshelper.
src/components/layout/Navbar.tsx(Line 13) carries its ownshortenAddress. Extract one shared helper so the abbreviation format cannot drift between the two navbars.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/home/layout/navbar.tsx` around lines 11 - 13, Extract the duplicate shortenAddress logic from the home and layout navbar components into one shared helper, then update both callers to import and use it. Preserve the existing four-character prefix, ellipsis, and four-character suffix format.
109-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConnected wallet control is an interactive button that does nothing. Both breakpoints duplicate the same control, and in both the connected state keeps
cursor-pointer, stays enabled, and remains keyboard-focusable whileonClickis a no-op (if (!address) setWalletOpen(true)). Extract one shared control and make the connected state non-interactive (or give it a real action, e.g. copy address / open a wallet menu).
src/components/home/layout/navbar.tsx#L109-L134: render a non-button element (ordisabled+ non-pointer cursor) whenaddressis set, and extract the shared control.src/components/home/layout/navbar.tsx#L200-L224: replace this duplicated block with the extracted control so the mobile menu gets the same behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/home/layout/navbar.tsx` around lines 109 - 134, The duplicated wallet controls at src/components/home/layout/navbar.tsx lines 109-134 and 200-224 should be replaced with one shared control. Update the control so the connected state is non-interactive, not keyboard-focusable, and uses a non-pointer cursor, while preserving the connect action, loading state, address display, and disconnect behavior; apply the extracted control consistently at both sites.src/components/CreateWalletModal.tsx (1)
41-45: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueConnected state ignores
isWrongNetwork.
connect()resolvestrueon a Mainnet-selected wallet too, so the modal shows "Freighter is now connected." while the navbars render the wrong-network alert. Consider readingisWrongNetwork/networkfromuseWallet()and adding a switch-to-Testnet hint in the connected panel.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/CreateWalletModal.tsx` around lines 41 - 45, Update handleConnect and the connected-panel rendering to account for isWrongNetwork/network from useWallet: only present the normal connected state when the wallet is on Testnet, and show a switch-to-Testnet hint when a Mainnet-selected wallet connects successfully. Preserve the existing error state for failed connections.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/providers/WalletProvider.tsx`:
- Line 22: Replace the invalid MOCK_ADDRESS in WalletProvider with a valid
56-character Stellar public key, preferably by reusing the existing
MOCK_WALLET_ADDRESS from the test mock instead of defining a duplicate. Ensure
mock mode passes StrKey/Keypair.fromPublicKey validation and the navbar displays
the valid address.
- Around line 285-295: Update the cached-connection handling around
readCachedConnection so it sets only isLoading (and clears any prior error)
without spreading cached address or network values into state. Keep refresh()
responsible for populating verified connection data through setRealConnection,
while preserving the early return when no cache exists.
---
Nitpick comments:
In `@src/components/CreateWalletModal.tsx`:
- Around line 41-45: Update handleConnect and the connected-panel rendering to
account for isWrongNetwork/network from useWallet: only present the normal
connected state when the wallet is on Testnet, and show a switch-to-Testnet hint
when a Mainnet-selected wallet connects successfully. Preserve the existing
error state for failed connections.
In `@src/components/home/layout/navbar.tsx`:
- Around line 11-13: Extract the duplicate shortenAddress logic from the home
and layout navbar components into one shared helper, then update both callers to
import and use it. Preserve the existing four-character prefix, ellipsis, and
four-character suffix format.
- Around line 109-134: The duplicated wallet controls at
src/components/home/layout/navbar.tsx lines 109-134 and 200-224 should be
replaced with one shared control. Update the control so the connected state is
non-interactive, not keyboard-focusable, and uses a non-pointer cursor, while
preserving the connect action, loading state, address display, and disconnect
behavior; apply the extracted control consistently at both sites.
In `@src/providers/WalletProvider.tsx`:
- Around line 149-152: Add an abort timeout to the Horizon fetch in the
account-loading flow, using an AbortController and passing its signal to the
request; ensure the timeout is cleared after completion and existing null/error
handling remains intact.
- Around line 480-487: Memoize the WalletContextValue object in the provider
using useMemo, with dependencies on state and the stable connect, disconnect,
and signTransaction callbacks. Preserve the existing isWrongNetwork calculation
and pass the memoized value to the context provider so watcher and state updates
do not rebuild it unnecessarily.
- Line 25: Update EXPECTED_NETWORK in WalletProvider to read from
process.env.NEXT_PUBLIC_STELLAR_NETWORK, falling back to "TESTNET" when unset,
so the existing isWrongNetwork and signing logic uses the configured network
without further code changes.
- Around line 222-233: Update the mock wallet state in the initialization flow
to use the existing MOCK_NETWORK_PASSPHRASE instead of an empty
networkPassphrase, and make the same change in setMockProfile. Reuse the
exported Testnet passphrase constant from tests/mocks/wallet.ts without changing
other mock state behavior.
In `@tests/mocks/wallet.ts`:
- Around line 59-62: Remove the unused setAllowed mock from the wallet test
mock. Confirm no remaining tests reference setAllowed, while preserving the
existing requestAccess-based mock behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a94df337-07f6-49c0-90b6-45d9be40e1c3
📒 Files selected for processing (5)
src/components/CreateWalletModal.tsxsrc/components/home/layout/navbar.tsxsrc/components/layout/Navbar.tsxsrc/providers/WalletProvider.tsxtests/mocks/wallet.ts
Summary
Integrates the wallet provider with the official
@stellar/freighter-api, replacing simulated wallet behavior with real Freighter connections, transaction signing, connection persistence, and network-change detection.Changes
isConnected()andrequestAccess().getAddress()API.signTransaction()throughuseWallet().WatchWalletChangesto detect account and network changes.Implementation Notes
getPublicKey()is not available in the installed@stellar/freighter-apiv6 package. The implementation uses its current replacement,getAddress().Connection persistence stores only public wallet information:
No private keys or transaction signatures are persisted.
Validation
git diff --checkpassesVisual Evidence
Before Implementation
Screencast.from.2026-07-26.21-19-38.webm
After implementation
2026-07-28.10-05-51.mp4
Existing Repository Constraints
Repository-wide TypeScript and lint checks still report unrelated pre-existing issues, including missing Playwright dependencies and errors in unrelated pages/components.
Closes #436