# Test mediator connection

> Quickly test your mediator server after deployment.

You have two options to test the mediator server you just created to ensure that users can connect to it and send messages.

## Test with DIDComm SDK for Dart

To test using the DIDComm library, follow the steps below:

### 1. Set up environment

- 
Install [Dart SDK](https://dart.dev/get-dart) version ^3.6.0 on your machine.

- 
Go to your desired director and create a folder called mediator from your terminal.

```bash
mkdir mediator
cd mediator
```

- Inside the mediator folder, create a pubspec.yaml file containing the details below.

```yaml
name: mediator
description: Test mediator connection
version: 1.0.0

environment:
  sdk: ^3.9.2

dependencies:
  path: ^1.9.0
  didcomm: ^2.0.0
  ssi: ^2.14.1
  uuid: ^4.5.1

dev_dependencies:
  lints: ^6.0.0
  test: ^1.25.6
```

- Install dependencies from the pubspec.yaml file.

```bash
dart pub get
```

### 2. Create a Dart script

- Create a mediator.dart file with the following codes. The code utilises the [DIDComm library](https://pub.dev/packages/didcomm) created by Affinidi.

```dart
import 'package:didcomm/didcomm.dart';
import 'package:ssi/ssi.dart';
import 'package:uuid/uuid.dart';

void main() async {
    // Run commands below in your terminal to generate keys for Alice and Bob:
    // openssl ecparam -name prime256v1 -genkey -noout -out example/keys/alice_private_key.pem
    // openssl ecparam -name prime256v1 -genkey -noout -out example/keys/bob_private_key.pem

    const mediatorDid = '';
    const alicePrivateKeyPath = './example/keys/alice_private_key.pem';
    const bobPrivateKeyPath = './example/keys/bob_private_key.pem';

    final aliceKeyStore = InMemoryKeyStore();
    final aliceWallet = PersistentWallet(aliceKeyStore);

    final bobKeyStore = InMemoryKeyStore();
    final bobWallet = PersistentWallet(bobKeyStore);

    final aliceDidManager = DidKeyManager(
        wallet: aliceWallet,
        store: InMemoryDidStore(),
    );

    final bobDidManager = DidKeyManager(
        wallet: bobWallet,
        store: InMemoryDidStore(),
    );

    final aliceKeyId = 'alice-key-1';
    final alicePrivateKeyBytes = await extractPrivateKeyBytes(
        alicePrivateKeyPath,
    );

    await aliceKeyStore.set(
        aliceKeyId,
        StoredKey(
        keyType: KeyType.p256,
        privateKeyBytes: alicePrivateKeyBytes,
        ),
    );

    await aliceDidManager.addVerificationMethod(aliceKeyId);
    final aliceDidDocument = await aliceDidManager.getDidDocument();

    prettyPrint(
        'Alice DID',
        object: aliceDidDocument.id,
    );

    final aliceSigner = await aliceDidManager.getSigner(
        aliceDidDocument.assertionMethod.first.id,
    );

    final bobKeyId = 'bob-key-1';
    final bobPrivateKeyBytes = await extractPrivateKeyBytes(
        bobPrivateKeyPath,
    );

    await bobKeyStore.set(
        bobKeyId,
        StoredKey(
        keyType: KeyType.p256,
        privateKeyBytes: bobPrivateKeyBytes,
        ),
    );

    await bobDidManager.addVerificationMethod(bobKeyId);
    final bobDidDocument = await bobDidManager.getDidDocument();

    prettyPrint(
        'Bob DID Document',
        object: bobDidDocument,
    );

    final bobMediatorDocument =
        await UniversalDIDResolver.defaultResolver.resolveDid(mediatorDid);

    final alicePlainTextMassage = PlainTextMessage(
        id: const Uuid().v4(),
        from: aliceDidDocument.id,
        to: [bobDidDocument.id],
        type: Uri.parse('https://didcomm.org/example/1.0/message'),
        body: {'content': 'Hello, Bob!'},
    );

    alicePlainTextMassage['custom-header'] = 'custom-value';

    prettyPrint(
        'Plain Text Message for Bob',
        object: alicePlainTextMassage,
    );

    final aliceSignedAndEncryptedMessage =
        await DidcommMessage.packIntoSignedAndEncryptedMessages(
        alicePlainTextMassage,
        keyType: [bobDidDocument].getCommonKeyTypesInKeyAgreements().first,
        recipientDidDocuments: [bobDidDocument],
        keyWrappingAlgorithm: KeyWrappingAlgorithm.ecdhEs,
        encryptionAlgorithm: EncryptionAlgorithm.a256cbc,
        signer: aliceSigner,
    );

    prettyPrint(
        'Encrypted and Signed Message by Alice',
        object: aliceSignedAndEncryptedMessage,
    );

    final createdTime = DateTime.now().toUtc();
    final expiresTime = createdTime.add(const Duration(seconds: 60));

    final forwardMessage = ForwardMessage(
        id: const Uuid().v4(),
        to: [bobMediatorDocument.id],
        from: aliceDidDocument.id,
        next: bobDidDocument.id,
        expiresTime: expiresTime,
        attachments: [
        Attachment(
            mediaType: 'application/json',
            data: AttachmentData(
            base64: base64UrlEncodeNoPadding(
                aliceSignedAndEncryptedMessage.toJsonBytes(),
            ),
            ),
        ),
        ],
    );

    prettyPrint(
        'Forward Message for Mediator that wraps Encrypted Message for Bob',
        object: forwardMessage,
    );

    // Alice is going to use Bob's Mediator to send him a message
    final aliceMediatorClient = await MediatorClient.init(
        mediatorDidDocument: bobMediatorDocument,
        didManager: aliceDidManager,
        authorizationProvider: await AffinidiAuthorizationProvider.init(
        mediatorDidDocument: bobMediatorDocument,
        didManager: aliceDidManager,
        ),
        forwardMessageOptions: const ForwardMessageOptions(
        shouldSign: true,
        keyWrappingAlgorithm: KeyWrappingAlgorithm.ecdhEs,
        encryptionAlgorithm: EncryptionAlgorithm.a256cbc,
        ),
    );

    final bobMediatorClient = await MediatorClient.init(
        mediatorDidDocument: bobMediatorDocument,
        didManager: bobDidManager,
        authorizationProvider: await AffinidiAuthorizationProvider.init(
        mediatorDidDocument: bobMediatorDocument,
        didManager: bobDidManager,
        ),
    );

    // Bob needs to add Alice's DID to his DID-level ACL to receive the message
    // Applies only if MODE_EXPLICIT_ALLOW policy is set
    final bobAccessListAddMessage = AccessListAddMessage(
        id: const Uuid().v4(),
        from: bobDidDocument.id,
        to: [bobMediatorDocument.id],
        theirDids: [aliceDidDocument.id],
        expiresTime: expiresTime,
    );

    final bobAccessListAddSentMessage =
        await bobMediatorClient.sendAclManagementMessage(
        bobAccessListAddMessage,
    );

    final sentMessage = await aliceMediatorClient.sendMessage(
        forwardMessage,
    );

    prettyPrint(
        'Encrypted and Signed Forward Message',
        object: sentMessage,
    );

    prettyPrint('Bob is fetching messages...');

    final messages = await bobMediatorClient.fetchMessages();

    for (final message in messages) {
        final originalPlainTextMessageFromAlice =
            await DidcommMessage.unpackToPlainTextMessage(
            message: message,
            recipientDidManager: bobDidManager,
            expectedMessageWrappingTypes: [
                MessageWrappingType.anoncryptSignPlaintext,
            ],
            expectedSigners: [
                aliceDidDocument.assertionMethod.first.didKeyId,
            ],
        );

        prettyPrint(
            'Unpacked Plain Text Message received by Bob via Mediator',
            object: originalPlainTextMessageFromAlice,
        );
    }
}
```

- Replace the mediatorDid variable with the mediator DID generated from the Affinidi Portal.

```dart
const mediatorDid = 'did:web:.atlas.affinidi.io';
```

### 3. Generate Cryptographic Keys

Generate cryptographic keys for Alice and Bob as our users.

```bash
mkdir -p example/keys
openssl ecparam -name prime256v1 -genkey -noout -out example/keys/alice_private_key.pem
openssl ecparam -name prime256v1 -genkey -noout -out example/keys/bob_private_key.pem
```

### 4. Run the Test Script

After setting up all the necessary codes and parameters, run the Dart script.

```bash
dart run mediator.dart
```

After running the script, the logs shows Alice sending message successfully to Bob and Bob successfully fetching and unpacking the DIDComm message.

## Test with DIDComm SDK for Rust

To test your instance using the Rust SDK, go through the following steps.

### 1. Set up environment

- 
Install Rust (1.85.0 2024 Edition) on your machine if you haven’t installed it yet using [this guide](https://www.rust-lang.org/tools/install).

- 
Install Docker on your machine if you haven’t installed it yet using [this guide](https://docs.docker.com/desktop/). We will need this to run Redis instance for the mediator to store messages temporarily and mediator configurations.

### 2. Clone the Mediator repository

- Clone the [GitHub repo](https://github.com/affinidi/affinidi-tdk-rs) on your local.

```bash
git clone git@github.com:affinidi/affinidi-tdk-rs.git
```

- Navigate to the crates/affinidi-messaging folder.

```bash
cd affinidi-tdk-rs/crates/affinidi-messaging
```

### 3. Set up the Mediator instance

- Run the Redis Docker container using the command below from your terminal:

```bash
docker run --name=redis-local --publish=6379:6379 --hostname=redis --restart=on-failure --detach redis:latest
```

The latest supported version of Redis is version 8.0.

- Run setup_environment to configure the mediator with all the required information to run locally.

```bash
cargo run --bin setup_environment
```

- In the on-screen example, it is important to select the Remote mediator option and provide the mediator DID generated from the Affinidi Portal.

After entering the mediator DID, the set up will resolve the DID to get the mediator URL to be configured in the environment settings.

- 
Skip SSL certificate and Admin account creation.

- 
Generate sample users to connect and send messages to the mediator server. The setup will generate 4 users and save them in the environment.json file.

### 4. Send ping to mediator

After setting up the environment, run the ping script to connect, send, and receive messages from the Mediator.

```bash
export RUST_LOG=none,affinidi_messaging_helpers=debug,affinidi_messaging_sdk=debug
cargo run --example mediator_ping
```

The above example will execute a code that authenticates to the mediator and send a ping message to the mediator. If successful, it sends a pong message back.

## What’s next

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

  [Explore different mediator deployment options](/products/affinidi-elements/affinidi-messaging/didcomm-mediator/deployment-options.md)
