Skip to content

Commit 2d8c713

Browse files
committed
Refactor TransactionSource for multi-chain support
- Update gradle - Remove Android extensions - Upgrade to Java 17
1 parent 23675dd commit 2d8c713

File tree

30 files changed

+247
-148
lines changed

30 files changed

+247
-148
lines changed

app/build.gradle

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
plugins {
22
id 'com.android.application'
33
id 'kotlin-android'
4-
id 'kotlin-android-extensions'
54
}
65

76
android {
8-
compileSdkVersion 32
7+
namespace 'io.horizontalsystems.ethereumkit.sample'
8+
compileSdkVersion 33
99
defaultConfig {
1010
applicationId "io.horizontalsystems.ethereumkit"
1111
minSdkVersion 26
12-
targetSdkVersion 32
12+
targetSdkVersion 33
1313
versionCode 1
1414
versionName "1.0"
1515
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1616
}
1717

18+
buildFeatures {
19+
viewBinding true
20+
}
21+
1822
buildFeatures {
1923
compose true
2024
}
@@ -33,16 +37,16 @@ android {
3337

3438

3539
compileOptions {
36-
sourceCompatibility JavaVersion.VERSION_11
37-
targetCompatibility JavaVersion.VERSION_11
40+
sourceCompatibility JavaVersion.VERSION_17
41+
targetCompatibility JavaVersion.VERSION_17
3842
}
3943

4044
kotlinOptions {
41-
jvmTarget = "11"
45+
jvmTarget = "17"
4246
}
4347

4448
composeOptions {
45-
kotlinCompilerExtensionVersion '1.3.0'
49+
kotlinCompilerExtensionVersion '1.5.8'
4650
}
4751
}
4852

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/addresswatch/AddressWatchActivity.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,42 @@ package io.horizontalsystems.ethereumkit.sample.modules.addresswatch
22

33
import android.os.Bundle
44
import android.view.View
5+
import android.widget.Button
6+
import android.widget.EditText
7+
import android.widget.ProgressBar
58
import android.widget.Toast
69
import androidx.appcompat.app.AppCompatActivity
710
import androidx.lifecycle.ViewModelProvider
811
import androidx.recyclerview.widget.LinearLayoutManager
12+
import androidx.recyclerview.widget.RecyclerView
913
import io.horizontalsystems.ethereumkit.sample.R
1014
import io.horizontalsystems.ethereumkit.sample.modules.main.ShowTxType
1115
import io.horizontalsystems.ethereumkit.sample.modules.main.TransactionsAdapter
12-
import kotlinx.android.synthetic.main.activity_address_watch.*
13-
import kotlinx.android.synthetic.main.activity_address_watch.ethFilter
14-
import kotlinx.android.synthetic.main.activity_address_watch.tokenFilter
15-
import kotlinx.android.synthetic.main.activity_address_watch.transactionsRecyclerView
1616

1717
class AddressWatchActivity : AppCompatActivity() {
1818

1919
private lateinit var viewModel: AddressWatchViewModel
2020

21+
private lateinit var addressInput: EditText
22+
private lateinit var watchButton: Button
23+
private lateinit var ethFilter: Button
24+
private lateinit var tokenFilter: Button
25+
private lateinit var transactionsRecyclerView: RecyclerView
26+
private lateinit var transactionSyncProgress: ProgressBar
27+
28+
2129
override fun onCreate(savedInstanceState: Bundle?) {
2230
super.onCreate(savedInstanceState)
2331

2432
viewModel = ViewModelProvider(this).get(AddressWatchViewModel::class.java)
2533

34+
addressInput = findViewById(R.id.addressInput)
35+
watchButton = findViewById(R.id.watchButton)
36+
ethFilter = findViewById(R.id.ethFilter)
37+
tokenFilter = findViewById(R.id.tokenFilter)
38+
transactionsRecyclerView = findViewById(R.id.transactionsRecyclerView)
39+
transactionSyncProgress = findViewById(R.id.transactionSyncProgress)
40+
2641
setContentView(R.layout.activity_address_watch)
2742

2843
watchButton.setOnClickListener {

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/addresswatch/AddressWatchViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ class AddressWatchViewModel : ViewModel() {
129129

130130
when (Configuration.chain) {
131131
Chain.BinanceSmartChain -> {
132-
transactionSource = TransactionSource.etherscanApi(Configuration.etherscanKey.split(","))
132+
transactionSource = TransactionSource.binance(Configuration.etherscanKey.split(","))
133133
rpcSource = RpcSource.binanceSmartChainHttp()
134134
}
135135
Chain.Ethereum -> {
136-
transactionSource = TransactionSource.etherscanApi(Configuration.etherscanKey.split(","))
136+
transactionSource = TransactionSource.ethereum(Configuration.etherscanKey.split(","))
137137
rpcSource = RpcSource.Http(listOf(URI(Configuration.ethereumRpc)), null)
138138
}
139139
else -> {

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/main/BalanceFragment.kt

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ import android.view.View
88
import android.view.ViewGroup
99
import androidx.lifecycle.ViewModelProvider
1010
import io.horizontalsystems.ethereumkit.core.EthereumKit
11-
import io.horizontalsystems.ethereumkit.sample.R
12-
import kotlinx.android.synthetic.main.fragment_balance.*
11+
import io.horizontalsystems.ethereumkit.sample.databinding.FragmentBalanceBinding
1312

1413
class BalanceFragment : Fragment() {
1514

1615
private lateinit var viewModel: MainViewModel
1716

18-
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
19-
return inflater.inflate(R.layout.fragment_balance, container, false)
17+
private var _binding: FragmentBalanceBinding? = null // 2. Add binding property
18+
private val binding get() = _binding!!
19+
20+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
21+
_binding = FragmentBalanceBinding.inflate(inflater, container, false) // 3. Inflate with ViewBinding
22+
return binding.root
2023
}
2124

2225
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -25,52 +28,52 @@ class BalanceFragment : Fragment() {
2528
viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
2629

2730
viewModel.balance.observe(viewLifecycleOwner, Observer { balance ->
28-
balanceValue.text = (balance ?: 0).toString()
31+
binding.balanceValue.text = (balance ?: 0).toString()
2932
})
3033

3134
viewModel.erc20TokenBalance.observe(viewLifecycleOwner, Observer { balance ->
32-
tokenBalanceValue.text = (balance ?: 0).toString()
35+
binding. tokenBalanceValue.text = (balance ?: 0).toString()
3336
})
3437

3538
viewModel.lastBlockHeight.observe(viewLifecycleOwner, Observer { lbh ->
36-
lbhValue.text = (lbh ?: 0).toString()
39+
binding.lbhValue.text = (lbh ?: 0).toString()
3740
})
3841

3942
viewModel.syncState.observe(viewLifecycleOwner, Observer { state ->
4043
val syncStateInfo = getSynStateInfo(state)
41-
syncStateValue.text = syncStateInfo.description
44+
binding.syncStateValue.text = syncStateInfo.description
4245
if (syncStateInfo.error == null) {
43-
syncStateError.visibility = View.GONE
46+
binding.syncStateError.visibility = View.GONE
4447
} else {
45-
syncStateError.text = syncStateInfo.error.message
46-
syncStateError.visibility = View.VISIBLE
48+
binding.syncStateError.text = syncStateInfo.error.message
49+
binding.syncStateError.visibility = View.VISIBLE
4750
}
4851
})
4952

5053
viewModel.transactionsSyncState.observe(viewLifecycleOwner, Observer { state ->
51-
txSyncStateValue.text = getSynStateInfo(state).description
54+
binding.txSyncStateValue.text = getSynStateInfo(state).description
5255
})
5356

5457
viewModel.erc20SyncState.observe(viewLifecycleOwner, Observer { state ->
5558
val syncStateInfo = getSynStateInfo(state)
56-
erc20SyncStateValue.text = syncStateInfo.description
59+
binding.erc20SyncStateValue.text = syncStateInfo.description
5760
if (syncStateInfo.error == null) {
58-
erc20SyncStateError.visibility = View.GONE
61+
binding.erc20SyncStateError.visibility = View.GONE
5962
} else {
60-
erc20SyncStateError.text = syncStateInfo.error.message
61-
erc20SyncStateError.visibility = View.VISIBLE
63+
binding.erc20SyncStateError.text = syncStateInfo.error.message
64+
binding.erc20SyncStateError.visibility = View.VISIBLE
6265
}
6366
})
6467

6568
viewModel.erc20TransactionsSyncState.observe(viewLifecycleOwner, Observer { state ->
66-
erc20TxSyncStateValue.text = getSynStateInfo(state).description
69+
binding.erc20TxSyncStateValue.text = getSynStateInfo(state).description
6770
})
6871

69-
buttonRefresh.setOnClickListener {
72+
binding.buttonRefresh.setOnClickListener {
7073
viewModel.refresh()
7174
}
7275

73-
buttonClear.setOnClickListener {
76+
binding.buttonClear.setOnClickListener {
7477
viewModel.clear()
7578
}
7679
}

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/main/MainActivity.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import androidx.fragment.app.Fragment
99
import androidx.lifecycle.ViewModelProvider
1010
import com.google.android.material.bottomnavigation.BottomNavigationView
1111
import io.horizontalsystems.ethereumkit.sample.R
12+
import io.horizontalsystems.ethereumkit.sample.databinding.ActivityMainBinding
1213
import io.horizontalsystems.ethereumkit.sample.modules.addresswatch.AddressWatchActivity
1314
import io.horizontalsystems.ethereumkit.sample.modules.uniswapV3.UniswapV3Fragment
14-
import kotlinx.android.synthetic.main.activity_main.*
1515

1616
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
1717

18+
private lateinit var binding: ActivityMainBinding
19+
1820
private val balanceFragment = BalanceFragment()
1921
private val transactionsFragment = TransactionsFragment()
2022
private val sendReceiveFragment = SendReceiveFragment()
@@ -28,9 +30,10 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
2830

2931
override fun onCreate(savedInstanceState: Bundle?) {
3032
super.onCreate(savedInstanceState)
33+
binding = ActivityMainBinding.inflate(layoutInflater)
3134
setContentView(R.layout.activity_main)
3235

33-
toolbar.setOnMenuItemClickListener { item ->
36+
binding.toolbar.setOnMenuItemClickListener { item ->
3437
when (item.itemId) {
3538
R.id.menuAddressWatch -> {
3639
val intent = Intent(this, AddressWatchActivity::class.java)

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/main/MainViewModel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,17 +193,17 @@ class MainViewModel : ViewModel() {
193193
private fun createKit(): EthereumKit {
194194
when (Configuration.chain) {
195195
Chain.BinanceSmartChain -> {
196-
transactionSource = TransactionSource.etherscanApi(Configuration.etherscanKey.split(","))
196+
transactionSource = TransactionSource.binance(Configuration.etherscanKey.split(","))
197197
rpcSource = RpcSource.binanceSmartChainHttp()
198198
}
199199

200200
Chain.Ethereum -> {
201-
transactionSource = TransactionSource.etherscanApi(Configuration.etherscanKey.split(","))
201+
transactionSource = TransactionSource.ethereum(Configuration.etherscanKey.split(","))
202202
rpcSource = RpcSource.Http(listOf(URI(Configuration.ethereumRpc)), null)
203203
}
204204

205205
Chain.ArbitrumOne -> {
206-
transactionSource = TransactionSource.etherscanApi(Configuration.etherscanKey.split(","))
206+
transactionSource = TransactionSource.arbitrumOne(Configuration.etherscanKey.split(","))
207207
rpcSource = RpcSource.arbitrumOneRpcHttp()
208208
}
209209

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/main/NftsFragment.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
7+
import androidx.appcompat.widget.Toolbar
78
import androidx.compose.foundation.layout.*
89
import androidx.compose.foundation.lazy.LazyColumn
910
import androidx.compose.foundation.text.selection.SelectionContainer
@@ -20,12 +21,13 @@ import androidx.compose.ui.unit.dp
2021
import androidx.fragment.app.Fragment
2122
import androidx.lifecycle.ViewModelProvider
2223
import androidx.lifecycle.viewmodel.compose.viewModel
23-
import kotlinx.android.synthetic.main.activity_main.*
24+
import io.horizontalsystems.ethereumkit.sample.R
2425

2526
class NftsFragment : Fragment() {
2627
private lateinit var mainViewModel: MainViewModel
2728

2829
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
30+
val toolbar = activity?.findViewById<Toolbar>(R.id.toolbar) // <-- FIND THE VIEW
2931
toolbar?.title = "Nfts"
3032

3133
mainViewModel = activity?.let { ViewModelProvider(it)[MainViewModel::class.java] } ?: return null

app/src/main/java/io/horizontalsystems/ethereumkit/sample/modules/main/SendReceiveFragment.kt

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@ import android.view.View
88
import android.view.ViewGroup
99
import android.widget.Toast
1010
import androidx.lifecycle.ViewModelProvider
11-
import io.horizontalsystems.ethereumkit.sample.R
12-
import kotlinx.android.synthetic.main.fragment_send_receive.*
11+
import io.horizontalsystems.ethereumkit.sample.databinding.FragmentSendReceiveBinding
1312
import java.math.BigDecimal
1413

1514
class SendReceiveFragment : Fragment() {
1615

1716
private lateinit var viewModel: MainViewModel
18-
19-
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
20-
return inflater.inflate(R.layout.fragment_send_receive, container, false)
17+
private var _binding: FragmentSendReceiveBinding? = null
18+
private val binding get() = _binding!!
19+
20+
override fun onCreateView(
21+
inflater: LayoutInflater,
22+
container: ViewGroup?,
23+
savedInstanceState: Bundle?
24+
): View {
25+
_binding = FragmentSendReceiveBinding.inflate(inflater, container, false)
26+
return binding.root
2127
}
2228

2329
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -26,46 +32,46 @@ class SendReceiveFragment : Fragment() {
2632
viewModel = activity?.let { ViewModelProvider(it).get(MainViewModel::class.java) } ?: return
2733

2834
viewModel.estimatedGas.observe(viewLifecycleOwner, Observer { estimatedGas ->
29-
estimateGasText.text = estimatedGas
35+
binding.estimateGasText.text = estimatedGas
3036
})
3137

3238
viewModel.sendStatus.observe(viewLifecycleOwner, Observer { sendError ->
3339
val msg = if (sendError != null) sendError.localizedMessage else " Successfully sent!"
3440
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
3541
})
3642

37-
receiveAddressButton.setOnClickListener {
38-
receiveAddressText.text = viewModel.receiveAddress()
43+
binding.receiveAddressButton.setOnClickListener {
44+
binding.receiveAddressText.text = viewModel.receiveAddress()
3945
}
4046

41-
estimateGasButton.setOnClickListener {
47+
binding.estimateGasButton.setOnClickListener {
4248
onTapEstimateGas(false)
4349
}
4450

45-
estimateErc20GasButton.setOnClickListener {
51+
binding.estimateErc20GasButton.setOnClickListener {
4652
onTapEstimateGas(true)
4753
}
4854

49-
sendButton.setOnClickListener {
55+
binding.sendButton.setOnClickListener {
5056
when {
51-
sendAddress.text.isEmpty() -> sendAddress.error = "Send address cannot be blank"
52-
sendAmount.text.isEmpty() -> sendAmount.error = "Send amount cannot be blank"
53-
else -> viewModel.send(sendAddress.text.toString(), sendAmount.text.toString().toBigDecimal())
57+
binding.sendAddress.text.isEmpty() -> binding.sendAddress.error = "Send address cannot be blank"
58+
binding.sendAmount.text.isEmpty() -> binding.sendAmount.error = "Send amount cannot be blank"
59+
else -> viewModel.send(binding.sendAddress.text.toString(), binding.sendAmount.text.toString().toBigDecimal())
5460
}
5561
}
5662

57-
sendErc20.setOnClickListener {
63+
binding.sendErc20.setOnClickListener {
5864
when {
59-
sendAmount.text.isEmpty() -> sendAmount.error = "Send amount cannot be blank"
60-
else -> viewModel.sendERC20(sendAddress.text.toString(), sendAmount.text.toString().toBigDecimal())
65+
binding.sendAmount.text.isEmpty() -> binding.sendAmount.error = "Send amount cannot be blank"
66+
else -> viewModel.sendERC20(binding.sendAddress.text.toString(), binding.sendAmount.text.toString().toBigDecimal())
6167
}
6268
}
6369
}
6470

6571
private fun onTapEstimateGas(isErc20: Boolean) {
66-
val toAddress = sendAddress.text.toString()
72+
val toAddress = binding.sendAddress.text.toString()
6773
val resolvedToAddress = if (toAddress.isNotBlank()) toAddress else null
68-
val resolvedAmount = sendAmount.text.toString().toBigDecimalOrNull() ?: BigDecimal.ZERO
74+
val resolvedAmount = binding.sendAmount.text.toString().toBigDecimalOrNull() ?: BigDecimal.ZERO
6975

7076
viewModel.estimateGas(resolvedToAddress, resolvedAmount, isErc20)
7177
}

0 commit comments

Comments
 (0)