# SDK - Guide for Fixed Staking

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:

```bash
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:

```javascript
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:

* Mainnet: <https://raw.githubusercontent.com/Fiva-protocol/assets/refs/heads/main/mainnet_SY.json>
* Testnet: <https://raw.githubusercontent.com/Fiva-protocol/assets/refs/heads/main/testnet_SY.json>

You can also check available pools and APYs in the FIVA application: <https://app.thefiva.com/fixed-yield>

### 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:

```javascript
import { FivaAsset, FivaClient } from '@fiva/sdk';
import { Address, toNano, TonClient4 } from '@ton/ton';

// Asset constants
const USDT_EVAA_SY = Address.parse('EQDi9blCcyT-k8iMpFMYY0t7mHVyiCB50ZsRgyUECJDuGvIl');
const USDT_PRECISION = 1_000_000; // 6 decimals
const FIVA_JETTON_PRECISION = 1_000_000_000; // 9 decimals

class FixedStakingIntegration {
  constructor(connector, endpoint = 'https://mainnet-v4.tonhubapi.com') {
    this.tonClient = new TonClient4({ endpoint });
    this.fivaClient = new FivaClient({ 
      connector, 
      tonClient: this.tonClient, 
      syAddress: USDT_EVAA_SY 
    });
  }
  
  // Get current fixed staking rate and maturity info
  async getFixedStakingInfo() {
    // Get maturity date as a JavaScript Date object
    const maturityDate = await this.fivaClient.getMaturityDate();
    const currentTime = Math.floor(Date.now() / 1000);
    const maturityTime = Math.floor(maturityDate.getTime() / 1000);
    const secondsToMaturity = maturityTime - currentTime;
    const daysToMaturity = Math.floor(secondsToMaturity / (60 * 60 * 24));
    
    // Get fixed APY directly from the SDK
    const fixedAPY = await this.fivaClient.getFixedAPY();
    
    return {
      fixedAPY: fixedAPY.toFixed(2),
      daysToMaturity,
      maturityDate: maturityDate.toLocaleDateString(),
      hasMatured: currentTime >= maturityTime
    };
  }
  
  // Calculate potential return for a specific amount
  async calculatePotentialReturn(amountUsdt) {
    const amount = BigInt(amountUsdt * USDT_PRECISION);
    
    // Calculate gain percentage for this specific amount
    const gainPercentage = await this.fivaClient.getGain(amount);
    
    // Calculate absolute gain amount
    const gainAmount = (amountUsdt * gainPercentage) / 100;
    
    return {
      inputAmount: amountUsdt,
      gainPercentage: gainPercentage.toFixed(2),
      gainAmount: gainAmount.toFixed(2),
      totalReturn: (amountUsdt + gainAmount).toFixed(2)
    };
  }
  
  // Stake with fixed yield
  async stakeWithFixedYield(amountUsdt, slippagePercentage = 1) {
    const queryId = Date.now();
    const amount = BigInt(amountUsdt * USDT_PRECISION);
    
    const expectedPtOut = await this.fivaClient.getExpectedSwapAmountOut(
      FivaAsset.Underlying, 
      FivaAsset.PT, 
      amount
    );
    
    // Calculate minimum output based on slippage
    const slippageFactor = 100 - slippagePercentage;
    const minPtOut = (expectedPtOut * BigInt(slippageFactor)) / 100n;
    
    return await this.fivaClient.swapAssetForPt(amount, queryId, minPtOut);
  }
  
  // Unstake before maturity
  async unstakeBeforeMaturity(ptAmount, slippagePercentage = 1) {
    const queryId = Date.now();
    const amount = BigInt(ptAmount * FIVA_JETTON_PRECISION);
    
    const expectedAssetOut = await this.fivaClient.getExpectedSwapAmountOut(
      FivaAsset.PT, 
      FivaAsset.Underlying, 
      amount
    );
    
    // Calculate minimum output based on slippage
    const slippageFactor = 100 - slippagePercentage;
    const minAssetOut = (expectedAssetOut * BigInt(slippageFactor)) / 100n;
    
    return await this.fivaClient.swapPtForAsset(amount, queryId, minAssetOut);
  }
  
  // Unstake after maturity
  async unstakeAfterMaturity(ptAmount) {
    const queryId = Date.now();
    const amount = BigInt(ptAmount * FIVA_JETTON_PRECISION);
    
    return await this.fivaClient.sendRedeemPT(amount, queryId);
  }
  
  // Get user's PT balance
  async getUserPtBalance(userAddress) {
    return await this.fivaClient.getPtBalance(userAddress);
  }
  
  // Check if maturity date has passed
  async hasMatured() {
    const maturityDate = await this.fivaClient.getMaturityDate();
    const currentTime = Math.floor(Date.now() / 1000);
    const maturityTime = Math.floor(maturityDate.getTime() / 1000);
    return currentTime >= maturityTime;
  }
}
```

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:

```javascript
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:

```javascript
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:

1. **Fixed Percentage** (as shown in examples):

   ```javascript
   // 1% slippage tolerance
   const minAmountOut = (expectedAmountOut * 99n) / 100n;
   ```
2. **User-Configurable**:

   ```javascript
   // 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:

```javascript
import { FivaAsset, FivaClient } from '@fiva/sdk';
import { Address, toNano, TonClient4 } from '@ton/ton';

// Asset constants
const USDT_EVAA_SY = Address.parse('EQDi9blCcyT-k8iMpFMYY0t7mHVyiCB50ZsRgyUECJDuGvIl');
const USDT_PRECISION = 1_000_000; // 6 decimals
const FIVA_JETTON_PRECISION = 1_000_000_000; // 9 decimals

class FixedStakingIntegration {
  constructor(connector, endpoint = 'https://mainnet-v4.tonhubapi.com') {
    this.tonClient = new TonClient4({ endpoint });
    this.fivaClient = new FivaClient({ 
      connector, 
      tonClient: this.tonClient, 
      syAddress: USDT_EVAA_SY 
    });
  }
  
  // Get current fixed staking rate and maturity info
  async getFixedStakingInfo() {
    const index = await this.fivaClient.getIndex();
    const maturityTimestamp = await this.fivaClient.getMaturityTimestamp();
    const currentTime = Math.floor(Date.now() / 1000);
    const secondsToMaturity = maturityTimestamp - currentTime;
    const daysToMaturity = secondsToMaturity / (60 * 60 * 24);
    
    // Calculate APY based on current swap rate
    const oneUsdtAmount = 1_000_000n; // 1 USDT
    const expectedPtOut = await this.fivaClient.getExpectedSwapAmountOut(
      FivaAsset.Underlying, 
      FivaAsset.PT, 
      oneUsdtAmount
    );
    
    // Calculate APY (simplified)
    const ptToAssetRatio = Number(expectedPtOut) / Number(oneUsdtAmount);
    const annualizedReturn = (1 / ptToAssetRatio - 1) * (365 / daysToMaturity) * 100;
    
    return {
      fixedAPY: annualizedReturn.toFixed(2),
      daysToMaturity: Math.floor(daysToMaturity),
      maturityDate: new Date(maturityTimestamp * 1000).toLocaleDateString(),
      hasMatured: currentTime >= maturityTimestamp
    };
  }
  
  // Stake with fixed yield
  async stakeWithFixedYield(amountUsdt, slippagePercentage = 1) {
    const queryId = Date.now();
    const amount = BigInt(amountUsdt * USDT_PRECISION);
    
    const expectedPtOut = await this.fivaClient.getExpectedSwapAmountOut(
      FivaAsset.Underlying, 
      FivaAsset.PT, 
      amount
    );
    
    // Calculate minimum output based on slippage
    const slippageFactor = 100 - slippagePercentage;
    const minPtOut = (expectedPtOut * BigInt(slippageFactor)) / 100n;
    
    return await this.fivaClient.swapAssetForPt(amount, queryId, minPtOut);
  }
  
  // Unstake before maturity
  async unstakeBeforeMaturity(ptAmount, slippagePercentage = 1) {
    const queryId = Date.now();
    const amount = BigInt(ptAmount * FIVA_JETTON_PRECISION);
    
    const expectedAssetOut = await this.fivaClient.getExpectedSwapAmountOut(
      FivaAsset.PT, 
      FivaAsset.Underlying, 
      amount
    );
    
    // Calculate minimum output based on slippage
    const slippageFactor = 100 - slippagePercentage;
    const minAssetOut = (expectedAssetOut * BigInt(slippageFactor)) / 100n;
    
    return await this.fivaClient.swapPtForAsset(amount, queryId, minAssetOut);
  }
  
  // Unstake after maturity
  async unstakeAfterMaturity(ptAmount) {
    const queryId = Date.now();
    const amount = BigInt(ptAmount * FIVA_JETTON_PRECISION);
    
    return await this.fivaClient.sendRedeemPT(amount, queryId);
  }
  
  // Get user's PT balance
  async getUserPtBalance(userAddress) {
    return await this.fivaClient.getPtBalance(userAddress);
  }
  
  // Check if maturity date has passed
  async hasMatured() {
    const maturityTimestamp = await this.fivaClient.getMaturityTimestamp();
    const currentTime = Math.floor(Date.now() / 1000);
    return currentTime >= maturityTimestamp;
  }
}
```

### Testing Your Integration

Before going live, we recommend testing your integration in our testnet environment:

* Use testnet SY addresses from our repository
* Test all three functions with small amounts
* Verify APY calculations match expected values
* Test the full lifecycle including maturity redemption

If you have questions about the integration process or need support, please contact <andrei.yazepchyk@thefiva.com> or join our [community on Telegram](https://t.me/fiva_community).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.thefiva.com/developers/integrating-fixed-rate-staking/sdk-guide-for-fixed-staking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
