Beginner Tutorial
π What You'll Learn
This guide teaches you how to integrate Soroswap API into your application using:
Freighter Wallet for secure wallet connection and transaction signing
Soroswap API for finding the best swap routes and transaction submission
π― Prerequisites
Before starting, make sure you have:
Basic knowledge of HTML, CSS, and JavaScript
Freighter Wallet extension installed
An API key from Soroswap sign up at https://api.soroswap.finance/login
A web browser with developer tools
5-10 minutes of focused time
ποΈ Project Structure Overview
Our swap application consists of 6 main parts:
1. HTML Structure β User interface elements with professional styling
2. External Libraries β Freighter API for wallet integration
3. Configuration β Centralized CONFIG object with all settings
4. Application State β Tracks wallet connection and transaction status
5. Utility Functions β Helper functions for UI updates and API calls
6. Core Functions β Connect, Quote, Sign, and Send (4 separate steps)
Since this guide is to use the api, we'll focus on the core functions that make the swap happen.
π§ Core Functions Explained
Function 1: Connect to Wallet π
async function connectStellarWallet() {
// Step 1: Check if Freighter wallet is installed
const hasFreighter = await freighter.isConnected();
console.log('Freighter connected:', hasFreighter);
// Step 2: If not installed, show error message
if (!hasFreighter.isConnected) {
alert('Please install the Freighter wallet extension first.');
return; // Stop function execution
}
// Step 3: Request permission to connect
console.log('Connecting to Freighter...');
account = await freighter.requestAccess();
account = account.address; // Extract just the address
// Step 4: Update the user interface
connectButton.disabled = true; // Disable connect button
document.getElementById('account').innerText = `Connected account: ${account}`;
}
π What this function does:
Checks if Freighter wallet is available
Requests permission to access the wallet
Stores the wallet address for later use
Updates the UI to show connection status
π¨ Common issues:
User doesn't have Freighter installed β Show installation instructions
User denies permission β Ask them to try again
Function 2: Get Quote and Build Transaction π±
async function getQuote() {
try {
// Make sure wallet is connected
if (!appState.connected) {
updateStatus('β Please connect your wallet first!', 'error');
return;
}
// PHASE 1: Get Quote
updateStatus('π Getting best price from exchanges...', 'info');
const quoteRequest = {
assetIn: CONFIG.TOKENS.XLM, // What we're selling
assetOut: CONFIG.TOKENS.USDC, // What we want to buy
amount: CONFIG.TRADE.AMOUNT, // How much we're selling
tradeType: CONFIG.TRADE.TYPE, // Exact input amount
protocols: CONFIG.TRADE.PROTOCOLS // Which exchanges to check
};
appState.currentQuote = await makeAPIRequest('/quote', quoteRequest);
const outputAmount = formatAmount(appState.currentQuote.amountOut, 7); // USDC has 7 decimals
updateStatus(`β
Quote received: ${outputAmount} USDC for 1 XLM<br>π Building transaction...`, 'info');
// PHASE 2: Build Transaction
const buildRequest = {
quote: appState.currentQuote, // Use the quote we just got
from: appState.walletAddress, // Who's sending
to: appState.walletAddress // Who's receiving (same person in a swap)
};
const buildResult = await makeAPIRequest('/quote/build', buildRequest);
appState.unsignedXdr = buildResult.xdr;
// Show the unsigned transaction for educational purposes
ELEMENTS.unsignedXdr.value = buildResult.xdr;
ELEMENTS.technicalDetails.classList.remove('hidden');
updateStatus(`β
Transaction built successfully!<br>β³ Ready for signing...`, 'info');
updateButtonStates();
} catch (error) {
console.error('Quote process failed:', error);
updateStatus(`β Process failed: ${error.message}`, 'error');
}
}
π What this function does:
Validates wallet connection first
Requests the best price from multiple exchanges
Builds a transaction based on that price
Prepares the transaction for signing (stores in app state)
Updates the UI to enable the next step
π¨ Common issues:
Wallet not connected β Connect wallet first
API key expired β Get a new one from dashboard
Insufficient balance β Make sure wallet has enough XLM
Function 3: Sign the Transaction βοΈ
async function signTransaction() {
try {
// Make sure wallet is connected and we have a transaction to sign
if (!appState.connected) {
updateStatus('β Please connect your wallet first!', 'error');
return;
}
if (!appState.unsignedXdr) {
updateStatus('β No transaction to sign. Please get a quote first!', 'error');
return;
}
updateStatus('π Please approve the transaction in Freighter...', 'info');
// Sign the transaction using Freighter
const signResult = await freighterAPI.signTransaction(appState.unsignedXdr, {
network: CONFIG.NETWORK,
networkPassphrase: 'Test SDF Network ; September 2015',
address: appState.walletAddress
});
appState.signedTransaction = signResult.signedTxXdr;
// Show the signed transaction for educational purposes
ELEMENTS.signedXdr.value = appState.signedTransaction;
const outputAmount = formatAmount(appState.currentQuote.amountOut, 6);
updateStatus(`β
Transaction signed successfully!<br>π Ready to swap 1 XLM for ${outputAmount} USDC`, 'success');
updateButtonStates();
} catch (error) {
console.error('Transaction signing failed:', error);
updateStatus(`β Transaction signing failed: ${error.message}`, 'error');
}
}
π What this function does:
Validates wallet connection and transaction availability
Calls Freighter to sign the transaction
Stores the signed transaction in app state
Updates UI to enable final step
π¨ Common issues:
User rejects signing β Ask them to try again
Freighter not connected β Check wallet connection
Wrong network β Ensure Freighter is on testnet
Function 4: Send Transaction to Network π
async function sendTransaction() {
try {
// Make sure we have a signed transaction
if (!appState.signedTransaction) {
updateStatus('β No signed transaction available. Please get a quote and sign it first.', 'error');
return;
}
updateStatus('π Broadcasting transaction to Stellar network...', 'info');
// Send the signed transaction
const sendRequest = {
xdr: appState.signedTransaction, // The signed transaction
launchtube: false // Use normal fees (not gasless)
};
const sendResult = await makeAPIRequest('/send', sendRequest);
// Create link to view transaction on Stellar Expert
const explorerUrl = `https://stellar.expert/explorer/${CONFIG.NETWORK}/tx/${sendResult.txHash}`;
// Show success message
ELEMENTS.transactionLink.innerHTML = `
<strong>Transaction Hash:</strong> <code>${sendResult.txHash}</code><br>
<a href="${explorerUrl}" target="_blank" rel="noopener">π View on Stellar Expert</a>
`;
ELEMENTS.finalResults.classList.remove('hidden');
updateStatus('π Swap completed successfully! Check the transaction link above.', 'success');
// Reset state for potential next transaction
appState.unsignedXdr = null;
appState.signedTransaction = null;
appState.currentQuote = null;
updateButtonStates();
} catch (error) {
console.error('Transaction send failed:', error);
updateStatus(`β Transaction failed: ${error.message}`, 'error');
}
}
π What this function does:
Validates we have a signed transaction ready
Submits the transaction to the Stellar network via Soroswap API
Shows success message with transaction hash and explorer link
Resets state for potential next transaction
π Complete Workflow Summary
4-Step Process:
π STEP 1: Connect Wallet
User clicks "Connect Freighter Wallet"
β connectWallet() function
App connects to Freighter wallet β
β
π± STEP 2: Get Quote & Build Transaction
User clicks "Quote & Build (1 XLM β USDC)"
β getQuote() function
App gets best price + builds unsigned transaction β
β
βοΈ STEP 3: Sign Transaction
User clicks "Sign Transaction"
β signTransaction() function
User approves transaction in Freighter wallet β
β
π STEP 4: Send to Network
User clicks "Send Transaction"
β sendTransaction() function
App broadcasts to Stellar network β
β
π SWAP COMPLETE!
π οΈ Key Concepts for Beginners
What is XDR?
XDR (External Data Representation) is how Stellar transactions are encoded:
Unsigned XDR: Transaction ready to be signed
Signed XDR: Transaction with digital signature, ready to submit
What is a Quote?
A quote tells you:
How much you'll receive for your trade
Which exchanges offer the best price
What path the trade will take
What is Signing?
Signing a transaction means:
Proving you own the wallet
Authorizing the transaction
Making it ready for the network
π¨ Security Best Practices
β
DO:
Use testnet for learning and testing
Keep your API keys secure
Verify transaction details before signing
Start with small amounts
β DON'T:
Put API keys in public code repositories
Sign transactions you don't understand
Use mainnet while learning
Hardcode private keys (never!)
π§ Common Troubleshooting
Problem: "Freighter not found"
Solution: Install Freighter wallet extension
Problem: "403 Forbidden" error
Solution: Check your API key is correct and not expired
Problem: "Insufficient liquidity"
Solution: Try a smaller amount or different token pair
Problem: Transaction fails
Solution: Check you have enough XLM for fees
π Next Steps
Once you understand this basic example:
Customize the UI with better styling
Add error handling for better user experience
Support multiple tokens instead of just XLMβUSDC
Add slippage protection for price changes
Try new methods from Soroswap API
Experiment using the SDK
π Additional Resources
Soroswap API Docs: https://api.soroswap.finance/docs
Freighter Docs: https://freighter.app/docs
Stellar Docs: https://developers.stellar.org
Stellar Expert: https://stellar.expert (blockchain explorer)
π‘ Pro Tips
Use browser dev tools to debug API calls
Check the console for error messages
Read API responses to understand what's happening
Last updated