Skip to content

Commit

Permalink
Merge branch 'main' into walletlib-expose-authv2-params
Browse files Browse the repository at this point in the history
  • Loading branch information
Funkatronics committed Oct 18, 2023
2 parents 7c147ea + 482c0d1 commit 8bb5634
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 141 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,49 @@
package com.solana.mobilewalletadapter.clientlib

import android.net.Uri
import androidx.annotation.Nullable
import com.solana.mobilewalletadapter.clientlib.protocol.MobileWalletAdapterClient

interface AdapterOperations {
suspend fun authorize(identityUri: Uri, iconUri: Uri, identityName: String, rpcCluster: RpcCluster = RpcCluster.MainnetBeta): MobileWalletAdapterClient.AuthorizationResult

@Deprecated(
"Replaced by updated authorize() method, which adds MWA 2.0 spec support",
replaceWith = ReplaceWith("authorize(identityUri, iconUri, identityName, chain, authToken, features, addresses)"),
DeprecationLevel.WARNING
)
suspend fun authorize(
identityUri: Uri,
iconUri: Uri,
identityName: String,
rpcCluster: RpcCluster = RpcCluster.MainnetBeta
): MobileWalletAdapterClient.AuthorizationResult

suspend fun authorize(
identityUri: Uri,
iconUri: Uri,
identityName: String,
chain: String,
authToken: String? = null,
features: Array<String>? = null,
addresses: Array<ByteArray>? = null
): MobileWalletAdapterClient.AuthorizationResult

suspend fun reauthorize(identityUri: Uri, iconUri: Uri, identityName: String, authToken: String): MobileWalletAdapterClient.AuthorizationResult

suspend fun deauthorize(authToken: String)

suspend fun getCapabilities(): MobileWalletAdapterClient.GetCapabilitiesResult

@Deprecated(
"Replaced by signMessagesDetached, which returns the improved MobileWalletAdapterClient.SignMessagesResult type",
replaceWith = ReplaceWith("signMessagesDetached(messages, addresses)"),
DeprecationLevel.WARNING
)
suspend fun signMessages(messages: Array<ByteArray>, addresses: Array<ByteArray>): MobileWalletAdapterClient.SignPayloadsResult

suspend fun signMessagesDetached(messages: Array<ByteArray>, addresses: Array<ByteArray>): MobileWalletAdapterClient.SignMessagesResult

suspend fun signTransactions(transactions: Array<ByteArray>): MobileWalletAdapterClient.SignPayloadsResult

suspend fun signAndSendTransactions(transactions: Array<ByteArray>, params: TransactionParams = DefaultTransactionParams): MobileWalletAdapterClient.SignAndSendTransactionsResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@ package com.solana.mobilewalletadapter.clientlib
import android.net.Uri
import com.solana.mobilewalletadapter.clientlib.protocol.MobileWalletAdapterClient.AuthorizationResult

sealed class CredentialState {
data class Provided(
val credentials: ConnectionIdentity
): CredentialState()

object NotProvided: CredentialState()
}

data class ConnectionIdentity(
val identityUri: Uri,
val iconUri: Uri,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class LocalAdapterOperations(

var client: MobileWalletAdapterClient? = null

@Deprecated(
"Replaced by updated authorize() method, which adds MWA 2.0 spec support",
replaceWith = ReplaceWith("authorize(identityUri, iconUri, identityName, chain, authToken, features, addresses)"),
DeprecationLevel.WARNING
)
override suspend fun authorize(identityUri: Uri, iconUri: Uri, identityName: String, rpcCluster: RpcCluster): MobileWalletAdapterClient.AuthorizationResult {
return withContext(ioDispatcher) {
@Suppress("BlockingMethodInNonBlockingContext")
Expand All @@ -24,6 +29,22 @@ class LocalAdapterOperations(
}
}

override suspend fun authorize(
identityUri: Uri,
iconUri: Uri,
identityName: String,
chain: String,
authToken: String?,
features: Array<String>?,
addresses: Array<ByteArray>?
): MobileWalletAdapterClient.AuthorizationResult {
return withContext(ioDispatcher) {
@Suppress("BlockingMethodInNonBlockingContext")
client?.authorize(identityUri, iconUri, identityName, chain, authToken, features, addresses)?.get()
?: throw InvalidObjectException("Provide a client before performing adapter operations")
}
}

override suspend fun reauthorize(identityUri: Uri, iconUri: Uri, identityName: String, authToken: String): MobileWalletAdapterClient.AuthorizationResult {
return withContext(ioDispatcher) {
@Suppress("BlockingMethodInNonBlockingContext")
Expand All @@ -48,6 +69,11 @@ class LocalAdapterOperations(
}
}

@Deprecated(
"Replaced by signMessagesDetached, which returns the improved MobileWalletAdapterClient.SignMessagesResult type",
replaceWith = ReplaceWith("signMessagesDetached(messages, addresses)"),
DeprecationLevel.WARNING
)
override suspend fun signMessages(messages: Array<ByteArray>, addresses: Array<ByteArray>): MobileWalletAdapterClient.SignPayloadsResult {
return withContext(ioDispatcher) {
@Suppress("BlockingMethodInNonBlockingContext")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.solana.mobilewalletadapter.clientlib.protocol.MobileWalletAdapterClie
import com.solana.mobilewalletadapter.clientlib.scenario.LocalAssociationIntentCreator
import com.solana.mobilewalletadapter.clientlib.scenario.Scenario
import com.solana.mobilewalletadapter.common.ProtocolContract
import com.solana.mobilewalletadapter.common.protocol.SessionProperties
import kotlinx.coroutines.*
import java.io.IOException
import java.util.concurrent.CancellationException
Expand All @@ -15,14 +16,12 @@ import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException

class MobileWalletAdapter(
private val connectionIdentity: ConnectionIdentity,
private val timeout: Int = Scenario.DEFAULT_CLIENT_TIMEOUT_MS,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val scenarioProvider: AssociationScenarioProvider = AssociationScenarioProvider(),
connectionIdentity: ConnectionIdentity? = null,
) {

private var credsState: CredentialState = CredentialState.NotProvided

private val adapterOperations = LocalAdapterOperations(ioDispatcher)

var authToken: String? = null
Expand All @@ -31,7 +30,7 @@ class MobileWalletAdapter(
* Specify the RPC cluster used for all operations. Note: changing at runtime will invalidate
* the auth token and reauthorization will be required
*/
var rpcCluster: RpcCluster = RpcCluster.Devnet
var blockchain: Blockchain = Solana.Devnet
set(value) {
if (value != field) {
authToken = null
Expand All @@ -40,18 +39,31 @@ class MobileWalletAdapter(
field = value
}

init {
connectionIdentity?.let {
credsState = CredentialState.Provided(it)
@Deprecated(
"RpcCluster provides only Solana clusters; use the Blockchain object for full multi-chain support.",
replaceWith = ReplaceWith("Set `blockchain` property moving forward."),
DeprecationLevel.WARNING
)
var rpcCluster: RpcCluster = RpcCluster.Devnet
set(value) {
when (value) {
RpcCluster.MainnetBeta -> {
blockchain = Solana.Mainnet
}
RpcCluster.Devnet -> {
blockchain = Solana.Devnet
}
RpcCluster.Testnet -> {
blockchain = Solana.Testnet
}
else -> { }
}

field = value
}
}

suspend fun connect(sender: ActivityResultSender): TransactionResult<Unit> {
return transact(sender) {
if (credsState is CredentialState.NotProvided) {
throw IllegalStateException("App identity credentials must be provided via the constructor to use the connect method.")
}
}
return transact(sender) { }
}

suspend fun <T> transact(
Expand Down Expand Up @@ -94,20 +106,23 @@ class MobileWalletAdapter(
val client = scenario.start().get(ASSOCIATION_CONNECT_DISCONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
adapterOperations.client = client

val authResult = credsState.let { creds ->
if (creds is CredentialState.Provided) {
with (creds.credentials) {
val authResult = authToken?.let { token ->
adapterOperations.reauthorize(identityUri, iconUri, identityName, token)
} ?: run {
adapterOperations.authorize(identityUri, iconUri, identityName, rpcCluster)
}

authToken = authResult.authToken
authResult
}
val protocolVersion = scenario.session.sessionProperties.protocolVersion

val authResult = with (connectionIdentity) {
if (protocolVersion == SessionProperties.ProtocolVersion.V1) {
/**
* TODO: Full MWA 2.0 support has feature & multi-address params. Will be implemented in a future minor release.
* Both the features & addresses params are set to null for now.
*/
adapterOperations.authorize(identityUri, iconUri, identityName, blockchain.fullName, authToken, null, null)
} else {
null
authToken?.let { token ->
adapterOperations.reauthorize(identityUri, iconUri, identityName, token)
} ?: run {
adapterOperations.authorize(identityUri, iconUri, identityName, RpcCluster.Custom(blockchain.cluster))
}.also {
authToken = it.authToken
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@ package com.solana.mobilewalletadapter.clientlib

import com.solana.mobilewalletadapter.common.ProtocolContract

@Deprecated(
"RpcCluster is deprecated as of MWA 2.0",
replaceWith = ReplaceWith("Use the Blockchain object for multi-chain support"),
DeprecationLevel.WARNING
)
sealed class RpcCluster(val name: String) {
object MainnetBeta : RpcCluster(ProtocolContract.CLUSTER_MAINNET_BETA)
object Testnet : RpcCluster(ProtocolContract.CLUSTER_TESTNET)
object Devnet : RpcCluster(ProtocolContract.CLUSTER_DEVNET)
class Custom(name: String) : RpcCluster(name)
}

sealed class Blockchain(
val name: String,
val cluster: String
) {
val fullName
get() = "$name:$cluster"
}

sealed class Solana {
object Mainnet: Blockchain("solana", "mainnet")
object Testnet: Blockchain("solana", ProtocolContract.CLUSTER_TESTNET)
object Devnet: Blockchain("solana", ProtocolContract.CLUSTER_DEVNET)
}

open class TransactionParams(
Expand Down
Loading

0 comments on commit 8bb5634

Please sign in to comment.