Official TypeScript SDK for Soroswap.Finance - The first DEX and exchange aggregator built on Stellar, powered by smart contracts on Soroban.
- π Simple API Key Authentication: Secure API key-based authentication
- π± Trading Operations: Get quotes, build transactions, send them to the network
- π§ Liquidity Management: Add/remove liquidity and track positions
- π Market Data: Access pools, prices, and asset information
- π Server-Side Focused: Secure handling of API keys and sensitive operations
- π TypeScript Support: Full type safety with comprehensive interfaces
- β‘ Lightweight: No complex authentication flows or token management
- π§ͺ Well Tested: Comprehensive unit test coverage
pnpm install soroswap-sdkimport { SoroswapSDK, SupportedNetworks, SupportedProtocols, TradeType } from '@soroswap/sdk';
// Initialize the SDK
const soroswapClient = new SoroswapSDK({
apiKey: 'sk_your_api_key_here'
});
// Get a quote for a swap
const quote = await soroswapClient.quote({
assetIn: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
assetOut: 'CDTKPWPLOURQA2SGTKTUQOWRCBZEORB4BWBOMJ3D3ZTQQSGE5F6JBQLV',
amount: 10000000n, // Note: Amount must be a BigInt
tradeType: TradeType.EXACT_IN,
protocols: [SupportedProtocols.SDEX, SupportedProtocols.SOROSWAP, SupportedProtocols.AQUA],
});
// Build the transaction XDR from the quote
const buildResponse = await soroswapClient.build({
quote,
from: 'YOUR_WALLET_ADDRESS',
to: 'RECIPIENT_ADDRESS'
});
// Sign the transaction with your preferred signer
const signedXdr = await yourSigner.sign(buildResponse.xdr);
// Send the signed transaction
const result = await soroswapClient.send(signedXdr, false); // launchtube = false
console.log('Transaction result:', result);interface SoroswapSDKConfig {
apiKey: string; // Your Soroswap API key (starts with 'sk_')
baseUrl?: string; // Custom API base URL (defaults to 'https://api.soroswap.finance')
defaultNetwork?: SupportedNetworks; // SupportedNetworks.MAINNET | SupportedNetworks.TESTNET
timeout?: number; // Request timeout in ms (defaults to 30000) you might want to adjust this if using launchtube
}For better security, you can use environment variables:
const soroswapClient = new SoroswapSDK({
apiKey: process.env.SOROSWAP_API_KEY!,
baseUrl: process.env.SOROSWAP_API_URL, // Optional: for localhost or custom API
defaultNetwork: process.env.NODE_ENV === 'production'
? SupportedNetworks.MAINNET
: SupportedNetworks.TESTNET
});
// Example for local development:
const localClient = new SoroswapSDK({
apiKey: 'sk_local_api_key',
baseUrl: 'http://localhost:3000',
defaultNetwork: SupportedNetworks.TESTNET
});The SDK uses API key authentication - no complex authentication flows needed:
// Simply initialize with your API key
const soroswapClient = new SoroswapSDK({
apiKey: 'sk_your_api_key_here'
});const protocols = await soroswapClient.getProtocols(SupportedNetworks.MAINNET);
// Returns: ['sdex', 'soroswap', 'phoenix', 'aqua']const quote = await soroswapClient.quote({
assetIn: 'TOKEN_A_CONTRACT',
assetOut: 'TOKEN_B_CONTRACT',
amount: 1000000n, // BigInt required
tradeType: TradeType.EXACT_IN,
protocols: [SupportedProtocols.SOROSWAP, SupportedProtocols.AQUA],
slippageBps: '50', // 0.5% in basis points
maxHops: 2,
feeBps: 30, // Optional fee in basis points
});After getting a quote, build the transaction XDR:
const buildResponse = await soroswapClient.build({
quote: quote,
from: 'YOUR_WALLET_ADDRESS',
to: 'RECIPIENT_ADDRESS', // Optional, defaults to 'from'
referralId: 'REFERRAL_WALLET_ADDRESS' // Required if quote includes feeBps
});
// buildResponse.xdr contains the transaction ready for signingconst result = await soroswapClient.send(
signedXdr, // The signed transaction XDR
false, // launchtube: boolean (default false)
SupportedNetworks.MAINNET // Optional network override
);// Get all pools for specific protocols
const pools = await soroswapClient.getPools(
SupportedNetworks.MAINNET,
[SupportedProtocols.SOROSWAP, SupportedProtocols.AQUA],
[SupportedAssetLists.SOROSWAP] // Optional asset list filter
);
// Get specific pool for token pair
const pool = await soroswapClient.getPoolByTokens(
'TOKEN_A_CONTRACT',
'TOKEN_B_CONTRACT',
SupportedNetworks.MAINNET,
[SupportedProtocols.SOROSWAP]
);Important: Before adding liquidity, you should fetch the existing pool to calculate the proper token proportions. The amounts must maintain the current pool ratio, otherwise the transaction will fail during simulation.
// First, get the current pool to understand the ratio
const pools = await soroswapClient.getPoolByTokens(
'TOKEN_A_CONTRACT',
'TOKEN_B_CONTRACT',
SupportedNetworks.MAINNET,
[SupportedProtocols.SOROSWAP]
);
if (pools.length > 0) {
const pool = pools[0];
const ratio = Number(pool.reserveB) / Number(pool.reserveA);
// Calculate proportional amounts
const amountA = '1000000';
const amountB = (Number(amountA) * ratio).toString();
const addLiquidityTx = await soroswapClient.addLiquidity({
assetA: 'TOKEN_A_CONTRACT',
assetB: 'TOKEN_B_CONTRACT',
amountA: amountA,
amountB: amountB,
to: 'YOUR_WALLET_ADDRESS',
slippageBps: '50' // 0.5%
});
// Sign and send the transaction
const signedXdr = await yourSigner.sign(addLiquidityTx.xdr);
const result = await soroswapClient.send(signedXdr, false);
}Note: All liquidity transactions are simulated before execution. If the amounts don't match the required proportions or if there are insufficient funds, the transaction will return an error during simulation.
const removeLiquidityTx = await soroswapClient.removeLiquidity({
assetA: 'TOKEN_A_CONTRACT',
assetB: 'TOKEN_B_CONTRACT',
liquidity: '500000',
amountA: '450000',
amountB: '900000',
to: 'YOUR_WALLET_ADDRESS',
slippageBps: '50'
});const positions = await soroswapClient.getUserPositions(
'USER_WALLET_ADDRESS',
SupportedNetworks.MAINNET
);// Single asset price
const prices = await soroswapClient.getPrice(
'TOKEN_CONTRACT_ADDRESS',
SupportedNetworks.MAINNET
);
// Multiple asset prices
const prices = await soroswapClient.getPrice([
'TOKEN_A_CONTRACT',
'TOKEN_B_CONTRACT'
], SupportedNetworks.MAINNET);// Get all available asset lists metadata
const assetListsInfo = await soroswapClient.getAssetList();
// Get specific asset list
const soroswapAssets = await soroswapClient.getAssetList(SupportedAssetLists.SOROSWAP);const factoryAddress = await soroswapClient.getContractAddress(SupportedNetworks.MAINNET, 'factory');
const routerAddress = await soroswapClient.getContractAddress(SupportedNetworks.MAINNET, 'router');
const aggregatorAddress = await soroswapClient.getContractAddress(SupportedNetworks.MAINNET, 'aggregator');- Environment Variables: Store API keys in environment variables, not in code
- Server-Side Only: This SDK is designed for server-side use only
- API Key Security: Keep your API keys secure and never commit them to version control
- Error Handling: Always wrap API calls in try-catch blocks
try {
const quote = await soroswapClient.quote(quoteParams);
const buildResponse = await soroswapClient.build({ quote, from: walletAddress });
// Handle success
} catch (error) {
console.error('Quote/build failed:', error.message);
// Handle error
}pnpm run buildThe SDK includes two types of tests:
Fast tests that mock all external dependencies:
# Run unit tests (default)
pnpm test
# Run with coverage
pnpm run test:coverage
# Watch mode for development
pnpm run test:watchTests that actually call the Soroswap API:
# Set up API key first
export SOROSWAP_API_KEY="sk_your_api_key_here"
# Run integration tests
pnpm run test:integration
# Run both unit and integration tests
pnpm run test:allNote: Integration tests require a valid Soroswap API key and may fail due to network issues or API changes. See Integration Test Documentation for detailed setup.
pnpm run lint
pnpm run lint:fixWhile this SDK is server-side focused, you can create secure frontend integrations:
// Backend API endpoint
app.post('/api/quote', async (req, res) => {
try {
const soroswapClient = new SoroswapSDK({
apiKey: process.env.SOROSWAP_API_KEY!
});
const quote = await soroswapClient.quote(req.body);
const buildResponse = await soroswapClient.build({
quote,
from: req.body.walletAddress
});
// Only return the XDR and quote data, not sensitive info
res.json({
xdr: buildResponse.xdr,
quote: {
assetIn: quote.assetIn,
assetOut: quote.assetOut,
tradeType: quote.tradeType
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Frontend widget
async function getQuoteAndBuild(quoteParams) {
const response = await fetch('/api/quote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(quoteParams)
});
return response.json();
}The SDK exports comprehensive TypeScript types:
import {
SoroswapSDK,
SoroswapSDKConfig,
SupportedNetworks,
SupportedProtocols,
SupportedAssetLists,
TradeType,
QuoteRequest,
QuoteResponse,
BuildQuoteRequest,
BuildQuoteResponse,
Pool,
UserPosition,
PriceData,
AssetList,
AssetListInfo,
// ... and many more
} from 'soroswap-sdk';import {
QuoteRequest,
TradeType,
SupportedProtocols,
ExactInBuildTradeReturn
} from 'soroswap-sdk';
const quoteRequest: QuoteRequest = {
assetIn: 'TOKEN_A',
assetOut: 'TOKEN_B',
amount: 1000000n,
tradeType: TradeType.EXACT_IN,
protocols: [SupportedProtocols.SOROSWAP]
};
const quote = await soroswapClient.quote(quoteRequest);
// Type-safe access to quote properties
if (quote.tradeType === TradeType.EXACT_IN) {
const exactInQuote = quote as ExactInBuildTradeReturn;
console.log('Expected output:', exactInQuote.trade.expectedAmountOut);
}Built with β€οΈ by the Soroswap team.