/bdk-flutter

Bitcoin Development Kit - Flutter Package

Primary LanguageDartMIT LicenseMIT

Bdk-Flutter

A Flutter library for the Bitcoin Development Kit (https://bitcoindevkit.org/)

Table of Contents

Requirements

Flutter

  • Flutter version : 3.0 or higher
  • Dart version : 2.17.1 or higher

Android

  • Android minSdkVersion. : API 23 or higher.
  • Android Target SDK version : API 29.

iOS

  • iOS Base SDK : 12 or greater.
  • Deployment target : iOS 12.0 or greater.

Installation

To use this plugin, add bdk-flutter as a dependency in your pubspec.yaml file.

Configuring iOS

Please navigate to the iOS folder in your project and run the following command:

pod install

Sample applications

  • BDK Flutter Demo App: The BDK Flutter Demo App is a simple bitcoin app built in flutter to serve as a reference app to demonstrate bdk-flutter api usage.

Usage

import 'package:bdk_flutter/bdk_flutter.dart';

Library API

All methods work in iOS:

All methods work in Android:

All methods return the response as follows:

The following methods can be used with this module. All methods can be called by the BdkWallet object.

Method Request Parameters
generateMnemonic() - wordCount, entropy
createDescriptors() - xprv, type, mnemonic, network, password, publicKeys, threshold , descriptorPath, changeDescriptorPath
createWallet() - mnemonic, password, descriptor, changeDescriptor, network, blockchainConfig
createExtendedKey() - network, mnemonic, password
createXprv() - network, mnemonic, password
createXpub() - network, mnemonic, password
getNewAddress() -
getLastUnusedAddress() -
getBalance() -
getTransactions() -
getPendingTransactions() -
getConfirmedTransactions() -
syncWallet() -
createTx() - address (recipient wallet address), amount*(sats) , feeRate
signTx() - psbt
broadcastTx() - sbt
quickSend() - address (recipient wallet address), amount*(sats) , feeRate

generateMnemonic()

Generates a random mnemonic seed phrase.
Reference: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic
This will generate a mnemonic sentence from the English word list.

The required entropy can be specified as the entropy parameter and can be in multiples of 64 from 128 to 256, 128 is used as default.

A wordCount or length can be specified instead as the length parameter and can be in multiples of 6 from 12 to 24.

final response = await generateMnemonic()
final  response = await generateMnemonic(entropy: Entropy.Entropy128)

Returned response example:

"daring erase travel point pull loud peanut apart attack lobster cross surprise actress dolphin gift journey mystery save"

createDescriptors()

Create a WalletDescriptor object containing a descriptor and a change descriptor, using xprv or mnemonic.

xprv will be used if passed otherwise mnemonic, network and password will be used.

type is an enum and can be one of P2PK, P2PKH, P2WPKH, P2SHP2WPKH, P2SHP2WSHP2PKH, MULTI. P2WPKH is used as default.

If type is MULTI then need to specify the signature threshold and publicKeys array. path is optional, m/84'/1'/0'/0 is used by default

final  response = createDescriptor(  network: Network.TESTNET, 
                                     mnemonic: 'puppy interest whip tonight dad never sudden response push zone pig patch', 
				     password: '', 
				     type: Descriptor.P2WPKH,
				     descriptorPath: "m/84'/1'/0'/0",
                                     changeDescriptorPath: "m/84'/1'/0'/1",
				  );

Returned response example:

{

descriptor: "wpkh([d91e6add/84'/1'/0'/0]tprv8gnnA5Zcbjai6d1mWvQatrK8c9eHfUAKSgJLoHfiryJb6gNBnQeAT7UuKKFmaBJUrc7pzyszqujrwxijJbDPBPi5edtPsm3jZ3pnNUzHbpm/*)"
changeDescriptor: "wpkh([d91e6add/84'/1'/0'/1]tprv8gnnA5Zcbjai9Wfiec82h4oP8R92SNuNFFD5g8Kqu8hMd3kb8h93wGynk4vgCH3tfoGkDvCroMtqaiMGnqHudQoEYd89297VuybvNWfgPuL/*)"

 }

createWallet()

Creates a new wallet. A wallet can be created using a mnemonic or wallet output descriptor.

Creating a wallet using mnemonic

To create a wallet with a mnemonic, menmonic argument has to be specified and descriptor and changeDescriptor should not be specified. All other parameters are optional and will take default values if not specified. A known mnemonic can be used when restoring a wallet, or a new mnemonic can be created using generateMnemonic method.

                                                
final response  =  await BdkFlutter().createWallet( mnemonic:"puppy interest whip tonight dad never sudden response push zone pig patch",
                                                    password: "password",
                                                    network: Network.TESTNET,
                                                    blockchainConfig: BlockchainConfig.electrum
						    (
						        config: ElectrumConfig(
                                                                   stopGap: 10,
								   timeout: 5,
								   retry: 5,
                                                                   url: "ssl://electrum.blockstream.info:60002")
						     )
                                                    
                                                 );
						 
final response  =  await BdkFlutter().createWallet( mnemonic:"puppy interest whip tonight dad never sudden response push zone pig patch" );						 
						    

Creating a wallet using descriptor.

A descriptor has to be specified and mnemonic should not be specified. All other arguments are optional and will take default values when not specified. A known descriptor and changeDescriptor can be used. createDescritpors method can be used to create a descriptor and changeDescriptor

final response  =  await BdkFlutter().createWallet( changeDescriptor: "wpkh([d91e6add/84'/1'/0'/1]tprv8iG3fH5MsxPcQh8jAvtzkbAc4VTvTQB8pdTiNw5ECciipgQkmcmWFCzkgBqocr8TRqnJD6rnnpzo9q7AUzUTJESHL1xQQfktMvG6Z5wDKZs/*)",
                                                    descriptor: "wpkh([d91e6add/84'/1'/0'/0]tprv8iG3fH5MsxPcQh8jAvtzkbAc4VTvTQB8pdTiNw5ECciipgQkmcmWFCzkgBqocr8TRqnJD6rnnpzo9q7AUzUTJESHL1xQQfktMvG6Z5wDKZs/*)",
                                                    network: Network.TESTNET,
						    blockchainConfig: BlockchainConfig.electrum
						    (
						        config: ElectrumConfig(
                                                                   stopGap: 10,
                                                                   retry: 5,
                                                                   url: "ssl://electrum.blockstream.info:60002")
						     )
                                                    
                                                 );						 


final response  =  await BdkFlutter().createWallet( descriptor: "wpkh([d91e6add/84'/1'/0'/0]tprv8iG3fH5MsxPcQh8jAvtzkbAc4VTvTQB8pdTiNw5ECciipgQkmcmWFCzkgBqocr8TRqnJD6rnnpzo9q7AUzUTJESHL1xQQfktMvG6Z5wDKZs/*)" );
						 

Returned response example:

{

address: "tb1ql5pqtl36xu6z4czdvsd9lr5fa6fyld49dff4gw"
balance: 100000

}

createExtendedKey()

This method will create an ExtendedKeyInfo object using the specified mnemonic seed phrase and password. ExtendedKeyInfo creates a key object which encapsulates the mnemonic and adds a private key using the mnemonic and password.

The extended key info object is required to be passed as an argument in some bdk methods.

final  response = await createExtendedKey(  network : Network.TESTNET
                                            mnemonic: 'daring erase travel point pull loud peanut apart attack lobster cross surprise',
                                            password: ''
                                         );
					   

Returned response example:

 {
	    xpub: "tpubDGdv2vah1pfxrqrHLgD7nYSE2RdbR9ExMQahBWcgsDt7PFdcXtV97jWc8tkXrFHDbKeyoKjPQaJ9UxA5xLEWvU1zv1h7JxdvsTMNpdBjsb9"
	    xprv: "tprv8jwstWYSsSzHyNpVT2YXP8n7TQ7fFp43n6yutzaPSx5iYmNquVfYwEtjxm2Wynm3NWjTfutiDr1AXXPFVwSyrZE7ixgycbpbqAkQ1GzcVx9"
 }
 

createXprv()

Creates the private key using mnemonic phrase and password.

final response = await createXprv(  network: Network.TESTNET, 
                                     mnemonic: 'daring erase travel point pull loud peanut apart attack lobster cross surprise', 
				     password: '' 
				  );

Returned response example:

"tprv8jwstWYSsSzHyNpVT2YXP8n7TQ7fFp43n6yutzaPSx5iYmNquVfYwEtjxm2Wynm3NWjTfutiDr1AXXPFVwSyrZE7ixgycbpbqAkQ1GzcVx9"

createXpub()

Create the public key using a mnemonic phrase and password.

final  response = await createXpub(  network: Network.TESTNET, 
                                     mnemonic: 'daring erase travel point pull loud peanut apart attack lobster cross surprise', 
				     password: '' 
				  );

Returned response example:

"tpubDGdv2vah1pfxrqrHLgD7nYSE2RdbR9ExMQahBWcgsDt7PFdcXtV97jWc8tkXrFHDbKeyoKjPQaJ9UxA5xLEWvU1zv1h7JxdvsTMNpdBjsb9"

getNewAddress()

Creates a new address for the wallet.

final response = await BdkFlutter().getNewAddress();

Returned response example:

"tb1qew48u6cfxladqpumcpzl0svdqyvc9h4rqd3dtw"

getLastUnusedAddress()

Returns the last unused address of the wallet.

final response = await BdkFlutter().getLastUnusedAddress();

Returned response example:

"tb1qew48u6cfxladqpumcpzl0svdqyvc9h4rqd3dtw"

getBalance()

Returns the Balance object consisting of spendable, total, confirmed, untrustedPending, trustedPending, and immature balances of your wallet.

final response = await BdkFlutter().getBalance();
final total    = response.total;

Returned response example:

 "8369", // balance in sats
 

getTransactions()

Returns a list of all the transactions made.

final response = await BdkFlutter().getTransactions();

Returned response example:

[
	{
	    "received": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	    "sent": "0" // in sats
	    "fees": "0" // in sats
	    "txid": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	}
]

getPendingTransactions()

Returns the list of unconfirmed transactions.

final response = await BdkFlutter().getPendingTransactions();

Returned response example:

[
	{
	    "received": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	    "sent": "0" // in sats
	    "fees": "0" // in sats
	    "txid": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	}
]

getConfirmedTransactions()

Returns the list of confirmed transactions.

final response = await BdkFlutter().getConfirmedTransactions();

Returned response example:

[
	{
	    "received": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	    "sent": "0" // in sats
	    "fees": "0" // in sats
	    "txid": "tb1qxg8g8cdzgs09cttu3y7lc33udqc4wsesunjnhe",
	}
]

syncWallet()

Syncs the wallet.

final response = await BdkWallet().syncWallet();

createTx()

Creates a bitcoin transaction. This can transaction can later be signed and broadcast. The transaction created is a Partially Signed Bitcoin Transaction(psbt).
Required params: address, amount, feeRate

final psbt =  await BdkFlutter().createTx(   recipient: 'tb1qhmk3ftsyctxf2st2fwnprwc0gl708f685t0j3t', 
					     amount: 2000, 
				             feeRate: 1
			                 );

Returned response example:

 'cHNidP8BAHQBAAAAAWxkL9CW6cpdkjO2eie+MXCxnvjL/Kemjmi2bnna1e+wAQAAAAD/////AlACAAAAAAAAFgAUmz1p6HT0uW0bDRhmY1sL92YbdtawBAAAAAAAABl2qRQ0Sg9IyhUOwrkDgXZgubaLE6ZwJoisAAAAAAABAOEBAAAAAAEBTevYyZI0SDB417CFQMW87Z8YkrBtdkrHIqfn5GAxH98BAAAAAP////8CsAQAAAAAAAAZdqkUNEoPSMoVDsK5A4F2YLm2ixOmcCaIrJAHAAAAAAAAFgAUMrIFB4W5c6b7/yiu+ph/N1JI5iwCRzBEAiBx5CL5kk4rvqInQ76atWwb+lUh/WcMPLZPLZirBLjgCQIgWLy2yuubrGDdMpg1/PUangucUxlVY3mzYSsBBPW6pigBIQLntzCxsOIpzhQe7I5rV+gEW0iJXUrnryU8gAa8sOOjtwAAAAABAR+QBwAAAAAAABYAFDKyBQeFuXOm+/8orvqYfzdSSOYsIgYCfoT0VFzm9d47mVZJ5kJn0/PSMZ6WedD5r9Q9TseuyvgY2R5q3VQAAIABAACAAAAAgAEAAAASAAAAACICA3+RBKNCI5Ev2vzb2+iGZ2+ODuqxgIxi5xRTEtobkC8tGNkeat1UAACAAQAAgAAAAIABAAAAGAAAAAAA', // psbt id
 

signTx()

Signs a bitcoin transaction with the associated private key as per the descriptor used to create the wallet. The method accepts an unsigned Partially Signed Bitcoin Transaction(psbt) and returns a signed psbt.
Required params: psbt (Partially Signed Bitcoin Transaction)

final psbt = 'cHNidP8BAHQBAAAAAWxkL9CW6cpdkjO2eie+MXCxnvjL/Kemjmi2bnna1e+wAQAAAAD/////AlACAAAAAAAAFgAUmz1p6HT0uW0bDRhmY1sL92YbdtawBAAAAAAAABl2qRQ0Sg9IyhUOwrkDgXZgubaLE6ZwJoisAAAAAAABAOEBAAAAAAEBTevYyZI0SDB417CFQMW87Z8YkrBtdkrHIqfn5GAxH98BAAAAAP////8CsAQAAAAAAAAZdqkUNEoPSMoVDsK5A4F2YLm2ixOmcCaIrJAHAAAAAAAAFgAUMrIFB4W5c6b7/yiu+ph/N1JI5iwCRzBEAiBx5CL5kk4rvqInQ76atWwb+lUh/WcMPLZPLZirBLjgCQIgWLy2yuubrGDdMpg1/PUangucUxlVY3mzYSsBBPW6pigBIQLntzCxsOIpzhQe7I5rV+gEW0iJXUrnryU8gAa8sOOjtwAAAAABAR+QBwAAAAAAABYAFDKyBQeFuXOm+/8orvqYfzdSSOYsIgYCfoT0VFzm9d47mVZJ5kJn0/PSMZ6WedD5r9Q9TseuyvgY2R5q3VQAAIABAACAAAAAgAEAAAASAAAAACICA3+RBKNCI5Ev2vzb2+iGZ2+ODuqxgIxi5xRTEtobkC8tGNkeat1UAACAAQAAgAAAAIABAAAAGAAAAAAA'; // psbt id from createPartiallySignedTransaction()

final response = await BdkFlutter().signTx(psbt:psbt);

Returned response example:

"cHNidP8BAHQBAAAAAWO9QVybfmhTpK6qzTVcf9yeiui/a0iNmTgljuw29UeQAQAAAAD+////AsUwEwAAAAAAFgAUbNeMOfAF9QTOiFfrlhV8bQnXWVnoAwAAAAAAABl2qRQ0Sg9IyhUOwrkDgXZgubaLE6ZwJois4NYjAAABAOEBAAAAAAEBHIAjDPiXGopfbzyQGDCQ/UjKxT2rhurl5iYZWIrY0ycAAAAAAP7///8C6AMAAAAAAAAZdqkUNEoPSMoVDsK5A4F2YLm2ixOmcCaIrD01EwAAAAAAFgAUHjTI1PY9tTZPado27T8PTGITvIUCRzBEAiA/C1zSpBrEZkgHwt1sfcadj13OUruw6eofeOVk2aHhUAIgLf/sYhD3kv8+nZrM5atuyYwKXCMDuNBPldaO2FQpxBUBIQPCWh5gAGcSYqmTy9aVpFb96u5Sgp+hjs/JDg+6SgKqVeDWIwABAR89NRMAAAAAABYAFB40yNT2PbU2T2naNu0/D0xiE7yFIgYChXdsXDGO5LXjWfyh3rRkTZzfPDbWmBBZHSKDesNSrggU2R5q3VQAAIAAAACAAQAAgD0AAAABBwABCGsCRzBEAiAo6eGvjAWQdyefCuSphc8FJewM9BZzgOhXJW9Uf+hQfAIgVvNJ6D7YC+MSqS01aMiTZ+0T2NJlXZLJFCBl585wescBIQKFd2xcMY7kteNZ/KHetGRNnN88NtaYEFkdIoN6w1KuCAAiAgKX6sfAUUzaIV9h3amzY+Wnxalxmi9T6lZZ76CBlWjB5RTZHmrdVAAAgAAAAIABAACAPgAAAAAA" //  sbt ( Signed Bitcoin Transaction)
  

broadcastTx()

Broadcasts a signed bitcoin transaction to the bitcoin network. The transaction is sent to the bitcoin node associated with the blockchain config that was used to create the wallet. The method accepts a signed bitcoin transaction. The psbt returned by signTx can be passed to broadcastTx().
Required params: sbt ( Signed Bitcoin Transaction)

final sbt = 'cHNidP8BAHQBAAAAAWO9QVybfmhTpK6qzTVcf9yeiui/a0iNmTgljuw29UeQAQAAAAD+////AsUwEwAAAAAAFgAUbNeMOfAF9QTOiFfrlhV8bQnXWVnoAwAAAAAAABl2qRQ0Sg9IyhUOwrkDgXZgubaLE6ZwJois4NYjAAABAOEBAAAAAAEBHIAjDPiXGopfbzyQGDCQ/UjKxT2rhurl5iYZWIrY0ycAAAAAAP7///8C6AMAAAAAAAAZdqkUNEoPSMoVDsK5A4F2YLm2ixOmcCaIrD01EwAAAAAAFgAUHjTI1PY9tTZPado27T8PTGITvIUCRzBEAiA/C1zSpBrEZkgHwt1sfcadj13OUruw6eofeOVk2aHhUAIgLf/sYhD3kv8+nZrM5atuyYwKXCMDuNBPldaO2FQpxBUBIQPCWh5gAGcSYqmTy9aVpFb96u5Sgp+hjs/JDg+6SgKqVeDWIwABAR89NRMAAAAAABYAFB40yNT2PbU2T2naNu0/D0xiE7yFIgYChXdsXDGO5LXjWfyh3rRkTZzfPDbWmBBZHSKDesNSrggU2R5q3VQAAIAAAACAAQAAgD0AAAABBwABCGsCRzBEAiAo6eGvjAWQdyefCuSphc8FJewM9BZzgOhXJW9Uf+hQfAIgVvNJ6D7YC+MSqS01aMiTZ+0T2NJlXZLJFCBl585wescBIQKFd2xcMY7kteNZ/KHetGRNnN88NtaYEFkdIoN6w1KuCAAiAgKX6sfAUUzaIV9h3amzY+Wnxalxmi9T6lZZ76CBlWjB5RTZHmrdVAAAgAAAAIABAACAPgAAAAAA'; // psbt id from createPartiallySignedTransaction()

final response = await BdkFlutter().broadcastTx(sbt:sbt);

Returned response example:

  
  "9b5ecd0ee3846a891201f3c59a484fe73501d845c20b05d63c45ec92bc2c16b3", // transaction id
 

quickSend()

Creates a Partially Signed Bitcoin Transaction, Signs the transaction, and Broadcasts to the given address.
.
Required params: address, amount, feeRate

final response = await BdkFlutter().quickSend( recipient: 'tb1qhmk3ftsyctxf2st2fwnprwc0gl708f685t0j3t', 
					       amount: 2000, 
					       feeRate: 1
					    );

Returned response example:

 "9b5ecd0ee3846a891201f3c59a484fe73501d845c20b05d63c45ec92bc2c16b3", // transaction id
 

Note: Caution this is pre-Alpha at this stage Please consider reviewing, experimenting, and contributing ⚡️

Thanks for taking a look!