Babylon
Getting Started
You can use this library or API to implement Babylon staking for Everstake validator.
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$ yarn add @everstake/wallet-sdkStep. 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-f159c2a6ef66Step. 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 unbondingwithdrawTimelockUnbonded(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
