Giter VIP home page Giter VIP logo

horizontalsystems / bitcoin-kit-ios Goto Github PK

View Code? Open in Web Editor NEW
241.0 14.0 72.0 30.19 MB

Comprehensive Bitcoin development library for iOS, implemented on Swift. SPV wallet implementation for Bitcoin, Bitcoin Cash, Litecoin and Dash blockchains. Comprehensive Bitcoin development library for iOS, implemented on Swift. SPV wallet implementation for Bitcoin, Bitcoin Cash, Litecoin and Dash blockchains. Fully compliant with existing standards and BIPs.

Home Page: https://unstoppable.money

License: MIT License

Ruby 0.72% Swift 99.28%
bitcoin bitcoin-wallet swift spv bitcoin-cash ios btc hd-wallet blockchain-wallet p2p

bitcoin-kit-ios's Introduction

BitcoinKit-iOS

Bitcoin, BitcoinCash(ABC) and Dash wallet toolkit for Swift. This is a full implementation of SPV node including wallet creation/restore, synchronization with network, send/receive transactions, and more. The repository includes the main BitcoinCore.swift and BitcoinKit.swift, BitcoinCashKit.swift and DashKit.swift separate pods.

Features

  • Full SPV implementation for fast mobile performance
  • Send/Receive Legacy transactions (P2PKH, P2PK, P2SH)
  • 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

BitcoinKit.swift

  • Send/Receive Segwit transactions (P2WPKH)
  • Send/Receive Segwit transactions compatible with legacy wallets (P2WPKH-SH)
  • base58, bech32

BitcoinCashKit.swift

  • bech32 cashaddr addresses

DashKit.swift

  • Instant send
  • LLMQ lock, Masternodes validation

Usage

On this page, we'll use Kits to refer to one of BitcoinKit.swift, BitcoinCashKit.swift and DashKit.swift kits.

Initialization

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

let words = ["word1", ... , "word12"]

Bitcoin

let bitcoinKit = BitcoinKit(withWords: words, walletId: "bitcoin-wallet-id", syncMode: .api, networkType: .mainNet)

Bitcoin Cash

let bitcoinCashKit = BitcoinCashKit(withWords: words, walletId: "bitcoin-cash-wallet-id", syncMode: .api, networkType: .mainNet)

Dash

let dashKit = DashKit(withWords: words, walletId: "dash-wallet-id", syncMode: .api, networkType: .mainNet)

All 3 Kits can be configured to work in .mainNet or .testNet.

syncMode parameter

Kits can restore existing wallet or create a new one. When restoring, it generates addresses for given wallet according to bip44 protocol, then it pulls all historical transactions for each of those addresses. This is done only once on initial sync. syncMode parameter defines where it pulls historical transactions from. When they are pulled, it continues to sync according to SPV protocol no matter which syncMode was used for initial sync. There are 3 modes available:

  • .full: Fully synchronizes from peer-to-peer network starting from the block when bip44 was introduced. This mode is the most private (since it fully complies with SPV protocol), but it takes approximately 2 hours to sync up to now (June 10, 2019).
  • .api: Transactions before checkpoint are pulled from API(currently Insight API or BcoinAPI). Then the rest is synchronized from peer-to-peer network. This is the fastest one, but it's possible for an attacker to learn which addresses you own. Checkpoints are updated with each new release and hardcoded so the blocks validation is not broken.
  • .newWallet: No need to pull transactions.
Additional parameters:
  • confirmationsThreshold: Minimum number of confirmations required for an unspent output in incoming transaction to be spent (default: 6)
  • minLogLevel: Can be configured for debug purposes if required.

Starting and Stopping

Kits require 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()

Getting wallet data

Kits hold all kinds of data obtained from and needed for working with blockchain network

Current Balance

Balance is provided in Satoshi:

bitcoinKit.balance

// 2937096768

Last Block Info

Last block info contains headerHash, height and timestamp that can be used for displaying sync info to user:

bitcoinKit.lastBlockInfo 

// ▿ Optional<BlockInfo>
//  ▿ some : BlockInfo
//    - headerHash : //"00000000000041ae2164b486398415cca902a41214cad72291ee04b212bed4c4"
//    - height : 1446751
//    ▿ timestamp : Optional<Int>
//      - some : 1544097931

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

// "mgv1KTzGZby57K5EngZVaPdPtphPmEWjiS"

Transactions

Kits have transactions(fromHash: nil, limit: nil) methods which return Single<TransactionInfo>(for BitcoinKit and BitcoinCashKit) and Single<DashTransactionInfo>(for DashKit) RX Single Observers.

TransactionInfo:

//   ▿ TransactionInfo
//     - transactionHash : "0f83c9b330f936dc4a2458b7d3bb06dce6647a521bf6d98f9c9d3cdd5f6d2a73"
//     - transactionIndex : 500000
//     ▿ from : 2 elements
//       ▿ 0 : TransactionAddressInfo
//         - address : "mft8jpnf3XwwqhaYSYMSXePFN85mGU4oBd"
//         - mine : true
//       ▿ 1 : TransactionAddressInfo
//         - address : "mnNS5LEQDnYC2xqT12MnQmcuSvhfpem8gt"
//         - mine : true
//     ▿ to : 2 elements
//       ▿ 0 : TransactionAddressInfo
//         - address : "n43efNftHQ1cXYMZK4Dc53wgR6XgzZHGjs"
//         - mine : false
//       ▿ 1 : TransactionAddressInfo
//         - address : "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY"
//         - mine : true
//     - amount : -800378
//     ▿ blockHeight : Optional<Int>
//       - some : 1446602
//    ▿ timestamp : Optional<Int>
//       - some : 1543995972

DashTransactionInfo:

//   ▿ DashTransactionInfo
//     - transactionHash : "0f83c9b330f936dc4a2458b7d3bb06dce6647a521bf6d98f9c9d3cdd5f6d2a73"
//     - transactionIndex : 500000
//     - instantTx : true
//     ▿ from : 2 elements
//       ▿ 0 : TransactionAddressInfo
//         - address : "mft8jpnf3XwwqhaYSYMSXePFN85mGU4oBd"
//         - mine : true
//       ▿ 1 : TransactionAddressInfo
//         - address : "mnNS5LEQDnYC2xqT12MnQmcuSvhfpem8gt"
//         - mine : true
//     ▿ to : 2 elements
//       ▿ 0 : TransactionAddressInfo
//         - address : "n43efNftHQ1cXYMZK4Dc53wgR6XgzZHGjs"
//         - mine : false
//       ▿ 1 : TransactionAddressInfo
//         - address : "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY"
//         - mine : true
//     - amount : -800378
//     ▿ blockHeight : Optional<Int>
//       - some : 1446602
//    ▿ timestamp : Optional<Int>
//       - some : 1543995972

Creating new transaction

In order to create new transaction, call send(to: String, value: Int, feeRate: Int) method on Kits

try bitcoinKit.send(to: "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY", value: 1000000, feeRate: 10000)

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.

Validating transaction before send

One can validate address and fee by using following methods:

try bitcoinKit.validate(address: "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY")
try bitcoinKit.fee(for: 1000000, toAddress: "mrjQyzbX9SiJxRC2mQhT4LvxFEmt9KEeRY", senderPay: true, feeRate: 10000)

senderPay parameter defines who pays the fee

Parsing BIP21 URI

You can use parse method to parse a BIP21 URI:

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

// ▿ BitcoinPaymentData
//   - address : "175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"
//   - version : nil
//   ▿ amount : Optional<Double>
//     - some : 50.0
//   ▿ label : Optional<String>
//     - some : "Luke-Jr"
//   ▿ message : Optional<String>
//     - some : "Donation for project xyz"
//   - parameters : nil

Subscribing to BitcoinKit data

Kits provide with data like transactions, blocks, balance, kits state in real-time. BitcoinCoreDelegate protocol must be implemented and set to Kits instance to receive that data.

class Manager {

	init(words: [String]) {
		bitcoinKit = BitcoinKit(withWords: words, walletId: "bitcoin-wallet-id")
        bitcoinKit.delegate = self
    }

}

extension Manager: BitcoinCoreDelegate {

    func transactionsUpdated(inserted: [TransactionInfo], updated: [TransactionInfo]) {
    }

    func transactionsDeleted(hashes: [String]) {
    }

    func balanceUpdated(balance: Int) {
    }

    func lastBlockInfoUpdated(lastBlockInfo: BlockInfo) {
    }

    public func kitStateUpdated(state: BitcoinCore.KitState) {
		// BitcoinCore.KitState can be one of 3 following states:
		// .synced
		// .syncing(progress: Double)
		// .notSynced
		// 
		// These states can be used to implement progress bar, etc
    }
    
}

Listener events are run in a dedicated background thread. It can be switched to main thread by setting the delegateQueue property to DispatchQueue.main

bitcoinKit.delegateQueue = DispatchQueue.main

Prerequisites

  • Xcode 10.0+
  • Swift 5+
  • iOS 11+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.5.0+ is required to build BitcoinKit.

To integrate BitcoinKit into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your Target Name>' do
  pod 'BitcoinCore.swift'
  pod 'BitcoinKit.swift'
  pod 'BitcoinCashKit.swift'
  pod 'DashKit.swift'
end

Then, run the following command:

$ pod install

Example Project

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

Dependencies

Dash dependencies

License

The BitcoinKit-iOS toolkit is open source and available under the terms of the MIT License.

bitcoin-kit-ios's People

Contributors

ant013 avatar ealymbaev avatar esen avatar esengulov avatar mnizhurin avatar rex4539 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitcoin-kit-ios's Issues

Encapsulate all internal models and logic for WalletKit library

  • RealmResults should not be public for transactions and unspent outputs. Simple TransactionInfo structure should be public.
  • balance should be fetched simply through Int value.
  • all changes should be observed via delegate protocol (realm observers and rx subject should not be used)
  • only WalletKit should be public and have public methods.

Refactor PeerGroup and Peer classes using PeerTask's

  • Create new PeerTask class for abstracting all app related tasks that are performed by Peers.
  • PeerGroup is responsible for creating new PeerTasks and distributing them among ready peers.
  • Also all peers should be assigned as "sync peer" one by one as they are ready.
  • PeerGroup should request header hashes and unsynced block hashes from its delegate in order to be able to create tasks.

BloomFilter optimization

Currently, our peers don't send transactions sending our P2PK outputs. Because, there's nothing matching our PKH/PK in their inputs. For this, FilterLoad message has a nFlag attribute. We should set it to 2 in order for peers to automatically update bloom filter with COutPoints of matched P2PK outputs.

This and this(#94 ) tickets gradually pollute the bloom filter. That's why we should track the false positives ratio and clear/reset bloom filter when that ratio raises

PeerGroup Windowed Download

PeerGroup should download blocks by "windows". Window means that it should concurrently download blocks in a range and provide it to app.
Application on the other hand - should request to download blocks by serial windows.

Peer Discovery is stuck if any dns is not responding

When discovering new peers for several dns seeds - if any seed will not respond or respond slowly - all peer discovery process is stuck.
Dns seeds should report their discovery results independently from each other.

Implement Fork Handler

Now HeaderHandler rejects all block headers that are not in its chain.
Instead it should check incoming block headers for the case of fork. If incoming headers are more "valid" than the chain on our database - it should replace it.

Block Validator is slow

BlockValidator's performance is quite bad. It should be revised and refactored to work faster.

Rethink usage of all DispatchQueue QOS params

Now all sync and handler jobs use DispatchQueues with qos = .background.
This is not quite correct because some tasks require more priority to make syncing of blockchain faster.
Every DispatchQueue in the app should be reviewed and correct qos should be selected.

Implement resending transactions on app restart.

Transactions are now can be sent only in "real-time". This means that in order for them to be sent successfully we should have started PeerGroup and connected Peers.
We should handle resending transactions when PeerGroup is ready and on app restart as well.

Process transactions in order

Current transaction parsing logic is developed for parsing them in random order.
After #83 - all blocks (and their transactions) are downloaded in order. So transaction parsing logic can be simplified according top this changes.

Update WalletKitPrivate class with swift implementation available in BitcoinKit

Currently there are files Crypto/WalletKitPrivate.m and Crypto/WalletKitPrivate.h which are swift implementations of some cryptographic algorithms used in bitcoin. Sometimes we get exceptions in Crypto/WalletKitPrivate.m#43 saying that key variable is NULL.

There's a new swift implementation available in BitcoinKit. Let's try to use them.

ProgressSyncer should report current sync session progress

Now ProgressSyncer reports progress calculated for all blocks in database (synced/non synced).
For the first sync session it shows correct progress, but for later sync sessions it shows incorrect progress.
We should get the last synced block in database and fetch the last block height from sync peer and calculate progress according to this data.

Clear database after full sync

After downloading and parsing all transactions - we can remove all transactions that are not related to our wallet. (they were downloaded by bloom filter false positive rate).
After removing transactions we can also remove all blocks that have no transactions, except the blocks that are required for blockchain validation (2016 last blocks usually).

Some transactions from TestNet are marked as "invalid"

It happens because TransactionExtractor cannot extract any data from a transaction.
It is incorrect behavior, because we should handle all transaction, even if we were not able to extract any "pubic key" or "address" data from it.

Update WalletKitPrivate class with swift implementation available in BitcoinKit

Currently there are files Crypto/WalletKitPrivate.m and Crypto/WalletKitPrivate.h which are swift implementations of some cryptographic algorithms used in bitcoin. Sometimes we get exceptions in Crypto/WalletKitPrivate.m#43 saying that key variable is NULL.

There's a new swift implementation available in BitcoinKit. Let's try to use them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.