Skip to content

Commit

Permalink
add holder api to demo app
Browse files Browse the repository at this point in the history
  • Loading branch information
swaptr committed Nov 11, 2023
1 parent d34914c commit d4c04b1
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 21 deletions.
12 changes: 9 additions & 3 deletions libvdrtools/indy-utils/src/crypto/base64/rust_base64.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use base64::{engine::general_purpose, Engine};
use base64::{
alphabet,
engine::{general_purpose, DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
Engine,
};
use indy_api_types::errors::prelude::*;

const ANY_PADDING: GeneralPurposeConfig =
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent);
const URL_SAFE_ANY_PADDING: GeneralPurpose = GeneralPurpose::new(&alphabet::URL_SAFE, ANY_PADDING);
pub fn encode(doc: &[u8]) -> String {
general_purpose::STANDARD.encode(doc)
}
Expand All @@ -16,7 +22,7 @@ pub fn encode_urlsafe(doc: &[u8]) -> String {
}

pub fn decode_urlsafe(doc: &str) -> Result<Vec<u8>, IndyError> {
general_purpose::URL_SAFE.decode(doc).map_err(|e| {
URL_SAFE_ANY_PADDING.decode(doc).map_err(|e| {
e.to_indy(
IndyErrorKind::InvalidStructure,
"Invalid base64URL_SAFE sequence",
Expand Down
4 changes: 2 additions & 2 deletions uniffi_aries_vcx/core/src/handlers/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,15 @@ impl Connection {

pub fn send_message(
&self,
profile_holder: Arc<ProfileHolder>,
profile: Arc<ProfileHolder>,
message: String,
) -> VcxUniFFIResult<()> {
let message = serde_json::from_str(&message)?;
let handler = self.handler.lock()?.clone();

block_on(async {
handler
.send_message(profile_holder.inner.wallet(), &message, &HttpClient)
.send_message(profile.inner.wallet(), &message, &HttpClient)
.await?;
Ok(())
})
Expand Down
3 changes: 3 additions & 0 deletions uniffi_aries_vcx/core/src/vcx.udl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ interface Connection {

[Throws=VcxUniFFIError]
void send_ack(ProfileHolder profile);

[Throws=VcxUniFFIError]
void send_message(ProfileHolder profile, string message);
};

interface Holder {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package org.hyperledger.ariesvcx

import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -18,16 +22,19 @@ import org.hyperledger.ariesvcx.utils.await
data class AppUiState(
val profileReady: Boolean = false,
val connectionInvitationReceived: Boolean = false,
val connectionCompleted: Boolean = false
val connectionCompleted: Boolean = false,
val offerReceived: Boolean = false
)

class AppDemoController : ViewModel() {
private val httpClient = OkHttpClient()

private var profile: ProfileHolder? = null
private var connection: Connection? = null
private var holder: Holder? = null

private var onConnectionComplete: (connection: Connection) -> Unit = {}
private var onOfferReceived: () -> Unit = {}

// Expose screen UI state
private val _state = MutableStateFlow(AppUiState())
Expand Down Expand Up @@ -88,7 +95,7 @@ class AppDemoController : ViewModel() {
val relayResponse = httpClient.newCall(pollRelayRequest).await()
if (relayResponse.code == 200) {
val message = relayResponse.body!!.string()

Log.d("MESSAGE", "awaitConnectionCompletion: $message")
val unpackedMessage = unpackMessage(
profile!!,
message
Expand All @@ -101,7 +108,7 @@ class AppDemoController : ViewModel() {
Log.d("AppDemoController", "connection state: ${connection!!.getState()}")

_state.update { it.copy(connectionCompleted = true) }
onConnectionComplete(connection!!)
onConnectionComplete.invoke(connection!!)
break
}
}
Expand All @@ -110,4 +117,43 @@ class AppDemoController : ViewModel() {
fun subscribeToConnectionComplete(onComplete: (connection: Connection) -> Unit) {
onConnectionComplete = onComplete
}

fun subscribeToShowDialog(onShowDialog: () -> Unit) {
onOfferReceived = onShowDialog
}

fun processOfferRequest() {
holder?.prepareCredentialRequest(profile!!, "4xE68b6S5VRFrKMMG1U95M")
val message = holder?.getMsgCredentialRequest()
connection?.sendMessage(profile!!, message!!)
}

suspend fun awaitCredentialPolling() {
val pollRelayRequest = Request.Builder()
.url("$BASE_RELAY_ENDPOINT/pop_user_message/$RELAY_USER_ID")
.build()
while(true) {
delay(2000)
val relayResponse = httpClient.newCall(pollRelayRequest).await()
if (relayResponse.code == 200) {
val message = relayResponse.body!!.string()

val unpackedMessage = unpackMessage(
profile!!,
message
)

if (holder == null) {
Log.d("OFFER", "awaitCredentialPolling: received offer")
holder = createFromOffer("", unpackedMessage.message)
_state.update { it.copy(offerReceived = true) }
onOfferReceived.invoke()
processOfferRequest()
} else {
Log.d("CREDENTIAL", "awaitCredentialPolling: received credential")
holder?.processCredential(profile!!, unpackedMessage.message)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package org.hyperledger.ariesvcx

// Set your public IP address here, this endpoint will be used while communicating with the peer(agent).
const val BASE_RELAY_ENDPOINT = "https://b199-27-57-116-96.ngrok-free.app";
const val BASE_RELAY_ENDPOINT = "https://7365-223-236-178-57.ngrok-free.app";
const val RELAY_USER_ID = "demo-user-1";
Original file line number Diff line number Diff line change
@@ -1,21 +1,83 @@
package org.hyperledger.ariesvcx

import android.net.Uri
import android.util.Base64
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@Composable
fun HolderScreen(
demoController: AppDemoController,
navController: NavHostController,
) {
val demoState by demoController.states.collectAsState()
val scope = rememberCoroutineScope()
val context = LocalContext.current

var credentialOffer by remember {
mutableStateOf<String?>(null)
}

credentialOffer?.let {
AlertDialog(
onDismissRequest = { credentialOffer = null },
title = { Text("Accept this invitation?") },
text = { Text(credentialOffer!!) },
confirmButton = {
TextButton(onClick = {
scope.launch {
demoController.processOfferRequest()
}
}) {
Text("Accept")
}
},
dismissButton = {
TextButton(onClick = { credentialOffer = null }) {
Text("Cancel")
}
},
)
}

LaunchedEffect(Unit) {
demoController.awaitCredentialPolling()
}

LaunchedEffect(Unit) {
demoController.subscribeToShowDialog {
scope.launch(Dispatchers.Main) {
Toast.makeText(
context,
"New Offer Received",
Toast.LENGTH_LONG
).show()
}
}
}

Column(
modifier = Modifier
.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
Expand Down Expand Up @@ -34,13 +37,16 @@ fun HomeScreen(
val scope = rememberCoroutineScope()
val context = LocalContext.current
val file = prepareGenesisFile(context)
demoController.subscribeToConnectionComplete { newConn ->
scope.launch(Dispatchers.Main) {
Toast.makeText(
context,
"New Connection Created",
Toast.LENGTH_SHORT
).show()

LaunchedEffect(key1 = Unit) {
demoController.subscribeToConnectionComplete {
scope.launch(Dispatchers.Main) {
Toast.makeText(
context,
"New Connection Created",
Toast.LENGTH_LONG
).show()
}
}
}

Expand Down Expand Up @@ -71,7 +77,7 @@ fun HomeScreen(
}) {
Text(text = "Scan QR Code")
}
Button(enabled = /*(demoState.connectionCompleted)*/ true,
Button(enabled = (demoState.connectionCompleted),
onClick = {
navController.navigate(Destination.Holder.route)
}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ fun ScanScreen(
LaunchedEffect(key1 = true) {
launcher.launch(Manifest.permission.CAMERA)
}

Column(
modifier = Modifier
.fillMaxSize()
Expand Down
8 changes: 4 additions & 4 deletions uniffi_aries_vcx/demo/app/src/main/res/raw/transactions
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"127.0.0.1","client_port":9702,"node_ip":"127.0.0.1","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"127.0.0.1","client_port":9704,"node_ip":"127.0.0.1","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"127.0.0.1","client_port":9706,"node_ip":"127.0.0.1","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"127.0.0.1","client_port":9708,"node_ip":"127.0.0.1","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blskey":"4N8aUNHSgjQVgkpm8nhNEfDf6txHznoYREg9kirmJrkivgL4oSEimFF6nsQ6M41QvhM2Z33nves5vfSn9n1UwNFJBYtWVnHYMATn76vLuL3zU88KyeAYcHfsih3He6UHcXDxcaecHVz6jhCYz1P2UZn2bDVruL5wXpehgBfBaLKm3Ba","blskey_pop":"RahHYiCvoNCtPTrVtP7nMC5eTYrsUA8WjXbdhNc8debh1agE9bGiJxWBXYNFbnJXoXhWFMvyqhqhRoq737YQemH5ik9oL7R4NTTCz2LEZhkgLJzB3QRQqJyBNyv7acbdHrAT8nQ9UkLbaVL9NBpnWXBTw4LEMePaSHEw66RzPNdAX1","client_ip":"138.197.138.255","client_port":9702,"node_ip":"138.197.138.255","node_port":9701,"services":["VALIDATOR"]},"dest":"Gw6pDLhcBcoQesN72qfotTgFa7cbuqZpkX3Xo6pLhPhv"},"metadata":{"from":"Th7MpTaRZVRYnPiabds81Y"},"type":"0"},"txnMetadata":{"seqNo":1,"txnId":"fea82e10e894419fe2bea7d96296a6d46f50f93f9eeda954ec461b2ed2950b62"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node2","blskey":"37rAPpXVoxzKhz7d9gkUe52XuXryuLXoM6P6LbWDB7LSbG62Lsb33sfG7zqS8TK1MXwuCHj1FKNzVpsnafmqLG1vXN88rt38mNFs9TENzm4QHdBzsvCuoBnPH7rpYYDo9DZNJePaDvRvqJKByCabubJz3XXKbEeshzpz4Ma5QYpJqjk","blskey_pop":"Qr658mWZ2YC8JXGXwMDQTzuZCWF7NK9EwxphGmcBvCh6ybUuLxbG65nsX4JvD4SPNtkJ2w9ug1yLTj6fgmuDg41TgECXjLCij3RMsV8CwewBVgVN67wsA45DFWvqvLtu4rjNnE9JbdFTc1Z4WCPA3Xan44K1HoHAq9EVeaRYs8zoF5","client_ip":"138.197.138.255","client_port":9704,"node_ip":"138.197.138.255","node_port":9703,"services":["VALIDATOR"]},"dest":"8ECVSk179mjsjKRLWiQtssMLgp6EPhWXtaYyStWPSGAb"},"metadata":{"from":"EbP4aYNeTHL6q385GuVpRV"},"type":"0"},"txnMetadata":{"seqNo":2,"txnId":"1ac8aece2a18ced660fef8694b61aac3af08ba875ce3026a160acbc3a3af35fc"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node3","blskey":"3WFpdbg7C5cnLYZwFZevJqhubkFALBfCBBok15GdrKMUhUjGsk3jV6QKj6MZgEubF7oqCafxNdkm7eswgA4sdKTRc82tLGzZBd6vNqU8dupzup6uYUf32KTHTPQbuUM8Yk4QFXjEf2Usu2TJcNkdgpyeUSX42u5LqdDDpNSWUK5deC5","blskey_pop":"QwDeb2CkNSx6r8QC8vGQK3GRv7Yndn84TGNijX8YXHPiagXajyfTjoR87rXUu4G4QLk2cF8NNyqWiYMus1623dELWwx57rLCFqGh7N4ZRbGDRP4fnVcaKg1BcUxQ866Ven4gw8y4N56S5HzxXNBZtLYmhGHvDtk6PFkFwCvxYrNYjh","client_ip":"138.197.138.255","client_port":9706,"node_ip":"138.197.138.255","node_port":9705,"services":["VALIDATOR"]},"dest":"DKVxG2fXXTU8yT5N7hGEbXB3dfdAnYv1JczDUHpmDxya"},"metadata":{"from":"4cU41vWW82ArfxJxHkzXPG"},"type":"0"},"txnMetadata":{"seqNo":3,"txnId":"7e9f355dffa78ed24668f0e0e369fd8c224076571c51e2ea8be5f26479edebe4"},"ver":"1"}
{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.138.255","client_port":9708,"node_ip":"138.197.138.255","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}

0 comments on commit d4c04b1

Please sign in to comment.