Skip to content

Send on Bitcoin

Bitcoin uses the same vaults, wallets, and transaction endpoint as EVM, with one difference in how you submit: a Bitcoin transaction is always sent as a signed canonical intent, never through the EVM convenience fields (to/amount).

const wallet = await xkova.createWallet(vault.id, { chain: "bitcoin" });
console.log("Fund on signet:", wallet.address);

On the sandbox this is a signet address. Fund it from a signet faucet before sending.

Where an EVM send lets you pass to and amount for convenience, Bitcoin requires the exact bytes:

  • Build the canonical intent for the spend.
  • Sign those bytes with your API key.
  • Submit the hex of the intent plus the signature.

The idempotency key is carried inside the signed intent, so it cannot be altered after you sign.

// intentHex / intentSig produced by your Bitcoin intent tooling
await xkova.request("POST", "/v1/transactions", {
wallet_id: wallet.id,
intent: intentHex, // hex of the exact canonical intent bytes
intent_signature: intentSig, // your Ed25519 signature over those bytes
});

request is the low-level, stamped call the typed helpers are built on — the same authentication as everywhere else applies.

A Bitcoin transaction commits to its specific inputs and outputs. Signing the exact canonical intent — rather than a convenience shorthand the server expands — means what MPC signs is precisely what you authorized, per input, with no room for the server to reinterpret amounts or destinations.

The returned Transaction walks the same lifecycle as EVM (Core concepts); chain_tx_hash is the Bitcoin txid once broadcast. Track it by polling or with webhooks.