Sign and Broadcast Transaction

To sign and broadcast a transaction to the Babylon Genesis network, follow these steps.

1. Prepare the Unsigned Transaction

Obtain the unsignedTransactionData object provided by the API endpoint or a transaction builder. The object will have the format returned in previous API responses.

Example (object form):

{
  "messages": [/*...Babylon messages...*/],
  "fee": {
    "amount": [{"denom": "ubbn", "amount": "1000"}],
    "gas": "200000"
  },
  "memo": ""
}

2. Sign the Transaction

Sign the transaction using your preferred signing method or the script below.

import { DirectSecp256k1HdWallet, Registry, GeneratedType } from '@cosmjs/proto-signing';
import { SigningCosmWasmClient, defaultRegistryTypes } from '@cosmjs/cosmwasm-stargate';
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import axios from 'axios';

// Replace with actual Babylon message types if needed
import {
  MsgWrappedDelegate,
  MsgWrappedUndelegate,
} from '@babylonlabs-io/babylon-proto-ts/dist/generated/babylon/epoching/v1/tx';

const BABYLON_RPC = '<BABYLON_NODE_RPC>'; // e.g. https://rpc.testnet.babylonchain.io:443
const BABYLON_API_URL = '<P2P_API_URL>';  // e.g. https://api.testnet.p2p.org
const BABYLON_API_KEY = '<P2P_API_KEY>';
const BABYLON_NETWORK = '<NETWORK_NAME>'; // e.g. testnet, mainnet
const BABYLON_MNEMONIC = '<MNEMONIC>';
const BABYLON_ADDRESS = '<BBN_ADDRESS>';  // e.g. bbn1xyz...

const UNSIGNED_TX = {
  // Paste your unsigned transaction object here
  messages: [],
  fee: {
    amount: [{ denom: 'ubbn', amount: '1000' }],
    gas: '200000',
  },
  memo: '',
};

function getBabylonRegistry(): Registry {
  const registry = new Registry([...defaultRegistryTypes]);
  registry.register(
    '/babylon.epoching.v1.MsgWrappedDelegate',
    MsgWrappedDelegate as unknown as GeneratedType
  );
  registry.register(
    '/babylon.epoching.v1.MsgWrappedUndelegate',
    MsgWrappedUndelegate as unknown as GeneratedType
  );
  return registry;
}

async function signTransaction(
  mnemonic: string,
  address: string,
  unsignedTx: any
): Promise<string> {
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: 'bbn' });
  const registry = getBabylonRegistry();
  const client = await SigningCosmWasmClient.connectWithSigner(BABYLON_RPC, wallet, { registry });

  const { bodyBytes, authInfoBytes, signatures } = await client.sign(
    address,
    unsignedTx.messages,
    unsignedTx.fee,
    unsignedTx.memo
  );

  const txRaw = TxRaw.fromPartial({
    bodyBytes,
    authInfoBytes,
    signatures,
  });

  // Return the signed transaction as hex string
  return Buffer.from(TxRaw.encode(txRaw).finish()).toString('hex');
}

async function broadcastTransaction(signedTxHex: string): Promise<string> {
  const endpoint = `${BABYLON_API_URL}/api/v1/babylon/${BABYLON_NETWORK}/transaction/send`;
  const response = await axios.post(
    endpoint,
    { signedTransaction: signedTxHex },
    {
      headers: {
        accept: 'application/json',
        'content-type': 'application/json',
        authorization: `Bearer ${BABYLON_API_KEY}`,
      },
    }
  );
  if (!response.data.result?.transactionHash) {
    throw new Error(`Broadcast failed: ${JSON.stringify(response.data)}`);
  }
  return response.data.result.transactionHash;
}

async function main() {
  if (!BABYLON_MNEMONIC || !BABYLON_ADDRESS) {
    throw new Error('❌ Babylon mnemonic or address is missing.');
  }
  if (!UNSIGNED_TX.messages || !Array.isArray(UNSIGNED_TX.messages)) {
    throw new Error('❌ Invalid unsigned transaction.');
  }

  const signedTxHex = await signTransaction(BABYLON_MNEMONIC, BABYLON_ADDRESS, UNSIGNED_TX);

  console.log('✅ Signed Babylon Tx (hex):');
  console.log(signedTxHex);

  // Broadcast (optional, can be run separately)
  const txHash = await broadcastTransaction(signedTxHex);

  console.log('✅ Broadcasted Tx Hash:', txHash);
}

main().catch(console.error);

Upon successful execution, the script prints the signed 0x-prefixed transaction in hexadecimal format and then broadcasts it.

Example output:

✅ Signed Babylon Tx (hex):
aabbcc...deadbeef

✅ Broadcasted Tx Hash:
BABYLON_TX_HASH_HERE

3. [Optional] Broadcast the Signed Transaction

If you used any other signing method, you need to broadcast the signed transaction to the Babylon Genesis network.

Send a POST request to /api/v1/babylon/[network]/transaction/send.

Example request (for babylon-testnet network):

curl --request POST \
     --url https://api-test.p2p.org/api/v1/babylon/babylon-testnet/transaction/send \
     --header 'accept: application/json' \
     --header 'authorization: Bearer <token>' \
     --header 'content-type: application/json' \
     --data '
     {
     "signedTransaction": "0aab010a9b010a232f636f736d6f732e7374616b696e672e763162657461312e4d736744656c656761746512740a2d636f736d6f733179397765666d6c706d30646a6b74387373656576656b653068747466756b67326136306730721234636f736d6f7376616c6f70657231376c676730337a65397836786b613032667330686877346164347777673035686571723279381a0d0a057561746f6d120434323030120b546865206d65737361676512670a500a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a2103b0c7ac278e1941ac0b65d6bd45d541cae58aa584058fbbd822311b8718708c0e12040a020801181312130a0d0a057561746f6d12043539353210dfc30e1a4026d73408f2f516a2a26604cb5a63f3d57262a4462d10931c21d36c1ce9d73d8f7d051f1c4aabc2e3142c7f01a4935b85c5c7d3854e8a3c41f0c218daf2a7b5ef"
     }'
  • signedTransaction — signed transaction in the hexadecimal which needs to be broadcasted to the network.

Example response:

{
    "error": null,
    "result": {
        "status": "success",
        "blockId": 18575267,
        "fee": 0.005952,
        "gas": {
            "used": 202947,
            "wanted": 238047
        },
        "transactionHash": "EDDA3AE81ACBF56CB1F154F4957779C04F10B6F4C23B13597EFFC61FE05A02D2"
    }
}
  • status — transaction status: success, failed.
  • blockId — unique identifier of the block in which the transaction has been included.
  • fee — total fee in BBN charged for processing the transaction.
  • gas — computational effort required to execute the transaction, measured in gas units.
    • used — amount of gas spent for the transaction.
    • wanted — maximum gas limit that the transaction initiator was willing to consume for the transaction.
  • transactionHash — hash of the transaction.

What's Next?