> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superearn.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate Earn USDT

> Build the future of stablecoin yield with EarnUSDT - a token that lets any app tap into real on-chain yield.

EarnUSDT is a yield‑bearing version of USDT backed by the **Super Vault**. Users deposit USDT and receive EarnUSDT (vault shares). As yield is generated, the value of each share increases.

There are two main ways to integrate EarnUSDT:

1. **Contract integration** – you deploy your own smart contract and that contract deposits into SuperEarn.
2. **Frontend‑only integration** – your UI calls SuperEarn directly from the user’s wallet.

The on-chain write flow (deposit / redeem) is slightly different between 1 and 2, but the read side depends on the currently supported public API surface. Confirm the active endpoint contract with the team before integrating.

***

### Common building blocks

You will need three addresses (See [smart contracts](https://docs.superearn.io/en/developers/smart-contracts) page):

* `SUPEREARN_ROUTER` – SuperEarn router (`ISuperEarnRouter`).
* `SUPER_VAULT` – the EarnUSDT Super Vault shares.
* `USDT` – Kaia USDT token.

Key router functions (simplified):

* `deposit(address superVault, uint256 amount, uint256 minSharesOut) returns (uint256 shares)`
* `deposit(address superVault, uint256 amount, address receiver, uint256 minSharesOut) returns (uint256 shares)`
* `depositWithPermit(...) returns (uint256 shares)`
* `previewDeposit(address superVault, uint256 amount) view returns (uint256 expectedShares)`
* `previewRedeem(address superVault, uint256 shares) view returns (uint256 expectedAssets)`
* `redeem(address superVault, uint256 shares, uint256 minAssetsOut) returns (uint256 requestId)`
* `redeem(address superVault, uint256 shares, address receiver, uint256 minAssetsOut) returns (uint256 requestId)`

Internally, the Super Vault holds **CooldownVault** shares and the actual cooldown logic lives in the `CooldownVault`). **All user / integrator deposits and withdrawals must go through `SuperEarnRouter`; CooldownVault deposits/redeems are restricted to protocol contracts. Claims are permissionless but normally handled by protocol keepers to batch requests.**\
You can get the CooldownVault address from the Super Vault:

```solidity theme={null}
address cooldownVault = IVault(SUPER_VAULT).token();
```

***

## 1. Contract integration (your own wrapper contract)

**When to use**

* Centralized service, CEX, wallet, or protocol that:

  * Holds users’ funds in its own contract, and
  * Wants to manage EarnUSDT on behalf of users.

Your contract holds the EarnUSDT shares, does accounting, and talks to `SuperEarnRouter`.

Assume:

```solidity theme={null}
ISuperEarnRouter constant ROUTER = ISuperEarnRouter(SUPEREARN_ROUTER);
IERC20            constant USDT   = IERC20(USDT_ADDRESS);
IERC20            constant SHARES = IERC20(SUPER_VAULT); // EarnUSDT shares
```

***

### 1-1. Deposit (USDT → EarnUSDT) via your contract

**High‑level flow**

1. User sends USDT into *your* contract (e.g. via `transferFrom`).
2. Your contract approves `SuperEarnRouter` to spend USDT.
3. Your contract calls `ROUTER.deposit(SUPER_VAULT, amount, receiver, minSharesOut)`.
4. EarnUSDT shares are minted to `receiver` (usually your contract).
5. You update your internal accounting.

**Example Solidity**

```solidity theme={null}
function depositIntoSuperVault(uint256 amountUSDT, address user) external {
    // 1. Pull USDT from the user into THIS contract
    USDT.transferFrom(user, address(this), amountUSDT);

    // 2. Approve SuperEarnRouter
    USDT.approve(address(ROUTER), amountUSDT);

    // 3. Quote and apply a slippage policy before depositing
    uint256 expectedShares = ROUTER.previewDeposit(SUPER_VAULT, amountUSDT);
    uint256 minSharesOut = expectedShares * 99 / 100;

    // 4. Deposit into Super Vault through SuperEarnRouter
    //    - receiver = this contract (wrapper)
    uint256 shares = ROUTER.deposit(
        SUPER_VAULT,
        amountUSDT,
        address(this),
        minSharesOut
    );

    // 5. Record user's shares in your own storage
    userShares[user] += shares;
}
```

If you want to show the user an estimate before depositing, call:

```solidity theme={null}
uint256 expectedShares = ROUTER.previewDeposit(SUPER_VAULT, amountUSDT);
```

***

### 1-2. Withdraw / redeem (EarnUSDT → USDT) via your contract

Redemption is a **2‑step process under the hood** (redeem request → claim after cooldown),
but your contract usually only needs to start the request. A keeper / bot normally handles claim.

**High‑level flow**

1. You reduce the user’s internal share balance.
2. Your contract approves `SuperEarnRouter` to spend its EarnUSDT shares.
3. Call `ROUTER.previewRedeem` for an estimate (optional).
4. Call `ROUTER.redeem(SUPER_VAULT, shares, receiver, minAssetsOut)`.
5. You get a `requestId` for the pending withdrawal.
6. After cooldown, USDT is delivered to `receiver` when the request is claimed.

**Example Solidity**

```solidity theme={null}
function requestWithdrawFromSuperVault(
    uint256 shares,
    address user,
    address receiver
) external returns (uint256 requestId) {
    // 1. Update your internal accounting
    require(userShares[user] >= shares, "insufficient shares");
    userShares[user] -= shares;

    // 2. Approve router to move shares from THIS contract
    SHARES.approve(address(ROUTER), shares);

    // 3. Preview how much USDT the user will get
    uint256 expectedAssets = ROUTER.previewRedeem(SUPER_VAULT, shares);
    uint256 minAssetsOut = expectedAssets * 99 / 100;

    // 4. Create redemption request
    //    - receiver = address that should receive USDT after cooldown
    requestId = ROUTER.redeem(
        SUPER_VAULT,
        shares,
        receiver,
        minAssetsOut
    );

    // 5. Store requestId if you want to show pending withdrawals
    userRedeemRequests[user].push(requestId);
}
```

Claims on CooldownVault are handled by protocol keepers; integrators should not call `deposit`, `redeem`, or `claim` on CooldownVault directly. Read access (e.g. `redeemRequests`) is fine for monitoring.

***

### 1-3. Read data via the supported public API (for contract integration)

> See the [Data access](/en/developers/data-access) page for current read-layer guidance.

For reads, do not assume older GraphQL contracts are still the supported public interface. Confirm the active public data surface with the team before shipping an integration.

For contract integration, the important read-side identity is still your wrapper contract address. In practice, you will usually need:

* vault discovery for the EarnUSDT Super Vault
* wrapper-level position and redemption status views
* optional balance and earnings history scoped to that vault

***

## 2. Frontend‑only integration (direct from user wallet)

**When to use**

* Non‑custodial dApps / wallets.
* You want the user’s wallet to hold EarnUSDT shares directly.
* No custom wrapper contract – just frontend and SuperEarn.

Your frontend calls `SuperEarnRouter` from the user’s wallet using `ethers`, `viem`, `wagmi`, etc.

Assume you have:

* `routerAddress = SUPEREARN_ROUTER`
* `superVaultAddress = SUPER_VAULT`
* `usdtAddress = USDT`

***

### 2-1. Deposit (USDT → EarnUSDT) directly from frontend

**High‑level UX**

1. User connects wallet.
2. Frontend asks user to approve USDT for `SuperEarnRouter`.
3. Frontend calls `deposit(superVault, amount, minSharesOut)` from the wallet.
4. User receives EarnUSDT shares (Super Vault shares) in their wallet.

**Example (TypeScript + viem/ethers‑style pseudocode)**

```ts theme={null}
const router = {
  address: routerAddress,
  abi: ISuperEarnRouterAbi,
} as const;

async function depositEarnUsdt(amountUSDT: bigint, account: `0x${string}`) {
  // 1. Approve USDT
  await writeContract({
    address: usdtAddress,
    abi: erc20Abi,
    functionName: 'approve',
    args: [routerAddress, amountUSDT],
    account,
  });

  // 2. Preview shares and apply your slippage policy
  const expectedShares = await readContract({
    ...router,
    functionName: 'previewDeposit',
    args: [superVaultAddress, amountUSDT],
  });
  const minSharesOut = expectedShares * 99n / 100n;

  // 3. Deposit
  const txHash = await writeContract({
    ...router,
    functionName: 'deposit',
    args: [superVaultAddress, amountUSDT, minSharesOut],
    account,
  });

  // Track txHash and show confirmation in UI
}
```

If you support `permit`, use `depositWithPermit` to skip the explicit ERC‑20 approval.

***

### 2-2. Withdraw / redeem (EarnUSDT → USDT) from frontend

From the user’s point of view:

1. They pick how much EarnUSDT to redeem.
2. Your UI shows an estimate using `previewRedeem`.
3. You call `redeem(superVault, shares, minAssetsOut)` from their wallet.
4. A redemption request is created; after the cooldown, USDT is claimable / delivered.

**Example (TypeScript pseudocode)**

```ts theme={null}
async function redeemEarnUsdt(shares: bigint, account: `0x${string}`) {
  // 1. Preview expected USDT and apply your slippage policy
  const expectedAssets = await readContract({
    address: routerAddress,
    abi: ISuperEarnRouterAbi,
    functionName: 'previewRedeem',
    args: [superVaultAddress, shares],
  });
  const minAssetsOut = expectedAssets * 99n / 100n;

  // 2. Approve router to spend EarnUSDT shares
  await writeContract({
    address: superVaultAddress,
    abi: erc20Abi,
    functionName: 'approve',
    args: [routerAddress, shares],
    account,
  });

  // 3. Create redeem request
  const requestId = await writeContract({
    address: routerAddress,
    abi: ISuperEarnRouterAbi,
    functionName: 'redeem',
    args: [superVaultAddress, shares, minAssetsOut],
    account,
  });

  // Store requestId in your app state if you want to show “pending withdrawal”
}
```

A backend keeper normally handles the actual **claim** on the CooldownVault once the cooldown period ends,
so your UI can just track `redeemRequests` and final balances rather than calling `claim` itself; end users should not call CooldownVault directly.

***

### 2-3. Read user data via the supported public API

> See the [Data access](/en/developers/data-access) page for current read-layer guidance.

For frontend-only integrations, use the connected wallet as the account identity for whichever supported public API surface the team confirms.

The product requirements are unchanged even if the public endpoint shape evolves. Your frontend will still typically need:

* EarnUSDT vault discovery
* the user’s current position and pending redemption state
* optional balance and earnings history scoped to the EarnUSDT vault

***

## 3. Direct contract queries

Most integrations should rely on the supported public read API layer, not raw indexing internals.
If you need **real‑time, raw on‑chain data** (e.g. your own indexer, custom monitoring), you can use the view
functions on `SUPER_VAULT` and `CooldownVault`.

### 3-1. Get EarnUSDT balances and underlying value

The Super Vault exposes the user's EarnUSDT share balance:

```solidity theme={null}
// EarnUSDT share balance
uint256 shares = IERC20(SUPER_VAULT).balanceOf(account);
```

To convert shares to underlying USDT equivalent, use price per share on the Super Vault:

```solidity theme={null}
uint256 assetsValue = shares * IVault(SUPER_VAULT).pricePerShare() / 10 ** IVault(SUPER_VAULT).decimals();
```

> In UI terms:
> **display balance in USDT = `convertToAssets(balanceOf(user))`**.

### 3-2. Check cooldown redemption details

When you call `ROUTER.redeem(...)`, the router internally creates a **CooldownVault RedeemRequest**.
You can read its state directly from `CooldownVault` using the `requestId` returned by the router.

1. Resolve the CooldownVault address

```solidity theme={null}
address cooldownVault = IVault(SUPER_VAULT).token();
```

2. Query a specific redemption request

```solidity theme={null}
(
  address receiver,
  uint256 assets,
  uint256 cooldownRequestedTime,
  uint256 cooldownPeriod,
  bool claimed
) = ICooldownVault(cooldownVault).redeemRequests(requestId);
```

With this you can:

* Compute **claimable time**:

```solidity theme={null}
uint256 claimableAt = cooldownRequestedTime + cooldownPeriod;
bool isClaimable = block.timestamp >= claimableAt && !claimed;
```

* Show “pending / claimable / claimed” states per `requestId`.

### 3-3. Check global cooldown configuration

You can read the **global cooldown period** applied to new redemption requests:

```solidity theme={null}
uint256 globalCooldownPeriod = ICooldownVault(cooldownVault).cooldownPeriod();
// e.g. convert to days:
uint256 cooldownDays = globalCooldownPeriod / 86400;
```

This is useful to:

* Show “estimated withdrawal time” in UI.
* Enforce minimum UX expectations (e.g. “cooldown ≈ 7 days”).

### 3-4. System status: emergency & pause

For safety‑aware integrations you may want to halt actions if the system is paused or in emergency mode.

```solidity theme={null}
// Super Vault emergency shutdown (deposits & redeems are blocked)
bool isEmergency = IVault(SUPER_VAULT).emergencyShutdown();

// CooldownVault pause state (cooldown flow disabled)
bool isPaused = ICooldownVault(cooldownVault).paused();
```

Typical pattern:

* **Block new deposits / redeems** in your app when `isEmergency || isPaused` is true.
* Keep reads enabled for transparency.

***

## 4. Events to watch (monitoring & indexing)

If you run your own indexer or monitoring system, you will mainly care about
events from **ISuperEarnRouter** and **CooldownVault**.

### 4-1. Router events (user‑facing actions)

Defined in `ISuperEarnRouter`:

```solidity theme={null}
event Deposited(
    address indexed sender,
    address indexed receiver,
    address indexed yVault,
    uint256 underlyingAmount,
    uint256 yShares
);

event Redeemed(
    address indexed sender,
    address indexed receiver,
    address indexed yVault,
    uint256 yShares,
    uint256 ySharesFilled,
    uint256 requestId,
    uint256 underlyingAmount
);
```

Usage:

* **Deposited**

  * Trigger on successful USDT → EarnUSDT deposits.
  * Index `(sender, receiver, yVault, underlyingAmount, yShares)` to reconstruct deposit history.

* **Redeemed**

  * Trigger when a redeem request is created (EarnUSDT → USDT with cooldown).
  * Use `requestId` to join with `CooldownVault.redeemRequests(requestId)` for full status.
  * `ySharesFilled` lets you detect partial fills in advanced scenarios.

### 4-2. CooldownVault events (cooldown lifecycle)

Core events from `ICooldownVault`:

```solidity theme={null}
event RedeemRequested(
    address indexed caller,
    address indexed receiver,
    uint256 indexed requestId,
    uint256 assets,
    uint256 shares,
    uint256 requestedTime
);

event Claimed(
    address indexed caller,
    uint256 indexed requestId,
    uint256 assets,
    uint256 claimable
);
```

(There are additional governance / strategy events such as `PredepositRequested`, `DebtRetrieved`, etc.,
but most EarnUSDT integrators can ignore those.)

Usage:

* **RedeemRequested**

  * Mirrors router `Redeemed`, but emitted at the CooldownVault level.
  * Good for verifying that a given `requestId` exists and carries `(assets, shares, requestedTime)`.

* **Claimed**

  * Emitted when a cooldown redemption is actually claimed and USDT is transferred.
  * Use it to mark a pending withdrawal as **completed** in your own indexer or notifications.

> In practice:
>
> * Track **user intent** via `Deposited` / `Redeemed` on the router.
> * Track **cooldown state + completion** via `RedeemRequested` / `Claimed` on CooldownVault.

***

## 5. Interface reference (abridged)

This section summarizes only the pieces of the on‑chain interfaces that most
integrators actually need. Strategy‑level interfaces such as `IStrategyCooldownAware`
are intentionally omitted.

### 5-1. `ISuperEarnRouter`

Full interface (simplified to the relevant parts):

```solidity theme={null}
interface ISuperEarnRouter {
    // EVENTS
    event Deposited(
        address indexed sender,
        address indexed receiver,
        address indexed yVault,
        uint256 underlyingAmount,
        uint256 yShares
    );

    event Redeemed(
        address indexed sender,
        address indexed receiver,
        address indexed yVault,
        uint256 yShares,
        uint256 ySharesFilled,
        uint256 requestId,
        uint256 underlyingAmount
    );

    // VIEW
    function registry() external view returns (address);
    function previewRedeem(address yVault, uint256 yShares) external view returns (uint256);
    function endorsedVault(address token) external view returns (address);

    // DEPOSIT
    function deposit(
        address yVault,
        uint256 amount,
        uint256 minSharesOut
    ) external returns (uint256);

    function deposit(
        address yVault,
        uint256 amount,
        address receiver,
        uint256 minSharesOut
    ) external returns (uint256);

    function depositWithPermit(
        address yVault,
        uint256 amount,
        address receiver,
        uint256 minSharesOut,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256);

    // REDEEM (cooldown‑based)
    function redeem(
        address yVault,
        uint256 yShares,
        uint256 minAssetsOut
    ) external returns (uint256 requestId);

    function redeem(
        address yVault,
        uint256 yShares,
        address receiver,
        uint256 minAssetsOut
    ) external returns (uint256 requestId);
}
```

> **Rule of thumb**:
>
> * For writes, you only need `deposit`, `depositWithPermit`, `redeem`.
> * For reads / UX, you mainly need `previewRedeem`.

### 5-2. `ICooldownVault` (high‑level subset)

`CooldownVault` is a vault with built‑in cooldown and loss‑limit logic.
Below are the main functions relevant to EarnUSDT integrators.

```solidity theme={null}
interface ICooldownVault {
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);
    function mint(uint256 shares, address receiver) external returns (uint256 assets);
    function previewDeposit(uint256 assets) external view returns (uint256 shares);
    function previewMint(uint256 shares) external view returns (uint256 assets);

    // Cooldown redemption
    function redeem(
        uint256 shares,
        address receiver,
        address owner
    ) external returns (uint256 assets);

    function withdraw(
        uint256 assets,
        address receiver,
        address owner
    ) external returns (uint256 shares);

    // Global cooldown config
    function cooldownPeriod() external view returns (uint256 period);

    // Individual redemption request
    function redeemRequests(uint256 requestId)
        external
        view
        returns (
            address receiver,
            uint256 assets,
            uint256 cooldownRequestedTime,
            uint256 cooldownPeriod,
            bool claimed
        );

    // Claim after cooldown
    function claim(uint256 requestId, uint256 maxLossBps) external returns (uint256 claimable);

    // Status
    function paused() external view returns (bool);
}
```

As an integrator:

* **Do not call `deposit` or `redeem` on CooldownVault** — these are restricted to protocol contracts and go through `SuperEarnRouter`.
* Claims are permissionless but typically executed by protocol keepers to batch/optimise redemptions.
* Helpful reads:

  * `cooldownPeriod()` – to show global cooldown.
  * `redeemRequests(requestId)` – to inspect a specific withdrawal.

### 5-3. `IVault` (Super Vault)

The Super Vault wraps **CooldownVault** shares. For EarnUSDT integration you typically only need:

```solidity theme={null}
interface IVault {
    // Underlying token of the vault (here: CooldownVault)
    function token() external view returns (address);

    // (Plus standard vault view functions, if you need them)
    // e.g. totalAssets(), pricePerShare(), etc.
}
```

In most cases you use `IVault(SUPER_VAULT).token()` just to resolve the **CooldownVault** address.

***

### Summary

For both integration styles:

* **Writes (deposit / redeem)** → call `SuperEarnRouter`:

  * `deposit` / `depositWithPermit` for USDT → EarnUSDT
  * `previewRedeem` + `redeem` for EarnUSDT → USDT (cooldown‑based)
* **Reads (positions / status)**:

  * Use the supported public read API layer for portfolio, PnL, and charts.
  * Optionally use **direct contract reads** for real‑time balances or custom monitoring.
* **Monitoring**:

  * Subscribe to `Deposited` / `Redeemed` on the router and `RedeemRequested` / `Claimed` on CooldownVault.

The only thing that changes between integration styles is which `accountAddress` you query:

* Contract integration → your wrapper contract address.
* Frontend‑only → the user’s wallet address.
