Updated on 2026-08-14

This commit is contained in:
Tangem 2020-10-23 13:56:29 +03:00
commit f0f2c81b34
651 changed files with 193 additions and 51800 deletions

9
.idea/misc.xml generated
View file

@ -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>

View file

@ -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'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -73,6 +73,7 @@ class PayIdManager {
Blockchain.BitcoinCash,
Blockchain.Binance,
Blockchain.RSK,
Blockchain.Tezos
)
fun isPayId(value: String?): Boolean = value?.contains(payIdRegExp) ?: false

View file

@ -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)

View file

@ -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))
}

View 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"
}
}

View file

@ -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"

View file

@ -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()
}
}

View file

@ -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 {

View file

@ -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> {

View file

@ -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
}

View file

@ -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

View file

@ -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()
}
}
}

View file

@ -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 -> {

View file

@ -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

View file

@ -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()

View file

@ -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)

View file

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Before After
Before After

View file

@ -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>

View 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>

View file

@ -1 +0,0 @@
/build

View file

@ -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'
}

View file

@ -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

View file

@ -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)
}
}

View file

@ -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>

View file

@ -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()
}
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -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>

View file

@ -1,3 +0,0 @@
<resources>
<string name="app_name">Blockchain Demo</string>
</resources>

View file

@ -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>

View file

@ -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>

View file

@ -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)
}
}

View file

@ -1 +0,0 @@
/build

View file

@ -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'
}

View file

@ -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

View file

@ -1 +0,0 @@
<manifest package="com.tangem.blockchain" />

View file

@ -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
}
}

View file

@ -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
)

View file

@ -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
}
}
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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) {
}
}

View file

@ -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));
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -1,11 +0,0 @@
package com.tangem.blockchain.blockchains.binance.client.domain;
public enum OrderStatus {
Ack,
PartialFill,
IocNoFill,
FullyFill,
Canceled,
Expired,
Unknown
}

View file

@ -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;
}
}

View file

@ -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();
}
}

Some files were not shown because too many files have changed in this diff Show more