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 @@ -35,7 +35,6 @@ object ControllerFactory {
repository = RepositoryFactory.createTransactionRepository(context, config),
swapRepository = RepositoryFactory.createSwapRepository(context, config),
accountController = createAccountController(context, config),
eventBus = module.providesEventBus(),
)
}
fun createCurrencyController(context: Context, config: ProtocolConfig): CurrencyController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.getcode.opencode.internal.network.api.intents.IntentDistribution
import com.getcode.opencode.internal.network.api.intents.IntentRemoteReceive
import com.getcode.opencode.internal.network.api.intents.IntentRemoteSend
import com.getcode.opencode.internal.network.api.intents.IntentTransfer
import com.getcode.opencode.internal.solana.extensions.newInstance
import com.getcode.opencode.internal.network.api.intents.IntentWithdraw
import com.getcode.opencode.internal.solana.model.SwapId
import com.getcode.opencode.model.accounts.AccountCluster
Expand All @@ -20,6 +21,7 @@ import com.getcode.opencode.model.financial.Fiat
import com.getcode.opencode.model.financial.Limits
import com.getcode.opencode.model.financial.LocalFiat
import com.getcode.opencode.model.financial.Token
import com.getcode.opencode.solana.keys.TimelockDerivedAccounts
import com.getcode.opencode.model.transactions.ExchangeData
import com.getcode.opencode.model.transactions.SwapFundingSource
import com.getcode.opencode.model.transactions.SwapMetadata
Expand All @@ -38,7 +40,6 @@ import com.getcode.utils.TraceType
import com.getcode.utils.base64
import com.getcode.utils.trace
import com.getcode.vendor.Base58
import com.hoc081098.channeleventbus.ChannelEventBus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
Expand All @@ -63,7 +64,6 @@ class TransactionController @Inject constructor(
private val repository: TransactionRepository,
private val swapRepository: SwapRepository,
private val accountController: AccountController,
private val eventBus: ChannelEventBus,
) : TransactionOperations {
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

Expand Down Expand Up @@ -122,6 +122,35 @@ class TransactionController @Inject constructor(
return submitIntent(scope, intent, source.authority.keyPair)
}

/**
* Sends funds directly to another user's vault by resolving their
* [destinationOwner] into a timelock-derived vault address.
*/
suspend fun directTransfer(
amount: VerifiedFiat,
token: Token,
source: AccountCluster,
destinationOwner: PublicKey,
scope: CoroutineScope = this.scope,
): Result<IntentType> {
val verifiedState = amount.verifiedState
?: return Result.failure(IllegalStateException("No verified state"))

val timelock = TimelockDerivedAccounts.newInstance(owner = destinationOwner, token = token)
val destinationVault = timelock.vault.publicKey

val intent = IntentTransfer.create(
amount = amount.localFiat,
mint = token.address,
sourceCluster = source,
destination = destinationVault,
destinationOwner = destinationOwner,
verifiedState = verifiedState,
)

return submitIntent(scope, intent, source.authority.keyPair)
}

override suspend fun withdraw(
amount: VerifiedFiat,
mint: Mint,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.getcode.opencode.internal.network.api.intents

import com.codeinc.opencode.gen.transaction.v1.TransactionService
import com.getcode.opencode.internal.manager.VerifiedState
import com.getcode.opencode.internal.network.api.intents.actions.ActionPublicTransfer
import com.getcode.opencode.model.accounts.AccountCluster
import com.getcode.opencode.internal.network.extensions.asProtobufMetadata
Expand All @@ -9,9 +10,20 @@ import com.getcode.opencode.model.transactions.ExchangeData
import com.getcode.opencode.model.transactions.TransactionMetadata
import com.getcode.opencode.solana.intents.ActionGroup
import com.getcode.opencode.solana.intents.IntentType
import com.getcode.opencode.utils.generate
import com.getcode.solana.keys.Mint
import com.getcode.solana.keys.PublicKey

/**
* A SendPublicPayment intent for transferring funds to another account.
*
* Two creation paths are supported:
* - **Rendezvous-based** ([create] with [ExchangeData.Verified]): used for
* peer-to-peer bill gives where the rendezvous key serves as the intent id.
* - **Direct** ([create] with [VerifiedState]): used for direct sends to a
* known recipient (e.g. Flipcash contact). A random intent id is generated
* and the [destinationOwner] is included in the metadata.
*/
internal class IntentTransfer(
override val id: PublicKey,
override val metadata: TransactionMetadata,
Expand All @@ -22,6 +34,7 @@ internal class IntentTransfer(
}

companion object {
/** Creates a rendezvous-based transfer for peer-to-peer bill gives. */
fun create(
amount: LocalFiat,
mint: Mint,
Expand Down Expand Up @@ -54,5 +67,40 @@ internal class IntentTransfer(
}
)
}

/** Creates a direct transfer to a known recipient's vault. */
fun create(
amount: LocalFiat,
mint: Mint,
sourceCluster: AccountCluster,
destination: PublicKey,
destinationOwner: PublicKey,
verifiedState: VerifiedState,
): IntentTransfer {
val transfer = ActionPublicTransfer.newInstance(
owner = sourceCluster.authority.keyPair,
source = sourceCluster.vaultPublicKey,
destination = destination,
amount = amount.underlyingTokenAmount,
mint = mint,
)

return IntentTransfer(
id = PublicKey.generate(),
metadata = TransactionMetadata.SendPublicPayment(
source = sourceCluster.vaultPublicKey,
destination = destination,
destinationOwner = destinationOwner,
amount = amount,
verifiedState = verifiedState,
mint = mint,
isRemoteSend = false,
isWithdrawal = false,
),
actionGroup = ActionGroup().apply {
actions = listOf(transfer)
},
)
}
}
}
Loading