async function simulateAddLiquidity() {
try {
const simulation = await client.simulateAddLiquidity({
poolId: "pool-public-key",
assetAAmount: "100000000", // 1 BTC
assetBAmount: "100000000000", // 100,000 USDB
});
console.log('LP tokens to mint:', simulation.lpTokensToMint);
console.log('Pool share %:', simulation.poolSharePercentage);
console.log('Asset A refund:', simulation.assetARefundAmount);
console.log('Asset B refund:', simulation.assetBRefundAmount);
return simulation;
} catch (error) {
console.error('Simulation failed:', error);
}
}
async function addLiquidity() {
try {
// First, check the pool to understand the current ratio
const pool = await client.getPool("pool-id");
console.log('Current pool ratio:', pool.assetAReserve, ':', pool.assetBReserve);
// Add liquidity maintaining the pool ratio
const response = await client.addLiquidity({
poolId: "pool-id",
assetAAmount: "100000000", // 1 BTC
assetBAmount: "100000000000", // 100,000 USDB
assetAMinAmountIn: "100000000", // set minimums to protect from price moves
assetBMinAmountIn: "100000000000",
});
console.log('Liquidity added successfully!');
console.log('LP tokens received:', response.lpTokensMinted);
// Check if any assets were refunded
if (response.refund) {
console.log('Asset A refunded:', response.refund.assetAAmount);
console.log('Asset B refunded:', response.refund.assetBAmount);
}
return response;
} catch (error) {
console.error('Failed to add liquidity:', error);
}
}
async function addLiquidityOptimal(poolId: string, assetADesired: bigint) {
// Get current pool state
const pool = await client.getPool(poolId);
// Calculate optimal asset B amount based on current ratio
const optimalAssetB = (assetADesired * BigInt(pool.assetBReserve)) / BigInt(pool.assetAReserve);
console.log('Optimal amounts:', {
assetA: assetADesired,
assetB: optimalAssetB
});
// Add liquidity with optimal amounts
const response = await client.addLiquidity({
poolId: poolId,
assetAAmount: assetADesired.toString(),
assetBAmount: optimalAssetB.toString(),
assetAMinAmountIn: assetADesired.toString(),
assetBMinAmountIn: optimalAssetB.toString(),
});
console.log('Added liquidity with no refunds');
return response;
}
async function trackPosition(poolId: string) {
// Get your current position
const position = await client.getLpPosition(poolId);
console.log('LP tokens owned:', position.lpTokensOwned);
console.log('Pool share:', position.sharePercentage, '%');
console.log('Current value - Asset A:', position.valueAssetA);
console.log('Current value - Asset B:', position.valueAssetB);
// Check principal amounts if available
if (position.principalAssetA !== undefined && position.principalAssetB !== undefined) {
console.log('Initial deposit - Asset A:', position.principalAssetA);
console.log('Initial deposit - Asset B:', position.principalAssetB);
}
// Check unrealized P&L if available
if (position.unrealizedProfitLossAssetA && position.unrealizedProfitLossAssetB) {
console.log('Unrealized P&L - Asset A:', position.unrealizedProfitLossAssetA);
console.log('Unrealized P&L - Asset B:', position.unrealizedProfitLossAssetB);
}
return position;
}
async function calculateReturns(poolId: string) {
const position = await client.getLpPosition(poolId);
// If principal amounts are available, calculate returns
if (position.principalAssetA !== undefined && position.principalAssetB !== undefined) {
const returnsA = position.valueAssetA - position.principalAssetA;
const returnsB = position.valueAssetB - position.principalAssetB;
// Calculate percentage returns
const percentReturnA = position.principalAssetA > 0
? (returnsA / position.principalAssetA) * 100
: 0;
const percentReturnB = position.principalAssetB > 0
? (returnsB / position.principalAssetB) * 100
: 0;
console.log('Returns:');
console.log(`Asset A: ${returnsA} (${percentReturnA.toFixed(2)}%)`);
console.log(`Asset B: ${returnsB} (${percentReturnB.toFixed(2)}%)`);
}
// The API provides unrealized P&L directly
if (position.unrealizedProfitLossAssetA && position.unrealizedProfitLossAssetB) {
console.log('Unrealized P&L from API:');
console.log(`Asset A: ${position.unrealizedProfitLossAssetA}`);
console.log(`Asset B: ${position.unrealizedProfitLossAssetB}`);
}
// Check for impermanent loss
const pool = await client.getPool(poolId);
const currentPrice = Number(pool.reserveB) / Number(pool.reserveA);
if (position.principalAssetA && position.principalAssetB) {
const initialPrice = position.principalAssetB / position.principalAssetA;
const priceChange = ((currentPrice - initialPrice) / initialPrice) * 100;
console.log(`Price change since deposit: ${priceChange.toFixed(2)}%`);
}
}
async function simulateRemoveLiquidity(poolId: string, lpTokensToRemove: string) {
try {
const simulation = await client.simulateRemoveLiquidity({
poolId: poolId,
providerPublicKey: (await client.wallet.getIdentityPublicKey()),
lpTokensToRemove: lpTokensToRemove,
});
console.log('Expected asset A:', simulation.assetAAmount);
console.log('Expected asset B:', simulation.assetBAmount);
return simulation;
} catch (error) {
console.error('Simulation failed:', error);
}
}
async function removeLiquidity(poolId: string, lpTokensToRemove: string) {
try {
// Check your LP balance first
const position = await client.getLpPosition(poolId);
const lpTokensOwned = BigInt(position.lpTokensOwned);
const tokensToRemove = BigInt(lpTokensToRemove);
if (lpTokensOwned < tokensToRemove) {
throw new Error(`Insufficient LP tokens. Owned: ${lpTokensOwned}, Requested: ${tokensToRemove}`);
}
// Remove liquidity
const response = await client.removeLiquidity({
poolId: poolId,
lpTokensToRemove: lpTokensToRemove,
});
console.log('Liquidity removed successfully!');
console.log('Asset A received:', response.assetAWithdrawn);
console.log('Asset B received:', response.assetBWithdrawn);
console.log('Transfers:', response.assetATransferId, response.assetBTransferId);
return response;
} catch (error) {
console.error('Failed to remove liquidity:', error);
}
}
// Remove all liquidity
async function removeAllLiquidity(poolId: string) {
const position = await client.getLpPosition(poolId);
return await removeLiquidity(poolId, position.lpTokensOwned);
}
// Remove partial liquidity (e.g., 50%)
async function removePartialLiquidity(poolId: string, percentage: number) {
const position = await client.getLpPosition(poolId);
const lpTokensToRemove = (BigInt(position.lpTokensOwned) * BigInt(percentage)) / 100n;
return await removeLiquidity(poolId, lpTokensToRemove.toString());
}
async function completeLiquidityLifecycle() {
const poolId = "pool-id";
// 1. Add liquidity
console.log('=== Adding Liquidity ===');
const addResponse = await client.addLiquidity({
poolId: poolId,
assetAAmount: 100000000n, // 1 BTC
assetBAmount: 100000000000n, // 100,000 USDB
});
const initialInvestment = {
assetA: 100000000n,
assetB: 100000000000n,
};
// 2. Monitor position over time
console.log('\n=== Monitoring Position ===');
await new Promise(resolve => setTimeout(resolve, 60000)); // Wait 1 minute
await trackPosition(poolId);
// 3. Calculate returns
console.log('\n=== Calculating Returns ===');
await calculateReturns(poolId);
// 4. Remove 50% of liquidity
console.log('\n=== Removing 50% Liquidity ===');
await removePartialLiquidity(poolId, 50);
// 5. Check remaining position
console.log('\n=== Remaining Position ===');
await trackPosition(poolId);
}
async function safeAddLiquidity(poolId: string, assetAAmount: bigint, assetBAmount: bigint) {
try {
// Check balances first
const balance = await client.getBalance();
// Validate sufficient balance
const pool = await client.getPool(poolId);
const BTC_PUBKEY = "020202020202020202020202020202020202020202020202020202020202020202";
const btcRequired = pool.assetAAddress === BTC_PUBKEY ? assetAAmount :
pool.assetBAddress === BTC_PUBKEY ? assetBAmount : 0n;
if (balance.balance < btcRequired) {
throw new Error('Insufficient BTC balance');
}
// Add liquidity
return await client.addLiquidity({
poolId: poolId,
assetAAmount: assetAAmount,
assetBAmount: assetBAmount,
});
} catch (error) {
if (error.message.includes('Insufficient balance')) {
console.error('Not enough funds');
} else if (error.message.includes('Pool inactive')) {
console.error('Pool is currently inactive');
} else if (error.message.includes('Below minimum')) {
console.error('Amount below minimum requirement');
} else {
console.error('Operation failed:', error);
}
throw error;
}
}
Was this page helpful?