Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile Connect #907

Merged
merged 72 commits into from
Jun 27, 2024
Merged

Mobile Connect #907

merged 72 commits into from
Jun 27, 2024

Conversation

jakub-rdx
Copy link
Contributor

@jakub-rdx jakub-rdx commented May 8, 2024

Description

Mobile Connect requests handling implementation flow
Changes:

  • added deep link handling which is tied to MobileConnectScreen
  • there are two types of deep links recognized now - linking and dapp request - see MobieConnectViewModel
  • updated MessageFromDataChannel to IncomingMessage since now messages could come from deep link or data channel.
  • each incoming request has now remoteEntityId which is sealed interface hierarchy representing origin of that request (mobile connect or CE`
  • WalletInteraction was replaced with DappToWalletInteractionUnvalidated from sargon and WalletInteractionResponse with WalletToDappInteractionResponse, while our domain models built from those network models are the same.
  • extracted logic that was used to respond after sucesfull/failed request handling into RespondToIncomingRequestUseCase. Use case decides if it should respond as usual via DappMessenger or if it should use Radix Connect Relay.

Test scenarios

  1. Use this dApp to test Mobile Connect flow.
  2. Test dApps like sandbox/dashboard/gumball to see if there are no serialization issues using sargon.

@jakub-rdx jakub-rdx force-pushed the feature/m2m-poc branch 3 times, most recently from 74a8e1b to 1da79f0 Compare May 28, 2024 14:18
@jakub-rdx jakub-rdx changed the title Mobile Connect PoC Mobile Connect Jun 3, 2024
@jakub-rdx jakub-rdx force-pushed the feature/m2m-poc branch 2 times, most recently from 5efeb07 to 01b9513 Compare June 10, 2024 11:23
@jakub-rdx jakub-rdx marked this pull request as ready for review June 10, 2024 18:26
Copy link
Contributor

Choose a reason for hiding this comment

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

💯

Copy link
Contributor

Choose a reason for hiding this comment

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

👌

@@ -43,5 +70,14 @@
tools:node="remove" />

</application>

<queries>
Copy link
Contributor

Choose a reason for hiding this comment

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

👌

): Result<Unit> {
val messageJson = try {
Json.encodeToString(response)
response.toJson()
Copy link
Contributor

Choose a reason for hiding this comment

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

}

class LedgerMessengerImpl @Inject constructor(
private val peerdroidClient: PeerdroidClient,
private val json: Json
Copy link
Contributor

Choose a reason for hiding this comment

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

Please rename this to jsonSerializer, or something similar.

Copy link
Contributor

Choose a reason for hiding this comment

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

if you decide to rename it, please do the same in ObserveAccountsAndSyncWithConnectorExtensionUseCase

is WalletInteraction -> payload.toDomainModel(remoteConnectorId = remoteConnectorId)
else -> (payload as LedgerInteractionResponse).toDomainModel()
val dappInteraction = runCatching {
DappToWalletInteractionUnvalidated.Companion.fromJson(messageInJsonString)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for Companion here.

import rdx.works.core.domain.TransactionManifestData

fun DappToWalletInteractionUnvalidated.toDomainModel(remoteEntityId: IncomingMessage.RemoteEntityID): IncomingMessage.IncomingRequest {
try {
Copy link
Contributor

Choose a reason for hiding this comment

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

Methods like these could be easier readable my converting them as

= runCatching {
    ....
}.mapError {
    RadixWalletException.IncomingMessageException.MessageParse(it)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

👌


val isInternal: Boolean
open val isInternal: Boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

Very nice that you did split the incoming messages with the notion of RemoteEntityId. On the other hand, the isInternal is becoming now confusing. I will see what I can do when I will work on this PR. We could explore maybe renaming the RemoteEntityID to RequestEntity. This entity can be

  • for radix connect
  • for CE
  • for internal messages.

I have not yet though about it throughout, but I think it is worth exploring.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it definitely makes sense and worth exploring, I didn't have time to actually think about this but seem very reasonable suggestion

@@ -37,7 +37,7 @@ import javax.inject.Inject
*/
class AuthorizeSpecifiedPersonaUseCase @Inject constructor(
private val dAppConnectionRepository: DAppConnectionRepository,
private val dAppMessenger: DappMessenger,
private val respondToIncomingRequestUseCase: RespondToIncomingRequestUseCase,
Copy link
Contributor

Choose a reason for hiding this comment

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

👌

Comment on lines 67 to 110
fun NavGraphBuilder.mobileConnect(onBackClick: () -> Unit) {
composable(
route = ROUTE,
deepLinks = listOf(
navDeepLink {
uriPattern =
"https://dr6vsuukf8610.cloudfront.net/?$ROUTE_ARGS"
},
navDeepLink {
uriPattern = "radixwallet://?${ROUTE_ARGS}"
}
),
arguments = listOf(
navArgument(ARG_PUBLIC_KEY) {
type = NavType.StringType
nullable = true
},
navArgument(ARG_SESSION_ID) {
type = NavType.StringType
nullable = true
},
navArgument(ARG_DAPP_ORIGIN) {
type = NavType.StringType
nullable = true
},
navArgument(ARG_INTERACTION_ID) {
type = NavType.StringType
nullable = true
},
navArgument(ARG_BROWSER) {
type = NavType.StringType
nullable = true
}
),
enterTransition = {
slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up)
},
exitTransition = {
slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down)
}
) {
MobileConnectScreen(onBackClick = onBackClick)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

So I guess this will be eventually removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

Comment on lines 194 to 226

@Suppress("MagicNumber")
fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }

return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}

fun generateX25519KeyPair(): Result<Pair<String, String>> {
return runCatching {
val generator = X25519KeyPairGenerator()
val params = X25519KeyGenerationParameters(SecureRandom())
generator.init(params)
val keypair1: AsymmetricCipherKeyPair = generator.generateKeyPair()
val priv1 = keypair1.private as X25519PrivateKeyParameters
val pub1 = keypair1.public as X25519PublicKeyParameters
Pair(priv1.encoded.toHexString(), pub1.encoded.toHexString())
}
}

fun generateX25519SharedSecret(privateKeyCompressed: ByteArray, publicKeyCompressed: ByteArray): Result<String> {
return runCatching {
val agreement = X25519Agreement().apply {
init(X25519PrivateKeyParameters(privateKeyCompressed))
}

val secret = ByteArray(agreement.agreementSize)
agreement.calculateAgreement(X25519PublicKeyParameters(publicKeyCompressed), secret, 0)
secret.toHexString()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Reminder to remove this code before merging

Copy link
Contributor Author

Choose a reason for hiding this comment

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

after using sargon for linking flow this goes away, it's just temporary for the PoC to work now.

sergiupuhalschi-rdx and others added 24 commits June 17, 2024 11:02
…ling

[ABW-3406] - RCfM Deep link handling
New request handling flow for mobile connect
# Conflicts:
#	app/src/main/java/com/babylon/wallet/android/utils/Constants.kt
#	gradle/libs.versions.toml
…flow

# Conflicts:
#	app/src/main/java/com/babylon/wallet/android/MainActivity.kt
#	app/src/main/java/com/babylon/wallet/android/presentation/navigation/NavigationHost.kt
#	app/src/main/res/values-en/strings.xml
#	gradle/libs.versions.toml
…ed-flow

Update mobile connect flow and UI
# Conflicts:
#	app/src/main/res/values-en/strings.xml
Copy link

sonarcloud bot commented Jun 27, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
3 Security Hotspots
0.0% Coverage on New Code (required ≥ 40%)

See analysis details on SonarCloud

@jakub-rdx jakub-rdx merged commit bb8d1ec into main Jun 27, 2024
7 of 9 checks passed
@jakub-rdx jakub-rdx deleted the feature/m2m-poc branch June 27, 2024 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants