Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ interface WalletDataProvider {
fun sendCoins(address: Address, amount: Coin): LiveData<Resource<Transaction>>

fun startSendCoinsForResult(activity: Activity, requestCode: Int, address: Address, amount: Coin?)
}

fun getWalletBalance(): Coin

fun createSentDashAddress(address: String): Address
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2022 Dash Core Group.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.dash.wallet.common.services

import org.bitcoinj.core.Address
import org.bitcoinj.core.Coin
import org.bitcoinj.core.Transaction

interface SendPaymentService {
suspend fun sendCoins(
address: Address,
amount: Coin,
constrainInputsTo: Address? = null,
emptyWallet: Boolean = false
): Transaction
}
Comment on lines +24 to +31

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Syn-McJ Didn't also make a similar service? or is this the same one?

@Syn-McJ Syn-McJ Mar 31, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same one as I understand, Hadia has asked me about sending coins and I have referenced my solution.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2022 Dash Core Group.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.dash.wallet.common.transactions

import org.bitcoinj.core.Address
import org.bitcoinj.core.Coin
import org.bitcoinj.core.TransactionOutput
import org.bitcoinj.script.ScriptPattern
import org.bitcoinj.wallet.CoinSelection
import org.bitcoinj.wallet.CoinSelector
import org.bitcoinj.wallet.ZeroConfCoinSelector

class ByAddressCoinSelector(private val address: Address) : CoinSelector {
private val selector = ZeroConfCoinSelector.get()

override fun select(
target: Coin,
candidates: MutableList<TransactionOutput>
): CoinSelection {
val filtered = candidates.filter { output ->
val script = output.scriptPubKey
(ScriptPattern.isP2PKH(script) || ScriptPattern.isP2SH(script)) &&
script.getToAddress(address.parameters) == address
}

return selector.select(target, filtered)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.dash.wallet.integration.coinbase_integration

const val CB_VERSION_KEY = "CB-VERSION"
const val CB_2FA_TOKEN_KEY = "CB-2FA-TOKEN"
const val CB_VERSION_VALUE = "2021-09-07"
const val TRANSACTION_TYPE_SEND = "send"
const val TRANSACTION_STATUS_PENDING = "pending"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,14 @@ class CommitBuyOrderMapper : Mapper<BuyOrderData?, CommitBuyOrderUIModel> {
}
}
}

class CoinbaseAddressMapper : Mapper<CoinBaseAccountAddressResponse?, String> {
override fun map(input: CoinBaseAccountAddressResponse?): String {
return if (input == null)
""
else {
input.data?.mapNotNull { it?.address }
?.firstOrNull { it.isNotEmpty() } ?: ""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.dash.wallet.common.Configuration
import org.dash.wallet.integration.coinbase_integration.CoinbaseAddressMapper
import org.dash.wallet.integration.coinbase_integration.CommitBuyOrderMapper
import org.dash.wallet.integration.coinbase_integration.PlaceBuyOrderMapper
import org.dash.wallet.integration.coinbase_integration.SwapTradeMapper
Expand Down Expand Up @@ -67,6 +68,8 @@ object CoinBaseModule {
fun provideSwapTradeMapper(): SwapTradeMapper = SwapTradeMapper()
@Provides
fun provideReceiver(): CloseCoinbasePortalBroadcaster = CloseCoinbasePortalBroadcaster()
@Provides
fun provideCoinbaseAddressMapper(): CoinbaseAddressMapper = CoinbaseAddressMapper()
}

@Module
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.dash.wallet.integration.coinbase_integration.model

import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize

@Parcelize
data class AddressesResponse(

@field:SerializedName("data")
val addresses: Addresses? = null
) : Parcelable

@Parcelize
data class Addresses(

@field:SerializedName("deposit_uri")
val depositUri: String? = null,

@field:SerializedName("address_info")
val addressInfo: AddressInfo? = null,

@field:SerializedName("address")
val address: String? = null,

@field:SerializedName("resource")
val resource: String? = null,

@field:SerializedName("warnings")
val warnings: List<String?>? = null,

@field:SerializedName("created_at")
val createdAt: String? = null,

@field:SerializedName("uri_scheme")
val uriScheme: String? = null,

@field:SerializedName("network")
val network: String? = null,

@field:SerializedName("callback_url")
val callbackUrl: String? = null,

@field:SerializedName("updated_at")
val updatedAt: String? = null,

@field:SerializedName("resource_path")
val resourcePath: String? = null,

@field:SerializedName("name")
val name: String? = null,

@field:SerializedName("id")
val id: String? = null
) : Parcelable

Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package org.dash.wallet.integration.coinbase_integration.model

import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize

@Parcelize
data class CoinBaseAccountAddressResponse(

@field:SerializedName("pagination")
val pagination: Pagination? = null,

@field:SerializedName("data")
val data: List<DataItem?>? = null
) : Parcelable

@Parcelize
data class CoinBaseAccountAddressInfo(
@field:SerializedName("address")
val address: String? = null
) : Parcelable

@Parcelize
data class WarningsItem(

@field:SerializedName("image_url")
val imageUrl: String? = null,

@field:SerializedName("options")
val options: List<OptionsItem?>? = null,

@field:SerializedName("details")
val details: String? = null,

@field:SerializedName("type")
val type: String? = null,

@field:SerializedName("title")
val title: String? = null
) : Parcelable

@Parcelize
data class OptionsItem(

@field:SerializedName("style")
val style: String? = null,

@field:SerializedName("text")
val text: String? = null,

@field:SerializedName("id")
val id: String? = null
) : Parcelable

@Parcelize
data class DataItem(

@field:SerializedName("deposit_uri")
val depositUri: String? = null,

@field:SerializedName("address_info")
val addressInfo: CoinBaseAccountAddressInfo? = null,

@field:SerializedName("address")
val address: String? = null,

@field:SerializedName("resource")
val resource: String? = null,

@field:SerializedName("warnings")
val warnings: List<WarningsItem?>? = null,

@field:SerializedName("created_at")
val createdAt: String? = null,

@field:SerializedName("uri_scheme")
val uriScheme: String? = null,

@field:SerializedName("network")
val network: String? = null,

@field:SerializedName("callback_url")
val callbackUrl: String? = null,

@field:SerializedName("updated_at")
val updatedAt: String? = null,

@field:SerializedName("resource_path")
val resourcePath: String? = null,

@field:SerializedName("name")
val name: String? = null,

@field:SerializedName("id")
val id: String? = null
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class CoinBaseRepository @Inject constructor(
private val userPreferences: Configuration,
private val placeBuyOrderMapper: PlaceBuyOrderMapper,
private val swapTradeMapper: SwapTradeMapper,
private val commitBuyOrderMapper: CommitBuyOrderMapper) : CoinBaseRepositoryInt {
private val commitBuyOrderMapper: CommitBuyOrderMapper,
private val coinbaseAddressMapper: CoinbaseAddressMapper
) : CoinBaseRepositoryInt {
override suspend fun getUserAccount() = safeApiCall {
val apiResponse = servicesApi.getUserAccounts()
val userAccountData = apiResponse?.data?.firstOrNull {
Expand Down Expand Up @@ -104,13 +106,19 @@ class CoinBaseRepository @Inject constructor(
placeBuyOrderMapper.map(apiResult?.data)
}


override suspend fun getUserAccountAddress(): ResponseResource<String> = safeApiCall {
val apiResult = servicesApi.getUserAccountAddress(accountId = userPreferences.coinbaseUserAccountId)
coinbaseAddressMapper.map(apiResult)
}

override suspend fun commitBuyOrder(buyOrderId: String) = safeApiCall {
val commitBuyResult = servicesApi.commitBuyOrder(accountId = userPreferences.coinbaseUserAccountId, buyOrderId = buyOrderId)
commitBuyOrderMapper.map(commitBuyResult?.data)
}

override suspend fun sendFundsToWallet(sendTransactionToWalletParams: SendTransactionToWalletParams) = safeApiCall {
servicesApi.sendCoinsToWallet(accountId = userPreferences.coinbaseUserAccountId, sendTransactionToWalletParams = sendTransactionToWalletParams)
override suspend fun sendFundsToWallet(sendTransactionToWalletParams: SendTransactionToWalletParams, api2FATokenVersion: String) = safeApiCall {
servicesApi.sendCoinsToWallet(accountId = userPreferences.coinbaseUserAccountId, sendTransactionToWalletParams = sendTransactionToWalletParams, api2FATokenVersion = api2FATokenVersion)
}

override fun getUserLastCoinbaseBalance(): String = userPreferences.lastCoinbaseBalance ?: ""
Expand All @@ -136,6 +144,10 @@ class CoinBaseRepository @Inject constructor(
}
WithdrawalLimitUIModel(userPreferences.coinbaseUserWithdrawalLimitAmount, userPreferences.coinbaseSendLimitCurrency)
}

override suspend fun createAddress(): ResponseResource<String?> = safeApiCall {
return@safeApiCall servicesApi.createAddress(accountId = userPreferences.coinbaseUserAccountId)?.addresses?.address
}
}

interface CoinBaseRepositoryInt {
Expand All @@ -146,10 +158,12 @@ interface CoinBaseRepositoryInt {
suspend fun disconnectCoinbaseAccount()
fun saveLastCoinbaseDashAccountBalance(amount: String?)
fun saveUserAccountId(accountId: String?)
suspend fun createAddress(): ResponseResource<String?>
suspend fun getUserAccountAddress(): ResponseResource<String>
suspend fun getActivePaymentMethods(): ResponseResource<List<PaymentMethodsData>>
suspend fun placeBuyOrder(placeBuyOrderParams: PlaceBuyOrderParams): ResponseResource<PlaceBuyOrderUIModel>
suspend fun commitBuyOrder(buyOrderId: String): ResponseResource<CommitBuyOrderUIModel>
suspend fun sendFundsToWallet(sendTransactionToWalletParams: SendTransactionToWalletParams): ResponseResource<SendTransactionToWalletResponse?>
suspend fun sendFundsToWallet(sendTransactionToWalletParams: SendTransactionToWalletParams, api2FATokenVersion: String): ResponseResource<SendTransactionToWalletResponse?>
fun getUserLastCoinbaseBalance(): String
fun isUserConnected(): Boolean
suspend fun swapTrade(tradesRequest: TradesRequest): ResponseResource<SwapTradeUIModel>
Expand All @@ -161,4 +175,4 @@ interface CoinBaseRepositoryInt {
data class WithdrawalLimitUIModel(
val amount: String?,
val currency: String
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.dash.wallet.integration.coinbase_integration.service

import org.dash.wallet.integration.coinbase_integration.CB_2FA_TOKEN_KEY
import org.dash.wallet.integration.coinbase_integration.CB_VERSION_KEY
import org.dash.wallet.integration.coinbase_integration.CB_VERSION_VALUE
import org.dash.wallet.integration.coinbase_integration.DASH_CURRENCY
Expand Down Expand Up @@ -57,6 +58,7 @@ interface CoinBaseServicesApi {
@POST("v2/accounts/{account_id}/transactions")
suspend fun sendCoinsToWallet(
@Header(CB_VERSION_KEY) apiVersion: String = CB_VERSION_VALUE,
@Header(CB_2FA_TOKEN_KEY) api2FATokenVersion: String,
@Path("account_id") accountId: String,
@Body sendTransactionToWalletParams: SendTransactionToWalletParams
): SendTransactionToWalletResponse?
Expand All @@ -83,4 +85,16 @@ interface CoinBaseServicesApi {
suspend fun getAuthorizationInformation(
@Header(CB_VERSION_KEY) apiVersion: String = CB_VERSION_VALUE
): UserAuthorizationInfoResponse?

@GET("v2/accounts/{account_id}/addresses")
suspend fun getUserAccountAddress(
@Path("account_id") accountId: String,
@Header(CB_VERSION_KEY) apiVersion: String = CB_VERSION_VALUE,
): CoinBaseAccountAddressResponse

@POST("v2/accounts/{account_id}/addresses")
suspend fun createAddress(
@Header(CB_VERSION_KEY) apiVersion: String = CB_VERSION_VALUE,
@Path("account_id") accountId: String
): AddressesResponse
}
Loading