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).

Installation

npm install @lombard.finance/sdk

Dependencies

The SDK requires the following peer dependencies:

npm install web3@^4 axios@^1 bignumber.js@^9 @bitcoin-js/tiny-secp256k1-asmjs@2.2.3 bitcoinjs-lib@6.1.5

User Staking: BTC -> LBTC

Firstly, check for an existing Bitcoin deposit address. Each Bitcoin Deposit Address is associated with a destination chain and address (for minting LBTC), and a partner ID.

1) Auto Mint: Sign and Store Network Fee Authorization

To automatically mint LBTC, the user will need to sign a network fee authorization allowing Lombard to spend a small amount of LBTC to cover the associated network fee.

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 { getLBTCMintingFee } from '@lombard.finance/sdk';

const fee = await getLBTCMintingFee({
  chainId: 1, // LBTC destination chain ID
  bakeGasEstimate: 28000, // Optional: Additional gas for 'Stake & Bake' DeFi operation
  rpcUrl: 'YOUR_RPC_URL' // Optional: Custom RPC URL
}); // Returns BigNumber (ie 0.000001)
  • chainId is where LBTC will be minted to

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

Sign Network Fee

Once you have the fee amount, get the user to sign it.

import { signNetworkFee } from '@lombard.finance/sdk';

const ONE_DAY_SECONDS = 24 * 60 * 60;
const expirySeconds = Math.floor(Date.now() / 1000 + ONE_DAY_SECONDS)

const { signature, typedData } = await signNetworkFee({
  address: '0x...', // User's EVM address
  provider: window.ethereum, // EIP-1193 provider
  chainId: 1,
  fee: fee.toString(10),
  expiry: expirySeconds,
  env: 'prod'
});

This signature can be used to generate a BTC address in step 2 below, so you can store and use it to generate an address immediately.

Store Network Fee Signature

After signing, store the signature:

import { storeNetworkFeeSignature } from '@lombard.finance/sdk';

const status = await storeNetworkFeeSignature({
  signature, // The signature returned from `signNetworkFee` above
  typedData, // The typedData returned from `signNetworkFee` above.
  address: '0x...', // User's address
  env: 'prod'
}) // "success";

Verify Network Fee Authorization

You can check if a user has a valid network fee signature:

import { getNetworkFeeSignature } from '@lombard.finance/sdk';

const { hasSignature, isDelayed, expirationDate } = await getNetworkFeeSignature({
  address: '0x...', // User's address
  chainId: 1,
  env: 'prod'
});

2) Retrieve a BTC deposit address

First, check for an existing Bitcoin deposit address. Each Bitcoin Deposit Address is associated with a destination chain, address (for minting LBTC), and a partner ID.

import { getDepositBtcAddress } from '@lombard.finance/sdk';
...
const depositBtcAddress = await getDepositBtcAddress({
  address: '0x...', // destination chain address
  chainId: 1, // destination chainID
  partnerId: 'YOUR_PARTNER_ID',
}); // bc1q...

If you have an address already, proceed to step 3. Otherwise, generate a new deposit address.

Generate Deposit Address

To generate a BTC address we need a signature signed by the user's wallet. This can be the signature returned by signNetworkFeein step 1.

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

import { generateDepositBtcAddress } from '@lombard.finance/sdk';

const btcAddress = await generateDepositBtcAddress({
  address: '0x...', // User's EVM address
  chainId: 1,
  signature, // The signature returned from `signNetworkFee` above. Proves user controls the destination address
  partnerId: 'YOUR_PARTNER_ID',
  referrerCode: 'USER_REFERRER_CODE', // Optional (user) referral code
  env: 'prod'
});

The user can send BTC directly to this deposit address. If they haven't signed and stored the network fee authorization, or if the authorization is expired, they will have to mint LBTC manually.

Get Address Confirmation Signature

If for some reason the user will first need to sign the destination address to prove ownership of their wallet address, as this will be the only place LBTC can be minted to for any deposits to the generated bitcoin deposit address.

import { signLbtcDestionationAddr } from '@lombard.finance/sdk';

const addressConfirmationSignature = await signLbtcDestionationAddr({
  account: '0x...', // User's EVM address
  chainId: 1,
  provider: window.ethereum // EIP-1193 provider
});

3) Prompt the user to deposit Bitcoin

The user can now send BTC directly to the deposit address. You should display the exchange rate and fee associated so the user understands how much LBTC they will receive for any amount of BTC they wish to deposit.

Exchange Rate Information

import { getLBTCExchangeRate } from '@lombard.finance/sdk';

const { exchangeRate, minAmount } = await getLBTCExchangeRate({
  chainId: 1, // Optional, defaults to Ethereum
  amount: 1, // Optional, amount in BTC
  env: 'prod'
});

// exchangeRate: (number) The current LBTC:BTC ratio
// minAmount: (number) Minimum stake amount in Satoshis

LBTC Minting Fee

import { getLBTCMintingFee } from '@lombard.finance/sdk';

const fee = await getLBTCMintingFee({
  chainId: 1,
  rpcUrl: 'CUSTOM_RPC_URL', // Optional, custom RPC URL
}); // Returns BigNumber

Prompt user to send BTC to deposit address

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

const provider = await getBtcProvider(); // Your BTC wallet provider
await provider.sendTx(depositAddress, amount.toString()); // Tx to send amount to depositAddress

4) Check and display the user's Bitcoin deposits

Finally you can use getDepositsByAddress to fetch and display the deposit history for a specified address.

import { getDepositsByAddress } from '@lombard.finance/sdk';
...
const deposits = await getDepositsByAddress({
  address: '0x...', // LBTC address
  env: 'prod', // 'prod' | 'testnet' | 'stage'
}); // Returns IDeposit[]

Last updated