Skip to content

Commit

Permalink
Merge pull request #225 from horizontalsystems/release-0.1.2
Browse files Browse the repository at this point in the history
Release 0.1.2
  • Loading branch information
rafaelekol committed Feb 13, 2019
2 parents 279f350 + 23332bd commit 56758ce
Show file tree
Hide file tree
Showing 62 changed files with 1,466 additions and 1,138 deletions.
7 changes: 7 additions & 0 deletions app/build.gradle
Expand Up @@ -18,6 +18,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
Expand All @@ -28,6 +32,9 @@ dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:27.1.1'

implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
kapt "android.arch.lifecycle:compiler:1.1.1"
Expand Down
Expand Up @@ -18,6 +18,7 @@ class BalanceFragment : Fragment() {
lateinit var lastBlockValue: TextView
lateinit var progressValue: TextView
lateinit var startButton: Button
lateinit var clearButton: Button
lateinit var buttonDebug: Button

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -70,12 +71,17 @@ class BalanceFragment : Fragment() {
lastBlockValue = view.findViewById(R.id.lastBlockValue)
progressValue = view.findViewById(R.id.progressValue)
startButton = view.findViewById(R.id.buttonStart)
clearButton = view.findViewById(R.id.buttonClear)
buttonDebug = view.findViewById(R.id.buttonDebug)

startButton.setOnClickListener {
viewModel.start()
}

clearButton.setOnClickListener {
viewModel.clear()
}

buttonDebug.setOnClickListener {
viewModel.showDebugInfo()
}
Expand Down
Expand Up @@ -6,6 +6,7 @@ import io.horizontalsystems.bitcoinkit.BitcoinKit
import io.horizontalsystems.bitcoinkit.BitcoinKit.KitState
import io.horizontalsystems.bitcoinkit.models.BlockInfo
import io.horizontalsystems.bitcoinkit.models.TransactionInfo
import io.reactivex.disposables.CompositeDisposable

class MainViewModel : ViewModel(), BitcoinKit.Listener {

Expand All @@ -19,6 +20,7 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {
val progress = MutableLiveData<Double>()
val status = MutableLiveData<State>()
val networkName: String
private val disposables = CompositeDisposable()

private var started = false
set(value) {
Expand All @@ -37,8 +39,14 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {

networkName = networkType.name
balance.value = bitcoinKit.balance
transactions.value = bitcoinKit.transactions.sortedBy { it.blockHeight?.times(-1) }
lastBlockHeight.value = bitcoinKit.lastBlockHeight

bitcoinKit.transactions().subscribe { txList: List<TransactionInfo> ->
transactions.value = txList.sortedByDescending { it.blockHeight }
}.let {
disposables.add(it)
}

lastBlockHeight.value = bitcoinKit.lastBlockInfo?.height ?: 0
progress.value = 0.0

started = false
Expand All @@ -51,15 +59,19 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {
bitcoinKit.start()
}

fun clear() {
bitcoinKit.clear()
}

fun receiveAddress(): String {
return bitcoinKit.receiveAddress()
}

fun send(address: String, amount: Int) {
fun send(address: String, amount: Long) {
bitcoinKit.send(address, amount)
}

fun fee(value: Int, address: String? = null): Int {
fun fee(value: Long, address: String? = null): Long {
return bitcoinKit.fee(value, address)
}

Expand All @@ -71,7 +83,11 @@ class MainViewModel : ViewModel(), BitcoinKit.Listener {
// BitcoinKit Listener implementations
//
override fun onTransactionsUpdate(bitcoinKit: BitcoinKit, inserted: List<TransactionInfo>, updated: List<TransactionInfo>, deleted: List<Int>) {
transactions.value = this.bitcoinKit.transactions.sortedBy { it.blockHeight?.times(-1) }
bitcoinKit.transactions().subscribe { txList: List<TransactionInfo> ->
transactions.value = txList.sortedByDescending { it.blockHeight }
}.let {
disposables.add(it)
}
}

override fun onBalanceUpdate(bitcoinKit: BitcoinKit, balance: Long) {
Expand Down
Expand Up @@ -66,15 +66,15 @@ class SendReceiveFragment : Fragment() {
private fun send() {
var message: String
try {
viewModel.send(sendAddress.text.toString(), sendAmount.text.toString().toInt())
viewModel.send(sendAddress.text.toString(), sendAmount.text.toString().toLong())
sendAmount.text = null
txFeeValue.text = null
sendAddress.text = null
message = "Transaction sent"
} catch (e: Exception) {
message = when (e) {
is UnspentOutputSelector.InsufficientUnspentOutputs,
is UnspentOutputSelector.EmptyUnspentOutputs -> "Insufficient balance"
is UnspentOutputSelector.Error.InsufficientUnspentOutputs,
is UnspentOutputSelector.Error.EmptyUnspentOutputs -> "Insufficient balance"
else -> e.message ?: "Failed to send transaction"
}
}
Expand All @@ -89,13 +89,12 @@ class SendReceiveFragment : Fragment() {
}

try {
val fee = viewModel.fee(
value = sendAmount.text.toString().toInt(),
txFeeValue.text = viewModel.fee(
value = sendAmount.text.toString().toLong(),
address = sendAddress.text.toString()
)

txFeeValue.text = fee.toString()
).toString()
} catch (e: Exception) {
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
}
}

Expand Down
Expand Up @@ -70,12 +70,9 @@ class ViewHolderTransaction(val containerView: View) : RecyclerView.ViewHolder(c
fun bind(transactionInfo: TransactionInfo, index: Int) {
containerView.setBackgroundColor(if (index % 2 == 0) Color.parseColor("#dddddd") else Color.TRANSPARENT)

val timeInMillis = transactionInfo.timestamp?.times(1000)
val timeInMillis = transactionInfo.timestamp.times(1000)

val date = when {
timeInMillis != null -> DateFormat.getInstance().format(Date(timeInMillis))
else -> "--"
}
val date = DateFormat.getInstance().format(Date(timeInMillis))

summary.text = "#$index" +
"\nFrom: ${transactionInfo.from.first().address}" +
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/layout/fragment_balance.xml
Expand Up @@ -104,4 +104,13 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lastBlockValue" />

<Button
android:id="@+id/buttonClear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Clear"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonStart" />

</android.support.constraint.ConstraintLayout>
13 changes: 10 additions & 3 deletions bitcoinkit/build.gradle
Expand Up @@ -10,7 +10,7 @@ android {
minSdkVersion 23
targetSdkVersion 28
versionCode 1
versionName "0.1.1"
versionName "0.1.2"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
Expand All @@ -33,6 +33,14 @@ android {
}

lintOptions { abortOnError false }

kotlinOptions {
jvmTarget = '1.8'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
Expand All @@ -43,12 +51,11 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

// For cryptocurrency
implementation 'org.bouncycastle:bcprov-jdk16:1.45'
implementation 'com.madgag.spongycastle:core:1.58.0.0'

implementation 'com.eclipsesource.minimal-json:minimal-json:0.9.5'

implementation 'com.github.horizontalsystems:hd-wallet-kit-android:1.0.0'
implementation 'com.github.horizontalsystems:hd-wallet-kit-android:a3666d8'

// Test helpers
testImplementation 'junit:junit:4.12'
Expand Down
Expand Up @@ -11,7 +11,7 @@ import io.horizontalsystems.bitcoinkit.models.*
import io.horizontalsystems.bitcoinkit.network.MainNet
import io.horizontalsystems.bitcoinkit.transactions.TransactionProcessor
import io.realm.Realm
import junit.framework.Assert
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
Expand Down Expand Up @@ -93,7 +93,7 @@ class BlockSyncerTest {

try {
blockSyncer.handleMerkleBlock(merkleBlock, 100)
Assert.fail("Expected exception")
fail("Expected exception")
} catch (e: BlockValidatorException.NoPreviousBlock) {
}
}
Expand Down Expand Up @@ -123,12 +123,12 @@ class BlockSyncerTest {

private fun assertBlockHashPresent(reversedHeaderHashHex: String, realm: Realm) {
val blockHash = realm.where(BlockHash::class.java).equalTo("reversedHeaderHashHex", reversedHeaderHashHex).findFirst()
Assert.assertNotNull(blockHash)
assertNotNull(blockHash)
}

private fun assertBlockHashNotPresent(reversedHeaderHashHex: String, realm: Realm) {
val blockHash = realm.where(BlockHash::class.java).equalTo("reversedHeaderHashHex", reversedHeaderHashHex).findFirst()
Assert.assertNull(blockHash)
assertNull(blockHash)
}

}
Expand Up @@ -7,7 +7,7 @@ import io.horizontalsystems.bitcoinkit.managers.BloomFilterManager
import io.horizontalsystems.bitcoinkit.models.BlockHash
import io.horizontalsystems.bitcoinkit.network.MainNet
import io.horizontalsystems.bitcoinkit.transactions.TransactionProcessor
import junit.framework.Assert
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
Expand Down Expand Up @@ -38,7 +38,7 @@ class BlockSyncerTest_localKnownBestBlockHeight {
fun localKnownBestBlockHeight_noBlockHashes() {
val expectedKnownBestBlockHeight = network.checkpointBlock.height

Assert.assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
}

@Test
Expand All @@ -50,7 +50,7 @@ class BlockSyncerTest_localKnownBestBlockHeight {
realm.insert(BlockHash(byteArrayOf(2), 0, 2))
}

Assert.assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
}

@Test
Expand All @@ -63,7 +63,7 @@ class BlockSyncerTest_localKnownBestBlockHeight {
realm.insert(BlockHash(byteArrayOf(2), 0, 3))
}

Assert.assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
}

@Test
Expand All @@ -75,6 +75,6 @@ class BlockSyncerTest_localKnownBestBlockHeight {
realm.insert(BlockHash(byteArrayOf(2), 0, 5))
}

Assert.assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
assertEquals(expectedKnownBestBlockHeight, blockSyncer.localKnownBestBlockHeight)
}
}
Expand Up @@ -5,7 +5,7 @@ import io.horizontalsystems.bitcoinkit.models.Block
import io.horizontalsystems.bitcoinkit.models.Transaction
import io.horizontalsystems.bitcoinkit.network.Network
import io.realm.Realm
import junit.framework.Assert
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
Expand Down Expand Up @@ -102,22 +102,22 @@ class BlockchainTest {

private fun assertBlocksPresent(blocksInChain: Map<Int, String>, realm: Realm) {
blocksInChain.forEach { (height, id) ->
Assert.assertEquals("Block $id($height) not found", 1, realm.where(Block::class.java).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
Assert.assertEquals("Transaction $id($height) not found", 1, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
assertEquals("Block $id($height) not found", 1, realm.where(Block::class.java).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
assertEquals("Transaction $id($height) not found", 1, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
}
}

private fun assertBlocksNotPresent(blocksInChain: Map<Int, String>, realm: Realm) {
blocksInChain.forEach { (height, id) ->
Assert.assertEquals("Block $id($height) should not present", 0, realm.where(Block::class.java).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
Assert.assertEquals("Transaction $id($height) should not present", 0, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
assertEquals("Block $id($height) should not present", 0, realm.where(Block::class.java).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
assertEquals("Transaction $id($height) should not present", 0, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
}
}

private fun assertNotStaleBlocksPresent(blocksInChain: Map<Int, String>, realm: Realm) {
blocksInChain.forEach { (height, id) ->
Assert.assertEquals("Not stale block $id($height) not found", 1, realm.where(Block::class.java).equalTo("stale", false).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
Assert.assertEquals("Transaction $id($height) not found", 1, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
assertEquals("Not stale block $id($height) not found", 1, realm.where(Block::class.java).equalTo("stale", false).equalTo("height", height).equalTo("reversedHeaderHashHex", id).count())
assertEquals("Transaction $id($height) not found", 1, realm.where(Transaction::class.java).equalTo("hashHexReversed", id).count())
}
}

Expand Down

0 comments on commit 56758ce

Please sign in to comment.