Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt

Use this file to discover all available pages before exploring further.

Overview

BitcoinModule provides native Bitcoin operations: message signing, PSBT signing, sending Bitcoin, building PSBTs, broadcasting raw transactions, and balance queries. Access it via DynamicSDK.instance().bitcoin.

Prerequisites

Get a Bitcoin Wallet

There are two paths to a Bitcoin wallet: filter the user’s existing wallets, or create a new one explicitly.

Filter existing wallets

If Bitcoin is enabled and the user has a Bitcoin wallet (created automatically at signup), find it via userWallets:
let sdk = DynamicSDK.instance()

guard let btcWallet = sdk.wallets.userWallets.first(where: { $0.chain == "BTC" }) else {
  fatalError("No Bitcoin wallet found")
}

print("Bitcoin address: \(btcWallet.address)")

Create a new Bitcoin wallet

Call createWallet with EmbeddedWalletChain.btc:
let wallet = try await sdk.wallets.embedded.createWallet(chain: .btc)
print("Created: \(wallet.address)")
Bitcoin wallets are derived as Native SegWit (bc1q…) by default. Mainnet is the only network supported today.

What is a satoshi?

A satoshi is the smallest unit of Bitcoin — 1 BTC = 100,000,000 satoshis. All amount fields in the Bitcoin module (sendBitcoin, buildPsbt, getBalance) are expressed in satoshis, not BTC.

What is a PSBT?

A Partially Signed Bitcoin Transaction (PSBT) is a standard for transactions that have not yet been fully signed. It lets different participants with different keys sign a transaction without sharing private keys, enabling safer multi-step or multi-sig flows.

Get Balance

Query the Bitcoin balance (in satoshis) for a wallet:
let sdk = DynamicSDK.instance()
guard let wallet = sdk.wallets.userWallets.first(where: { $0.chain == "BTC" }) else { return }

let balance = try await sdk.bitcoin.getBalance(walletId: wallet.id)
print("Balance: \(balance) satoshis")

Sign a Message

Sign a message using ECDSA (default) or BIP-322:
let signature = try await sdk.bitcoin.signMessage(
  walletId: wallet.id,
  message: "Hello, Bitcoin!"
)
print("Signature: \(signature)")
For BIP-322 signing, pass the protocol and optional addressType:
let signature = try await sdk.bitcoin.signMessage(
  walletId: wallet.id,
  message: "Hello, Bitcoin!",
  protocol: "bip322-simple",
  addressType: "payment"
)

Send Bitcoin

Send BTC to a recipient. Returns the transaction ID.
let txId = try await sdk.bitcoin.sendBitcoin(
  walletId: wallet.id,
  recipientAddress: "bc1q...",
  amount: "10000",      // satoshis
  feePriority: "medium" // optional: "high" | "medium" | "low"
)
print("TX ID: \(txId)")

Build a PSBT

Build an unsigned PSBT (base64-encoded) you can sign later or hand off to another signer:
let psbtBase64 = try await sdk.bitcoin.buildPsbt(
  walletId: wallet.id,
  recipientAddress: "bc1q...",
  amount: "10000",
  feePriority: "medium" // optional
)

Sign PSBTs

Sign a single PSBT, or batch-sign multiple PSBTs:
// Single
let signed = try await sdk.bitcoin.signPsbt(
  walletId: wallet.id,
  request: ["unsignedPsbtBase64": psbtBase64]
)

// Batch
let signedList = try await sdk.bitcoin.signPsbts(
  walletId: wallet.id,
  requests: [
    ["unsignedPsbtBase64": psbtBase64]
  ]
)

Send a Raw Transaction

Broadcast a pre-signed transaction in hex form:
let txId = try await sdk.bitcoin.sendRawTransaction(
  walletId: wallet.id,
  rawTransactionHex: "0200000001..."
)

API Reference

MethodReturnsDescription
getBalanceStringGet wallet balance in satoshis
signMessageStringSign a message (ECDSA or BIP-322)
sendBitcoinStringSend BTC, returns transaction ID
buildPsbtStringBuild unsigned PSBT (base64)
signPsbtStringSign a single PSBT
signPsbts[String]Sign multiple PSBTs
sendRawTransactionStringBroadcast a raw transaction hex

Next Steps