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