Skip to content
Open
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
1 change: 1 addition & 0 deletions .cache/cache1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[]]
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import com.gemwallet.android.features.onboarding.AcceptTermsDestination
import com.gemwallet.android.features.onboarding.AcceptTermsRoute
import com.gemwallet.android.features.onboarding.OnboardingRoute
import com.gemwallet.android.features.setup_wallet.navigation.SetupWalletRoute
import com.gemwallet.android.features.swap.viewmodels.models.SwapItemType
import com.gemwallet.android.domains.swap.SwapItemType
import com.gemwallet.android.model.AmountParams
import com.gemwallet.android.model.ConfirmParams
import com.gemwallet.android.model.ImportType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.gemwallet.android.ui.navigation.routes
import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import com.gemwallet.android.features.swap.viewmodels.models.SwapItemType
import com.gemwallet.android.domains.swap.SwapItemType
import com.gemwallet.android.features.swap.views.SwapScreen
import com.gemwallet.android.features.swap.views.SwapSelectScreen
import com.gemwallet.android.model.ConfirmParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.gemwallet.android.features.onboarding.AcceptTermsDestination
import com.gemwallet.android.features.onboarding.AcceptTermsRoute
import com.gemwallet.android.features.onboarding.OnboardingRoute
import com.gemwallet.android.features.setup_wallet.navigation.SetupWalletRoute
import com.gemwallet.android.features.swap.viewmodels.models.SwapItemType
import com.gemwallet.android.domains.swap.SwapItemType
import com.gemwallet.android.model.ImportType
import com.gemwallet.android.testkit.mockAssetId
import com.gemwallet.android.testkit.mockWalletId
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.gemwallet.android.data.coordinators.di

import com.gemwallet.android.application.PasswordStore
import com.gemwallet.android.application.swap.coordinators.BuildSwapConfirmParams
import com.gemwallet.android.application.swap.coordinators.GetSwapQuoteData
import com.gemwallet.android.application.swap.coordinators.GetSwapQuotes
import com.gemwallet.android.application.swap.coordinators.GetSwapSupported
import com.gemwallet.android.application.swap.coordinators.RequestSwapQuotes
import com.gemwallet.android.application.swap.coordinators.SearchSwapAssets
import com.gemwallet.android.blockchain.operators.LoadPrivateKeyOperator
import com.gemwallet.android.blockchain.services.SignClientProxy
import com.gemwallet.android.data.coordinators.swap.BuildSwapConfirmParamsImpl
import com.gemwallet.android.data.coordinators.swap.GetSwapQuoteDataImpl
import com.gemwallet.android.data.coordinators.swap.GetSwapQuotesImpl
import com.gemwallet.android.data.coordinators.swap.GetSwapSupportedImpl
import com.gemwallet.android.data.coordinators.swap.RequestSwapQuotesImpl
import com.gemwallet.android.data.coordinators.swap.SearchSwapAssetsImpl
import com.gemwallet.android.data.repositories.assets.AssetsRepository
import com.gemwallet.android.data.repositories.session.SessionRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import uniffi.gemstone.AlienProvider
import uniffi.gemstone.GemSwapper
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
object SwapModule {

@Singleton
@Provides
fun provideGemSwapper(
alienProvider: AlienProvider,
): GemSwapper = GemSwapper(alienProvider)

@Singleton
@Provides
fun provideGetSwapQuotes(
gemSwapper: GemSwapper,
): GetSwapQuotes = GetSwapQuotesImpl(gemSwapper)

@Singleton
@Provides
fun provideGetSwapSupported(
gemSwapper: GemSwapper,
): GetSwapSupported = GetSwapSupportedImpl(gemSwapper)

@Singleton
@Provides
fun provideGetSwapQuoteData(
gemSwapper: GemSwapper,
signClient: SignClientProxy,
passwordStore: PasswordStore,
loadPrivateKeyOperator: LoadPrivateKeyOperator,
): GetSwapQuoteData = GetSwapQuoteDataImpl(
gemSwapper = gemSwapper,
signClient = signClient,
passwordStore = passwordStore,
loadPrivateKeyOperator = loadPrivateKeyOperator,
)

@Singleton
@Provides
fun provideRequestSwapQuotes(
getSwapQuotes: GetSwapQuotes,
): RequestSwapQuotes = RequestSwapQuotesImpl(getSwapQuotes)

@Singleton
@Provides
fun provideBuildSwapConfirmParams(
sessionRepository: SessionRepository,
getSwapQuoteData: GetSwapQuoteData,
): BuildSwapConfirmParams = BuildSwapConfirmParamsImpl(
sessionRepository = sessionRepository,
getSwapQuoteData = getSwapQuoteData,
)

@Singleton
@Provides
fun provideSearchSwapAssets(
assetsRepository: AssetsRepository,
getSwapSupported: GetSwapSupported,
): SearchSwapAssets = SearchSwapAssetsImpl(
assetsRepository = assetsRepository,
getSwapSupported = getSwapSupported,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.gemwallet.android.data.coordinators.swap

import com.gemwallet.android.application.swap.coordinators.BuildSwapConfirmParams
import com.gemwallet.android.application.swap.coordinators.GetSwapQuoteData
import com.gemwallet.android.application.swap.coordinators.SwapNoQuoteException
import com.gemwallet.android.data.repositories.session.SessionRepository
import com.gemwallet.android.model.AssetInfo
import com.gemwallet.android.model.ConfirmParams
import com.gemwallet.android.model.toModel
import kotlinx.coroutines.flow.firstOrNull
import uniffi.gemstone.SwapperQuote
import java.math.BigInteger

class BuildSwapConfirmParamsImpl(
private val sessionRepository: SessionRepository,
private val getSwapQuoteData: GetSwapQuoteData,
) : BuildSwapConfirmParams {

override suspend fun invoke(
quote: SwapperQuote,
pay: AssetInfo,
receive: AssetInfo,
): ConfirmParams.SwapParams? {
val wallet = sessionRepository.session().firstOrNull()?.wallet ?: return null

val swapData = try {
getSwapQuoteData(quote, wallet)
} catch (_: Throwable) {
throw SwapNoQuoteException()
}

val from = pay.owner ?: throw SwapNoQuoteException()
return ConfirmParams.SwapParams(
from = from,
fromAsset = pay.asset,
toAsset = receive.asset,
fromAmount = BigInteger(quote.fromValue),
toAmount = BigInteger(quote.toValue),
swapData = swapData.data,
providerId = quote.data.provider.id,
protocol = quote.data.provider.protocol,
providerName = quote.data.provider.name,
protocolId = quote.data.provider.protocolId,
toAddress = swapData.to,
value = swapData.value,
approval = swapData.approval?.toModel(),
gasLimit = swapData.gasLimit?.toBigIntegerOrNull(),
useMaxAmount = quote.request.options.useMaxAmount,
etaInSeconds = quote.etaInSeconds,
slippageBps = quote.data.slippageBps,
memo = swapData.memo,
dataType = swapData.dataType,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.gemwallet.android.data.coordinators.swap

import com.gemwallet.android.application.PasswordStore
import com.gemwallet.android.application.swap.coordinators.GetSwapQuoteData
import com.gemwallet.android.blockchain.operators.LoadPrivateKeyOperator
import com.gemwallet.android.blockchain.services.SignClientProxy
import com.gemwallet.android.ext.nowSeconds
import com.gemwallet.android.ext.toAssetId
import com.gemwallet.android.math.decodeHex
import com.wallet.core.primitives.Wallet
import uniffi.gemstone.Config
import uniffi.gemstone.FetchQuoteData
import uniffi.gemstone.GemSwapQuoteData
import uniffi.gemstone.GemSwapper
import uniffi.gemstone.Permit2Data
import uniffi.gemstone.Permit2Detail
import uniffi.gemstone.PermitSingle
import uniffi.gemstone.SwapperQuote
import uniffi.gemstone.permit2DataToEip712Json
import java.util.Arrays

class GetSwapQuoteDataImpl(
private val gemSwapper: GemSwapper,
private val signClient: SignClientProxy,
private val passwordStore: PasswordStore,
private val loadPrivateKeyOperator: LoadPrivateKeyOperator,
) : GetSwapQuoteData {

override suspend fun invoke(quote: SwapperQuote, wallet: Wallet): GemSwapQuoteData {
val permit = gemSwapper.getPermit2ForQuote(quote = quote)

if (permit == null) {
return gemSwapper.getQuoteData(quote, FetchQuoteData.None)
}

val permit2Single = permit2Single(
token = permit.token,
spender = permit.spender,
value = permit.value,
nonce = permit.permit2Nonce,
)
val chain = checkNotNull(quote.request.fromAsset.id.toAssetId()?.chain) {
"Swap quote has invalid asset id"
}
val permit2Json = permit2DataToEip712Json(
chain = chain.string,
data = permit2Single,
contract = permit.permit2Contract,
)
val key = loadPrivateKeyOperator.invoke(wallet, chain, passwordStore.getPassword(key = wallet.id))
val signature = try {
signClient.signTypedMessage(
chain = chain,
input = permit2Json.toByteArray(),
privateKey = key,
).decodeHex()
} finally {
Arrays.fill(key, 0)
}
val permitData = Permit2Data(permit2Single, signature)
return gemSwapper.getQuoteData(quote, FetchQuoteData.Permit2(permitData))
}

private fun permit2Single(token: String, spender: String, value: String, nonce: ULong): PermitSingle {
val config = Config().getSwapConfig()
val now = nowSeconds()
return PermitSingle(
details = Permit2Detail(
token = token,
amount = value,
expiration = now + config.permit2Expiration,
nonce = nonce,
),
spender = spender,
sigDeadline = now + config.permit2SigDeadline,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.gemwallet.android.data.coordinators.swap

import com.gemwallet.android.application.swap.coordinators.GetSwapQuotes
import com.gemwallet.android.domains.asset.chain
import com.gemwallet.android.ext.toIdentifier
import com.wallet.core.primitives.Asset
import uniffi.gemstone.Config
import uniffi.gemstone.GemSwapper
import uniffi.gemstone.SwapperMode
import uniffi.gemstone.SwapperOptions
import uniffi.gemstone.SwapperQuote
import uniffi.gemstone.SwapperQuoteAsset
import uniffi.gemstone.SwapperQuoteRequest
import uniffi.gemstone.getDefaultSlippage
import java.math.BigInteger

class GetSwapQuotesImpl(
private val gemSwapper: GemSwapper,
) : GetSwapQuotes {
override suspend fun getQuotes(
ownerAddress: String,
destination: String,
from: Asset,
to: Asset,
amount: String,
useMaxAmount: Boolean,
): List<SwapperQuote> {
val swapRequest = SwapperQuoteRequest(
fromAsset = SwapperQuoteAsset(
id = from.id.toIdentifier(),
symbol = from.symbol,
decimals = from.decimals.toUInt(),
),
toAsset = SwapperQuoteAsset(
id = to.id.toIdentifier(),
symbol = to.symbol,
decimals = to.decimals.toUInt(),
),
walletAddress = ownerAddress,
destinationAddress = destination,
value = amount,
mode = SwapperMode.EXACT_IN,
options = SwapperOptions(
slippage = getDefaultSlippage(from.chain.string),
fee = Config().getSwapConfig().referralFee,
preferredProviders = emptyList(),
useMaxAmount = useMaxAmount,
)
)
return gemSwapper.getQuote(swapRequest)
.sortedByDescending { BigInteger(it.toValue) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gemwallet.android.data.coordinators.swap

import com.gemwallet.android.application.swap.coordinators.GetSwapSupported
import com.gemwallet.android.ext.toIdentifier
import com.wallet.core.primitives.AssetId
import uniffi.gemstone.GemSwapper
import uniffi.gemstone.SwapperAssetList

class GetSwapSupportedImpl(
private val gemSwapper: GemSwapper,
) : GetSwapSupported {
override fun getSwapSupportChains(assetId: AssetId): SwapperAssetList {
return gemSwapper.supportedChainsForFromAsset(assetId.toIdentifier())
}
}
Loading
Loading