Skip to content
Full SPV wallet toolkit implementation for Bitcoin and Bitcoin Cash protocols. Implemented on Kotlin.
Branch: master
Clone or download
abdrasulov Merge pull request #253 from horizontalsystems/sync
Correctly check relayed transactions for existence
Latest commit 3496bbb Mar 19, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
app Extract BitcoinKit creation to separate class Builder (#246) Mar 18, 2019
bitcoinkit
gradle/wrapper
.gitignore Add sample app Sep 3, 2018
LICENSE add license to repository Sep 12, 2018
README.md
build.gradle Update kotlin version Mar 13, 2019
gradle.properties
gradlew
gradlew.bat Add sample app Sep 3, 2018
settings.gradle Rename module name Oct 18, 2018

README.md

BitcoinKit

Bitcoin and Bitcoin Cash(ABC) SPV wallet toolkit implemented in Kotlin. This is a full implementation of SPV node including wallet creation/restore, syncronzation with network, send/receive transactions, and more.

Features

  • Full SPV implementation for fast mobile performance
  • Send/Receive Legacy transactions (P2PKH, P2PK, P2SH)
  • Send/Receive Segwit transactions (P2WPKH)
  • Send/Receive Segwit transactions compatible with legacy wallets (P2WPKH-SH)
  • Fee calculation depending on wether sender pays the fee or receiver
  • Encoding/Decoding of base58, bech32, cashaddr addresses
  • BIP32 hierarchical deterministic wallets implementation.
  • BIP39 mnemonic code for generating deterministic keys.
  • BIP44 multi-account hierarchy for deterministic wallets.
  • BIP21 URI schemes, which include payment address, amount, label and other params
  • Real-time fee rates

Usage

Initialization

BitcoinKit requires you to provide mnemonic phrase when it is initialized:

val words = listOf("skill", ..., "century")

Bitcoin

val bitcoinKit = BitcoinKit(words, BitcoinKit.NetworkType.MainNet)

Bitcoin Cash

val bitCashKit = BitcoinKit(words, BitcoinKit.NetworkType.MainNetBitCash)

Both networks can be configured to work in MainNet or TestNet

Additional parameters:
  • peerSize: Can be configured for number of peers to be connected (default: 10)
  • confirmationsThreshold: Minimum number of confirmations required for an unspent output in incoming transaction to be spent (default: 6)

Starting and Stopping

BitcoinKit requires to be started with start command, but does not need to be stopped. It will be in synced state as long as it is possible:

bitcoinKit.start()

Clearing data from device

BitcoinKit uses internal database for storing data fetched from blockchain. The clear command can be used to stop and clean all stored data:

bitcoinKit.clear()

Getting wallet data

BitcoinKit holds all kinds of data obtained from and needed for working with blockchain network

Current Balance

Balance is provided in Satoshi:

bitcoinKit.balance
// 2937096768

Receive Address

Get an address which you can receive coins to. Receive address is changed each time after you actually get a transaction in which you receive coins to that address

bitcoinKit.receiveAddress()
// mfu3iYeZuh18uuN4CrGYz34HSMynZBgZyg

Transactions

You can get all your transactions as follows:

bitcoinKit.transactions

TransactionInfo(
    transactionHash=baede6420b4b2869cba87d768a7b4e2eef2a9899149f24c5c3d3ff66b8ad1405,
    from=[TransactionAddress(address=my1ysPMHdeQD6kwnimipbvFrr5NRHDvNgz, mine=false)],
    to=[
        TransactionAddress(address=moyrWfrks5EsHLb2hqUr8nUnC9q9DYXMtK, mine=true),
        TransactionAddress(address=2NDk1BuuKnbVqDAMVgGr6xurnctfaQVxFoN, mine=false)
    ],
    amount=32500000,
    blockHeight=1316822,
    timestamp=1527595501
  ),
  TransactionInfo(
    transactionHash=60ff9d204c17e0e71a1fd2d3f60b1bada5573857691d30d7518311057cc75720, 
    from=[
        TransactionAddress(address=mtmnfGuW4e5RbC64r3vx2qFhS3pobf57Ty, mine=false)
    ], 
    to=[
        TransactionAddress(address=mt59yxihUxy117RPQuEVQ7QSRuHJnRT4fG, mine=true), 
        TransactionAddress(address=2NAn7FBKvMFWteiHKSDDBudUP4vPwiBfVkr, mine=false)
    ], 
    amount=16250000, 
    blockHeight=1316823, 
    timestamp=1527595771
)
...

Sending new transaction

In order to create new transaction, call send(address: String, value: Int, senderPay: Boolean = true) method on BitcoinKit

  • senderPay: parameter defines who pays the fee
bitcoinKit.send("mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY", 1000000)

This function first validates a given address and amount, creates new transaction, then sends it over the peers network. If there's any error with given address/amount or network, it raises an exception.

Validating transaction before send

One can validate address and fee by using following methods:

bitcoinKit.validate(address = "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY")
bitcoinKit.fee(value = 1000000, address = "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY", senderPay: true)
  • senderPay: parameter defines who pays the fee

Parsing BIP21 URI

You can use parsePaymentAddress method to parse a BIP21 URI:

bitcoinKit.parsePaymentAddress("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=50&label=Luke-Jr&message=Donation%20for%20project%20xyz")

BitcoinPaymentData(
  address=175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W, 
  version=null, 
  amount=50.0,
  label=Luke-Jr,
  message=Donation for project xyz,
  parameters=null
)

Subscribing to BitcoinKit data

BitcoinKit provides with data like transactions, blocks, balance, kitState in real-time. BitcoinKit.Listener interface must be implemented and set to BitcoinKit instance to receive that data.

class MainViewModel : ViewModel(), BitcoinKit.Listener {

    private var bitcoinKit: BitcoinKit
    ...
    
    init {
        bitcoinKit = BitcoinKit(words, BitcoinKit.NetworkType.TestNet)
        bitcoinKit.listener = this
    }
    
    override fun onTransactionsUpdate(bitcoinKit: BitcoinKit, inserted: List<TransactionInfo>, updated: List<TransactionInfo>) {
        // do something with transactions
    }

    override fun onTransactionsDelete(hashes: List<String>) {
        // do something with transactions
    }

    override fun onBalanceUpdate(bitcoinKit: BitcoinKit, balance: Long) {
        // do something with balance
    }

    override fun onLastBlockInfoUpdate(bitcoinKit: BitcoinKit, blockInfo: BlockInfo) {
        // do something with blockInfo
    }

    override fun onKitStateUpdate(bitcoinKit: BitcoinKit, state: KitState) {
        // These states can be used to implement progress bar, etc
        when (state) {
            is KitState.Synced -> {

            }
            is KitState.Syncing -> {
                // val progress: Double = state.progress
            }
            is KitState.NotSynced -> {
                
            }
        }
    }
}

Listener events are run in a dedicated background thread. It can be switched to main thread by setting the listenerExecutor property to MainThreadExecutor()

bitcoinKit.listenerExecutor = MainThreadExecutor()

Prerequisites

  • JDK >= 1.8
  • Android 6 (minSdkVersion 23) or greater

Installation

Add the JitPack to module build.gradle

repositories {
    maven { url 'https://jitpack.io' }
}

Add the following dependency to your build.gradle file:

dependencies {
    implementation 'com.github.horizontalsystems:bitcoin-kit-android:master-SNAPSHOT'
}

Example App

All features of the library are used in example project. It can be referred as a starting point for usage of the library.

Dependencies

  • HDWalletKit - HD Wallet related features, mnemonic phrase

License

The BitcoinKit is open source and available under the terms of the MIT License

You can’t perform that action at this time.