Integration guide

In this integration guide, we are going to integrate the e2e flow for your users to select which vaults they want to deposit on, do a deposit transaction to start earning rewards and withdraw (part of) their positions.

Example of integration on a fictive wallet

Example of integration on a fictive wallet


1. Setup

First, let's make sure you have all the resources you need to start integrating the product.

Deployments

We have public deployments already made for testing purposes that you can use.

NetworkLending ProtocolAssetAddress
Arbitrum OneCompound v3USDbC0xC268C59fa29220208EfbeC31380e9f4DBE143621
Arbitrum OneCompound v3USDC0xCA8F5dbC4c90678763B291217e6ddDfcA00341d0
Arbitrum OneAAVE v3USDT0x0f11f7fbdb33347688441400186b210f1f4eebb9
Arbitrum OneAAVE v3USDC0xFf131917E1D6751e4d1B17612751Db521b1403c5
BNBVenusUSDC0x6E90B52A5eAb4e4a08135dcf8c93ABdf6caE9C91
PolygonAAVE v3USDC0x899b8cd1d209e4368c41dc9fd2de04a866b5d19a
PolygonCompound v3USDC.e0xd4c6dDA2158EFd3a41597d89349F06E17dFfbBFd
SepoliaAAVE v3USDC0xf3a9A790f84B2E0301069BE589fc976Cf3eB5661
SepoliaCompound v3USDC0xf3a9A790f84B2E0301069BE589fc976Cf3eB5661

πŸ“˜

The protocol you want to test is not in this list?

Fill out this form to request custom deployments

❗️

These vaults SHOULD NOT be used in production

They are either testnet or staging deployments made for testing purposes only.

πŸ’‘ Some L2 do not have a stable testnet for defi applications so staging deployments are done on mainnet but should never end up on your production setup.


Setup your API credentials

Connect to your kiln dashboard organization on testnet and get your api token.

Refer to this section of the documentation to get more infos on how to generate and manage your keys in your backend.


2. Backend

In this section, we are going to query the data required for "view" displays that we will use on the frontend later.

⚠️

Vault registry

You should define a vault registry list on your side, which is a list of vault addresses you want to expose your users to per network. For security reasons you cannot fetch your vault addresses from Kiln api without knowing them in advance so you have to define this list on your application.

We recommend having a mapping chainId <> vaultAddress[] so you can always query the vaults per chain.


Get vault(s) information

🫨

API - GET /v1/defi/network-stats?vaults=

  • Query using ?vaults parameter to specify the vaults you want to query data of
    • πŸ’‘ use the mapping you have to query the vault list on the network you want

Example:

{
  "data": [
    {
      "asset": "0x94a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c8",
      "asset_icon": "https://public.kiln.fi/icons/assets/usdc.svg",
      "asset_symbol": "skUSDC",
      "share_symbol": "skcUSDC",
      "tvl": "1980000",
      "protocol": "aave_v3",
      "protocol_icon": "https://public.kiln.fi/icons/defi-protocols/aave.svg",
      "protocol_tvl": "1980000",
      "protocol_supply_limit": "1980000",
      "grr": 0.028795338310400043,
      "nrr": 0.028507384927296042,
      "vault": "0x9aB5F9101a3C1B868e2c422E294cc2ee685551D5",
      "chain": "eth",
      "chain_id": 1,
      "asset_decimals": 6,
      "updated_at_block": 220379047
    }
  ]
}

In this response you can see useful vault information:

  • underlying protocol information: name, icon, tvl, supply limit (ie asset amount left to supply, if 0 nothing can be supplied)
  • GRR (gross rewards rate) and NRR (net rewards rate) users can earn by depositing through this vault
  • asset information: name, icon, symbol
  • share symbol: what the user will receive in exchange for depositing assets
  • when the data was last refreshed: updated_at_block

Get user positions

🫨

API - GET /v1/defi/stakes?wallets=&vaults=

  • Query using ?vaults parameter to specify the vaults you want to query stakes on
    • πŸ’‘use the mapping you have to query the vault list on the network you want
  • Query using ?wallets parameter to get the user(s) stakes in the scope of the vault list you specify

Example:

{
  "data": [
    {
      "owner": "0x356c33675674691ad6b8ac92ecfb91960c5d2c30",
      "current_balance": "1880000",
      "total_rewards": "0",
      "total_deposited_amount": "1980000",
      "total_withdrawn_amount": "100000",
      "vault": "0x9aB5F9101a3C1B868e2c422E294cc2ee685551D5",
      "chain": "eth",
      "updated_at_block": 220379047
    }
  ]
}

Here we can see:

  • the current "staked" balance in assets
  • user total rewards earned, in assets
  • user total rewards deposited and withdrawn amounts, in assets
  • the vault the stake in made on
  • when the data was last refreshed

(Optional) Get user history

🫨

API - GET /v1/defi/operations?wallets=&vaults=

  • Query using ?vaults parameter to specify the vaults you want to query stakes on
  • πŸ’‘use the mapping you have to query the vault list on the network you want
  • Query using ?wallets parameter to get the user(s) stakes in the scope of the vault list you specify

Example:

{
  "data": [
    {
      "type": "withdrawal",
      "owner": "0x356c33675674691ad6b8ac92ecfb91960c5d2c30",
      "assets": "100000",
      "shares": "100000",
      "sender": "0x356c33675674691ad6b8ac92ecfb91960c5d2c30",
      "timestamp": "1710434028",
      "tx_hash": "0xca1e9f9a9ed7b632dbb71e9d22730d1541df010e915d65af91d1ca102600c965",
      "vault": "0x9aB5F9101a3C1B868e2c422E294cc2ee685551D5",
      "chain": "eth"
    }
  ]
}

Here we can see:

  • the type of the operation: withdrawal or deposit
  • the amount of assets and shares involved in the operation
  • the vault it is made on
  • the owner of the stake, the transaction sender
  • the vault the operation is made on

3. Frontend


Now that we have setup the backend data query, we can start the integration within the UI. There are 4 main flows to integrate:

  1. [VIEW] As a User, I can see the vaults and their information available on the chain I am connected on, so I can assess which DeFi protocol I want to be exposed to
  2. [TX] As a User, I can deposit on the vault, so I can start earning
  3. [VIEW] As a User, I see my positions and rewards, so that I can assess my performance
  4. [TX] As a User, I can withdraw from vaults, so I can get back my assets

1 - [VIEW] As a User, I can see the vaults and their information available on the chain I am connected on, so I can assess which DeFi protocol I want to be exposed to

Example of a fictive wallet displaying available vaults to deposit on

Example of a fictive wallet displaying available vaults to deposit on


Use the queried data in the "Get vault(s) information" section.

Some recommendations:

  • Use the protocol and asset icons to give a more visual experience
  • Sort by descending NRR, or have a "sort by APY" button
  • Display if the user already deposited in a vault (using the "Get user positions")
  • Do no display vaults where protocol_supply_limit is < 5000 assets to avoid the user being not able to deposit.

2 - [TX] As a User, I can deposit on the vault, so I can start earning

Example of a fictive wallet displaying ability to deposit in the vaults

Example of a fictive wallet displaying ability to deposit in the vaults

πŸ“˜

Show a preview of the tx to the user

You can compute the amount of shares the user will receive and using the "Get vault(s) information" data show the name of the shares. As they are not pegged 1:1 with the deposited assets, it can be useful to help the user understand what he is doing.

You can preview this amount by doing a view call on the vault and calling previewDeposit(uint256 assets) where assets is the amount of ERC20 to deposit in assets expressed in the lowest unit of the token (ie asset_amount * 10**decimal).

If this call reverts, it can mean that the underlying protocol is not accepting supply funds at the moment, you can then display a "Deposits on this protocol are unavailable at the moment, retry later".

Before depositing X assets, you must make sure the user approved the vault to spend X on its behalf on the asset contract.

To check the allowance, call the allowance(address owner, address spender)(uint256) function on the ERC20 asset contract, if there is not enough allowance, you must make the user perform an approve:

🫨

TX - function: approve(address spender, uint256 amount)

  • to: asset contract address
  • from: user wallet address
  • value: 0
  • parameters:
    • spender: vault address
    • amount: amount the user inputed in asset wei (ie amount * decimals)

❗️

ONLY MAKE THE USER APPROVE THE AMOUNT IT WANTS TO DEPOSIT TO THE VAULT

Now that there is enough allowance, we can make the user deposit to the vault.

Example of an user position on a AAVE USDC vault

Example of an user deposit on a AAVE USDC vault

🫨

TX - function: deposit(uint256 assets, address receiver)

  • to: vault address
  • from: user wallet address
  • value: 0
  • parameters:
    • assets: amount the user inputed in asset expressed in the lowest unit of the token (ie asset_amount * 10**decimal).
    • receiver: user wallet address (or another if you want to let the user input a receiver wallet)

Now the user successfully deposited, received vault shares and can now receive supply rewards as frequently as the protocol distributes them!


3 - [VIEW] As a User, I see my positions and rewards, so that I can assess my performance

Example of displaying a position on a vault, and rewards

Example of displaying a position on a vault, and rewards


Use the data collected in the "Get user positions" section of this guide.

Recommendations:

  • display amounts in assets and in fiat value

4 - [TX] As a User, I can withdraw my position from vaults, so I can get back my assets


The UI can be a simple input, with a showcase of how much can be withdrawn

The UI can be a simple input, with a showcase of how much can be withdrawn


Case 1: exit part of a position


Example of withdrawal flow on a AAVE USDC vault

Example of withdrawal flow on a AAVE USDC vault


πŸ“˜

Show a preview of the tx to the user

You can compute the amount of assets the user will receive after withdrawing.

You can preview this amount by doing a view call on the vault calling previewWithdraw(uint256 assets) where assets is the amount of ERC20 to deposit in assets expressed in the lowest unit of the token (ie asset_amount * 10**decimal).

If this call reverts, it can mean that the underlying protocol is not accepting withdraw of supply funds at the moment, you can then display a "Withdrawals on this protocol are unavailable at the moment, retry later".

🫨

TX - function: withdraw(uint256 assets, address receiver, address owner)

  • to: vault address
  • from: user wallet address
  • value: 0
  • parameters:
    • assets: amount the user inputed in asset expressed in the lowest unit of the token (ie asset_amount * 10**decimal).
    • receiver: user wallet address (or another if you want to let the user input a receiver wallet)
    • owner: user wallet address

Case 2: exit 100% of the positions

This case is made to avoid leaving dust on the contract, as there is time between the user input and the actual moment the transaction is executed, shares rate might have changed.

Example of redeem flow on AAVE USDC vault

Example of redeem flow on AAVE USDC vault


πŸ“˜

Show a preview of the tx to the user

You can compute the amount of assets the user will receive after withdrawing.

You can preview this amount by doing a view call on the vault calling previewRedeem(uint256 assets) where assets is the amount of ERC20 to deposit in assets expressed in the lowest unit of the token (ie asset_amount * 10**decimal).

If this call reverts, it can mean that the underlying protocol is not accepting withdraw of supply funds at the moment, you can then display a "Withdrawals on this protocol are unavailable at the moment, retry later".

🫨

TX - function: redeem(uint256 shares, address receiver, address owner)

  • to: vault address
  • from: user wallet address
  • value: 0
  • parameters:
    • shares: amount in shares, you MUST get this value by calling balanceOf(address owner) on the vault before-end where owner is the user wallet address.
    • receiver: user wallet address (or another if you want to let the user input a receiver wallet)
    • owner: user wallet address

πŸš€ We now completed the full E2E flow of Kiln DeFi on your application πŸš€

4. Testing


Now let's validate that the implementation works properly. We recommend creating a test suite from this list and running it frequently, and especially during each release.

  1. As a User, I should be able to see all available vaults on the chain I am connected on
  2. As a User, I should see an info message / be redirected if there are no deployments on the chain I'm connected on
  3. As a User, I should be able to see each vault NRR, its asset, and the protocol it relies on
  4. As a User, I should be able to select a vault to deposit on based on the asset on my wallet
  5. As a User, I should be able to see the amount of shares and the name I will receive when inputing a number of asset to deposit
  6. As a User with no allowance on the asset to the vault, I should sign an approve transaction with the amount to deposit as amount
    1. on explorer, transaction must be valid with the specs above (from, to, value, param values etc)
  7. As a User with enough allowance on the asset to the vault, I should not be asked to sign an approval transaction
  8. As a User, I should be able to deposit my assets on the vault.
    1. on explorer, transaction must be valid with the specs above (from, to, value, param values etc)
  9. As a User, I should be able to see my positions in all of your vaults with the amount in assets and fiat value and my rewards amount
  10. As a User, I should be able to select a vault to withdraw on based on my positions
  11. As a User, I should be able to preview the withdrawal of my positions, by seeing the asset I will receive on my wallet, when inputing the value to withdraw
  12. As a User who wants to withdraw part of its positions, I should be able to sign a withdraw transaction
    1. on explorer, transaction must be valid with the specs above (from, to, value, param values etc)
  13. As a User who wants to withdraw 100% of its positions, I should be able to sign a redeem transaction
    1. on explorer, transaction must be valid with the specs above (from, to, value, param values etc)