> ## Documentation Index
> Fetch the complete documentation index at: https://docs.p2p.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Cardano Transaction Signing

> Sign and broadcast Cardano transactions built with the P2P.org Unified API.

To sign and broadcast the transaction to the Cardano network, follow these steps:

1. Prepare <Tooltip tip="A transaction that must be signed and broadcasted to the blockchain network.">unsigned transaction</Tooltip> in Base64 encrypted format.

2. Sign the transaction using the following code:

<CodeGroup>
  ```javascript JavaScript theme={null}
  import {
      Bip32PrivateKey,
      Transaction,
      TransactionHash,
      TransactionWitnessSet,
      Vkey,
      Vkeywitness,
      Vkeywitnesses,
  } from "@emurgo/cardano-serialization-lib-nodejs";
  import { mnemonicToEntropy } from "bip39";
  import { blake2b } from "blakejs";

  const MNEMONIC = "<MNEMONIC>";
  const RAW_TX_HEX = "<RAW_TX_HEX>";

  function deriveKey(mnemonic: string, role: number, index = 0): Bip32PrivateKey {
      const entropy = Buffer.from(mnemonicToEntropy(mnemonic), "hex");
      const rootKey = Bip32PrivateKey.from_bip39_entropy(entropy, Buffer.from(""));

      return rootKey
          .derive(1852 | 0x80000000) // purpose
          .derive(1815 | 0x80000000) // coin type
          .derive(0 | 0x80000000)    // account 0
          .derive(role)              // role: 0=payment, 2=stake
          .derive(index);            // index
  }

  function signTransactionHex(
      unsignedHex: string,
      paymentKey: Bip32PrivateKey,
      stakeKey: Bip32PrivateKey
  ): string {
      const tx = Transaction.from_bytes(Buffer.from(unsignedHex, "hex"));
      const txHashBytes = blake2b(tx.body().to_bytes(), undefined, 32);
      const txHash = TransactionHash.from_bytes(txHashBytes);

      const witnesses = Vkeywitnesses.new();

      // Payment key witness
      const rawPaymentKey = paymentKey.to_raw_key();
      witnesses.add(
          Vkeywitness.new(
              Vkey.new(rawPaymentKey.to_public()),
              rawPaymentKey.sign(txHash.to_bytes())
          )
      );

      // Stake key witness
      const rawStakeKey = stakeKey.to_raw_key();
      witnesses.add(
          Vkeywitness.new(
              Vkey.new(rawStakeKey.to_public()),
              rawStakeKey.sign(txHash.to_bytes())
          )
      );

      const witnessSet = TransactionWitnessSet.new();
      witnessSet.set_vkeys(witnesses);

      const signedTx = Transaction.new(tx.body(), witnessSet, tx.auxiliary_data());
      return Buffer.from(signedTx.to_bytes()).toString("hex");
  }

  async function main() {
      if (!RAW_TX_HEX || RAW_TX_HEX.length < 10) {
          throw new Error("❌ RAW_TX_HEX is missing or invalid.");
      }

      const paymentKey = deriveKey(MNEMONIC, 0); // m/1852'/1815'/0'/0/0
      const stakeKey = deriveKey(MNEMONIC, 2);   // m/1852'/1815'/0'/2/0

      const signedHex = signTransactionHex(RAW_TX_HEX, paymentKey, stakeKey);

      console.log("✅ Signed Cardano Tx (hex):");
      console.log(signedHex);
  }

  main().catch(console.error);
  ```
</CodeGroup>

Upon successful execution, the script prints the signed transaction in hexadecimal format, ready to be broadcasted:

<CodeGroup>
  ```bash bash theme={null}
  ✅ Signed Cardano Tx (hex): ...
  ```
</CodeGroup>

3. Broadcast the transaction to the Cardano network by sending a POST request to [/api/v1/unified/transaction/broadcast](/reference/unified-transaction-send).


## Related topics

- [Networks Supported](/docs/unified-api-networks.md)
- [Getting Started](/docs/unified-api-getting-started.md)
- [Unified API Reference](/reference/unified-create-stake-transaction.md)
