Bitcoin and Babylonchain
Note that BTC is staked on the Bitcoin chain, while the Finality Provider and BABY rewards reside on the Babylonchain. Our API uses mainnet to refer to Bitcoin mainnet and Babylonchain mainnet, and testnet to refer to Bitcoin signet and Babylonchain testnet.
Flow
The API interactions to stake are outlined below. TLDR is:
Step 1 - Intent
- Use the Create Babylon Delegation endpoint and get back 2 PBSTs (Slashing tx and Unbonding tx) and 1 message (Proof of ownership of Babylon address).
- You will also get a uuid called stake_id (this will allow you to get back this response later without needing to start over).
- The state of the flow moves to initialized
Once you've signed them...
Step 2 - Delegate (on Babylon)
- Using the 3 signatures above, pass them to the Create Delegate Tx endpoint and get back a Babylon Chain MsgCreateBTCDelegation that you will need to sign and broadcast
- The state moves to waiting_for_delegation
- Sign this transaction
- Broadcast it
- if you want us to do it for you, use the Broadcast Delegate Tx endpoint.
- if you do it yourself, use Update Delegate Tx endpoint to send us the tx hash. We will need it to monitor the status of delegation before building a viable staking tx
Step 3 - Stake (on Bitcoin)
- Once the delegation has been confirmed onchain, call the Bitcoin Stake Tx endpoint with stake_id and you will get back an unsigned Bitcoin staking tx. Once signed...
- Broadcast Staking Tx:
- if you want us to broadcast it for you, use the Broadcast Staking Tx (Docs TBD) endpoint.
- if you broadcast it yourself, use Update Staking Tx endpoint to send us the tx hash.
Babylonchain Delegation Signing
The below script can be ran like this:
node index.js (tx hex unsigned payload) (nonce) ( account number)
With the assumption that the private key can be found in ./.key'. It will output the signed hash of the provided unsigned payload.
JavaScript
import slate from '@figmentio/slate'
import cosmos from 'cosmos-lib'
import { btcstakingtx } from "@babylonlabs-io/babylon-proto-ts";
import {
DirectSecp256k1Wallet,
Registry
} from '@cosmjs/proto-signing';
import {
SigningStargateClient,
calculateFee
} from '@cosmjs/stargate';
import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx.js"
import { fromHex } from "@cosmjs/encoding";
import { MsgCreateBTCDelegation } from '@babylonlabs-io/babylon-proto-ts/dist/generated/babylon/btcstaking/v1/tx.js'
import fs from 'fs';
const privateKey = fs.readFileSync('./.key', "utf8").trim();
const signingPayload = process.argv[2];
const txBuf = Buffer.from(signingPayload, "hex");
const txJson = JSON.parse(txBuf.toString());
// TODO: look these up from the Blockchain
const nonce = process.argv[3];
const accountNumber = process.argv[4];
const msg = btcstakingtx.MsgCreateBTCDelegation.fromJSON(txJson['messages'][0].value);
txJson['messages'][0].value = msg
const sign = async (txJson, privateKeys, options) => {
const signer = await DirectSecp256k1Wallet.fromKey(
fromHex(privateKeys[0]),
"bbn"
);
const { address } = (await signer.getAccounts())[0];
const registry = new Registry();
registry.register(
"/babylon.btcstaking.v1.MsgCreateBTCDelegation",
MsgCreateBTCDelegation
);
const signingClient = await SigningStargateClient.offline(signer, { registry });
const { accountNumber, sequence, chainId } = options;
const txRaw = await signingClient.sign(
address,
txJson.messages,
txJson.fee,
txJson.memo,
{
accountNumber,
sequence,
chainId,
}
);
const txBytes = TxRaw.encode(txRaw).finish();
return txBytes.toString("hex");
}
const signed = await sign(txJson, [privateKey], {
accountNumber: accountNumber,
sequence: nonce,
chainId: 'bbn-test-5'
})
console.log(signed)