# Integrate DIDComm for Rust

> Learn how to integrate Affinidi Messaging into your projects to enable secure, private and trusted messaging.

The DIDComm for Rust integration guide provides a step-by-step overview for developers to integrate DIDComm-based communication to enable their application to send DIDComm messages, which enables secure, privacy-preserving, and verifiable messaging between decentralised identifiers (DIDs), allowing users to exchange messages securely and privately without relying on centralised intermediaries.

## Key features

- 
Implements the DIDComm v2.1 protocol.

- 
Support for DIDComm Messaging Envelope types.

- 
Connect and authenticate with different mediator services that follow the DIDComm v2.1 protocol.

## Requirements

- 
Rust (1.85.0) 2024 Edition

- 
Redis 8.0

## Required packages

| Package | Description |
| [Affinidi Messaging - DIDComm for Rust](https://crates.io/crates/affinidi-messaging-didcomm) | The package for sending and receiving messages using the DIDComm protocol. It is designed to be used with the Affinidi Messaging SDK. |
| [Affinidi Messaging SDK](https://crates.io/crates/affinidi-messaging-sdk) | A Software Development Kit (SDK) to simplify the implementation of Affinidi Messaging into your application. |
| [Affinidi Trust Development Kit](https://crates.io/crates/affinidi-tdk) | Simplifies development of privacy preserving solutions using decentralised identity and data sharing technologies. |

## Sample usage

The examples demonstrate how to construct, sign, encrypt, and send messages according to the [DIDComm Messaging spec](https://identity.foundation/didcomm-messaging/spec/v2.1/). Check out [these](https://github.com/affinidi/affinidi-tdk-rs/tree/main/crates/messaging/affinidi-messaging-helpers/examples) examples if you need more code references.

### Instantiate the TDK

Initialise the Trust Development Kit.

```rust
let tdk = TDK::new(
        TDKConfig::builder()
            .with_environment_name(environment_name.clone())
            .build()?,
        None,
    )
    .await?;

let environment = &tdk.get_shared_state().environment;
let atm = tdk.atm.clone().unwrap();
let protocols = Protocols::new();
```

### Activate profiles

Enable profiles needed for communication.

```rust
// Activate Alice profile
let tdk_alice = if let Some(alice) = environment.profiles.get("Alice") {
    tdk.add_profile(alice).await;
    alice
} else {
    return Err(ATMError::ConfigError(
        format!("Alice not found in Environment: {}", environment_name).to_string(),
    ));
};

let atm_alice = atm
    .profile_add(&ATMProfile::from_tdk_profile(&atm, tdk_alice).await?, true)
    .await?;

let Some(alice_info) = protocols
    .mediator
    .account_get(&atm, &atm_alice, None)
    .await?
else {
    panic!("Alice account not found on mediator");
};
info!("Alice profile active: {:?}", alice_info);

let alice_acl_mode = MediatorACLSet::from_u64(alice_info.acls)
    .get_access_list_mode()
    .0;
info!("Alice ACL Mode Type: {:?}", alice_acl_mode);

// Activate Bob profile
let tdk_bob = if let Some(bob) = environment.profiles.get("Bob") {
    tdk.add_profile(bob).await;
    bob
} else {
    return Err(ATMError::ConfigError(
        format!("Bob not found in Environment: {}", environment_name).to_string(),
    ));
};

let atm_bob = atm
    .profile_add(&ATMProfile::from_tdk_profile(&atm, tdk_bob).await?, true)
    .await?;

let Some(bob_info) = protocols.mediator.account_get(&atm, &atm_bob, None).await? else {
    panic!("Bob account not found on mediator");
};
info!("Bob profile active: {:?}", bob_info);

let bob_acl_mode = MediatorACLSet::from_u64(bob_info.acls)
    .get_access_list_mode()
    .0;
info!("Bob ACL Mode Type: {:?}", bob_acl_mode);
```

### Add Sender DID to ACL (Access Control List)

To be able to send a message, sender DID should be added to the recipient Access Control List.

```rust
// Ensure Bob is added to Alice explicit allow list
if let AccessListModeType::ExplicitAllow = alice_acl_mode {
        protocols
            .mediator
            .access_list_add(&atm, &atm_alice, None, &[&bob_info.did_hash])
            .await?;
}

// Ensure Alice is added to Bob explicit allow list
if let AccessListModeType::ExplicitAllow = bob_acl_mode {
        protocols
            .mediator
            .access_list_add(&atm, &atm_bob, None, &[&alice_info.did_hash])
            .await?;
}
```

### Compose plaintext message

A plain text message is a simple JSON message with headers and a body.

```rust
let now = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .unwrap()
        .as_secs();

let msg = Message::build(
        Uuid::new_v4().into(),
        "Chatty Alice".into(),
        json!("Hello Bob!"),
    )
    .to(atm_bob.inner.did.clone())
    .from(atm_alice.inner.did.clone())
    .created_time(now)
    .expires_time(now + 10)
    .finalize();

let msg_id = msg.id.clone();
```

### Pack DIDComm message

Convert the plaintext message into DIDComm message by signing and encrypting it to ensure secure and authenticated transmission.

```rust
//Pack encrypted and signed message from Alice to Bob
let packed_msg = atm
        .pack_encrypted(
            &msg,
            &atm_bob.inner.did,
            Some(&atm_alice.inner.did),
            Some(&atm_alice.inner.did),
            None,
        )
        .await?;
```

### Send message

Transmits the packed DIDComm mesage to the recipient.

```rust
//Forward message from Alice to Mediator
let bobs_mediator_did = tdk_bob.mediator.to_owned().unwrap();

let (_forward_id, forward_msg) = protocols
        .routing
        .forward_message(
            &atm,
            &atm_alice,
            false,
            &packed_msg.0,
            &bobs_mediator_did,
            &atm_bob.inner.did,
            None,
            None,
        )
        .await?;

// Alice sent message to Mediator
match atm
        .send_message(&atm_alice, &forward_msg, &msg_id, false, false)
        .await
```

### Receive message

Accepts the incoming DIDComm message.

```rust
// Bob gets his message
match protocols
        .message_pickup
        .live_stream_get(&atm, &atm_bob, &msg_id, Duration::from_secs(5), true)
        .await?
```

## What’s next

  [Explore Meeting Place, an implementation of Affinidi Messaging](/products/affinidi-elements/affinidi-messaging/meeting-place.md)

  [Integrate Affinidi Messaging into your applications](/products/affinidi-elements/affinidi-messaging/integration-guides.md)
