Skip to content

Commit

Permalink
Merge pull request #72 from horizontalsystems/merge-master
Browse files Browse the repository at this point in the history
Merge master
  • Loading branch information
rafaelekol authored May 9, 2019
2 parents 28ff3cd + d728423 commit aa45bc7
Show file tree
Hide file tree
Showing 177 changed files with 5,451 additions and 2,566 deletions.
16 changes: 11 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 27
compileSdkVersion 28
defaultConfig {
applicationId "io.horizontalsystems.ethereumkit"
minSdkVersion 23
targetSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Expand All @@ -33,20 +33,26 @@ dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.github.horizontalsystems:hd-wallet-kit-android:a3666d8'

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:design:28.0.0'

implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
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"

// For debug
implementation 'com.facebook.stetho:stetho:1.5.1'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

implementation project(':ethereumkit')
implementation project(':erc20kit')
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package io.horizontalsystems.ethereumkit.sample

import android.app.Application
import com.facebook.stetho.Stetho

class App : Application() {

override fun onCreate() {
super.onCreate()
instance = this

// Enable debug bridge
Stetho.initializeWithDefaults(this)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import io.horizontalsystems.ethereumkit.EthereumKit
import io.horizontalsystems.ethereumkit.core.EthereumKit

class BalanceFragment : Fragment() {

Expand All @@ -21,6 +21,7 @@ class BalanceFragment : Fragment() {
lateinit var kitStateValue: TextView
lateinit var erc20StateValue: TextView
lateinit var refreshButton: Button
lateinit var clearButton: Button

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -73,6 +74,7 @@ class BalanceFragment : Fragment() {
balanceValue = view.findViewById(R.id.balanceValue)
tokenBalanceValue = view.findViewById(R.id.tokenBalanceValue)
refreshButton = view.findViewById(R.id.buttonRefresh)
clearButton = view.findViewById(R.id.buttonClear)
feeValue = view.findViewById(R.id.feeValue)
lbhValue = view.findViewById(R.id.lbhValue)
kitStateValue = view.findViewById(R.id.kitStateValue)
Expand All @@ -81,5 +83,9 @@ class BalanceFragment : Fragment() {
refreshButton.setOnClickListener {
viewModel.refresh()
}

clearButton.setOnClickListener {
viewModel.clear()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package io.horizontalsystems.ethereumkit.sample
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import android.util.Log
import android.widget.Toast
import io.horizontalsystems.ethereumkit.EthereumKit
import io.horizontalsystems.ethereumkit.EthereumKit.SyncState
import io.horizontalsystems.erc20kit.core.Erc20Kit
import io.horizontalsystems.ethereumkit.core.EthereumKit
import io.horizontalsystems.ethereumkit.core.EthereumKit.NetworkType
import io.horizontalsystems.ethereumkit.core.EthereumKit.SyncState
import io.horizontalsystems.ethereumkit.sample.core.Erc20Adapter
import io.horizontalsystems.ethereumkit.sample.core.EthereumAdapter
import io.horizontalsystems.ethereumkit.sample.core.TransactionRecord
import io.horizontalsystems.hdwalletkit.HDWallet
import io.horizontalsystems.hdwalletkit.Mnemonic
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import java.math.BigDecimal
Expand All @@ -23,36 +26,43 @@ class MainViewModel : ViewModel() {

private val disposables = CompositeDisposable()

private var ethereumKit: EthereumKit
private val erc20Adapter: Erc20Adapter
private val ethereumAdapter: EthereumAdapter

private lateinit var ethereumKit: EthereumKit
private lateinit var ethereumAdapter: EthereumAdapter

private lateinit var erc20Adapter: Erc20Adapter

val transactions = MutableLiveData<List<TransactionRecord>>()
val balance = MutableLiveData<BigDecimal>()
val fee = MutableLiveData<BigDecimal>()
val lastBlockHeight = MutableLiveData<Int>()
val lastBlockHeight = MutableLiveData<Long>()
val etherState = MutableLiveData<SyncState>()
val erc20State = MutableLiveData<SyncState>()

val erc20TokenBalance = MutableLiveData<BigDecimal>()
val sendStatus = SingleLiveEvent<Throwable?>()
val gasPriceInWei = 3000000000L


val gasPrice: Long = 5_000_000_000

init {
init()
}

fun init() {
// val words = "subway plate brick pattern inform used oblige identify cherry drop flush balance".split(" ")
val words = "mom year father track attend frown loyal goddess crisp abandon juice roof".split(" ")

ethereumKit = EthereumKit.ethereumKit(App.instance, words, "unique-wallet-id", testMode, infuraKey = infuraKey, etherscanKey = etherscanKey)
ethereumAdapter = EthereumAdapter(ethereumKit)
erc20Adapter = Erc20Adapter(ethereumKit, contractAddress, contractDecimal)
val seed = Mnemonic().toSeed(words)
val hdWallet = HDWallet(seed, if (testMode) 1 else 60)
val privateKey = hdWallet.privateKey(0, 0, true).privKey
val nodePrivateKey = hdWallet.privateKey(102, 102, true).privKey

ethereumKit.start()
ethereumKit = EthereumKit.getInstance(App.instance, privateKey, EthereumKit.SyncMode.ApiSyncMode(infuraKey, etherscanKey), NetworkType.Ropsten, "unique-wallet-id")
ethereumAdapter = EthereumAdapter(ethereumKit)

erc20Adapter = Erc20Adapter(App.instance, ethereumKit, "Max Token", "MXT", contractAddress, contractDecimal)

fee.value = ethereumKit.fee(gasPriceInWei)
fee.value = ethereumKit.fee(gasPrice)
updateBalance()
updateErc20Balance()
updateState()
Expand All @@ -62,46 +72,54 @@ class MainViewModel : ViewModel() {
//
// Ethereum
//
ethereumAdapter.transactionSubject.subscribe {
updateTransactions()

ethereumAdapter.lastBlockHeightFlowable.subscribe {
updateLastBlockHeight()
}.let {
disposables.add(it)
}

ethereumAdapter.balanceSubject.subscribe {
updateBalance()
ethereumAdapter.transactionsFlowable.subscribe {
updateTransactions()
}.let {
disposables.add(it)
}

ethereumAdapter.lastBlockHeightSubject.subscribe {
updateLastBlockHeight()
ethereumAdapter.balanceFlowable.subscribe {
updateBalance()
}.let {
disposables.add(it)
}

ethereumAdapter.syncStateUpdateSubject.subscribe {
ethereumAdapter.syncStateFlowable.subscribe {
updateState()
}.let {
disposables.add(it)
}

erc20Adapter.syncStateUpdateSubject.subscribe {
updateErc20State()
}.let {
disposables.add(it)
}

//
// ERC20
//

erc20Adapter.balanceSubject.subscribe {
erc20Adapter.transactionsFlowable.subscribe {
updateErc20Transactions()
}.let {
disposables.add(it)
}

erc20Adapter.balanceFlowable.subscribe {
updateErc20Balance()
}.let {
disposables.add(it)
}

erc20Adapter.syncStateFlowable.subscribe {
updateErc20State()
}.let {
disposables.add(it)
}

ethereumKit.start()
}

Expand All @@ -125,26 +143,53 @@ class MainViewModel : ViewModel() {
erc20TokenBalance.postValue(erc20Adapter.balance)
}

private fun updateTransactions() {
ethereumAdapter.transactions()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { list: List<TransactionRecord> ->
transactions.value = list
}.let {
disposables.add(it)
}
}

private fun updateErc20Transactions() {
erc20Adapter.transactions()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { list: List<TransactionRecord> ->
transactions.value = list
}.let {
disposables.add(it)
}
}


//
// Ethereum
//

fun refresh() {
ethereumKit.start()
fee.postValue(ethereumKit.fee(gasPriceInWei))
ethereumKit.refresh()
fee.postValue(ethereumKit.fee(gasPrice))
}

fun clear() {
EthereumKit.clear(App.instance)
Erc20Kit.clear(App.instance)
init()
}

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

fun send(address: String, amount: BigDecimal) {
ethereumAdapter.sendSingle(address, amount)
ethereumAdapter.send(address, amount)
.subscribeOn(io.reactivex.schedulers.Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
//success
Toast.makeText(App.instance, "Success", Toast.LENGTH_SHORT).show()
sendStatus.value = null
}, {
Log.e("MainViewModel", "send failed ${it.message}")
sendStatus.value = it
Expand All @@ -157,20 +202,20 @@ class MainViewModel : ViewModel() {
//

fun sendERC20(address: String, amount: BigDecimal) {
erc20Adapter.sendSingle(address, amount)
erc20Adapter.send(address, amount)
.subscribeOn(io.reactivex.schedulers.Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
//success
Toast.makeText(App.instance, "Success", Toast.LENGTH_SHORT).show()
sendStatus.value = null
}, {
Log.e("MainViewModel", "send failed ${it.message}")
sendStatus.value = it
})?.let { disposables.add(it) }
}

fun filterTransactions(ethTx: Boolean) {
val txMethod = if (ethTx) ethereumAdapter.transactionsSingle() else erc20Adapter.transactionsSingle()
val txMethod = if (ethTx) ethereumAdapter.transactions() else erc20Adapter.transactions()

txMethod
.observeOn(AndroidSchedulers.mainThread())
Expand All @@ -181,18 +226,4 @@ class MainViewModel : ViewModel() {
}
}

//
// Private
//

private fun updateTransactions() {
ethereumAdapter.transactionsSingle()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { list: List<TransactionRecord> ->
transactions.value = list
}.let {
disposables.add(it)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class SendReceiveFragment : Fragment() {
return inflater.inflate(R.layout.fragment_send_receive, null)
}


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import io.horizontalsystems.ethereumkit.sample.core.TransactionRecord
import java.text.SimpleDateFormat
import java.util.*

class TransactionsFragment : Fragment() {

Expand Down Expand Up @@ -67,7 +69,7 @@ class TransactionsFragment : Fragment() {

class TransactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var items = listOf<TransactionRecord>()
var lastBlockHeight: Int = 0
var lastBlockHeight: Long = 0

override fun getItemCount() = items.size

Expand All @@ -84,14 +86,20 @@ class TransactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class ViewHolderTransaction(private val containerView: View) : RecyclerView.ViewHolder(containerView) {
private val summary = containerView.findViewById<TextView>(R.id.summary)!!

fun bind(tx: TransactionRecord, index: Int, lastBlockHeight: Int) {
fun bind(tx: TransactionRecord, index: Int, lastBlockHeight: Long) {
containerView.setBackgroundColor(if (index % 2 == 0)
Color.parseColor("#dddddd") else
Color.TRANSPARENT
)

val format = SimpleDateFormat("dd-MM-yyyy HH:mm:ss")

var value = """
- #$index
- Tx Hash: ${tx.transactionHash}
- Tx Index: ${tx.transactionIndex}
- Inter Tx Index: ${tx.interTransactionIndex}
- Time: ${format.format(Date(tx.timestamp * 1000))}
- From: ${tx.from.address}
- To: ${tx.to.address}
- Amount: ${tx.amount.stripTrailingZeros()}
Expand All @@ -100,9 +108,6 @@ class ViewHolderTransaction(private val containerView: View) : RecyclerView.View
if (lastBlockHeight > 0)
value += "\n- Confirmations: ${tx.blockHeight?.let { lastBlockHeight - it } ?: 0}"

if (tx.contractAddress.isNotEmpty())
value += "\n- Contract: ${tx.contractAddress}"

summary.text = value.trimIndent()
}
}
Loading

0 comments on commit aa45bc7

Please sign in to comment.