Staking SDK V2

Integrate native Bitcoin staking into your own application, providing your community easy access to earning yield through liquid staking, with LBTC.

This is a draft of the Staking SDK V2 spec; the final software has not yet been published on NPM.

Our TypeScript Staking SDK can be integrated into any frontend app: wallets, portfolio management apps, staking dashboards, custody portals.

If you're interested in integrating our Staking SDK please fill out this Google Form and we will issue you with a partner Id.

Important: You must take all measures for your app and its users to comply with our Terms of Service, including removing access for unauthorized countries.

⭐️ New Features

  • LBTC is automatically minted by Lombard for users. This improves user experience, by the user explicitly agreeing for a small amount of LBTC to be diverted to Lombard's treasury to cover gas costs.

  • LBTC is optionally deployed immediately into DeFi via "Stake & Bake", with the user explicitly agreeing to an ERC20 Permit approval and providing a contract call (e.g. deploying into DeFi Vault).

User Staking: BTC -> LBTC

1) Get minting fee

Retrieve the destination chain gas fee, as Lombard automatically mints for the user. This is offset by the minting fee from the user (receives less LBTC to cover the cost).

import { getMintingFee } from '@lombard.finance/sdk';
...
const mintingFee = await getMintingFee({
  chainId: 1, // LBTC destination chainID
  bakeGasEstimate: 28_000 // optional
}); // 0.000001 LBTC
  • chainId is where LBTC will be minted to

  • bakeGasEstimate is an optional parameter to cover the additional contract call that will be made. Provide an accurate value, as Lombard API will check accuracy before minting.

2) Get params

Retrieve the current exchange rate of LBTC:BTC and the minimum BTC amount that can be staked.

import { getExchangeRate } from '@lombard.finance/sdk';
...
const { exchangeRate, minAmount } = await getParams(); // 1.0 (float), 100_000 (uint)

3) Check user BTC staking amount

Prompt the user to input the amount of BTC they wish to stake and display the corresponding LBTC they will receive. Inform the user of the minimum BTC stake. Any amounts smaller than this minimum are ignored by Lombard Protocol. Every individual BTC deposit must be above this amount.

Minimum LBTC received = (BTC deposit * exchangeRate) - mintingFee

4) Sign to approve fee

This fee approval is valid for 3 hours.

import { signMintFee } from '@lombard.finance/sdk';
...
// connect to the wallet using web3.js or ethers.js or any other library
// and get the provider, account and chainId
const signedMintFee = await signMintFee({
  provider: window.ethereum,
  mintingFee: 100_000,
  address: '0x...', // destination address where LBTC will be minted to
  chainId: 1, // destination chain where LBTC will be minted
  partnerId: "DEMO"
}); // '0x...'

5) Optional Bake: Sign ERC20 permit and DeFi operation

The user must also sign an ERC20 permit function, allowing a designated spender to reallocate the user's LBTC as soon as it is minted to their wallet. User wallet -> Defi protocol.

import { getPermitNonce } from '@lombard.finance/sdk';
...
// do connect to the wallet using web3.js or ethers.js or any other library
// and get the provider, address and chainId
const permitNonce = await getPermitNonce({
  provider: window.ethereum,
  address: "0x",
  chainId: 1
}); // '0x...'
import { signBake } from '@lombard.finance/sdk';
...
// do connect to the wallet using web3.js or ethers.js or any other library
// and get the provider, address and chainId
const signedBake = await signBake({
  provider: window.ethereum,
  permitNonce: 3, // Retreieved from chain
  spender: "0x", // Address to permit
  amount: 2_000_000, // LBTC amount to permit
  callContract: "0x", // called after spender is authorized
  callContractData: "0x",
  chainId: 1,
  address: "0x",
}); // '0x...'

6) Fetch the Bitcoin Deposit Address

Using the previous signatures, generate a new deposit Bitcoin address (note this can take several minutes for the security consortium to validate). Populate the partnerId with the referral code we've provided you:

import { getBtcDepositAddress } from '@lombard.finance/sdk';
...
const btcDepositAddress = await getBtcDepositAddress({
  signedMintFee: signedMintFee,
  mintingFee: 100_000,
  address: "0x",
  chainId: 1,
  partnerId: "DEMO",
  
  bake: {
    permitNonce: 3,
    spender: "0x",
    signedBake: signedBake,
    spender: "0x",
    callContract: "0x",
    callContractData: "0x",
  } // optional
  
}); // bc1q...

This will retrieve a BTC deposit address from the Lombard API and verify this address locally.

That's it! You now have an existing, or new, BTC deposit address, unique to the user. This address is a SegWit address for maximum compatibility, so your users can deposit from any wallet or centralized exchange.

7) Prompt the user to deposit Bitcoin

The user can now send BTC directly to the deposit address.

Note: The minimum amount from step (2) must be made clear to the user. Any deposit below this will not be authorized to mint.

8) Check the user's Bitcoin deposit status

import { getDepositsByAddress } from '@lombard.finance/sdk';
...
const deposits = await getDeposits({
  address: '0x...', // LBTC address
  chainId: 1,
});
/*
 [
   {
     status: "MINTED", // "MINTED", "MINTING", "AWAITING_NOTORIZATION", AWAITING_CONFIRMATIONS, ERROR
     link: "https://lombard.finance/app/..", // optional
     btcHash: "br23r21",
     btcAmount: 0.32,
     btcStakeDetectedAt: "", // TODO What timestamp format?
     btcConfirmations: 0,
     btcConfirmationsRequired: 6,
     mintHash: "0x", // optional
   }
 ]
*/

Last updated