This guide provides a detailed walkthrough of integrating FIVA's fixed staking functionality into your platform using our SDK. We'll cover the full implementation process with code examples and best practices.
Getting Started with the SDK
First, install the FIVA SDK in your project:
npm install @fiva/sdk
# or
yarn add @fiva/sdk
# or
pnpm install @fiva/sdk
Client Initialization
The first step is to initialize the FIVA client with your wallet connector, TON client, and the SY address for the asset you want to work with:
import { FivaClient } from '@fiva/sdk';
import { Address, TonClient4 } from '@ton/ton';
// Initialize TON client
const tonClient = new TonClient4({
endpoint: 'https://mainnet-v4.tonhubapi.com'
});
// Initialize FIVA client for USDT-EVAA fixed staking
const fivaClient = new FivaClient({
connector, // Your wallet connector
tonClient,
syAddress: Address.parse('EQDi9blCcyT-k8iMpFMYY0t7mHVyiCB50ZsRgyUECJDuGvIl') // USDT-EVAA SY address
});
You can find all supported SY addresses at:
Implementing Core Fixed Staking Functions
Let's implement the three core functions needed for fixed staking:
1. Stake (Fixed Yield)
This function allows users to lock in current rates by swapping their asset for PT tokens:
import { FivaAsset } from '@fiva/sdk';
async function stakeWithFixedYield(amount, userWalletAddress) {
const queryId = Date.now();
// Get expected PT amount to display to user
const expectedPtOut = await fivaClient.getExpectedSwapAmountOut(
FivaAsset.Underlying,
FivaAsset.PT,
amount
);
// Set minimum output with slippage protection
// This is crucial for protecting users from price movements
const minPtOut = (expectedPtOut * 99n) / 100n; // 1% slippage tolerance
// Execute the stake transaction
const result = await fivaClient.swapAssetForPt(
amount,
queryId,
minPtOut,
userWalletAddress // Optional: recipient address (defaults to sender)
);
return result;
}
When presenting this to users, you should frame it as "Fixed Staking" with a guaranteed return at maturity.
2. Unstake Before Maturity
This function allows users to exit their position early:
async function unstakeBeforeMaturity(ptAmount, userWalletAddress) {
const queryId = Date.now();
// Get expected asset amount to display to user
const expectedAssetOut = await fivaClient.getExpectedSwapAmountOut(
FivaAsset.PT,
FivaAsset.Underlying,
ptAmount
);
// Set minimum output with slippage protection
const minAssetOut = (expectedAssetOut * 99n) / 100n; // 1% slippage tolerance
// Execute the unstake transaction
const result = await fivaClient.swapPtForAsset(
ptAmount,
queryId,
minAssetOut,
userWalletAddress // Optional: recipient address
);
return result;
}
When presenting this option to users, make it clear that early unstaking will return an amount determined by current market conditions, which may differ from the initially promised fixed rate.
3. Unstake After Maturity
This function allows users to redeem their PT tokens after maturity:
async function unstakeAfterMaturity(ptAmount, userWalletAddress) {
const queryId = Date.now();
// Execute the redeem transaction
const result = await fivaClient.sendRedeemPT(
ptAmount,
queryId,
userWalletAddress // Optional: recipient address
);
return result;
}
This function should be presented as "Claim" or "Withdraw" after the maturity date is reached.
Understanding Minimum Amount Out and Slippage Protection
Slippage protection is a critical aspect of any on-chain transaction, and it's especially important for fixed staking operations where users expect predictable outcomes.
What is minAmountOut?
In the SDK functions swapAssetForPt and swapPtForAsset, the minPtOut and minAssetOut parameters represent the minimum amount of tokens the user is willing to accept from the transaction. If the actual output would be less than this minimum (due to price movements or other factors), the transaction will revert.
Implementing Slippage Protection
There are two main approaches to implementing slippage protection:
// Allow users to set their own slippage tolerance (e.g., 0.5%, 1%, 2%)
function calculateMinAmountOut(expectedAmountOut, slippagePercentage) {
// slippagePercentage is a number like 0.5, 1, 2
const slippageFactor = 100 - slippagePercentage;
return (expectedAmountOut * BigInt(slippageFactor * 100)) / 10000n;
}
// Usage:
const minAmountOut = calculateMinAmountOut(expectedAmountOut, userSelectedSlippage);
Importance of Slippage Protection
Without appropriate slippage protection:
Transactions may execute at unfavorable rates during periods of high volatility
Users may receive significantly less than expected, especially in pools with lower liquidity
Front-running attacks become possible in some scenarios
Important Note: If the transaction would result in receiving less than the specified minAmountOut, the entire transaction will be reverted. This protects users from unexpected outcomes and ensures they always get at least what they specified or nothing at all (allowing them to try again).
Complete Integration Example
Here's a comprehensive example that ties everything together: