Embedded Wallet Differences
The Bitcoin functions work with both external wallets (browser extensions such as Xverse, Unisat, OKX, and Phantom) and Dynamic embedded wallets. Most behave identically. A few accept options that an embedded wallet cannot act on, because an embedded wallet is a single MPC key rather than a wallet application managing several addresses. This page lists every difference. If a function is not mentioned here, it behaves the same for both wallet types.Why the differences exist
An embedded Bitcoin wallet is one key at one fixed derivation path. Three consequences follow, and they explain every entry below. One address type per wallet. The address type is chosen when the wallet is created, either Native SegWit or Taproot, and cannot change afterwards. An external wallet can expose a payment address and a separate ordinals address at the same time, so its functions accept anaddressType to select between them. An embedded wallet has only one address type, so there is nothing to select.
No derived addresses. The derivation path is fixed per address type, with no account or index component, and a user has one Bitcoin embedded wallet. You cannot derive additional receiving addresses from it.
One address, encoded per network. The same key produces a different address string on each network, because only the prefix and checksum differ:
signPsbt and signPsbts
An embedded wallet signs only the inputs that belong to its own address. Inputs owned by other addresses in the PSBT are left untouched, so a PSBT can still be co-signed by another party afterwards. The one exception is a P2WSH multisig input that you explicitly allow with
allowedWitnessScripts.signature[].address must be your wallet’s own address for the active network. On testnet, use the tb1... encoding. An address the wallet does not own is rejected rather than ignored, so a mistyped or mainnet-encoded address returns an error instead of a PSBT with nothing signed.
signature[].signingIndexes limits signing to a subset of your wallet’s inputs. Requesting an index the wallet does not own throws an error, and no input is signed.
signature[].disableAddressValidation has no effect. On an external wallet the extension verifies key ownership itself before signing, so skipping Dynamic’s check still leaves a check in place. On an embedded wallet the ownership check is the only one, so it always runs.
allowedSighash restricts which signature hash (sighash) types the wallet will sign. The type itself comes from the PSBT (BIP-174 PSBT_IN_SIGHASH_TYPE), so this option can only reject a type, never select one.
Defaults
Two separate settings determine what is signed: which inputs, and which sighash type is accepted. Omitting either one never extends signing beyond the inputs the wallet owns.An empty
allowedSighash means “accept any type”, not “use SIGHASH_ALL”. The type always comes from the PSBT. SIGHASH_ALL is the fallback only when the PSBT itself declares nothing, which is the common case for a PSBT built by sendBitcoin or a standard wallet.Co-signing P2WSH multisig inputs
By default an embedded wallet signs only inputs that spend from its own address. To co-sign a P2WSH multisig, for example a 2-of-3 that holds the embedded wallet’s key next to keys held elsewhere, pass the multisig’s witness script inallowedWitnessScripts. This option is available for embedded wallets only, and requires @dynamic-labs-sdk/bitcoin 1.48.0 or later.
allowedWitnessScripts is an array of hex-encoded witness scripts. The wallet signs a P2WSH input only when all of these hold:
- The input’s witness script is in
allowedWitnessScripts. - The SHA-256 of the witness script matches the input’s
scriptPubKey. - The script is a standard
m-of-nmultisig. - The wallet’s own compressed public key is one of the keys in the script.
signingIndexes naming that input, the call throws signingIndexes contains indexes that do not belong to the signing address.
The returned PSBT is not finalized. It carries this wallet’s partial signature, and you merge the signatures from the other co-signers and finalize it yourself before broadcasting.
publicKey of the Native SegWit entry in the wallet account’s addressesWithTypes.
signMessageWithCustomOptions
Both options are ignored for embedded wallets. The call succeeds and returns a valid signature over the message, using the wallet’s single address and BIP-322.
addressType has no effect. An embedded wallet has one address type, fixed at creation, so there is nothing to select.
protocol is not supported. Embedded wallets sign messages with BIP-322 only, and Dynamic verifies the BIP-322 hash on the server. Requesting ecdsa does not change the signature that is produced.
To sign a message with an embedded wallet, use signMessage, which needs neither option.
Functions that behave the same
Related functions
- signPsbt - Sign a PSBT
- signPsbts - Sign multiple PSBTs
- signMessageWithCustomOptions - Sign a message with custom options