Skip to content

Commit

Permalink
Add simple client implementation
Browse files Browse the repository at this point in the history
Has majorly common code with mediator agent.
It's in essence one hybrid, with organized code. Then again, aries agents are meant to be horizontal.

Signed-off-by: nain-F49FF806 <[email protected]>
  • Loading branch information
nain-F49FF806 committed Sep 13, 2023
1 parent 4adc7dd commit ba7b96f
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 4 deletions.
1 change: 1 addition & 0 deletions mediator/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions mediator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ env_logger = "0.10.0"
fast_qr = { version = "0.10.2", features = ["svg"] }
log = "0.4.20"
messages = { version = "0.58.0", path = "../messages" }
reqwest = { version = "0.11.20", features = ["json"] }
serde_json = "1.0.106"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
tower-http = { version = "0.4.4", features = ["catch-panic"] }
url = "2.4.1"
uuid = "1.4.1"

[dev-dependencies]
reqwest = "0.11.20"
88 changes: 88 additions & 0 deletions mediator/src/agent/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::sync::Arc;

use aries_vcx::handlers::util::AnyInvitation;
// use aries_vcx::protocols::connection::initiation_type::Invitee;
use aries_vcx::protocols::connection::invitee::states::initial::Initial as ClientInit;
// use aries_vcx::protocols::connection::invitee::states::invited::Invited;
use aries_vcx::protocols::connection::invitee::states::requested::Requested as ClientRequestSent;
use aries_vcx::protocols::connection::invitee::InviteeConnection;

use aries_vcx::protocols::connection::Connection;
use aries_vcx::protocols::mediated_connection::pairwise_info::PairwiseInfo;
// use aries_vcx::protocols::oob;
use aries_vcx::utils::mockdata::profile::mock_ledger::MockLedger;
use aries_vcx_core::ledger::base_ledger::IndyLedgerRead;
use aries_vcx_core::wallet::base_wallet::BaseWallet;
use aries_vcx_core::wallet::indy::IndySdkWallet;
use diddoc_legacy::aries::diddoc::AriesDidDoc;
// use diddoc_legacy::aries::service::AriesService;
use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation;
use messages::msg_fields::protocols::out_of_band::invitation::OobService;

use super::Agent;
use crate::utils::prelude::*;

pub fn oob2did(oob: OOBInvitation) -> AriesDidDoc {
let mut did_doc: AriesDidDoc = AriesDidDoc::default();
did_doc.set_id(oob.id.clone());
let oob_service = oob.content.services.first().expect("OOB needs a service").clone();

match oob_service {
OobService::AriesService(service) => {
did_doc.set_service_endpoint(service.service_endpoint);
did_doc.set_recipient_keys(service.recipient_keys);
did_doc.set_routing_keys(service.routing_keys);
}
_ => panic!("Assuming fully clean AriesService variant only"),
}
did_doc
}

// client role utilities
impl Agent<IndySdkWallet> {
/// Starts a new connection and tries to create request to the specified OOB invite endpoint
pub async fn client_connect_req(&self, oob_invite: OOBInvitation) -> InviteeConnection<ClientRequestSent> {
// let (did, vk) = self.wallet.create_and_store_my_did(None, None).await.unwrap();
// let client_conn =
// InviteeConnection::<Initial>::new_invitee("foo".into(), PairwiseInfo { pw_did: did, pw_vk: vk });

// fn accept_invitation(
// client_conn: InviteeConnection<Initial>,
// oob_invite: OOBInvitation,
// ) -> InviteeConnection<Invited> {
// let did_doc = oob2did(oob_invite.clone());
// let state = Invited::new(did_doc, AnyInvitation::Oob(oob_invite));
// // Convert to `InvitedState`
// Connection {
// state,
// source_id: "foo".into(),
// pairwise_info: client_conn.pairwise_info().clone(),
// initiation_type: Invitee,
// }
// }
// let client_conn = accept_invitation(client_conn, oob_invite);
// todo!()

let (pw_did, pw_vk) = self.wallet.create_and_store_my_did(None, None).await.unwrap();

let mock_ledger: Arc<dyn IndyLedgerRead> = Arc::new(MockLedger {}); // cause we know we want call ledger *eew...*
let mut client_conn =
InviteeConnection::<ClientInit>::new_invitee("foo".into(), PairwiseInfo { pw_did, pw_vk })
.accept_invitation(&mock_ledger, AnyInvitation::Oob(oob_invite))
.await
.unwrap();

let client_conn = client_conn
.prepare_request("http://response.http.alt".parse().unwrap(), vec![])
.await
.unwrap();

let msg_connection_request = client_conn.get_request().clone();
info!("Client Connection Request: {:#?}", msg_connection_request);
// invitee_requested
// .send_message(&self.wallet, &msg_connection_request.into(), &HttpClient)
// .await
// .unwrap();
client_conn
}
}
3 changes: 3 additions & 0 deletions mediator/src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use diddoc_legacy::aries::service::AriesService;
use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation;

use crate::utils::Result_;
// #[cfg(test)]
pub mod client;

#[derive(Debug, Clone)]
pub struct Agent<T>
Expand Down Expand Up @@ -41,6 +43,7 @@ impl Agent<IndySdkWallet> {
Self::new_from_wallet_config(config).await
}
}

// Utils
impl<T> Agent<T>
where
Expand Down
32 changes: 32 additions & 0 deletions mediator/src/routes/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use super::*;
use crate::agent::client::oob2did;
use log::info;
use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation;

#[debug_handler]
pub async fn connection_request(
State(agent): State<ArcAgent<IndySdkWallet>>,
Json(oob_invite): Json<OOBInvitation>,
) -> Json<Value> {
let state = agent.client_connect_req(oob_invite.clone()).await;
let req_msg = serde_json::to_value(state.get_request()).unwrap();
info!(
"Sending Connection Request: {},",
serde_json::to_string_pretty(&req_msg).unwrap()
);
let service_endpoint = oob2did(oob_invite).get_endpoint().expect("Service needs an endpoint");
let http_client = reqwest::Client::new();
let res = http_client
.post(service_endpoint)
.json(&req_msg)
.send()
.await
.expect("Something went wrong")
.error_for_status()
.expect("Unexpected response")
.json::<Value>()
.await
.expect("Decoding should mostly succeed");
info!("Received response: {},", serde_json::to_string_pretty(&res).unwrap());
Json(res)
}
12 changes: 8 additions & 4 deletions mediator/src/routes.rs → mediator/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ use std::sync::Arc;
use aries_vcx_core::wallet::indy::IndySdkWallet;
use axum::extract::State;
use axum::response::Html;
use axum::routing::get;
use axum::Router;
use axum::routing::{get, post};
use axum::{Json, Router};
use axum_macros::debug_handler;
use serde_json::Value;

use crate::agent::Agent;
type ArcAgent<T> = Arc<Agent<T>>;

pub mod client;

#[debug_handler]
pub async fn oob_invite_qr(State(agent): State<Arc<Agent<IndySdkWallet>>>) -> Html<String> {
pub async fn oob_invite_qr(State(agent): State<ArcAgent<IndySdkWallet>>) -> Html<String> {
let oob = agent.get_oob_invite().unwrap();
let oob_string = serde_json::to_string_pretty(&oob).unwrap();
let qr = fast_qr::QRBuilder::new(oob_string.clone()).build().unwrap();
Expand All @@ -34,7 +38,7 @@ pub async fn readme() -> Html<String> {
pub async fn build_router(endpoint_root: &str) -> Router {
let mut agent = Agent::new_demo_agent().await.unwrap();
agent
.init_service(vec![], format!("http://{endpoint_root}").parse().unwrap())
.init_service(vec![], format!("http://{endpoint_root}/aries").parse().unwrap())
.await
.unwrap();
Router::default()
Expand Down

0 comments on commit ba7b96f

Please sign in to comment.