Skip to content

Issue 4.1 connect freighter wallet#21

Merged
soomtochukwu merged 5 commits intoDXmakers:mainfrom
sudo-robi:issue-4.1-connect-freighter-wallet
Apr 1, 2026
Merged

Issue 4.1 connect freighter wallet#21
soomtochukwu merged 5 commits intoDXmakers:mainfrom
sudo-robi:issue-4.1-connect-freighter-wallet

Conversation

@sudo-robi
Copy link
Copy Markdown
Contributor

closes #11

Summary
Integrates Freighter wallet connectivity into the Smasage frontend dashboard, enabling users to authenticate with their Stellar account for transaction signing and identity verification.

Changes
ConnectWalletButton.tsx — Reusable button component that detects the Freighter extension and triggers wallet connection
WalletContext.tsx — React context provider managing the user's public key state across the app
DashboardHeader.tsx — Updated header to display connected wallet status
page.tsx / layout.tsx — Integrated wallet context provider and connect button into the dashboard
package.json — Added @stellar/freighter-api dependency
jest.config.js — Test configuration for wallet integration tests

@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 27, 2026

@sudo-robi Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@soomtochukwu
Copy link
Copy Markdown
Contributor

@sudo-robi, could you look into this?

@sudo-robi
Copy link
Copy Markdown
Contributor Author

@soomtochukwu all issues have been handled

@sudo-robi sudo-robi force-pushed the issue-4.1-connect-freighter-wallet branch from 1958d2e to 14c9005 Compare April 1, 2026 11:29
Copilot AI review requested due to automatic review settings April 1, 2026 11:29
Copy link
Copy Markdown

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

Integrates Freighter wallet connection UI into the Next.js dashboard (wallet context + connect button + install prompt), while also introducing a Jest setup at repo root and a large set of Soroban contract changes (Blend-related state, functions, and tests).

Changes:

  • Added wallet state management via a React context provider and integrated a “Connect Wallet” button into the dashboard UI.
  • Added root-level Jest + ts-jest configuration.
  • Expanded Soroban contract logic/tests (Blend position tracking, initialization helpers, and updated snapshots).

Reviewed changes

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

Show a summary per file
File Description
package.json Adds root Jest devDependencies, but does not add the required Freighter dependency to frontend/package.json.
jest.config.js Adds a basic ts-jest Jest config at repo root.
frontend/src/app/page.tsx Adds wallet connect flow, header integration, and an install modal (currently implemented with runtime style injection).
frontend/src/app/layout.tsx Wraps the app in WalletProvider so wallet state is available throughout the app.
frontend/src/app/components/WalletContext.tsx New client-side React context for storing the connected Stellar public key.
frontend/src/app/components/DashboardHeader.tsx New header wrapper used to display the app name + wallet connect UI.
frontend/src/app/components/ConnectWalletButton.tsx New button component that displays a truncated public key when connected.
contracts/test_snapshots/test/test_deposit_withdraw.1.json Snapshot updated but contains unresolved merge-conflict markers (invalid JSON).
contracts/src/lib.rs Adds/changes Blend-related contract logic and extensive tests (currently with multiple correctness/compilation/security issues).

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

Comment on lines +1 to +7
{
"devDependencies": {
"@types/jest": "^30.0.0",
"jest": "^30.3.0",
"ts-jest": "^29.4.6"
}
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Issue requirements/PR description say to add @stellar/freighter-api to frontend/package.json, but this root package.json only adds Jest devDependencies and does not include the Freighter dependency anywhere. Please add @stellar/freighter-api to frontend/package.json (dependencies) and avoid introducing/using a separate root package.json unless the repo intentionally has a root Node workspace.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +33
const { publicKey, setPublicKey } = useWallet();
const [showInstallModal, setShowInstallModal] = useState(false);
// Connect Wallet logic
const handleConnectWallet = async () => {
if (!(window as any).freighterApi) {
setShowInstallModal(true);
return;
}
try {
const key = await (window as any).freighterApi.getPublicKey();
setPublicKey(key);
} catch (e) {
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

handleConnectWallet checks window.freighterApi and calls getPublicKey() directly, but the PR adds @stellar/freighter-api (per description/issue) and should use that package’s API (e.g., isConnected/getPublicKey) instead of an untyped window lookup. Using the library also makes install detection and error handling more reliable across extension versions.

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +184
if (typeof window !== 'undefined' && !document.getElementById('modal-styles')) {
const style = document.createElement('style');
style.id = 'modal-styles';
style.innerHTML = modalStyles;
document.head.appendChild(style);
}

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This component adds a <style> tag to document.head during render (if (...) { document.createElement(...) }). That introduces side effects during rendering (and can run twice in React Strict Mode), which can cause hydration/render inconsistencies. Move the style injection into a useEffect with cleanup, or better: put these modal styles into globals.css / a CSS module and only toggle the modal markup here.

Suggested change
if (typeof window !== 'undefined' && !document.getElementById('modal-styles')) {
const style = document.createElement('style');
style.id = 'modal-styles';
style.innerHTML = modalStyles;
document.head.appendChild(style);
}
useEffect(() => {
if (typeof document === 'undefined') {
return;
}
let styleElement = document.getElementById('modal-styles') as HTMLStyleElement | null;
let created = false;
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = 'modal-styles';
styleElement.innerHTML = modalStyles;
document.head.appendChild(styleElement);
created = true;
}
return () => {
if (created && styleElement && styleElement.parentNode) {
styleElement.parentNode.removeChild(styleElement);
}
};
}, []);

Copilot uses AI. Check for mistakes.
Comment on lines +186 to +200
<>
<DashboardHeader>
<ConnectWalletButton onClick={handleConnectWallet} publicKey={publicKey || undefined} />
</DashboardHeader>
{showInstallModal && (
<div className="modal-overlay">
<div className="modal-content">
<h2>Freighter Wallet Not Detected</h2>
<p>Please install the Freighter browser extension to connect your wallet.</p>
<a href="https://freighter.app/" target="_blank" rel="noopener noreferrer" className="install-link">Install Freighter</a>
<button onClick={() => setShowInstallModal(false)} className="close-modal">Close</button>
</div>
</div>
)}
<main className="app-container">
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

<DashboardHeader> is rendered as a sibling before the .app-container main. In globals.css, body is display: flex with default flex-direction: row, so adding a header + main as siblings will lay them out side-by-side rather than vertically and likely break the page layout. Consider moving the header inside the main container or updating the global layout (e.g., body { flex-direction: column; } and making header full-width).

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +17
export interface ConnectWalletButtonProps {
onClick: () => void;
publicKey?: string;
}

function truncatePublicKey(key: string) {
if (!key) return '';
return key.slice(0, 4) + '...' + key.slice(-4);
}

export const ConnectWalletButton: React.FC<ConnectWalletButtonProps> = ({ onClick, publicKey }) => {
return (
<button onClick={onClick} className="connect-wallet-btn">
{publicKey ? truncatePublicKey(publicKey) : 'Connect Wallet'}
</button>
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This ConnectWalletButton is described as a reusable component that detects Freighter and triggers connection, but it currently only renders a button and delegates all detection/connection logic to callers via onClick. To meet the stated requirement and avoid duplicating logic, consider moving Freighter detection + connect flow (and possibly the “install Freighter” UX trigger) into this component (or a shared hook used by it).

Copilot uses AI. Check for mistakes.
assert!(blend_percentage + lp_percentage + gold_percentage <= 100, "Allocation exceeds 100%");

// Transfer USDC from user to contract
let usdc_addr: Address = env.storage().persistent().get(&DataKey::UsdcToken).expect("USDC not initialized");
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

deposit reads the USDC token address from DataKey::UsdcToken, but the Blend initialization path stores USDC under DataKey::UsdcTokenAddress. As-is, calling initialize_blend without initialize_soroswap will leave UsdcToken unset and make deposit panic with "USDC not initialized". Please use a single canonical storage key for the USDC token address (or clearly separate Soroswap vs Blend paths and document/validate the required initialization).

Suggested change
let usdc_addr: Address = env.storage().persistent().get(&DataKey::UsdcToken).expect("USDC not initialized");
let usdc_addr: Address = match env.storage().persistent().get(&DataKey::UsdcToken) {
Some(addr) => addr,
None => {
// Fallback for Blend initialization path, which stores under UsdcTokenAddress
let addr: Address = env
.storage()
.persistent()
.get(&DataKey::UsdcTokenAddress)
.expect("USDC not initialized");
// Normalize storage so future reads can use the canonical UsdcToken key
env.storage().persistent().set(&DataKey::UsdcToken, &addr);
addr
}
};

Copilot uses AI. Check for mistakes.
Comment on lines +692 to +697
// Deposit 1000 USDC, 50% to LP
client.deposit(&user, &1000, &0, &50);

// 60% Blend, 30% LP, 10% Gold
client.deposit(&user, &1000, &60, &30, &10);

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

test_soroswap_integration calls client.deposit with too few arguments (e.g., deposit(&user, &1000, &0, &50)), but the contract’s deposit signature requires amount + 3 allocation percentages. This test won’t compile against the current ABI; update the calls to match the function signature.

Copilot uses AI. Check for mistakes.
Comment on lines +698 to +703
assert_eq!(client.get_balance(&user), 1000);
assert_eq!(client.get_gold_balance(&user), 100);
assert_eq!(client.get_lp_shares(&user), 300);

// 50% of 1000 is 500. Our MockRouter returns 100 LP shares for any add_liquidity.
assert_eq!(client.get_lp_shares(&user), 100);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

These assertions are internally inconsistent: the test asserts get_lp_shares(&user) equals 300 (after a deposit with 30% LP), and then immediately asserts it equals 100 with the same state. One of these expectations is wrong, and as written the test will always fail. Please remove/fix the contradictory assertion(s) and align them with the mocked router behavior (always minting 100 LP shares).

Copilot uses AI. Check for mistakes.
}
}

use mock_token::MockToken;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

In the test module you already define pub struct MockToken (used for Soroswap/legacy tests). Importing mock_token::MockToken here introduces a duplicate name in the same module and will not compile. Rename one of the token mocks (e.g., MockUsdcToken) or avoid use mock_token::MockToken and reference it with a qualified path.

Suggested change
use mock_token::MockToken;

Copilot uses AI. Check for mistakes.
Comment on lines 37 to +58
// Issue 2: Smart Contract - Stellar Path Payments & Yield Allocation (Blend Integration)
// Issue 3: Withdraw functionality with Blend and Soroswap unwinding

/// Blend Pool interface for supplying and withdrawing assets
/// This trait defines the interface for interacting with the Blend Protocol
pub trait BlendPoolInterface {
/// Supply assets to the Blend pool and receive bTokens
fn supply(env: Env, from: Address, amount: i128) -> i128;

/// Withdraw assets from the Blend pool by redeeming bTokens
fn withdraw(env: Env, to: Address, b_tokens: i128) -> i128;

/// Get the current index rate for yield calculation
/// The index rate represents the exchange rate between underlying assets and bTokens
fn get_index_rate(env: Env) -> i128;

/// Get the total bToken supply for the pool
fn get_b_token_supply(env: Env) -> i128;

/// Get the total underlying assets in the pool
fn get_total_supply(env: Env) -> i128;
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This PR is scoped to Freighter wallet connectivity (Issue 4.1), but this diff also introduces substantial on-chain contract changes (Blend pool interface/position tracking, new storage keys, deposit/withdraw behavior, and extensive new tests). This scope expansion makes review and rollout riskier; please consider splitting the smart-contract refactor into a separate PR (or clearly justify why it must be coupled to the frontend wallet work).

Copilot uses AI. Check for mistakes.
@sudo-robi
Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

@soomtochukwu soomtochukwu merged commit db10a57 into DXmakers:main Apr 1, 2026
3 checks passed
@drips-wave drips-wave bot mentioned this pull request Apr 7, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue 4.1: Connect Freighter Wallet

3 participants