Documentation v1.0 has been released! Staking Guide, Protocols, Glossary, FAQ, and Support sections have been added.

Babylon

Getting Started

You can use this library or API to implement Babylon staking for Everstake validator.

Be carefully! This library may have compatibility issues with other versions of the libraries.

As an example we use:

  • node: v22.11.0

  • bitcoinjs-lib: ^6.1.5

  • ecpair: ^2.1.0

  • tiny-secp256k1: ^2.2.3

  • @everstake/wallet-sdk: v0.*

Step. 1: Installing the Library

Install the npm library or yarn by copying the code below.

$ npm install @everstake/wallet-sdk

Step. 2: Import Wallet SDK

After installing the app, you can import module of needed blockchain (Ethereum, Aptos, Solana, Cosmos, Polygon are available) and use the SDK:

Import ES6

// or you can also use
import * as Babylon from '@everstake/wallet-sdk/babylon';
// import needed class
import { Babylon } from '@everstake/wallet-sdk/babylon';

Import ES5

// import module
const { Babylon } = require("@everstake/wallet-sdk");
// or you can also use
const { Babylon } = require("@everstake/wallet-sdk/babylon");

Step. 3: Create Auth Token

In order to access all the features of the Wallet SDK, it's necessary for you to generate an authentication token. This token will be required in all of the methods you use.

// import
const { CreateToken } = require("@everstake/wallet-sdk");

// Project name
const name = 'Everstake Wallet SDK';
// wallet | Dapp | Other
const type = 'SDK';

// Create Token - return token ID
const token = await CreateToken(name, type);
console.log(token); // 3155f389-d943-4966-8e18-f159c2a6ef66

Step. 4: Create Babylon instance

const { Babylon, signetNetwork } = require("@everstake/wallet-sdk/babylon");

// public key from KeyPair. Buffer type
const publicKey = Buffer.from(keyPair.publicKey)

const babylon = new Babylon(signetNetwork, publicKey, 'YOUR_TOKEN');

Example of using keyPair to get public key and address (signet)

const {payments, initEccLib, networks} = require('bitcoinjs-lib');
const ecc = require('tiny-secp256k1');  // For elliptic curve operations
const {ECPairFactory} = require('ecpair')
const ECPair = ECPairFactory(ecc);
const bs58 = require('bs58');

// Taproot requires tiny-secp256k1 for ECC operations
bitcoin.initEccLib(ecc);

const privateKey = 'XXXXXXXXXXXXqdUAXbpr92hF7M28kTsXXXXXXXXXXXXX'
const keyPair = ECPair.fromWIF(privateKey, networks.testnet)

// Taproot address generation (using single public key)
const { address } = bitcoin.payments.p2tr({
    internalPubkey: keyPair.publicKey.slice(1, 33),  // Remove prefix byte
    network: signetNetwork,
});
console.log('address:', address);
console.log('public key:', bs58.encode(keyPair.publicKey));

Example of using PSBT API

// decode PSBT that have been got from API response
const resultFromAPI = "012.....0123"
const decodedTx = Psbt.fromHex(resultFromAPI)

// sign tx
const signedTx = decodedTx.signInput(0, keyPair);
signedTx.finalizeAllInputs()

// send to network
const tx = Psbt.fromHex(signedTx.toHex()).extractTransaction();
fetch('https://mempool.space/signet/api/tx', {
    method: 'POST',
    headers: { 'Content-Type': 'text/plain' },
    body: tx.toHex()
})
    .then(response => response.text())
    .then(txid => {
        console.log('Broadcasted Transaction ID:', txid);
    })
    .catch(error => {
        console.error('Failed to broadcast transaction:', error);
    });

Stake

The stake method creates unsigned transaction for stake/delegation

  • stake(amount, feeRate = 1): Stake bitcoin stats from and for specific address. Min. stake is 0.0005 BTC

const { Babylon, signetNetwork } = require("@everstake/wallet-sdk/babylon");
const {crypto, Psbt} = require('bitcoinjs-lib');

// Token ID.
const token = process.env.TOKEN; // 3155f389-d943-4966-8e18-f159c2a6ef66

// create instance of Babylon class
const babylon = new Babylon(signetNetwork, Buffer.from(keyPair.publicKey), token);

// amount of stake (sats)
const amount = 50000;

// get unsigned stake tx
const unsignedStakeTx = await babylon.stake(amount);

// sign tx
const tweakedChildNode = keyPair.tweak(
    crypto.taggedHash('TapTweak', keyPair.publicKey.slice(1, 33)),
);
const signedTx = unsignedStakeTx.psbt.signInput(0, tweakedChildNode);
signedTx.finalizeAllInputs()

// extract and sent to network
const stakingTx = Psbt.fromHex(signedTx.toHex()).extractTransaction();
fetch('https://mempool.space/signet/api/tx', {
    method: 'POST',
    headers: { 'Content-Type': 'text/plain' },
    body: stakingTx.toHex()
})
    .then(response => response.text())
    .then(txid => {
        console.log('Broadcasted Transaction ID:', txid);
    })
    .catch(error => {
        console.error('Failed to broadcast transaction:', error);
    });

Unstake

The unbonding method creates unsigned transaction for unbonding (undelegation which need to withdraw then)

  • unbonding(stakingTxHash): Unbond stake from specific staking Tx.

const { Babylon, signetNetwork } = require("@everstake/wallet-sdk/babylon");
const { Psbt } = require('bitcoinjs-lib');

// Token ID.
const token = process.env.TOKEN; // 3155f389-d943-4966-8e18-f159c2a6ef66

// create instance of Babylon class
const babylon = new Babylon(signetNetwork, Buffer.from(keyPair.publicKey), token);

// stake tx hash which need to unbond
const stakeTxHash = '00000000000000000000000000000000000000'

// get unsigned tx
const unsignedUnbondingTx = await babylon.unbonding(stakeTxHash);

// sign tx
const signedTx = unsignedUnbondingTx.psbt.signInput(0, keyPair);
signedTx.finalizeAllInputs();
const tx = Psbt.fromHex(signedTx.toHex()).extractTransaction();

// collect data and send it to Babylon API
const stakerSignature = tx.ins[0].witness[0].toString('hex')
const unbondingTxHex = tx.toHex()
await babylon.sendUnbondingTx({
    staker_signed_signature_hex: stakerSignature,
    staking_tx_hash_hex: stakeTxHash,
    unbonding_tx_hash_hex: tx.getId(),
    unbonding_tx_hex: unbondingTxHex,
})

Unbonding using API

At first, you need use /babylon/unbonding endpoint to create unbonding tx, then you need to sign this transaction and make a payload which need to send to another endpoint /babylon/unbonding/send to make order for unbonding.

Withdraw

There are at least two types of withdrawing:

  • withdrawEarlyUnbonded(stakingTxHash, feeRate = 1): withdraw your stake after unbonding

  • withdrawTimelockUnbonded(stakingTxHash, feeRate = 1): withdraw your stake after your stake period is expired. No need to make unbonding before

const { Babylon, signetNetwork } = require("@everstake/wallet-sdk/babylon");
const { Psbt } = require('bitcoinjs-lib');

// Token ID.
const token = process.env.TOKEN; // 3155f389-d943-4966-8e18-f159c2a6ef66

// create instance of Babylon class
const babylon = new Babylon(signetNetwork, Buffer.from(keyPair.publicKey), token);

// stake tx hash which need to withdraw
const stakeTxHash = '00000000000000000000000000000000000000'

// get unsigned tx
const unsignedWithdrawalTx = await babylon.withdrawEarlyUnbonded(stakeTxHash);
// or you should use withdrawTimelockUnbonded instead of withdrawEarlyUnbonded, it depends on conditions

// sign tx
const signedTx = unsignedWithdrawalTx.psbt.signInput(0, keyPair);
signedTx.finalizeAllInputs();
const tx = Psbt.fromHex(signedTx.toHex()).extractTransaction();

// sent to network
fetch('https://mempool.space/signet/api/tx', {
    method: 'POST',
    headers: { 'Content-Type': 'text/plain' },
    body: tx.toHex()
})
    .then(response => response.text())
    .then(txid => {
        console.log('Broadcasted Transaction ID:', txid);
    })
    .catch(error => {
        console.error('Failed to broadcast transaction:', error);
    });

Getting Info

  • getDelegations(): Gets all user's delegations using the current public key.

  • getGlobalParamsVersions(): Gets all versions of global params.

const { Babylon, signetNetwork } = require("@everstake/wallet-sdk/babylon");

// Token ID.
const token = process.env.TOKEN; // 3155f389-d943-4966-8e18-f159c2a6ef66

// create instance of Babylon class
const babylon = new Babylon(signetNetwork, keyPair.publicKey, token);

console.log(await babylon.getDelegations()); // list of delegations