Updated on 2026-08-14
9
.idea/misc.xml
generated
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -31,6 +31,9 @@ android {
|
|||
minifyEnabled false
|
||||
applicationIdSuffix ".dev"
|
||||
signingConfig signingConfigs.debug
|
||||
firebaseCrashlytics {
|
||||
mappingFileUploadEnabled false
|
||||
}
|
||||
}
|
||||
debug_beta {
|
||||
initWith debug
|
||||
|
|
@ -67,7 +70,7 @@ dependencies {
|
|||
implementation 'com.google.android.material:material:1.2.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
|
||||
implementation 'com.tangem:blockchain:1.83.0'
|
||||
implementation 'com.tangem:blockchain:1.96.0'
|
||||
implementation 'com.tangem:core:1.68.0'
|
||||
implementation 'com.tangem:sdk:1.68.0'
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
|
@ -73,6 +73,7 @@ class PayIdManager {
|
|||
Blockchain.BitcoinCash,
|
||||
Blockchain.Binance,
|
||||
Blockchain.RSK,
|
||||
Blockchain.Tezos
|
||||
)
|
||||
|
||||
fun isPayId(value: String?): Boolean = value?.contains(payIdRegExp) ?: false
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.wallet.R
|
|||
|
||||
interface TapErrors
|
||||
|
||||
interface ArgError{
|
||||
interface ArgError {
|
||||
val args: List<Any>?
|
||||
}
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ sealed class TapError(
|
|||
) : Throwable(), TapErrors, ArgError {
|
||||
|
||||
object UnknownError : TapError(R.string.send_error_unknown)
|
||||
data class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage))
|
||||
object PayIdAlreadyCreated : TapError(R.string.wallet_create_payid_error_already_created)
|
||||
object PayIdCreatingError : TapError(R.string.wallet_create_payid_error_message)
|
||||
object PayIdEmptyField : TapError(R.string.wallet_create_payid_empty)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import com.tangem.tap.common.redux.global.GlobalAction
|
|||
import com.tangem.tap.domain.extensions.amountToCreateAccount
|
||||
import com.tangem.tap.domain.extensions.isNoAccountError
|
||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
import com.tangem.tap.features.wallet.redux.PayIdState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
|
||||
|
|
@ -25,6 +24,7 @@ import java.math.BigDecimal
|
|||
class TapWalletManager {
|
||||
private val payIdManager = PayIdManager()
|
||||
private val coinMarketCapService = CoinMarketCapService()
|
||||
private var tapWorkarounds: TapWorkarounds? = null
|
||||
|
||||
suspend fun loadWalletData() {
|
||||
val walletManager = store.state.globalState.scanNoteResponse?.walletManager
|
||||
|
|
@ -78,6 +78,7 @@ class TapWalletManager {
|
|||
}
|
||||
|
||||
suspend fun onCardScanned(data: ScanNoteResponse) {
|
||||
tapWorkarounds = TapWorkarounds(data.card)
|
||||
withContext(Dispatchers.Main) {
|
||||
store.dispatch(WalletAction.ResetState)
|
||||
store.dispatch(GlobalAction.SaveScanNoteResponse(data))
|
||||
|
|
@ -142,7 +143,6 @@ class TapWalletManager {
|
|||
private suspend fun loadPayIdIfNeeded(): Result<String?>? {
|
||||
val scanNoteResponse = store.state.globalState.scanNoteResponse
|
||||
if (!TapConfig.usePayId ||
|
||||
store.state.walletState.payIdData.payIdState == PayIdState.Disabled ||
|
||||
scanNoteResponse?.walletManager?.wallet?.blockchain?.isPayIdSupported() == false) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -160,7 +160,11 @@ class TapWalletManager {
|
|||
is Result.Success -> {
|
||||
val payId = result.data
|
||||
if (payId == null) {
|
||||
store.dispatch(WalletAction.LoadPayId.NotCreated)
|
||||
if (tapWorkarounds?.isPayIdCreationEnabled() == false) {
|
||||
store.dispatch(WalletAction.DisablePayId)
|
||||
} else {
|
||||
store.dispatch(WalletAction.LoadPayId.NotCreated)
|
||||
}
|
||||
} else {
|
||||
store.dispatch(WalletAction.LoadPayId.Success(payId))
|
||||
}
|
||||
|
|
|
|||
17
app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.tap.domain
|
||||
|
||||
import com.tangem.commands.Card
|
||||
|
||||
class TapWorkarounds(val card: Card) {
|
||||
|
||||
private val isStart2Coin: Boolean = card.cardData?.issuerName == START_2_COIN_ISSUER
|
||||
|
||||
fun isPayIdCreationEnabled(): Boolean {
|
||||
if (isStart2Coin) return false
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val START_2_COIN_ISSUER = "start2coin"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.domain.extensions
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import org.stellar.sdk.requests.ErrorResponse
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
||||
fun Blockchain.isNoAccountError(exception: Throwable): Boolean {
|
||||
|
|
@ -17,10 +18,14 @@ fun Blockchain.isNoAccountError(exception: Throwable): Boolean {
|
|||
|
||||
fun Blockchain.amountToCreateAccount(token: Token? = null): Double? {
|
||||
return when (this) {
|
||||
Blockchain.Stellar -> if (token?.symbol == NODL) 1.5 else 1.toDouble()
|
||||
Blockchain.Stellar -> if (token?.symbol == NODL) 1.5 else 1.toDouble()
|
||||
Blockchain.XRP -> 20.toDouble()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun Blockchain.minimalAmount(): BigDecimal {
|
||||
return 1.toBigDecimal().movePointLeft(decimals())
|
||||
}
|
||||
|
||||
private const val NODL = "NODL"
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux
|
|||
|
||||
import com.tangem.Message
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.tangem_sdk_new.ui.animation.VoidCallback
|
||||
import com.tangem.tap.common.redux.ErrorAction
|
||||
import com.tangem.tap.common.redux.ToastNotificationAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
|
|
@ -114,4 +115,13 @@ sealed class SendAction : SendScreenAction {
|
|||
}
|
||||
|
||||
data class SendError(override val error: TapError) : SendAction(), ErrorAction
|
||||
|
||||
sealed class Dialog : SendAction() {
|
||||
data class ShowTezosWarningDialog(
|
||||
val reduceCallback: VoidCallback,
|
||||
val sendAllCallback: VoidCallback,
|
||||
val reduceAmount: BigDecimal,
|
||||
) : Dialog()
|
||||
object Hide : Dialog()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.send.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.TransactionError
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
|
|
@ -59,6 +60,7 @@ class AmountMiddleware {
|
|||
|
||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto))
|
||||
val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee)
|
||||
transactionErrors.remove(TransactionError.TezosSendAll)
|
||||
if (transactionErrors.isEmpty()) {
|
||||
dispatch(AmountAction.SetAmountError(null))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.domain.extensions.minimalAmount
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.SendActionUi
|
||||
import com.tangem.tap.features.send.redux.states.SendButtonState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.scope
|
||||
|
|
@ -55,12 +53,35 @@ private fun verifyAndSendTransaction(
|
|||
|
||||
val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend())
|
||||
|
||||
val verifyResult = walletManager.validateTransaction(amountToSend, feeAmount)
|
||||
if (verifyResult.isNotEmpty()) {
|
||||
dispatch(SendAction.SendError(createValidateTransactionError(verifyResult, walletManager)))
|
||||
return
|
||||
val transactionErrors = walletManager.validateTransaction(amountToSend, feeAmount)
|
||||
val hadTezosError = transactionErrors.remove(TransactionError.TezosSendAll)
|
||||
when {
|
||||
hadTezosError -> {
|
||||
val reduceAmount = walletManager.wallet.blockchain.minimalAmount()
|
||||
dispatch(SendAction.Dialog.ShowTezosWarningDialog(reduceCallback = {
|
||||
dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false))
|
||||
dispatch(AmountActionUi.CheckAmountToSend)
|
||||
}, sendAllCallback = {
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, recipientAddress, dispatch)
|
||||
}, reduceAmount))
|
||||
}
|
||||
transactionErrors.isNotEmpty() -> {
|
||||
dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager)))
|
||||
}
|
||||
else -> {
|
||||
sendTransaction(action, walletManager, amountToSend, feeAmount, recipientAddress, dispatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendTransaction(
|
||||
action: SendActionUi.SendAmountToRecipient,
|
||||
walletManager: WalletManager,
|
||||
amountToSend: Amount,
|
||||
feeAmount: Amount,
|
||||
recipientAddress: String,
|
||||
dispatch: (Action) -> Unit
|
||||
) {
|
||||
dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS))
|
||||
val txData = walletManager.createTransaction(amountToSend, feeAmount, recipientAddress)
|
||||
scope.launch {
|
||||
|
|
@ -89,7 +110,8 @@ private fun verifyAndSendTransaction(
|
|||
}
|
||||
}
|
||||
is Throwable -> {
|
||||
val message = (result.error as Throwable).message
|
||||
val throwable = result.error as Throwable
|
||||
val message = throwable.message
|
||||
when {
|
||||
message == null -> {
|
||||
dispatch(SendAction.SendError(TapError.UnknownError))
|
||||
|
|
@ -98,8 +120,9 @@ private fun verifyAndSendTransaction(
|
|||
// user was cancelled the operation by closing the Sdk bottom sheet
|
||||
}
|
||||
else -> {
|
||||
Timber.e(result.error)
|
||||
dispatch(SendAction.SendError(TapError.BlockchainInternalError))
|
||||
Timber.e(throwable)
|
||||
FirebaseCrashlytics.getInstance().recordException(throwable)
|
||||
dispatch(SendAction.SendError(TapError.CustomError(message)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +132,6 @@ private fun verifyAndSendTransaction(
|
|||
dispatch(SendAction.ChangeSendButtonState(SendButtonState.ENABLED))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun extractErrorsForAmountField(errors: EnumSet<TransactionError>): EnumSet<TransactionError> {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ private class SendReducer : SendInternalReducer {
|
|||
override fun handle(action: SendScreenAction, sendState: SendState): SendState {
|
||||
val result = when (action) {
|
||||
is SendAction.ChangeSendButtonState -> sendState.copy(sendButtonState = action.state)
|
||||
is SendAction.Dialog.ShowTezosWarningDialog -> sendState.copy(dialog = action)
|
||||
is SendAction.Dialog.Hide -> sendState.copy(dialog = null)
|
||||
else -> return sendState
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.tap.common.CurrencyConverter
|
|||
import com.tangem.tap.common.entities.TapCurrency
|
||||
import com.tangem.tap.common.text.DecimalDigitsInputFilter
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.StateType
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -35,7 +36,8 @@ data class SendState(
|
|||
val amountState: AmountState = AmountState(),
|
||||
val feeState: FeeState = FeeState(),
|
||||
val receiptState: ReceiptState = ReceiptState(),
|
||||
val sendButtonState: SendButtonState = SendButtonState.DISABLED
|
||||
val sendButtonState: SendButtonState = SendButtonState.DISABLED,
|
||||
val dialog: SendAction.Dialog? = null
|
||||
) : SendScreenState {
|
||||
|
||||
override val stateId: StateId = StateId.SEND_SCREEN
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.tap.features.send.ui.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
class TezosWarningDialog(context: Context) : AlertDialog(context) {
|
||||
|
||||
companion object {
|
||||
fun create(context: Context, showDialogData: SendAction.Dialog.ShowTezosWarningDialog): AlertDialog {
|
||||
val reduceAmount = showDialogData.reduceAmount.toPlainString()
|
||||
return Builder(context).apply {
|
||||
setTitle(context.getString(R.string.common_warning))
|
||||
setMessage(context.getString(R.string.xtz_withdrawal_message_warning, reduceAmount))
|
||||
setNegativeButton(R.string.xtz_withdrawal_message_ignore) { _, _ ->
|
||||
showDialogData.sendAllCallback()
|
||||
}
|
||||
setPositiveButton(context.getString(R.string.xtz_withdrawal_message_reduce, reduceAmount)) { _, _ ->
|
||||
showDialogData.reduceCallback()
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(SendAction.Dialog.Hide)
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.send.ui.stateSubscribers
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.ViewGroup
|
||||
|
|
@ -16,10 +17,12 @@ import com.tangem.tap.domain.assembleErrors
|
|||
import com.tangem.tap.features.send.BaseStoreFragment
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.reducers.ReceiptReducer
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.send.ui.FeeUiHelper
|
||||
import com.tangem.tap.features.send.ui.SendFragment
|
||||
import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.btn_expand_collapse.*
|
||||
|
|
@ -37,6 +40,8 @@ import kotlinx.android.synthetic.main.layout_send_receipt.*
|
|||
*/
|
||||
class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber<SendState>(fragment) {
|
||||
|
||||
private var dialog: Dialog? = null
|
||||
|
||||
override fun updateWithNewState(fg: BaseStoreFragment, state: SendState) {
|
||||
val lastChangedStates = state.lastChangedStates.toList()
|
||||
state.lastChangedStates.clear()
|
||||
|
|
@ -54,6 +59,19 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
private fun handleSendScreen(fg: BaseStoreFragment, state: SendState) {
|
||||
val sendFragment = (fg as? SendFragment) ?: return
|
||||
|
||||
when (state.dialog) {
|
||||
is SendAction.Dialog.ShowTezosWarningDialog -> {
|
||||
if (dialog == null) {
|
||||
dialog = TezosWarningDialog.create(fg.requireContext(), state.dialog)
|
||||
dialog?.show()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
dialog?.dismiss()
|
||||
dialog = null
|
||||
}
|
||||
}
|
||||
|
||||
when (state.sendButtonState) {
|
||||
SendButtonState.ENABLED -> {
|
||||
fg.btnSend.isEnabled = true
|
||||
|
|
@ -235,10 +253,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
totalLayout.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}")
|
||||
|
||||
val willSent = getString(
|
||||
R.string.send_total_subtitle_asset_format,
|
||||
receipt.symbols.token ?: "", receipt.willSentToken,
|
||||
receipt.symbols.crypto, receipt.willSentFeeCoin
|
||||
)
|
||||
R.string.send_total_subtitle_asset_format,
|
||||
receipt.symbols.token ?: "", receipt.willSentToken,
|
||||
receipt.symbols.crypto, receipt.willSentFeeCoin
|
||||
)
|
||||
totalLayout.tvWillBeSentValue.update(willSent)
|
||||
}
|
||||
ReceiptLayoutType.TOKEN_CRYPTO -> {
|
||||
|
|
|
|||
|
|
@ -11,15 +11,21 @@ data class PendingTransaction(
|
|||
val type: PendingTransactionType
|
||||
)
|
||||
|
||||
enum class PendingTransactionType { Incoming, Outcoming }
|
||||
enum class PendingTransactionType { Incoming, Outgoing, Unknown }
|
||||
|
||||
fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransaction? {
|
||||
if (this.status == TransactionStatus.Confirmed) return null
|
||||
|
||||
val type: PendingTransactionType = if (this.sourceAddress == walletAddress) {
|
||||
PendingTransactionType.Outcoming
|
||||
} else {
|
||||
PendingTransactionType.Incoming
|
||||
val type: PendingTransactionType = when {
|
||||
// this.sourceAddress == walletAddress -> {
|
||||
// PendingTransactionType.Outgoing
|
||||
// }
|
||||
// this.destinationAddress == walletAddress -> {
|
||||
// PendingTransactionType.Incoming
|
||||
// }
|
||||
else -> {
|
||||
PendingTransactionType.Unknown
|
||||
}
|
||||
}
|
||||
val address = if (this.sourceAddress == walletAddress) {
|
||||
this.destinationAddress
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ sealed class WalletAction : Action {
|
|||
object Failure : WalletAction()
|
||||
}
|
||||
|
||||
object DisablePayId: WalletAction()
|
||||
|
||||
data class LoadArtwork(val card: Card, val artworkId: String?) : WalletAction() {
|
||||
data class Success(val artwork: Artwork) : WalletAction()
|
||||
object Failure : WalletAction()
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
is WalletAction.LoadPayId.NotCreated -> newState = newState.copy(
|
||||
payIdData = PayIdData(PayIdState.NotCreated, null)
|
||||
)
|
||||
is WalletAction.DisablePayId -> newState = newState.copy(
|
||||
payIdData = PayIdData(PayIdState.Disabled, null)
|
||||
)
|
||||
is WalletAction.CreatePayId, is WalletAction.CreatePayId.Failure ->
|
||||
newState = newState.copy(
|
||||
walletDialog = WalletDialog.CreatePayIdDialog(CreatingPayIdState.EnterPayId)
|
||||
|
|
|
|||
|
|
@ -42,15 +42,18 @@ class PendingTransactionsAdapter
|
|||
fun bind(transaction: PendingTransaction) {
|
||||
val transactionDescriptionRes = when (transaction.type) {
|
||||
PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving
|
||||
PendingTransactionType.Outcoming -> R.string.wallet_pending_tx_sending
|
||||
PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending
|
||||
PendingTransactionType.Unknown -> return
|
||||
}
|
||||
val transactionAddressRes = when (transaction.type) {
|
||||
PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving_address_format
|
||||
PendingTransactionType.Outcoming -> R.string.wallet_pending_tx_sending_address_format
|
||||
PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending_address_format
|
||||
PendingTransactionType.Unknown -> return
|
||||
}
|
||||
val image = when (transaction.type) {
|
||||
PendingTransactionType.Incoming -> R.drawable.ic_arrow_left
|
||||
PendingTransactionType.Outcoming -> R.drawable.ic_arrow_right_20
|
||||
PendingTransactionType.Outgoing -> R.drawable.ic_arrow_right_20
|
||||
PendingTransactionType.Unknown -> return
|
||||
}
|
||||
view.tv_pending_transaction.text = view.context.getString(transactionDescriptionRes)
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
|
|
@ -9,6 +9,7 @@
|
|||
<string name="common_done">Done</string>
|
||||
<string name="common_cancel">Cancel</string>
|
||||
<string name="common_accept">Accept</string>
|
||||
<string name="common_custom_string" translatable="false">%s</string>
|
||||
|
||||
<string name="common_camera_denied_alert_title">Camera access denied</string>
|
||||
<string name="common_camera_denied_alert_message">You have not given access to your camera, please adjust your privacy settings</string>
|
||||
|
|
|
|||
7
app/src/main/res/values/strings_untranslated.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<string name="xtz_withdrawal_message_warning" translatable="false">To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_reduce" translatable="false">Reduce by %s XTZ</string>
|
||||
<string name="xtz_withdrawal_message_ignore" translatable="false">No, send all</string>
|
||||
|
||||
</resources>
|
||||
1
blockchain-demo/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
/build
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.blockchain_demo"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'lib/x86_64/darwin/libscrypt.dylib'
|
||||
exclude 'lib/x86_64/freebsd/libscrypt.so'
|
||||
exclude 'lib/x86_64/linux/libscrypt.so'
|
||||
}
|
||||
|
||||
viewBinding {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':blockchain')
|
||||
|
||||
implementation 'com.tangem:core:0.10.4'
|
||||
implementation 'com.tangem:sdk:0.10.4'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
21
blockchain-demo/proguard-rules.pro
vendored
|
|
@ -1,21 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.tangem.blockchain_demo
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.blockchain_demo", appContext.packageName)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.tangem.blockchain_demo">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.nfc"
|
||||
android:required="true" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name="com.tangem.blockchain_demo.BlockchainDemoActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data
|
||||
android:host="www.tangem.com"
|
||||
android:scheme="http" />
|
||||
<data
|
||||
android:host="www.tangem.com"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="tangem.com"
|
||||
android:scheme="http" />
|
||||
<data
|
||||
android:host="tangem.com"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.TECH_DISCOVERED" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.nfc.action.TECH_DISCOVERED"
|
||||
android:resource="@xml/nfc_tech_filter" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
package com.tangem.blockchain_demo
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.TangemSdkError
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.Signer
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.blockchain_demo.databinding.ActivityBlockchainDemoBinding
|
||||
import com.tangem.commands.Card
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.tangem_sdk_new.extensions.init
|
||||
import kotlinx.coroutines.*
|
||||
import java.math.BigDecimal
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BlockchainDemoActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var tangemSdk: TangemSdk
|
||||
private lateinit var signer: TransactionSigner
|
||||
private lateinit var card: Card
|
||||
private lateinit var walletManager: WalletManager
|
||||
private var issuerDataCounter: Int = 1
|
||||
|
||||
private lateinit var fee: BigDecimal
|
||||
|
||||
private lateinit var binding: ActivityBlockchainDemoBinding
|
||||
|
||||
private val parentJob = Job()
|
||||
private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
|
||||
handleError(throwable.localizedMessage)
|
||||
}
|
||||
private val coroutineContext: CoroutineContext
|
||||
get() = parentJob + Dispatchers.IO + exceptionHandler
|
||||
private val scope = CoroutineScope(coroutineContext)
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityBlockchainDemoBinding.inflate(layoutInflater)
|
||||
val view = binding.root
|
||||
setContentView(view)
|
||||
|
||||
tangemSdk = TangemSdk.init(this)
|
||||
signer = Signer(tangemSdk)
|
||||
|
||||
binding.btnScan.setOnClickListener { scan() }
|
||||
|
||||
binding.btnCheckFee.setOnClickListener { requestFee() }
|
||||
|
||||
binding.btnSend.setOnClickListener { send() }
|
||||
}
|
||||
|
||||
|
||||
private fun scan() {
|
||||
tangemSdk.scanCard { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
walletManager = WalletManagerFactory.makeWalletManager(result.data)!!
|
||||
getInfo()
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
if (result.error !is TangemSdkError.UserCancelled) {
|
||||
handleError(result.error.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInfo() {
|
||||
scope.launch {
|
||||
walletManager.update()
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.tvBalance.text =
|
||||
"${walletManager.wallet.amounts[AmountType.Coin]?.value?.toPlainString()
|
||||
?: "error"} ${walletManager.wallet.blockchain.currency}"
|
||||
val token = walletManager.wallet.amounts[AmountType.Token]
|
||||
if (token != null) {
|
||||
binding.tvBalance.text = token.value?.toPlainString() + " " + token.currencySymbol
|
||||
binding.etSumToSend.text = Editable.Factory.getInstance().newEditable(
|
||||
token.value?.toPlainString() ?: ""
|
||||
)
|
||||
} else {
|
||||
binding.etSumToSend.text =
|
||||
Editable.Factory.getInstance().newEditable(
|
||||
walletManager.wallet.amounts[AmountType.Coin]?.value?.toPlainString()
|
||||
)
|
||||
}
|
||||
binding.btnCheckFee.isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestFee() {
|
||||
if (binding.etReceiverAddress.text.isBlank()) {
|
||||
Toast.makeText(this, "Please enter receiver address", Toast.LENGTH_LONG).show()
|
||||
return
|
||||
} else if (binding.etSumToSend.text.isBlank()) {
|
||||
Toast.makeText(this, "Choose sum to send", Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
val feeResult = (walletManager as TransactionSender).getFee(
|
||||
walletManager.wallet.amounts[AmountType.Token]
|
||||
?: walletManager.wallet.amounts[AmountType.Coin]!!,
|
||||
binding.etReceiverAddress.text.toString())
|
||||
withContext(Dispatchers.Main) {
|
||||
when (feeResult) {
|
||||
is Result.Failure -> {
|
||||
handleError(feeResult.error?.localizedMessage ?: "Error")
|
||||
}
|
||||
is Result.Success -> {
|
||||
binding.btnSend.isEnabled = true
|
||||
val fees = feeResult.data
|
||||
if (fees.size == 1) {
|
||||
binding.tvFee.text = fees[0].value.toString()
|
||||
fee = fees[0].value ?: BigDecimal(0)
|
||||
} else {
|
||||
binding.tvFee.text = fees[0].value.toString() + "\n" +
|
||||
fees[1].value.toString() + "\n" +
|
||||
fees[2].value.toString()
|
||||
fee = fees[1].value ?: BigDecimal(0)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun send() {
|
||||
scope.launch {
|
||||
val result = (walletManager as TransactionSender).send(
|
||||
formTransactionData(),
|
||||
signer)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is SimpleResult.Failure -> {
|
||||
handleError(result.error?.localizedMessage ?: "Error")
|
||||
}
|
||||
is SimpleResult.Success -> {
|
||||
binding.tvFee.text = "Success"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formTransactionData(): TransactionData {
|
||||
val amount = if (walletManager.wallet.amounts[AmountType.Token] != null) {
|
||||
walletManager.wallet.amounts[AmountType.Token]!!.copy(
|
||||
value = binding.etSumToSend.text.toString().toBigDecimal()
|
||||
)
|
||||
} else {
|
||||
walletManager.wallet.amounts[AmountType.Coin]!!.copy(
|
||||
value = binding.etSumToSend.text.toString().toBigDecimal() - fee
|
||||
)
|
||||
}
|
||||
return TransactionData(
|
||||
amount,
|
||||
walletManager.wallet.amounts[AmountType.Coin]!!.copy(value = fee),
|
||||
walletManager.wallet.amounts[AmountType.Coin]!!.address!!,
|
||||
binding.etReceiverAddress.text.toString(),
|
||||
contractAddress = walletManager.wallet.amounts[AmountType.Token]?.address
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleError(error: String?) {
|
||||
Toast.makeText(this, error, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".BlockchainDemoActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_balance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:layout_weight="3"
|
||||
android:padding="16dp"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="26sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="BTC 0.500000034" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_fee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="48dp"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"
|
||||
app:layout_constraintBottom_toTopOf="@id/et_receiver_address"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
tools:text="MinFee: 200, Fee: 300, Priority: 400" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_receiver_address"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="60dp"
|
||||
android:hint="Send to:"
|
||||
app:layout_constraintBottom_toTopOf="@id/et_sum_to_send"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_sum_to_send"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:hint="Enter amount to send"
|
||||
app:layout_constraintBottom_toTopOf="@id/btn_scan"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Scan card and get info"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.6" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_check_fee"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:enabled="false"
|
||||
android:text="Check fee"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_scan" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_send"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:enabled="false"
|
||||
android:text="Send transaction"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_check_fee" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#527Aff</color>
|
||||
<color name="colorPrimaryDark">#027AFF</color>
|
||||
<color name="colorAccent">#027AFF</color>
|
||||
<color name="fab">#4f98c0</color>
|
||||
</resources>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<resources>
|
||||
<string name="app_name">Blockchain Demo</string>
|
||||
</resources>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<tech-list>
|
||||
<tech>android.nfc.tech.IsoDep</tech>
|
||||
<tech>android.nfc.tech.Ndef</tech>
|
||||
<tech>android.nfc.tech.NfcV</tech>
|
||||
</tech-list>
|
||||
</resources>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package com.tangem.blockchain_demo
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
1
blockchain/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
/build
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.tangem:core:1.13'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
|
||||
implementation 'com.squareup.retrofit2:converter-moshi:2.6.0'
|
||||
implementation 'com.squareup.moshi:moshi:1.9.2'
|
||||
implementation "com.squareup.moshi:moshi-kotlin:1.9.2"
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:1.9.2")
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3"
|
||||
|
||||
implementation 'org.bitcoinj:bitcoinj-core:0.15.2'
|
||||
implementation 'com.github.stellar:java-stellar-sdk:0.14.0'
|
||||
|
||||
implementation "com.madgag.spongycastle:core:1.58.0.0"
|
||||
implementation "com.madgag.spongycastle:prov:1.58.0.0"
|
||||
|
||||
ext.kethereum_version = '0.81.2'
|
||||
implementation "com.github.walleth.kethereum:extensions_kotlin:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:extensions_transactions:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:erc55:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:keccak_shortcut:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:wallet:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:crypto_impl_spongycastle:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:crypto:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:crypto_api:$kethereum_version"
|
||||
implementation "com.github.walleth.kethereum:model:$kethereum_version"
|
||||
|
||||
implementation 'co.nstant.in:cbor:0.8'
|
||||
|
||||
implementation files('libs/ripple-core-0.0.1.jar')
|
||||
//4 dependencies for ripple-core
|
||||
implementation 'net.i2p.crypto:eddsa:0.3.0'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.61'
|
||||
//noinspection DuplicatePlatformClasses
|
||||
implementation 'org.json:json:20180813'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
|
||||
|
||||
//dependencies for binance
|
||||
implementation 'com.google.protobuf:protobuf-java:3.6.1'
|
||||
implementation 'io.grpc:grpc-protobuf:1.17.1'
|
||||
implementation 'io.grpc:grpc-stub:1.17.1'
|
||||
implementation 'commons-codec:commons-codec:1.10'
|
||||
implementation 'org.apache.commons:commons-lang3:3.6'
|
||||
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.8'
|
||||
implementation 'joda-time:joda-time:2.10.1'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation 'com.squareup.retrofit2:converter-jackson:2.6.0'
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
|
||||
testImplementation "com.google.truth:truth:1.0"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
||||
21
blockchain/proguard-rules.pro
vendored
|
|
@ -1,21 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
|
@ -1 +0,0 @@
|
|||
<manifest package="com.tangem.blockchain" />
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.Crypto
|
||||
import com.tangem.blockchain.common.AddressService
|
||||
import com.tangem.common.extensions.calculateRipemd160
|
||||
import com.tangem.common.extensions.calculateSha256
|
||||
import com.tangem.common.extensions.toCompressedPublicKey
|
||||
import org.bitcoinj.core.Bech32
|
||||
|
||||
class BinanceAddressService(private val testNet: Boolean = false) : AddressService {
|
||||
override fun makeAddress(walletPublicKey: ByteArray): String {
|
||||
val publicKeyHash = walletPublicKey.toCompressedPublicKey().calculateSha256().calculateRipemd160()
|
||||
return if (testNet) {
|
||||
Bech32.encode("tbnb", Crypto.convertBits(publicKeyHash, 0,
|
||||
publicKeyHash.size, 8, 5, false)
|
||||
)
|
||||
} else {
|
||||
Bech32.encode("bnb", Crypto.convertBits(publicKeyHash, 0,
|
||||
publicKeyHash.size, 8, 5, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun validate(address: String): Boolean {
|
||||
return try {
|
||||
Crypto.decodeAddress(address)
|
||||
if (testNet) {
|
||||
address.startsWith("tbnb1")
|
||||
} else {
|
||||
address.startsWith("bnb1")
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class BinanceChain(val value: String) {
|
||||
Nile("Binance-Chain-Nile"),
|
||||
Tigris("Binance-Chain-Tigris");
|
||||
|
||||
companion object {
|
||||
fun getChain(testNet: Boolean): BinanceChain = if (testNet) Nile else Tigris
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.TransactionOption
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.Transfer
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.message.MessageType
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.message.TransactionRequestAssemblerExtSign
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.message.TransferMessage
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.isAboveZero
|
||||
import com.tangem.common.extensions.calculateSha256
|
||||
import com.tangem.common.extensions.toCompressedPublicKey
|
||||
import org.bitcoinj.core.ECKey
|
||||
import org.bitcoinj.core.Utils
|
||||
import java.math.BigInteger
|
||||
|
||||
class BinanceTransactionBuilder(
|
||||
publicKey: ByteArray, isTestNet: Boolean = false
|
||||
) {
|
||||
var accountNumber: Long? = null
|
||||
var sequence: Long? = null
|
||||
|
||||
private val chainId = BinanceChain.getChain(isTestNet).value
|
||||
private val prefixedPubKey = MessageType.PubKey.typePrefixBytes + 33.toByte() + publicKey.toCompressedPublicKey()
|
||||
|
||||
private var transactionAssembler: TransactionRequestAssemblerExtSign? = null
|
||||
private var transferMessage: TransferMessage? = null
|
||||
|
||||
fun buildToSign(transactionData: TransactionData): Result<ByteArray> {
|
||||
val amount = transactionData.amount
|
||||
|
||||
if (!amount.isAboveZero()) return Result.Failure(Exception("Transaction amount is not defined"))
|
||||
val accountNumber = accountNumber ?: return Result.Failure(Exception("No account number"))
|
||||
val sequence = sequence ?: return Result.Failure(Exception("No sequence"))
|
||||
|
||||
val transfer = Transfer()
|
||||
transfer.coin = if (amount.type == AmountType.Coin) amount.currencySymbol else amount.address
|
||||
transfer.fromAddress = transactionData.sourceAddress
|
||||
transfer.toAddress = transactionData.destinationAddress
|
||||
transfer.amount = transactionData.amount.value!!
|
||||
.setScale(Blockchain.Binance.decimals()).toPlainString()
|
||||
|
||||
val options = TransactionOption.DEFAULT_INSTANCE
|
||||
|
||||
val accountData = BinanceAccountData(chainId, accountNumber, sequence)
|
||||
|
||||
transactionAssembler = TransactionRequestAssemblerExtSign(accountData, prefixedPubKey, options)
|
||||
transferMessage = transactionAssembler!!.createTransferMessage(transfer)
|
||||
|
||||
return Result.Success(transactionAssembler!!.prepareForSign(transferMessage).calculateSha256())
|
||||
}
|
||||
|
||||
fun buildToSend(signature: ByteArray): ByteArray {
|
||||
val r = BigInteger(1, signature.copyOfRange(0, 32))
|
||||
val s = BigInteger(1, signature.copyOfRange(32, 64))
|
||||
val canonicalS = ECKey.ECDSASignature(r, s).toCanonicalised().s
|
||||
|
||||
//bigIntegerToBytes cuts leading zero if present
|
||||
val canonicalSignature = Utils.bigIntegerToBytes(r, 32) + Utils.bigIntegerToBytes(canonicalS, 32)
|
||||
val encodedSignature = transactionAssembler!!.encodeSignature(canonicalSignature)
|
||||
|
||||
val encodedTransferMessage = transactionAssembler!!.encodeTransferMessage(transferMessage)
|
||||
|
||||
return transactionAssembler!!.encodeStdTx(encodedTransferMessage, encodedSignature)
|
||||
}
|
||||
}
|
||||
|
||||
data class BinanceAccountData(
|
||||
val chainId: String,
|
||||
val accountNumber: Long,
|
||||
val sequence: Long
|
||||
)
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance
|
||||
|
||||
import android.util.Log
|
||||
import com.tangem.blockchain.blockchains.binance.network.BinanceNetworkManager
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.blockchain.blockchains.binance.network.BinanceInfoResponse
|
||||
|
||||
class BinanceWalletManager(
|
||||
cardId: String,
|
||||
wallet: Wallet,
|
||||
private val transactionBuilder: BinanceTransactionBuilder,
|
||||
private val networkManager: BinanceNetworkManager
|
||||
) : WalletManager(cardId, wallet), TransactionSender {
|
||||
|
||||
private val blockchain = wallet.blockchain
|
||||
|
||||
override suspend fun update() {
|
||||
val result = networkManager.getInfo(wallet.address, wallet.amounts[AmountType.Token]?.address)
|
||||
when (result) {
|
||||
is Result.Success -> updateWallet(result.data)
|
||||
is Result.Failure -> updateError(result.error)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWallet(response: BinanceInfoResponse) {
|
||||
Log.d(this::class.java.simpleName, "Balance is ${response.balance}")
|
||||
wallet.amounts[AmountType.Coin]?.value = response.balance
|
||||
wallet.amounts[AmountType.Token]?.value = response.assetBalance
|
||||
|
||||
transactionBuilder.accountNumber = response.accountNumber
|
||||
transactionBuilder.sequence = response.sequence
|
||||
}
|
||||
|
||||
private fun updateError(error: Throwable?) {
|
||||
Log.e(this::class.java.simpleName, error?.message ?: "")
|
||||
if (error != null) throw error
|
||||
}
|
||||
|
||||
override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult {
|
||||
val buildTransactionResult = transactionBuilder.buildToSign(transactionData)
|
||||
when (buildTransactionResult) {
|
||||
is Result.Failure -> return SimpleResult.Failure(buildTransactionResult.error)
|
||||
is Result.Success -> {
|
||||
when (val signerResponse = signer.sign(arrayOf(buildTransactionResult.data), cardId)) {
|
||||
is CompletionResult.Success -> {
|
||||
val transactionToSend = transactionBuilder.buildToSend(signerResponse.data.signature)
|
||||
return networkManager.sendTransaction(transactionToSend)
|
||||
}
|
||||
is CompletionResult.Failure -> return SimpleResult.Failure(signerResponse.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getFee(amount: Amount, destination: String): Result<List<Amount>> {
|
||||
when (val result = networkManager.getFee()) {
|
||||
is Result.Success -> return Result.Success(listOf(Amount(result.data, blockchain)))
|
||||
is Result.Failure -> return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Account;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.AccountSequence;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Candlestick;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Infos;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Market;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Order;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderBook;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderList;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Peer;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TickerStatistics;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Time;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Token;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TradePage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionMetadata;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionPage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Validators;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface BinanceDexApi {
|
||||
@GET("/api/v1/time")
|
||||
Call<Time> getTime();
|
||||
|
||||
@GET("/api/v1/node-info")
|
||||
Call<Infos> getNodeInfo();
|
||||
|
||||
@GET("/api/v1/validators")
|
||||
Call<Validators> getValidators();
|
||||
|
||||
@GET("/api/v1/peers")
|
||||
Call<List<Peer>> getPeers();
|
||||
|
||||
@GET("/api/v1/account/{address}")
|
||||
Call<Account> getAccount(@Path("address") String address);
|
||||
|
||||
@GET("/api/v1/account/{address}/sequence")
|
||||
Call<AccountSequence> getAccountSequence(@Path("address") String address);
|
||||
|
||||
@GET("/api/v1/tx/{hash}")
|
||||
Call<TransactionMetadata> getTransactionMetadata(@Path("hash") String hash);
|
||||
|
||||
@GET("/api/v1/tokens")
|
||||
Call<List<Token>> getTokens();
|
||||
|
||||
@GET("/api/v1/markets")
|
||||
Call<List<Market>> getMarkets();
|
||||
|
||||
|
||||
@GET("/api/v1/depth")
|
||||
Call<OrderBook> getOrderBook(@Query("symbol") String symbol, @Query("limit") Integer limit);
|
||||
|
||||
@GET("/api/v1/klines")
|
||||
Call<List<Candlestick>> getCandlestickBars(@Query("symbol") String symbol, @Query("interval") String interval,
|
||||
@Query("limit") Integer limit, @Query("startTime") Long startTime,
|
||||
@Query("endTime") Long endTime);
|
||||
|
||||
@GET("/api/v1/orders/open")
|
||||
Call<OrderList> getOpenOrders(@Query("address") String address, @Query("limit") Integer limit,
|
||||
@Query("offset") Integer offset, @Query("symbol") String symbol,
|
||||
@Query("total") Integer total);
|
||||
|
||||
@GET("/api/v1/orders/closed")
|
||||
Call<OrderList> getClosedOrders(@Query("address") String address, @Query("end") Long end,
|
||||
@Query("limit") Integer limit, @Query("offset") Integer offset,
|
||||
@Query("side") String side, @Query("start") Long start,
|
||||
@Query("status") List<String> status, @Query("symbol") String symbol,
|
||||
@Query("total") Integer total);
|
||||
|
||||
@GET("/api/v1/orders/{id}")
|
||||
Call<Order> getOrder(@Path("id") String id);
|
||||
|
||||
@GET("/api/v1/ticker/24hr")
|
||||
Call<List<TickerStatistics>> get24HrPriceStatistics();
|
||||
|
||||
@GET("/api/v1/trades")
|
||||
Call<TradePage> getTrades(@Query("address") String address,
|
||||
@Query("buyerOrderId") String buyerOrderId, @Query("end") Long end,
|
||||
@Query("height") Long height, @Query("limit") Integer limit,
|
||||
@Query("offset") Integer offset, @Query("quoteAsset") String quoteAsset,
|
||||
@Query("sellerOrderId") String sellerOrderId, @Query("side") String side,
|
||||
@Query("start") Long start, @Query("symbol") String symbol, @Query("total") Integer total);
|
||||
|
||||
@GET("/api/v1/transactions")
|
||||
Call<TransactionPage> getTransactions(@Query("address") String address, @Query("blockHeight") Long blockHeight,
|
||||
@Query("endTime") Long endTime, @Query("limit") Integer limit,
|
||||
@Query("offset") Integer offset, @Query("side") String side,
|
||||
@Query("startTime") Long startTime, @Query("txAsset") String txAsset,
|
||||
@Query("txType") String txType);
|
||||
|
||||
@POST("/api/v1/broadcast")
|
||||
Call<List<TransactionMetadata>> broadcast(@Query("sync") boolean sync, @Body RequestBody transaction);
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Account;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.AccountSequence;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Candlestick;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.CandlestickInterval;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Infos;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Market;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Order;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderBook;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderList;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Peer;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TickerStatistics;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Time;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Token;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TradePage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionMetadata;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionPage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Validators;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.ClosedOrdersRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.OpenOrdersRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.TradesRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.TransactionsRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BinanceDexApiAsyncRestClient {
|
||||
void getTime(BinanceDexApiCallback<Time> callback);
|
||||
|
||||
void getNodeInfo(BinanceDexApiCallback<Infos> callback);
|
||||
|
||||
void getValidators(BinanceDexApiCallback<Validators> callback);
|
||||
|
||||
void getPeers(BinanceDexApiCallback<List<Peer>> callback);
|
||||
|
||||
void getMarkets(BinanceDexApiCallback<List<Market>> callback);
|
||||
|
||||
void getAccount(String address, BinanceDexApiCallback<Account> callback);
|
||||
|
||||
void getAccountSequence(String address, BinanceDexApiCallback<AccountSequence> callback);
|
||||
|
||||
void getTransactionMetadata(String hash, BinanceDexApiCallback<TransactionMetadata> callback);
|
||||
|
||||
void getTokens(BinanceDexApiCallback<List<Token>> callback);
|
||||
|
||||
void getOrderBook(String symbol, Integer limit, BinanceDexApiCallback<OrderBook> callback);
|
||||
|
||||
void getCandleStickBars(String symbol, CandlestickInterval interval,
|
||||
BinanceDexApiCallback<List<Candlestick>> callback);
|
||||
|
||||
void getCandleStickBars(String symbol, CandlestickInterval interval, Integer limit, Long startTime, Long endTime,
|
||||
BinanceDexApiCallback<List<Candlestick>> callback);
|
||||
|
||||
void getOpenOrders(String address, BinanceDexApiCallback<OrderList> callback);
|
||||
|
||||
void getOpenOrders(OpenOrdersRequest request, BinanceDexApiCallback<OrderList> callback);
|
||||
|
||||
void getClosedOrders(String address, BinanceDexApiCallback<OrderList> callback);
|
||||
|
||||
void getClosedOrders(ClosedOrdersRequest request, BinanceDexApiCallback<OrderList> callback);
|
||||
|
||||
void getOrder(String id, BinanceDexApiCallback<Order> callback);
|
||||
|
||||
void get24HrPriceStatistics(BinanceDexApiCallback<List<TickerStatistics>> callback);
|
||||
|
||||
void getTrades(BinanceDexApiCallback<TradePage> callback);
|
||||
|
||||
void getTrades(TradesRequest request, BinanceDexApiCallback<TradePage> callback);
|
||||
|
||||
void getTransactions(String address, BinanceDexApiCallback<TransactionPage> callback);
|
||||
|
||||
void getTransactions(TransactionsRequest request, BinanceDexApiCallback<TransactionPage> callback);
|
||||
|
||||
// Do not support async broadcast due to account sequence
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
/**
|
||||
* BinanceDexApiCallback is a functional interface used together with the BinanceApiAsyncClient to provide a non-blocking REST client.
|
||||
*
|
||||
* @param <T> the return type from the callback
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BinanceDexApiCallback<T> {
|
||||
|
||||
/**
|
||||
* Called whenever a response comes back from the Binance API.
|
||||
*
|
||||
* @param response the expected response object
|
||||
*/
|
||||
void onResponse(T response);
|
||||
|
||||
/**
|
||||
* Called whenever an error occurs.
|
||||
*
|
||||
* @param cause the cause of the failure
|
||||
*/
|
||||
default void onFailure(Throwable cause) {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
import static com.tangem.blockchain.blockchains.binance.client.BinanceDexApiClientGenerator.getBinanceApiError;
|
||||
|
||||
/**
|
||||
* An adapter/wrapper which transforms a Callback from Retrofit into a BinanceDexApiCallback which is exposed to the client.
|
||||
*/
|
||||
public class BinanceDexApiCallbackAdapter<T> implements Callback<T> {
|
||||
|
||||
private final BinanceDexApiCallback<T> callback;
|
||||
|
||||
public BinanceDexApiCallbackAdapter(BinanceDexApiCallback<T> callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public void onResponse(Call<T> call, Response<T> response) {
|
||||
if (response.isSuccessful()) {
|
||||
callback.onResponse(response.body());
|
||||
} else {
|
||||
if (response.code() == 504) {
|
||||
// HTTP 504 return code is used when the API successfully sent the message but not get a response within the timeout period.
|
||||
// It is important to NOT treat this as a failure; the execution status is UNKNOWN and could have been a success.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
BinanceDexApiError apiError = getBinanceApiError(response);
|
||||
onFailure(call, new BinanceDexApiException(apiError));
|
||||
} catch (IOException e) {
|
||||
onFailure(call, new BinanceDexApiException(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<T> call, Throwable throwable) {
|
||||
if (throwable instanceof BinanceDexApiException) {
|
||||
callback.onFailure(throwable);
|
||||
} else {
|
||||
callback.onFailure(new BinanceDexApiException(throwable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.impl.BinanceDexApiAsyncRestClientImpl;
|
||||
import com.tangem.blockchain.blockchains.binance.client.impl.BinanceDexApiRestClientImpl;
|
||||
|
||||
public class BinanceDexApiClientFactory {
|
||||
private BinanceDexApiClientFactory() {
|
||||
}
|
||||
|
||||
public static BinanceDexApiClientFactory newInstance() {
|
||||
return new BinanceDexApiClientFactory();
|
||||
}
|
||||
|
||||
public BinanceDexApiRestClient newRestClient() {
|
||||
return newRestClient(BinanceDexEnvironment.PROD.getBaseUrl());
|
||||
}
|
||||
|
||||
public BinanceDexApiRestClient newRestClient(String baseUrl) {
|
||||
return new BinanceDexApiRestClientImpl(baseUrl);
|
||||
}
|
||||
|
||||
public BinanceDexApiAsyncRestClient newAsyncRestClient() {
|
||||
return newAsyncRestClient(BinanceDexEnvironment.PROD.getBaseUrl());
|
||||
}
|
||||
|
||||
public BinanceDexApiAsyncRestClient newAsyncRestClient(String baseUrl) {
|
||||
return new BinanceDexApiAsyncRestClientImpl(baseUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.joda.JodaModule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Converter;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory;
|
||||
|
||||
public class BinanceDexApiClientGenerator {
|
||||
private static final OkHttpClient sharedClient = new OkHttpClient.Builder()
|
||||
.pingInterval(20, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
private static final Converter.Factory converterFactory =
|
||||
JacksonConverterFactory.create(new ObjectMapper().registerModule(new JodaModule()));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Converter<ResponseBody, BinanceDexApiError> errorBodyConverter =
|
||||
(Converter<ResponseBody, BinanceDexApiError>) converterFactory.responseBodyConverter(
|
||||
BinanceDexApiError.class, new Annotation[0], null);
|
||||
|
||||
public static <S> S createService(Class<S> serviceClass, String baseUrl) {
|
||||
Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(converterFactory);
|
||||
|
||||
retrofitBuilder.client(sharedClient);
|
||||
|
||||
Retrofit retrofit = retrofitBuilder.build();
|
||||
|
||||
return retrofit.create(serviceClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a REST call and block until the response is received.
|
||||
*/
|
||||
public static <T> T executeSync(Call<T> call) {
|
||||
try {
|
||||
Response<T> response = call.execute();
|
||||
if (response.isSuccessful()) {
|
||||
return response.body();
|
||||
} else {
|
||||
try {
|
||||
BinanceDexApiError apiError = getBinanceApiError(response);
|
||||
throw new BinanceDexApiException(apiError);
|
||||
} catch (IOException e) {
|
||||
throw new BinanceDexApiException(response.toString(), e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new BinanceDexApiException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts and converts the response error body into an object.
|
||||
*/
|
||||
public static BinanceDexApiError getBinanceApiError(Response<?> response) throws IOException {
|
||||
return errorBodyConverter.convert(response.errorBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared OkHttpClient instance.
|
||||
*/
|
||||
public static OkHttpClient getSharedClient() {
|
||||
return sharedClient;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class BinanceDexApiError {
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("code", code)
|
||||
.append("message", message)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
|
||||
public class BinanceDexApiException extends RuntimeException {
|
||||
private static final long serialVersionUID = 3788669840036201041L;
|
||||
private BinanceDexApiError error;
|
||||
|
||||
public BinanceDexApiException(BinanceDexApiError error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public BinanceDexApiException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public BinanceDexApiException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BinanceDexApiError getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
if (error != null) {
|
||||
return error.getMessage();
|
||||
}
|
||||
return super.getMessage();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.BinanceAccountData;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Account;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.AccountSequence;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Candlestick;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.CandlestickInterval;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Infos;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Market;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Order;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderBook;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.OrderList;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Peer;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TickerStatistics;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Time;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Token;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TradePage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionMetadata;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.TransactionPage;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Validators;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.CancelOrder;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.NewOrder;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.TokenFreeze;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.TokenUnfreeze;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.TransactionOption;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.broadcast.Transfer;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.ClosedOrdersRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.OpenOrdersRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.TradesRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.request.TransactionsRequest;
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.message.TransactionRequestAssemblerExtSign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
public interface BinanceDexApiRestClient {
|
||||
Time getTime();
|
||||
|
||||
Infos getNodeInfo();
|
||||
|
||||
Validators getValidators();
|
||||
|
||||
List<Peer> getPeers();
|
||||
|
||||
List<Market> getMarkets();
|
||||
|
||||
Account getAccount(String address);
|
||||
|
||||
AccountSequence getAccountSequence(String address);
|
||||
|
||||
TransactionMetadata getTransactionMetadata(String hash);
|
||||
|
||||
List<Token> getTokens();
|
||||
|
||||
OrderBook getOrderBook(String symbol, Integer limit);
|
||||
|
||||
List<Candlestick> getCandleStickBars(String symbol, CandlestickInterval interval);
|
||||
|
||||
List<Candlestick> getCandleStickBars(String symbol, CandlestickInterval interval, Integer limit, Long startTime, Long endTime);
|
||||
|
||||
OrderList getOpenOrders(String address);
|
||||
|
||||
OrderList getOpenOrders(OpenOrdersRequest request);
|
||||
|
||||
OrderList getClosedOrders(String address);
|
||||
|
||||
OrderList getClosedOrders(ClosedOrdersRequest request);
|
||||
|
||||
Order getOrder(String id);
|
||||
|
||||
List<TickerStatistics> get24HrPriceStatistics();
|
||||
|
||||
TradePage getTrades();
|
||||
|
||||
TradePage getTrades(TradesRequest request);
|
||||
|
||||
TransactionPage getTransactions(String address);
|
||||
|
||||
TransactionPage getTransactions(TransactionsRequest request);
|
||||
|
||||
public List<TransactionMetadata> broadcastNoWallet(RequestBody requestBody, boolean sync) throws BinanceDexApiException;
|
||||
|
||||
List<TransactionMetadata> newOrder(NewOrder newOrder, Wallet wallet, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
|
||||
List<TransactionMetadata> cancelOrder(CancelOrder cancelOrder, Wallet wallet, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
|
||||
List<TransactionMetadata> transfer(Transfer transfer, Wallet wallet, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
|
||||
TransactionRequestAssemblerExtSign prepareTransfer(Transfer transfer, BinanceAccountData binanceAccountData, byte[] pubKeyForSign, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
|
||||
List<TransactionMetadata> freeze(TokenFreeze freeze, Wallet wallet, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
|
||||
List<TransactionMetadata> unfreeze(TokenUnfreeze unfreeze, Wallet wallet, TransactionOption options, boolean sync)
|
||||
throws IOException, NoSuchAlgorithmException;
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class BinanceDexConstants {
|
||||
|
||||
/**
|
||||
* Identifier of this client.
|
||||
*/
|
||||
public static final long BINANCE_DEX_API_CLIENT_JAVA_SOURCE = 3L;
|
||||
|
||||
/**
|
||||
* Default ToStringStyle used by toString methods.
|
||||
* Override this to change the output format of the overridden toString methods.
|
||||
* - Example ToStringStyle.JSON_STYLE
|
||||
*/
|
||||
public static final ToStringStyle BINANCE_DEX_TO_STRING_STYLE = ToStringStyle.SHORT_PREFIX_STYLE;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
public enum BinanceDexEnvironment {
|
||||
PROD(
|
||||
"https://dex.binance.org",
|
||||
"wss://dex.binance.org/api/",
|
||||
"bnb"
|
||||
),
|
||||
TEST_NET(
|
||||
"https://testnet-dex.binance.org",
|
||||
"wss://testnet-dex.binance.org/api/",
|
||||
"tbnb"
|
||||
);
|
||||
// Rest API base URL
|
||||
private String baseUrl;
|
||||
// Websocket API base URL
|
||||
private String wsBaseUrl;
|
||||
// Address human readable part prefix
|
||||
private String hrp;
|
||||
|
||||
private BinanceDexEnvironment(String baseUrl, String wsBaseUrl, String hrp) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.wsBaseUrl = wsBaseUrl;
|
||||
this.hrp = hrp;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public String getWsBaseUrl() {
|
||||
return wsBaseUrl;
|
||||
}
|
||||
|
||||
public String getHrp() {
|
||||
return hrp;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client;
|
||||
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Account;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.AccountSequence;
|
||||
import com.tangem.blockchain.blockchains.binance.client.domain.Infos;
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.Crypto;
|
||||
import com.tangem.blockchain.blockchains.binance.client.encoding.message.MessageType;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Wallet {
|
||||
private final static Map<BinanceDexEnvironment, String> CHAIN_IDS = new HashMap<>();
|
||||
private String privateKey;
|
||||
private String address;
|
||||
private ECKey ecKey;
|
||||
private byte[] addressBytes;
|
||||
private byte[] pubKeyForSign;
|
||||
private Integer accountNumber;
|
||||
private Long sequence = null;
|
||||
private BinanceDexEnvironment env;
|
||||
|
||||
private String chainId;
|
||||
|
||||
public Wallet(String privateKey, BinanceDexEnvironment env) {
|
||||
if (!StringUtils.isEmpty(privateKey)) {
|
||||
this.privateKey = privateKey;
|
||||
this.env = env;
|
||||
this.ecKey = ECKey.fromPrivate(new BigInteger(privateKey, 16));
|
||||
this.address = Crypto.getAddressFromECKey(this.ecKey, env.getHrp());
|
||||
this.addressBytes = Crypto.decodeAddress(this.address);
|
||||
byte[] pubKey = ecKey.getPubKeyPoint().getEncoded(true);
|
||||
byte[] pubKeyPrefix = MessageType.PubKey.getTypePrefixBytes();
|
||||
this.pubKeyForSign = new byte[pubKey.length + pubKeyPrefix.length + 1];
|
||||
System.arraycopy(pubKeyPrefix, 0, this.pubKeyForSign, 0, pubKeyPrefix.length);
|
||||
pubKeyForSign[pubKeyPrefix.length] = (byte) 33;
|
||||
System.arraycopy(pubKey, 0, this.pubKeyForSign, pubKeyPrefix.length + 1, pubKey.length);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Private key cannot be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
public static Wallet createRandomWallet(BinanceDexEnvironment env) throws IOException {
|
||||
return createWalletFromMnemonicCode(Crypto.generateMnemonicCode(), env);
|
||||
}
|
||||
|
||||
public static Wallet createWalletFromMnemonicCode(List<String> words, BinanceDexEnvironment env) throws IOException {
|
||||
String privateKey = Crypto.getPrivateKeyFromMnemonicCode(words);
|
||||
return new Wallet(privateKey, env);
|
||||
}
|
||||
|
||||
public synchronized void initAccount(BinanceDexApiRestClient client) {
|
||||
Account account = client.getAccount(this.address);
|
||||
if (account != null) {
|
||||
this.accountNumber = account.getAccountNumber();
|
||||
this.sequence = account.getSequence();
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot get account information for address " + this.address);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void reloadAccountSequence(BinanceDexApiRestClient client) {
|
||||
AccountSequence accountSequence = client.getAccountSequence(this.address);
|
||||
this.sequence = accountSequence.getSequence();
|
||||
}
|
||||
|
||||
public synchronized void increaseAccountSequence() {
|
||||
if (this.sequence != null)
|
||||
this.sequence++;
|
||||
}
|
||||
|
||||
public synchronized void decreaseAccountSequence() {
|
||||
if (this.sequence != null)
|
||||
this.sequence--;
|
||||
}
|
||||
|
||||
public synchronized long getSequence() {
|
||||
if (sequence == null)
|
||||
throw new IllegalStateException("Account sequence is not initialized.");
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public synchronized void setAccountNumber(Integer accountNumber) {
|
||||
this.accountNumber = accountNumber;
|
||||
}
|
||||
|
||||
public synchronized void setSequence(Long sequence) {
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public synchronized void setChainId(String chainId) {
|
||||
this.chainId = chainId;
|
||||
}
|
||||
|
||||
public synchronized void invalidAccountSequence() {
|
||||
this.sequence = null;
|
||||
}
|
||||
|
||||
public synchronized void ensureWalletIsReady(BinanceDexApiRestClient client) {
|
||||
if (accountNumber == null) {
|
||||
initAccount(client);
|
||||
} else if (sequence == null) {
|
||||
reloadAccountSequence(client);
|
||||
}
|
||||
|
||||
if (chainId == null) {
|
||||
chainId = CHAIN_IDS.get(chainId);
|
||||
if (chainId == null) {
|
||||
initChainId(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void initChainId(BinanceDexApiRestClient client) {
|
||||
Infos info = client.getNodeInfo();
|
||||
chainId = info.getNodeInfo().getNetwork();
|
||||
CHAIN_IDS.put(env, chainId);
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public ECKey getEcKey() {
|
||||
return ecKey;
|
||||
}
|
||||
|
||||
public byte[] getPubKeyForSign() {
|
||||
return pubKeyForSign;
|
||||
}
|
||||
|
||||
public int getAccountNumber() {
|
||||
return accountNumber;
|
||||
}
|
||||
|
||||
public String getChainId() {
|
||||
return chainId;
|
||||
}
|
||||
|
||||
public byte[] getAddressBytes() {
|
||||
return addressBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("addressBytes", addressBytes)
|
||||
.append("address", address)
|
||||
.append("ecKey", ecKey)
|
||||
.append("pubKeyForSign", pubKeyForSign)
|
||||
.append("accountNumber", accountNumber)
|
||||
.append("sequence", sequence)
|
||||
.append("chainId", chainId)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Account {
|
||||
@JsonProperty("account_number")
|
||||
private Integer accountNumber;
|
||||
private String address;
|
||||
private List<Balance> balances;
|
||||
@JsonProperty("public_key")
|
||||
private List<Integer> publicKey;
|
||||
private Long sequence;
|
||||
|
||||
public Integer getAccountNumber() {
|
||||
return accountNumber;
|
||||
}
|
||||
|
||||
public void setAccountNumber(Integer accountNumber) {
|
||||
this.accountNumber = accountNumber;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public List<Balance> getBalances() {
|
||||
return balances;
|
||||
}
|
||||
|
||||
public void setBalances(List<Balance> balances) {
|
||||
this.balances = balances;
|
||||
}
|
||||
|
||||
public List<Integer> getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(List<Integer> publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public Long getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public void setSequence(Long sequence) {
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("accountNumber", accountNumber)
|
||||
.append("address", address)
|
||||
.append("balances", balances)
|
||||
.append("publicKey", publicKey)
|
||||
.append("sequence", sequence)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AccountSequence {
|
||||
private Long sequence;
|
||||
|
||||
public Long getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public void setSequence(Long sequence) {
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("sequence", sequence)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Balance {
|
||||
private String symbol;
|
||||
private String free;
|
||||
private String locked;
|
||||
private String frozen;
|
||||
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void setSymbol(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getFree() {
|
||||
return free;
|
||||
}
|
||||
|
||||
public void setFree(String free) {
|
||||
this.free = free;
|
||||
}
|
||||
|
||||
public String getLocked() {
|
||||
return locked;
|
||||
}
|
||||
|
||||
public void setLocked(String locked) {
|
||||
this.locked = locked;
|
||||
}
|
||||
|
||||
public String getFrozen() {
|
||||
return frozen;
|
||||
}
|
||||
|
||||
public void setFrozen(String frozen) {
|
||||
this.frozen = frozen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("symbol", symbol)
|
||||
.append("free", free)
|
||||
.append("locked", locked)
|
||||
.append("frozen", frozen)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
/**
|
||||
* Kline/Candlestick bars for a symbol. Klines are uniquely identified by their open time.
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.ARRAY)
|
||||
@JsonPropertyOrder()
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Candlestick {
|
||||
|
||||
private Long openTime;
|
||||
|
||||
private String open;
|
||||
|
||||
private String high;
|
||||
|
||||
private String low;
|
||||
|
||||
private String close;
|
||||
|
||||
private String volume;
|
||||
|
||||
private Long closeTime;
|
||||
|
||||
private String quoteAssetVolume;
|
||||
|
||||
private Long numberOfTrades;
|
||||
|
||||
public Long getOpenTime() {
|
||||
return openTime;
|
||||
}
|
||||
|
||||
public void setOpenTime(Long openTime) {
|
||||
this.openTime = openTime;
|
||||
}
|
||||
|
||||
public String getOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
public void setOpen(String open) {
|
||||
this.open = open;
|
||||
}
|
||||
|
||||
public String getHigh() {
|
||||
return high;
|
||||
}
|
||||
|
||||
public void setHigh(String high) {
|
||||
this.high = high;
|
||||
}
|
||||
|
||||
public String getLow() {
|
||||
return low;
|
||||
}
|
||||
|
||||
public void setLow(String low) {
|
||||
this.low = low;
|
||||
}
|
||||
|
||||
public String getClose() {
|
||||
return close;
|
||||
}
|
||||
|
||||
public void setClose(String close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
public String getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public void setVolume(String volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
public Long getCloseTime() {
|
||||
return closeTime;
|
||||
}
|
||||
|
||||
public void setCloseTime(Long closeTime) {
|
||||
this.closeTime = closeTime;
|
||||
}
|
||||
|
||||
public String getQuoteAssetVolume() {
|
||||
return quoteAssetVolume;
|
||||
}
|
||||
|
||||
public void setQuoteAssetVolume(String quoteAssetVolume) {
|
||||
this.quoteAssetVolume = quoteAssetVolume;
|
||||
}
|
||||
|
||||
public Long getNumberOfTrades() {
|
||||
return numberOfTrades;
|
||||
}
|
||||
|
||||
public void setNumberOfTrades(Long numberOfTrades) {
|
||||
this.numberOfTrades = numberOfTrades;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("openTime", openTime)
|
||||
.append("open", open)
|
||||
.append("high", high)
|
||||
.append("low", low)
|
||||
.append("close", close)
|
||||
.append("volume", volume)
|
||||
.append("closeTime", closeTime)
|
||||
.append("quoteAssetVolume", quoteAssetVolume)
|
||||
.append("numberOfTrades", numberOfTrades)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Kline/Candlestick intervals.
|
||||
* m -> minutes; h -> hours; d -> days; w -> weeks; M -> months
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public enum CandlestickInterval {
|
||||
ONE_MINUTE("1m"),
|
||||
THREE_MINUTES("3m"),
|
||||
FIVE_MINUTES("5m"),
|
||||
FIFTEEN_MINUTES("15m"),
|
||||
HALF_HOURLY("30m"),
|
||||
HOURLY("1h"),
|
||||
TWO_HOURLY("2h"),
|
||||
FOUR_HOURLY("4h"),
|
||||
SIX_HOURLY("6h"),
|
||||
EIGHT_HOURLY("8h"),
|
||||
TWELVE_HOURLY("12h"),
|
||||
DAILY("1d"),
|
||||
THREE_DAILY("3d"),
|
||||
WEEKLY("1w"),
|
||||
MONTHLY("1M");
|
||||
|
||||
private final String intervalId;
|
||||
|
||||
CandlestickInterval(String intervalId) {
|
||||
this.intervalId = intervalId;
|
||||
}
|
||||
|
||||
public String getIntervalId() {
|
||||
return intervalId;
|
||||
}
|
||||
|
||||
public static CandlestickInterval fromIntervalId(String intervalId) {
|
||||
if (intervalId == null) {
|
||||
throw new IllegalArgumentException("Null interval id");
|
||||
}
|
||||
String id = intervalId.toLowerCase();
|
||||
for (CandlestickInterval interval : values()) {
|
||||
if (id.equals(interval.getIntervalId())) {
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown interval id: " + intervalId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Infos {
|
||||
@JsonProperty("node_info")
|
||||
private NodeInfo nodeInfo;
|
||||
@JsonProperty("sync_info")
|
||||
private SyncInfo syncInfo;
|
||||
@JsonProperty("validator_info")
|
||||
private ValidatorInfo validatorInfo;
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
public void setNodeInfo(NodeInfo nodeInfo) {
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public SyncInfo getSyncInfo() {
|
||||
return syncInfo;
|
||||
}
|
||||
|
||||
public void setSyncInfo(SyncInfo syncInfo) {
|
||||
this.syncInfo = syncInfo;
|
||||
}
|
||||
|
||||
public ValidatorInfo getValidatorInfo() {
|
||||
return validatorInfo;
|
||||
}
|
||||
|
||||
public void setValidatorInfo(ValidatorInfo validatorInfo) {
|
||||
this.validatorInfo = validatorInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("nodeInfo", nodeInfo)
|
||||
.append("syncInfo", syncInfo)
|
||||
.append("validatorInfo", validatorInfo)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Market {
|
||||
public String baseAssetSymbol;
|
||||
public String quoteAssetSymbol;
|
||||
public String price;
|
||||
public String tickSize;
|
||||
public String lotSize;
|
||||
|
||||
@JsonProperty("base_asset_symbol")
|
||||
public String getBaseAssetSymbol() {
|
||||
return baseAssetSymbol;
|
||||
}
|
||||
|
||||
public void setBaseAssetSymbol(String baseAssetSymbol) {
|
||||
this.baseAssetSymbol = baseAssetSymbol;
|
||||
}
|
||||
|
||||
@JsonProperty("quote_asset_symbol")
|
||||
public String getQuoteAssetSymbol() {
|
||||
return quoteAssetSymbol;
|
||||
}
|
||||
|
||||
public void setQuoteAssetSymbol(String quoteAssetSymbol) {
|
||||
this.quoteAssetSymbol = quoteAssetSymbol;
|
||||
}
|
||||
|
||||
@JsonProperty("price")
|
||||
public String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(String price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
@JsonProperty("tick_size")
|
||||
public String getTickSize() {
|
||||
return tickSize;
|
||||
}
|
||||
|
||||
public void setTickSize(String tickSize) {
|
||||
this.tickSize = tickSize;
|
||||
}
|
||||
|
||||
@JsonProperty("lot_size")
|
||||
public String getLotSize() {
|
||||
return lotSize;
|
||||
}
|
||||
|
||||
public void setLotSize(String lotSize) {
|
||||
this.lotSize = lotSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("baseAssetSymbol", baseAssetSymbol)
|
||||
.append("quoteAssetSymbol", quoteAssetSymbol)
|
||||
.append("price", price)
|
||||
.append("tickSize", tickSize)
|
||||
.append("lotSize", lotSize)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class NodeInfo {
|
||||
private String id;
|
||||
@JsonProperty("listen_addr")
|
||||
private String listenAddr;
|
||||
private String network;
|
||||
private String version;
|
||||
private String channels;
|
||||
private String moniker;
|
||||
private Map<String, Object> other;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getListenAddr() {
|
||||
return listenAddr;
|
||||
}
|
||||
|
||||
public void setListenAddr(String listenAddr) {
|
||||
this.listenAddr = listenAddr;
|
||||
}
|
||||
|
||||
public String getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public void setNetwork(String network) {
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getChannels() {
|
||||
return channels;
|
||||
}
|
||||
|
||||
public void setChannels(String channels) {
|
||||
this.channels = channels;
|
||||
}
|
||||
|
||||
public String getMoniker() {
|
||||
return moniker;
|
||||
}
|
||||
|
||||
public void setMoniker(String moniker) {
|
||||
this.moniker = moniker;
|
||||
}
|
||||
|
||||
public Map<String, Object> getOther() {
|
||||
return other;
|
||||
}
|
||||
|
||||
public void setOther(Map<String, Object> other) {
|
||||
this.other = other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("id", id)
|
||||
.append("listenAddr", listenAddr)
|
||||
.append("network", network)
|
||||
.append("version", version)
|
||||
.append("channels", channels)
|
||||
.append("moniker", moniker)
|
||||
.append("other", other)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Order {
|
||||
private String orderId;
|
||||
private String symbol;
|
||||
private String owner;
|
||||
private String price;
|
||||
private String quantity;
|
||||
private String cumulateQuantity;
|
||||
private String fee;
|
||||
private DateTime orderCreateTime;
|
||||
private DateTime transactionTime;
|
||||
private OrderStatus status;
|
||||
private TimeInForce timeInForce;
|
||||
private OrderSide side;
|
||||
private OrderType type;
|
||||
private String tradeId;
|
||||
private String lastExecutedPrice;
|
||||
private String lastExecutedQuantity;
|
||||
private String transactionHash;
|
||||
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void setSymbol(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(String price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(String quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public String getCumulateQuantity() {
|
||||
return cumulateQuantity;
|
||||
}
|
||||
|
||||
public void setCumulateQuantity(String cumulateQuantity) {
|
||||
this.cumulateQuantity = cumulateQuantity;
|
||||
}
|
||||
|
||||
public String getFee() {
|
||||
return fee;
|
||||
}
|
||||
|
||||
public void setFee(String fee) {
|
||||
this.fee = fee;
|
||||
}
|
||||
|
||||
public DateTime getOrderCreateTime() {
|
||||
return orderCreateTime;
|
||||
}
|
||||
|
||||
public void setOrderCreateTime(DateTime orderCreateTime) {
|
||||
this.orderCreateTime = orderCreateTime;
|
||||
}
|
||||
|
||||
public DateTime getTransactionTime() {
|
||||
return transactionTime;
|
||||
}
|
||||
|
||||
public void setTransactionTime(DateTime transactionTime) {
|
||||
this.transactionTime = transactionTime;
|
||||
}
|
||||
|
||||
public OrderStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(OrderStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public TimeInForce getTimeInForce() {
|
||||
return timeInForce;
|
||||
}
|
||||
|
||||
public void setTimeInForce(TimeInForce timeInForce) {
|
||||
this.timeInForce = timeInForce;
|
||||
}
|
||||
|
||||
public OrderSide getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public void setSide(OrderSide side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public OrderType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(OrderType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getTradeId() {
|
||||
return tradeId;
|
||||
}
|
||||
|
||||
public void setTradeId(String tradeId) {
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
|
||||
public String getLastExecutedPrice() {
|
||||
return lastExecutedPrice;
|
||||
}
|
||||
|
||||
public void setLastExecutedPrice(String lastExecutedPrice) {
|
||||
this.lastExecutedPrice = lastExecutedPrice;
|
||||
}
|
||||
|
||||
public String getLastExecutedQuantity() {
|
||||
return lastExecutedQuantity;
|
||||
}
|
||||
|
||||
public void setLastExecutedQuantity(String lastExecutedQuantity) {
|
||||
this.lastExecutedQuantity = lastExecutedQuantity;
|
||||
}
|
||||
|
||||
public String getTransactionHash() {
|
||||
return transactionHash;
|
||||
}
|
||||
|
||||
public void setTransactionHash(String transactionHash) {
|
||||
this.transactionHash = transactionHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("orderId", orderId)
|
||||
.append("symbol", symbol)
|
||||
.append("owner", owner)
|
||||
.append("price", price)
|
||||
.append("quantity", quantity)
|
||||
.append("cumulateQuantity", cumulateQuantity)
|
||||
.append("fee", fee)
|
||||
.append("orderCreateTime", orderCreateTime)
|
||||
.append("transactionTime", transactionTime)
|
||||
.append("status", status)
|
||||
.append("timeInForce", timeInForce)
|
||||
.append("side", side)
|
||||
.append("type", type)
|
||||
.append("tradeId", tradeId)
|
||||
.append("lastExecutedPrice", lastExecutedPrice)
|
||||
.append("lastExecutedQuantity", lastExecutedQuantity)
|
||||
.append("transactionHash", transactionHash)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class OrderBook {
|
||||
private List<OrderBookEntry> asks;
|
||||
private List<OrderBookEntry> bids;
|
||||
private long height;
|
||||
|
||||
public List<OrderBookEntry> getAsks() {
|
||||
return asks;
|
||||
}
|
||||
|
||||
public void setAsks(List<OrderBookEntry> asks) {
|
||||
this.asks = asks;
|
||||
}
|
||||
|
||||
public List<OrderBookEntry> getBids() {
|
||||
return bids;
|
||||
}
|
||||
|
||||
public void setBids(List<OrderBookEntry> bids) {
|
||||
this.bids = bids;
|
||||
}
|
||||
|
||||
public long getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(long height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("asks", asks)
|
||||
.append("bids", bids)
|
||||
.append("height", height)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
@JsonDeserialize(using = OrderBookEntryDeserializer.class)
|
||||
@JsonSerialize(using = OrderBookEntrySerializer.class)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class OrderBookEntry {
|
||||
private String price;
|
||||
private String quantity;
|
||||
|
||||
public String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(String price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(String quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("price", price)
|
||||
.append("quantity", quantity)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.ObjectCodec;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OrderBookEntryDeserializer extends JsonDeserializer<OrderBookEntry> {
|
||||
@Override
|
||||
public OrderBookEntry deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
|
||||
ObjectCodec oc = jp.getCodec();
|
||||
JsonNode node = oc.readTree(jp);
|
||||
final String price = node.get(0).asText();
|
||||
final String qty = node.get(1).asText();
|
||||
|
||||
OrderBookEntry orderBookEntry = new OrderBookEntry();
|
||||
orderBookEntry.setPrice(price);
|
||||
orderBookEntry.setQuantity(qty);
|
||||
return orderBookEntry;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OrderBookEntrySerializer extends JsonSerializer<OrderBookEntry> {
|
||||
@Override
|
||||
public void serialize(OrderBookEntry orderBookEntry, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeStartArray();
|
||||
gen.writeString(orderBookEntry.getPrice());
|
||||
gen.writeString(orderBookEntry.getQuantity());
|
||||
gen.writeEndArray();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class OrderList {
|
||||
private List<Order> order;
|
||||
private Long total;
|
||||
|
||||
public List<Order> getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(List<Order> order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public Long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("order", order)
|
||||
.append("total", total)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum OrderSide {
|
||||
BUY(1L), SELL(2L);
|
||||
|
||||
private long value;
|
||||
|
||||
OrderSide(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static OrderSide fromValue(long value) {
|
||||
for (OrderSide os : OrderSide.values()) {
|
||||
if (os.value == value) {
|
||||
return os;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public long toValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
public enum OrderStatus {
|
||||
Ack,
|
||||
PartialFill,
|
||||
IocNoFill,
|
||||
FullyFill,
|
||||
Canceled,
|
||||
Expired,
|
||||
Unknown
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum OrderType {
|
||||
LIMIT(2L);
|
||||
|
||||
private long value;
|
||||
|
||||
OrderType(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static OrderType fromValue(long value) {
|
||||
for (OrderType ot : OrderType.values()) {
|
||||
if (ot.value == value) {
|
||||
return ot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public long toValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
package com.tangem.blockchain.blockchains.binance.client.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.tangem.blockchain.blockchains.binance.client.BinanceDexConstants;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Peer {
|
||||
private Boolean accelerated;
|
||||
@JsonProperty("access_addr")
|
||||
private String accessAddress;
|
||||
private List<String> capabilities;
|
||||
private String id;
|
||||
@JsonProperty("listen_addr")
|
||||
private String listenAddress;
|
||||
private String moniker;
|
||||
private String network;
|
||||
@JsonProperty("stream_addr")
|
||||
private String streamAddress;
|
||||
private String version;
|
||||
|
||||
public Boolean getAccelerated() {
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
public void setAccelerated(Boolean accelerated) {
|
||||
this.accelerated = accelerated;
|
||||
}
|
||||
|
||||
public String getAccessAddress() {
|
||||
return accessAddress;
|
||||
}
|
||||
|
||||
public void setAccessAddress(String accessAddress) {
|
||||
this.accessAddress = accessAddress;
|
||||
}
|
||||
|
||||
public List<String> getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
public void setCapabilities(List<String> capabilities) {
|
||||
this.capabilities = capabilities;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getListenAddress() {
|
||||
return listenAddress;
|
||||
}
|
||||
|
||||
public void setListenAddress(String listenAddress) {
|
||||
this.listenAddress = listenAddress;
|
||||
}
|
||||
|
||||
public String getMoniker() {
|
||||
return moniker;
|
||||
}
|
||||
|
||||
public void setMoniker(String moniker) {
|
||||
this.moniker = moniker;
|
||||
}
|
||||
|
||||
public String getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public void setNetwork(String network) {
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
public String getStreamAddress() {
|
||||
return streamAddress;
|
||||
}
|
||||
|
||||
public void setStreamAddress(String streamAddress) {
|
||||
this.streamAddress = streamAddress;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, BinanceDexConstants.BINANCE_DEX_TO_STRING_STYLE)
|
||||
.append("accelerated", accelerated)
|
||||
.append("accessAddress", accessAddress)
|
||||
.append("capabilities", capabilities)
|
||||
.append("id", id)
|
||||
.append("listenAddress", listenAddress)
|
||||
.append("moniker", moniker)
|
||||
.append("network", network)
|
||||
.append("streamAddress", streamAddress)
|
||||
.append("version", version)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||