Skip to main content

Depositing into Smart Pools

This guide explains how to programmatically deposit assets into Smart Pools.

Installation​

First, install the Steer Protocol SDK:

npm install @steerprotocol/sdk

Client Setup​

Initialize the Steer Protocol client:

import { SteerClient } from '@steerprotocol/sdk';
import { createPublicClient, createWalletClient, http } from 'viem';
import { polygon } from 'viem/chains';

// Create Viem clients
const publicClient = createPublicClient({
chain: polygon,
transport: http()
});

const walletClient = createWalletClient({
chain: polygon,
transport: http()
});

// Initialize SteerClient
const steerClient = new SteerClient({
environment: 'production', // Use 'testnet' for testing
client: publicClient,
walletClient: walletClient
});

Prerequisites​

Before depositing into a Smart Pool, ensure you have:

  1. Smart Pools SDK installed and client initialized
  2. Sufficient token balance for deposit
  3. Approved token spending for the Smart Pool contract

Implementation Steps​

1. Calculate Deposit Amounts​

Before preparing the deposit parameters, you'll need to calculate the correct token amounts using the SDK's helper functions:

Get Deposit Ratio​

To maintain the pool's balance, you need to get the correct deposit ratio for your tokens:

interface SteerResponse<T> {
data: T | null;
status: number;
success: boolean;
error?: string;
}

interface VaultDetailsResponse {
details: VaultDetails | AlgebraVaultDetails;
ratio: number | bigint | string;
}

// Get deposit ratio for token1 when you have token0
// Set zeroForOne to true if calculating for token0 -> token1
// Set zeroForOne to false if calculating for token1 -> token0
const ratioResponse = await steerClient.vaults.getDepositRatio(vaultAddress, zeroForOne);

if (!ratioResponse.success || !ratioResponse.data) {
throw new Error('Failed to get deposit ratio');
}

const { ratio } = ratioResponse.data;

Calculate Corresponding Token Amount​

Once you have one token amount, calculate the required amount of the other token:

// Example: Calculate token1 amount when you have token0 amount
const amount0 = parseUnits('100', token0Decimals); // Example: 100 tokens
const amount1Response = await steerClient.vaults.getCorrespondingTokenAmount(
vaultAddress,
amount0,
false // false for token0 -> token1, true for token1 -> token0
);

if (!amount1Response.success || !amount1Response.data) {
throw new Error('Failed to calculate corresponding token amount');
}

const amount1 = amount1Response.data; // This is a bigint

2. Prepare Deposit Transaction​

You can use the SDK's prepareDepositTx method to prepare the deposit transaction parameters:

// Prepare deposit parameters
const amount0Desired = parseUnits('1', token0Decimals); // Example: 1 token0
const amount1Desired = parseUnits('2', token1Decimals); // Example: 2 token1
const slippage = 0.01; // 1% slippage tolerance

// Prepare the deposit transaction
const response = await steerClient.prepareDepositTx({
vaultAddress: vaultAddress as `0x${string}`,
amount0Desired,
amount1Desired,
slippage
});

if (!response.success || !response.data) {
throw new Error('Failed to prepare deposit transaction');
}

// The response contains all necessary transaction parameters
const {
address, // The vault contract address
functionName, // 'deposit'
abi, // The ABI for the deposit function
args // Arguments for the deposit function
} = response.data;

3. Execute Deposit​

You can execute the deposit using either Viem or Ethers.js with the prepared transaction parameters:

Using Viem​

// First approve both tokens
const token0Contract = {
address: pool.token0,
abi: [{
name: 'approve',
type: 'function',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' }
],
outputs: [{ type: 'bool' }]
}]
};

const token1Contract = {
address: pool.token1,
abi: token0Contract.abi
};

// Approve token0
await walletClient.writeContract({
...token0Contract,
functionName: 'approve',
args: [address, amount0Desired]
});

// Approve token1
await walletClient.writeContract({
...token1Contract,
functionName: 'approve',
args: [address, amount1Desired]
});

// Execute deposit using prepared transaction
const hash = await walletClient.writeContract({
address,
abi,
functionName,
args
});

Using Ethers.js​

import { ethers } from 'ethers';

// Create contract instances
const vaultContract = new ethers.Contract(
address,
abi,
signer
);

const token0Contract = new ethers.Contract(
pool.token0,
erc20ABI,
signer
);

const token1Contract = new ethers.Contract(
pool.token1,
erc20ABI,
signer
);

// Approve both tokens
await token0Contract.approve(address, amount0Desired);
await token1Contract.approve(address, amount1Desired);

// Execute deposit using prepared transaction
const tx = await vaultContract[functionName](...args);
await tx.wait();

Important Notes​

  1. Token Approval

    • Always check existing allowance before approving
    • Consider using infinite approval for gas savings
    • Reset approvals when needed for security
  2. Slippage Protection

    • Always use minSharesOut parameter
    • Calculate based on current pool share price
    • Add buffer for price movements
  3. Gas Optimization

    • Implement proper gas estimation
    • Consider network conditions
    • Bundle transactions when possible

Error Handling​

try {
// Check token balance
const balance = await erc20Contract.balanceOf(address);
if (balance.lt(depositAmount)) {
throw new Error('Insufficient token balance');
}

// Check allowance
const allowance = await erc20Contract.allowance(address, pool.address);
if (allowance.lt(depositAmount)) {
// Handle approval needed
}

// Proceed with deposit
// ...
} catch (error) {
console.error('Deposit failed:', error);
// Handle error appropriately
}

Best Practices​

  1. Pre-deposit Checks

    • Verify token balance
    • Check token allowance
    • Validate pool status
  2. Transaction Monitoring

    • Monitor approval transaction
    • Monitor deposit transaction
    • Implement proper error handling
  3. Share Price Considerations

    • Monitor share price impact
    • Calculate expected shares
    • Implement proper slippage protection

Next Steps​