horizontalsystems /
BitcoinCore.Swift
Comprehensive Bitcoin development library for iOS, implemented on Swift.
58/100 healthLoading repository data…
horizontalsystems / repository
Comprehensive Bitcoin development library for Android, implemented on Kotlin. SPV wallet implementation for Bitcoin, Bitcoin Cash, Litecoin and Dash blockchains. Fully compliant with existing standards and BIPs.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
bitcoin-kit-android is a Bitcoin wallet toolkit implemented in Kotlin. It consists of following libraries:
bitcoincore is a core library that implements a full Simplified Payment Verification (SPV) client in Kotlin. It implements Bitcoin P2P Protocol and can be extended to be a client of other Bitcoin forks like BitcoinCash, Litecoin, etc.bitcoinkit extends bitcoincore, makes it usable with Bitcoin network.bitcoincashkit extends bitcoincore, makes it usable with BitcoinCash(ABC) network.litecoinkit extends bitcoincore, makes it usable with Litecoin network.dashkit extends bitcoincore, makes it usable with Dash network.hodler is a plugin for bitcoincore, that makes it possible to lock certain amount of coins until some time in the future.Being an SPV client, bitcoincore downloads and validates all the block headers, inclusion of transactions in the blocks, integrity and immutability of transactions as described in the Bitcoin whitepaper or delegates validation to the extensions that implement the forks of Bitcoin.
P2PK, P2PKH, P2SH-P2WPKH, P2WPKH outputs support.Watch account unable to spend funds)Selected from shared topics, language and repository description—not editorial ratings.
horizontalsystems /
Comprehensive Bitcoin development library for iOS, implemented on Swift.
58/100 healthFirst, you need an instance of BitcoinKit class. You can initialize it with Mnemonic seed or BIP32 extended key (private or public). To generate seed from mnemonic seed phrase you can use HdWalletKit to convert a word list to a seed.
val words = listOf("mnemonic", "phrase", "words")
val passphrase: String = ""
val seed = Mnemonic().toSeed(words, passphrase)
Then you can pass a seed to initialize an instance of BitcoinKit
val context = Application()
val bitcoinKit = BitcoinKit(
context = context,
seed = seed,
walletId = "unique_wallet_id",
syncMode = BitcoinCore.SyncMode.Api(),
networkType = NetworkType.MainNet,
confirmationsThreshold = 6,
purpose = HDWallet.Purpose.BIP84
)
purposebitcoinkit supports BIP44, BIP49 and BIP84 wallets. They have different derivation paths, so you need to specify this on kit initialization.
syncModebitcoinkit pulls all historical transactions of given account from bitcoin peers according to SPV protocol. This process may take several hours as it needs to download every block header with some transactions to find transactions concerning the accounts addresses. In order to speed up the initial blockchain scan, bitcoincore has some optimization options:
It doesn't download blocks added before the BIP44 was implemented by wallets, because there were no transactions concerning addresses generated by BIP44 wallets.
If you set API() or NewWallet() to syncMode parameter, it first requests from an API(currently Blockchain.com) the hashes of the blocks where there are transactions we need. Then, it downloads those blocks from the bitcoin peers. This reduces the initial synchronization time to several minutes. This also carries some risks that makes it possible for a middle-man attacker to learn about the addresses requested from your IP address. But your funds are totally safe.
If you set Full() to syncMode, then only decentralized peers are used. Once the initial blockchain scan is completed, the remaining synchronization works with decentralized peers only for all syncModes.
networkType: Mainnet or TestnetconfirmationsThreshold: Minimum number of confirmations required for an unspent output to be available for use (default: 6)You can initialize BitcoinKit using BIP32 Extended Private/Public Key as follows:
val extendedKey = HDExtendedKey("xprvA1BgyAq84AiAsrMm6DKqwCXDwxLBXq76dpUfuNXNziGMzDxYLjE9AkuYBAQTpt6aJu4nFYamh6BbrRkys5fJcxGd7qixNrpVpPBxui9oYyF")
val bitcoinKit = BitcoinKit(
context = context,
extendedKey = extendedKey,
walletId = "unique_wallet_id",
syncMode = BitcoinCore.SyncMode.Api(),
networkType = NetworkType.MainNet,
confirmationsThreshold = 6
)
If you restore with a public extended key, then you only will be able to watch the wallet. You won't be able to send any transactions. This is how the watch account feature is implemented.
BitcoinKit requires to be started with start command. It will be in synced state as long as it is possible. You can call stop to stop it
bitcoinKit.start()
bitcoinKit.stop()
Balance is provided in Satoshis:
val balance = bitcoinKit.balance
println(balance.spendable)
println(balance.unspendable)
Unspendable balance is non-zero if you have UTXO that is currently not spendable due to some custom unlock script. These custom scripts can be implemented as a plugin, like Hodler
val blockInfo = bitcoinKit.lastBlockInfo ?: return
println(blockInfo.headerHash)
println(blockInfo.height)
println(blockInfo.timestamp)
Get an address which you can receive coins to. Receive address is changed each time after you actually get some coins in that address
bitcoinKit.receiveAddress() // "mgv1KTzGZby57K5EngZVaPdPtphPmEWjiS"
You can get your transactions using transactions(fromUid: String? = null, type: TransactionFilterType? = null, limit: Int? = null) method of the BitcoinKit instance. It returns Single<List>. You'll need to subscribe and get transactions asynchronously. See RX Single Observers for more info.
val disposables = CompositeDisposable()
bitcoinKit.transactions().subscribe { transactionInfos ->
for (transactionInfo in transactionInfos) {
println("Uid: ${transactionInfo.uid}")
println("Hash: ${transactionInfo.transactionHash}")
}
}.let {
disposables.add(it)
}
fromUid and limit parameters can be used for pagination.type parameter enables to filter transactions by coins flow. You can pass incoming OR outgoing to get filtered transactionsA sample dump:
// transactionInfo = {TransactionInfo}
// amount = 13114
// blockHeight = 740024
// conflictingTxHash = null
// fee = null
// inputs = {ArrayList} size = 1
// 0 = {TransactionInputInfo}
// address = "16s6q8dAgLbDT3szEc4nvTh81deRCBtEa1"
// mine = false
// value = null
// outputs = {ArrayList} size = 2
// 0 = {TransactionOutputInfo}
// address = "bc1qsg9ul383f8pespcvc8u3katl6gnsr7sjyfe3pc"
// changeOutput = false
// mine = true
// pluginData = null
// pluginDataString = null
// pluginId = null
// value = 13114
// 1 = {TransactionOutputInfo}
// address = "16VCm8mYhHE3EiELi8GiYEqAjnPu1TSgAV"
// changeOutput = false
// mine = false
// pluginData = null
// pluginDataString = null
// pluginId = null
// value = 1422
// status = {TransactionStatus} RELAYED
// timestamp = 1654766137
// transactionHash = "cadf99db1e145dcfadfa2bc3eacb94831eb6c53d376f4f873aa4ac017b8c7f8f"
// transactionIndex = 2760
// type = {TransactionType} Incoming
// uid = "75934663-3c84-4b38-9b6d-810d3433de17"
uid
A local unique ID
type
status
bitcoinKit.send(address = "36k1UofZ2iP2NYax9znDCsksajfKeKLLMJ", value = 100000000, feeRate = 10, sortType = TransactionDataSortType.Bip69)
This 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.
bitcoinKit.validateAddress(address = "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY")
bitcoinKit.fee(address = "36k1UofZ2iP2NYax9znDCsksajfKeKLLMJ", value = 100000000, feeRate = 10)
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
Balance, transactions, last blocks synced and kit state are available in real-time. BitcoinKit.Listener interface must be implemented and set to BitcoinKit instance to receive that.
class Manager(val bitcoinKit: BitcoinKit) : BitcoinKit.Listener {
init {
bitcoinKit.listener = this
}
override fun onBalanceUpdate(balance: BalanceInfo) {
}
override fun onLastBlockInfoUpdate(blockInfo: BlockInfo) {
}
override fun onKitStateUpdate(state: BitcoinCore.KitState) {
}
override fun onTransactionsUpdate(inserted: List<TransactionInfo>, updated: List<TransactionInfo>) {
}
override fun onTransactionsDelete(hashes: List<String>) {
}
}
Base58 and Bech32ASERT, DAA, EDA validationsBecause BitcoinCash is a fork of Bitcoin, the usage of this library does not differ much from bitcoinkit. So we only describe some differences between them.
All BitcoinCash wallets use default BIP44 derivation path where coinType is 145 according to SLIP44. But since it's a fork of Bitcoin, 0 coinType also can be restored.
val context = Application()
val seed = Mnemonic().toSeed(listOf("mnemonic", "phrase", "words"), "")
val bitcoinCashKit = BitcoinCashKit(
context = context,
seed = seed,
walletId = "unique_wallet_id",
syncMode = BitcoinCore.SyncMode.Api(),
networkType = NetworkType.MainNet(MainNetBitcoinCash.CoinType.Type145),
confirmationsThreshold = 6
)
Usage identical to bitcoinkit
val context = Application()
val seed = Mnemonic().toSeed(listOf("mnemonic", "phrase", "words"), "")
val dashKit = DashKit(
context = context,
seed = seed,
walletId = "unique_wa