### Dart SDK Installation and Usage Example Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_mediator/README.md Demonstrates how to install the Affinidi Meeting Place Mediator SDK for Dart using `dart pub add` and provides a comprehensive usage example. The example covers initializing the SDK, authenticating with a mediator, creating and retrieving Out-Of-Band invitations, sending plaintext DIDComm messages, and fetching pending messages. ```bash dart pub add meeting_place_mediator ``` ```yaml dependencies: meeting_place_mediator: ^ ``` ```bash dart pub get ``` ```dart import 'package:meeting_place_mediator/meeting_place_mediator.dart'; import 'package:ssi/ssi.dart'; import 'package:didcomm/didcomm.dart'; void main() async { // Provide concrete implementations final DidResolver didResolver = /* your DidResolver */; final DidManager ownerDidManager = /* owner DidManager */; final DidManager clientDidManager = /* client DidManager */; final DidDocument recipientDidDocument = /* recipient DID Document */; // Initialize SDK final sdk = MeetingPlaceMediatorSDK( mediatorDid: 'did:example:mediator', didResolver: didResolver, ); // Authenticate (returns a MediatorSessionClient) final session = await sdk.authenticateWithDid(ownerDidManager); print('Authenticated to mediator'); // Create an Out-Of-Band invitation (URI you can share) final Uri oobUri = await sdk.createOob(clientDidManager, null); print('OOB URI: $oobUri'); // Retrieve OOB details from URI final oob = await sdk.getOob(oobUri, didManager: clientDidManager); print('OOB invitation received: $oob'); // Send a plaintext DIDComm message final PlainTextMessage message = PlainTextMessage( /* fill message fields per your didcomm implementation, e.g. body/text */ ); await sdk.sendMessage( message, senderDidManager: ownerDidManager, recipientDidDocument: recipientDidDocument, ); print('Message sent'); // Fetch pending messages from mediator final messages = await sdk.fetchMessages( didManager: ownerDidManager, deleteOnRetrieve: true, ); for (final m in messages) { print('Fetched message hash=${m.messageHash}, message=${m.message}'); } } ``` -------------------------------- ### Initialize and Publish Offer with Affinidi MeetingPlace SDK (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/README.md This code snippet demonstrates the initialization of the MeetingPlaceCoreSDK in Dart, including setting up storage and wallet configurations. It then proceeds to register for push notifications and publish an example offer with specified details and validity. ```dart import 'dart:async'; import 'dart:convert'; import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:ssi/ssi.dart'; import 'package:uuid/uuid.dart'; void main() async { final storage = InMemoryStorage(); final aliceSDK = MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:samplemediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:samplecontrolplane.affinidi.io', ); await aliceSDK.registerForPushNotifications(const Uuid().v4()); final publishOfferResult = await aliceSDK.publishOffer( offerName: 'Example offer', offerDescription: 'Example offer to test.', contactCard: ContactCard( did: 'did:test:alice', type: 'human', contactInfo: { 'n': {'given': 'Alice'}, }, ), publishAsGroup: false, validUntil: DateTime.now().toUtc().add(const Duration(minutes: 5)), ); } ``` -------------------------------- ### Install Meeting Place Core SDK (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/README.md This snippet shows how to add the `meeting_place_core` package to your Dart project using the `dart pub add` command or by manually updating the `pubspec.yaml` file. ```bash dart pub add meeting_place_core ``` ```yaml dependencies: meeting_place_core: ^ ``` -------------------------------- ### Initialize Individual Chat (Alice) - Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_core/example/README.md Publishes a connection offer (invitation) and initializes an individual chat. This example demonstrates the sender's side of initiating a DIDComm v2.1 connection. ```dart dart run offer/alice.dart ``` -------------------------------- ### Initialize Individual Chat (Bob) - Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_core/example/README.md Finds and accepts a connection offer, then initializes an individual chat. This example demonstrates the receiver's side of accepting a DIDComm v2.1 connection. ```dart dart run offer/bob.dart ``` -------------------------------- ### Install Core SDK - Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Installs the core SDK package for the Affinidi Meeting Place SDK using Dart's package manager. ```bash dart pub add meeting_place_core ``` -------------------------------- ### Outreach Communication Example - Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_core/example/README.md Illustrates how to use the outreach functionality of the Affinidi Meeting Place Core SDK. This typically involves initiating communication or discovering services in a decentralized manner. ```dart dart run outreach/bob.dart ``` -------------------------------- ### Initialize Group Chat - Bob (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/example/README.md Explains how Bob finds and accepts a connection offer, and initializes the group chat after the group owner approves the connection request, using the Affinidi Meeting Place Chat SDK. Bob then sends a message within the group chat. ```dart dart run group_chat/bob.dart ``` -------------------------------- ### Initialize Individual Chat - Alice (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/example/README.md Demonstrates how Alice publishes a connection offer (invitation) and initializes an individual chat using the Affinidi Meeting Place Chat SDK. This involves setting up communication channels based on Decentralised Identifiers (DIDs). ```dart dart run chat/alice.dart ``` -------------------------------- ### Initialize Individual Chat - Bob (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/example/README.md Illustrates how Bob finds and accepts a connection offer, then initializes an individual chat with Alice using the Affinidi Meeting Place Chat SDK. This process involves DID resolution and DIDComm message exchange. ```dart dart run chat/bob.dart ``` -------------------------------- ### Add Meeting Place Drift Repository SDK to pubspec.yaml Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_drift_repository/README.md Manually adds the Affinidi Meeting Place Drift Repository SDK to your project's pubspec.yaml file. After updating the file, run 'dart pub get' to install the package. ```yaml dependencies: meeting_place_drift_repository: ^ ``` -------------------------------- ### Out-of-Band Communication Example - Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_core/example/README.md Demonstrates initiating and responding to communication using out-of-band (OOB) mechanisms within the Affinidi Meeting Place Core SDK. This is useful for establishing connections without prior explicit invitations. ```dart dart run oob/alice.dart dart run oob/bob.dart ``` -------------------------------- ### Install Meeting Place Drift Repository SDK Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_drift_repository/README.md Installs the Affinidi Meeting Place Drift Repository SDK using Dart's package manager. This command adds the package as a dependency to your project. ```bash dart pub add meeting_place_drift_repository ``` -------------------------------- ### Initialize Group Chat - Alice (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/example/README.md Shows how Alice, as the group owner, publishes a connection offer, approves connection requests, and initializes a group chat using the Affinidi Meeting Place Chat SDK. This sets up a multi-party communication channel. ```dart dart run group_chat/alice.dart ``` -------------------------------- ### Install Meeting Place Control Plane SDK for Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_control_plane/README.md Instructions on how to install the Affinidi Meeting Place Control Plane SDK for Dart using the Dart package manager. This involves adding the package to your project's dependencies. ```bash dart pub add meeting_place_control_plane ``` ```yaml dependencies: meeting_place_control_plane: ^ ``` ```bash dart pub get ``` -------------------------------- ### Group Chat Messaging - Charlie (Dart) Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/example/README.md Details how Charlie finds and accepts a connection offer, initializes the group chat after approval, receives messages on the chat stream, and sends messages back using the Affinidi Meeting Place Chat SDK. This demonstrates bidirectional group communication. ```dart dart run group_chat/charlie.dart ``` -------------------------------- ### Interact Directly with Mediator using MeetingPlaceMediatorSDK in Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Provides low-level SDK functions for direct mediator interactions, including authentication, Access Control List (ACL) management, and message routing. This example demonstrates authenticating with a mediator, creating an OOB invitation URI, sending messages through the mediator, and fetching pending messages. It requires a DID resolver and a DID manager implementation. ```dart import 'package:meeting_place_mediator/meeting_place_mediator.dart'; import 'package:ssi/ssi.dart'; Future useMediatorSDK() async { final didResolver = /* your DidResolver implementation */; final mediatorSDK = MeetingPlaceMediatorSDK( mediatorDid: 'did:web:mediator.affinidi.io:.well-known', didResolver: didResolver, options: MeetingPlaceMediatorSDKOptions( maxRetries: 3, maxRetriesDelay: Duration(seconds: 2), ), ); // Authenticate with the mediator final ownerDidManager = /* your DidManager */; final session = await mediatorSDK.authenticateWithDid(ownerDidManager); print('Authenticated to mediator'); // Create OOB invitation URI final oobUri = await mediatorSDK.createOob(ownerDidManager, null); print('OOB URI: $oobUri'); // Send a message through mediator final message = PlainTextMessage( id: 'msg-123', type: Uri.parse('https://example.com/message'), from: 'did:test:sender', to: ['did:test:recipient'], body: {'content': 'Hello'}, ); await mediatorSDK.sendMessage( message, senderDidManager: ownerDidManager, recipientDidDocument: recipientDidDocument, ); // Fetch pending messages final messages = await mediatorSDK.fetchMessages( didManager: ownerDidManager, deleteOnRetrieve: true, ); for (final m in messages) { print('Message: ${m.message}'); } } ``` -------------------------------- ### Start Chat Session and Send Text Messages in Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Initiates a chat session using the MeetingPlaceChatSDK and demonstrates sending text messages, including those with attachments. It also covers listening for incoming messages, sending activity indicators like typing and presence, reacting to messages, and ending the chat session. This function requires an initialized MeetingPlaceChatSDK instance. ```dart import 'package:meeting_place_chat/meeting_place_chat.dart'; Future startChatAndSendMessages(MeetingPlaceChatSDK chatSDK) async { // Start the chat session final chat = await chatSDK.startChatSession(); print('Chat started with ID: ${chat.id}'); // Get existing messages final existingMessages = await chatSDK.messages; print('Loaded ${existingMessages.length} existing messages'); // Listen for new messages final stream = await chatSDK.chatStreamSubscription; stream?.listen((data) { if (data.plainTextMessage != null) { print('New DIDComm message: ${data.plainTextMessage!.body}'); } if (data.chatItem != null) { print('New chat item: ${data.chatItem!.messageId}'); } }); // Send a text message final sentMessage = await chatSDK.sendTextMessage( 'Hello! How are you doing today?', ); print('Message sent: ${sentMessage.messageId}'); // Send message with attachments final messageWithAttachment = await chatSDK.sendTextMessage( 'Check out this document', attachments: [ Attachment( id: 'attachment-1', mimeType: 'application/pdf', filename: 'report.pdf', data: AttachmentData(base64: ''), ), ], ); // Send typing indicator await chatSDK.sendChatActivity(); // Send presence (online status) await chatSDK.sendChatPresence(); // React to a message await chatSDK.reactOnMessage(sentMessage, reaction: '👍'); // End session when done chatSDK.endChatSession(); } ``` -------------------------------- ### Initialize and Use MeetingPlaceCoreSDK in Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_core/README.md Demonstrates how to initialize the MeetingPlaceCoreSDK with necessary configurations like wallet and repository settings. It also shows how to register for push notifications and publish an offer with specified details. This requires the 'meeting_place_core', 'ssi', and 'uuid' packages. ```dart import 'dart:async'; import 'dart:convert'; import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:ssi/ssi.dart'; import 'package:uuid/uuid.dart'; void main() async { final storage = InMemoryStorage(); final aliceSDK = MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:samplemediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:samplecontrolplane.affinidi.io', ); await aliceSDK.registerForPushNotifications(const Uuid().v4()); final publishOfferResult = await aliceSDK.publishOffer( offerName: 'Example offer', offerDescription: 'Example offer to test.', contactCard: ContactCard( did: 'did:test:alice', type: 'human', contactInfo: { 'n': {'given': 'Alice'}, }, ), publishAsGroup: false, validUntil: DateTime.now().toUtc().add(const Duration(minutes: 5)), ); } ``` -------------------------------- ### Initialize and Use Meetingplace SDK in Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_chat/README.md This Dart code snippet demonstrates the initialization of the MeetingplaceCoreSDK, publishing a connection offer, and approving a connection request. It utilizes various components of the SDK for managing wallets, repositories, and chat functionalities. Dependencies include dart:async, dart:convert, dart:io, chat_sdk.dart, meeting_place_core, ssi, and uuid. ```dart import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'lib/chat_sdk.dart'; import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:ssi/ssi.dart'; import 'package:uuid/uuid.dart'; void main() async { final storage = InMemoryStorage(); final aliceSDK = MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:samplemediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:samplecontrolplane.affinidi.io', ); await aliceSDK.registerForPushNotifications(const Uuid().v4()); final publishOfferResult = await aliceSDK.publishOffer( offerName: 'Example offer', offerDescription: 'Example offer to test.', contactCard: ContactCard( did: 'did:test:alice', type: 'human', contactInfo: { 'n': {'given': 'Alice'}, }, ), publishAsGroup: false, validUntil: DateTime.now().toUtc().add(const Duration(minutes: 5)), ); final waitForInvitationAccept = Completer(); final waitForChannelActivity = Completer(); aliceSDK.discoveryEventsStream.listen((event) { if (event.type == DiscoveryEventType.InvitationAccept) { waitForInvitationAccept.complete(event); } }); final receivedEvent = await waitForInvitationAccept.future; final channel = await aliceSDK.approveConnectionRequest( connectionOffer: publishOfferResult.connectionOffer, channel: receivedEvent.channel, ); final aliceChatSDK = await ChatSDK.initialiseFromChannel( channel, coreSDK: aliceSDK, chatRepository: ChatRepositoryImpl(storage: InMemoryStorage()), ); } ``` -------------------------------- ### Initialize and Use Drift Repositories in Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt This snippet shows how to initialize the Drift database and create repositories for channels, connection offers, groups, chat history, and keys. It then demonstrates basic operations like creating and finding a channel, and creating and listing chat messages. Dependencies include the 'meeting_place_drift_repository' and 'drift' packages. ```dart import 'package:meeting_place_drift_repository/meeting_place_drift_repository.dart'; import 'package:drift/drift.dart'; // Initialize with Drift database Future setupDriftRepositories() async { // Create database instance final database = MeetingPlaceDatabase(/* your database executor */); // Create repositories final channelRepository = DriftChannelRepository(database); final connectionOfferRepository = DriftConnectionOfferRepository(database); final groupRepository = DriftGroupRepository(database); final chatRepository = DriftChatRepository(database); final keyRepository = DriftKeyRepository(database); // Use with Core SDK final repositoryConfig = RepositoryConfig( connectionOfferRepository: connectionOfferRepository, groupRepository: groupRepository, channelRepository: channelRepository, keyRepository: keyRepository, ); // Channel operations final channel = Channel( offerLink: 'offer-123', publishOfferDid: 'did:test:publisher', mediatorDid: 'did:web:mediator', status: ChannelStatus.inaugurated, type: ChannelType.individual, contactCard: ContactCard(did: 'did:test:me', type: 'individual', contactInfo: {}), ); await channelRepository.createChannel(channel); final foundChannel = await channelRepository.findChannelByDid('did:test:me'); print('Found channel: ${foundChannel?.id}'); // Chat history operations final chatMessage = Message( chatId: 'chat-123', messageId: 'msg-456', senderDid: 'did:test:sender', isFromMe: true, dateCreated: DateTime.now().toUtc(), status: ChatItemStatus.sent, text: 'Hello world!', ); await chatRepository.createMessage(chatMessage); final messages = await chatRepository.listMessages('chat-123'); print('Chat has ${messages.length} messages'); } ``` -------------------------------- ### Initialize and Use ControlPlaneSDK in Dart Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_control_plane/README.md Demonstrates how to initialize the ControlPlaneSDK with DID manager, DID resolver, and control plane/mediator DIDs. It also shows how to set device information and execute a control plane command, including error handling for SDK-specific exceptions. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:ssi/ssi.dart'; import 'lib/discovery_sdk.dart'; void main() async { // Create or obtain implementations for DidManager and DidResolver final didManager = /* DidManager implementation */; final didResolver = /* DidResolver implementation */; // Initialize SDK final sdk = ControlPlaneSDK( didManager: didManager, controlPlaneDid: 'did:example:control-plane', // your control plane DID mediatorDid: 'did:example:mediator', // your mediator DID didResolver: didResolver, ); // Set device info (must be set before commands that require a device) sdk.device = Device(deviceToken: 'FCM_DEVICE_TOKEN', platformType: 'android'); try { // Example: execute a control-plane command. // Replace `SomeControlPlaneCommand` with a real command from the SDK, // e.g. RegisterOfferCommand, QueryOfferCommand, AcceptOfferCommand, CreateOobCommand, etc. final result = await sdk.execute(SomeControlPlaneCommand(/* params */)); // Handle result print('Command result: $result'); } on ControlPlaneSDKException catch (e) { // SDK-specific errors are wrapped in ControlPlaneSDKException print('Control plane SDK error: ${e.message} (code: ${e.code})'); } catch (e) { print('Unexpected error: $e'); } } ``` -------------------------------- ### Initialize MeetingPlaceCoreSDK - Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Creates and initializes the Core SDK instance with wallet, repository configuration, and mediator/control plane DIDs. This is the primary entry point for all Meeting Place functionality. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:ssi/ssi.dart'; Future initializeSDK() async { final storage = InMemoryStorage(); final sdk = await MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:mediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:controlplane.affinidi.io', options: MeetingPlaceCoreSDKOptions( maxRetries: 3, maxRetriesDelay: Duration(seconds: 2), ), ); return sdk; } ``` -------------------------------- ### Find and Accept Offer (Dart) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Discovers a published offer using its mnemonic and accepts it with the user's contact card. It then prints the acceptance details. Requires the SDK and the offer's mnemonic phrase as input. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; Future findAndAcceptOffer(MeetingPlaceCoreSDK sdk, String mnemonic) async { // Find the offer using the mnemonic phrase final findResult = await sdk.findOffer(mnemonic: mnemonic); if (findResult.connectionOffer == null) { print('Offer not found or expired. Error: ${findResult.errorCode}'); return; } print('Found offer: ${findResult.connectionOffer!.name}'); print('Description: ${findResult.connectionOffer!.description}'); print('Publisher: ${findResult.connectionOffer!.contactCard?.contactInfo}'); // Accept the offer with your contact card final acceptResult = await sdk.acceptOffer( connectionOffer: findResult.connectionOffer!, contactCard: ContactCard( did: 'did:test:bob', type: 'individual', contactInfo: { 'n': {'given': 'Bob', 'family': 'Jones'}, }, ), senderInfo: 'Bob Jones', // Shown in notification to publisher ); print('Offer accepted. Accept DID: ${acceptResult.acceptOfferDid}'); print('Permanent Channel DID: ${acceptResult.permanentChannelDid}'); // Now wait for the publisher to approve the connection } ``` -------------------------------- ### Initialize Chat SDK from Channel (Dart) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Initializes the Chat SDK from an established channel. This function automatically determines and creates the appropriate SDK type (individual or group) based on the channel type. It configures options such as presence intervals and activity expiry, and includes a ContactCard for the channel. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:meeting_place_chat/meeting_place_chat.dart'; Future initializeChatFromChannel( MeetingPlaceCoreSDK coreSDK, Channel channel, ChatRepository chatRepository, ) async { final chatSDK = await MeetingPlaceChatSDK.initialiseFromChannel( channel, coreSDK: coreSDK, chatRepository: chatRepository, options: ChatSDKOptions( chatPresenceSendInterval: const Duration(seconds: 60), chatActivityExpiry: const Duration(seconds: 30), ), card: ContactCard( did: channel.permanentChannelDid!, type: 'individual', contactInfo: {'n': {'given': 'Alice'}}, ), ); return chatSDK; } ``` -------------------------------- ### Publish Connection Offer (Dart) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Publishes a connection offer, supporting individual and group invitations. It allows customization of validity, usage limits, and includes optional custom phrases. Requires an initialized MeetingPlaceCoreSDK instance. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; Future publishConnectionOffer(MeetingPlaceCoreSDK sdk) async { // Publish an individual invitation final publishResult = await sdk.publishOffer( offerName: 'Connect with Alice', offerDescription: 'Personal connection invitation for friends.', type: SDKConnectionOfferType.invitation, contactCard: ContactCard( did: 'did:test:alice', type: 'individual', contactInfo: { 'n': {'given': 'Alice', 'family': 'Smith'}, }, ), validUntil: DateTime.now().toUtc().add(const Duration(days: 7)), maximumUsage: 10, customPhrase: 'alice-connect-2024', // Optional custom mnemonic ); print('Offer published with mnemonic: ${publishResult.connectionOffer.mnemonic}'); print('Published offer DID: ${publishResult.publishedOfferDidManager}'); // For group invitations final groupResult = await sdk.publishOffer( offerName: 'Team Chat Group', offerDescription: 'Join our team discussion group.', type: SDKConnectionOfferType.groupInvitation, contactCard: ContactCard( did: 'did:test:alice', type: 'organization', contactInfo: {'org': 'Acme Corp'}, ), validUntil: DateTime.now().toUtc().add(const Duration(days: 30)), ); print('Group created with owner DID: ${groupResult.groupOwnerDidManager}'); } ``` -------------------------------- ### Dart Connection Flow: Publisher (Alice) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Alice's flow to publish a connection offer, subscribe to events, approve a connection request, and initialize a chat session. It requires the MeetingPlaceCoreSDK and MeetingPlaceChatSDK. ```dart import 'dart:async'; import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:meeting_place_chat/meeting_place_chat.dart'; import 'package:ssi/ssi.dart'; // Alice (Publisher) Flow Future alicePublisherFlow() async { final storage = InMemoryStorage(); final aliceSDK = await MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:mediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:controlplane.affinidi.io', ); // 1. Register for notifications final notification = await aliceSDK.registerForDIDCommNotifications(); final notificationDid = (await notification.recipientDid.getDidDocument()).id; // 2. Publish offer final publishResult = await aliceSDK.publishOffer( offerName: 'Connect with Alice', offerDescription: 'Private chat invitation', type: SDKConnectionOfferType.invitation, contactCard: ContactCard(did: 'did:test:alice', type: 'individual', contactInfo: {}), validUntil: DateTime.now().toUtc().add(const Duration(days: 7)), ); print('Share this mnemonic: ${publishResult.connectionOffer.mnemonic}'); // 3. Subscribe and listen for events final subscription = await aliceSDK.subscribeToMediator(notificationDid); final waitForAccept = Completer(); aliceSDK.controlPlaneEventsStream.listen((event) { if (event.type == ControlPlaneEventType.InvitationAccept) { waitForAccept.complete(event); } }); subscription.stream.listen((data) async { await aliceSDK.processControlPlaneEvents(); }); // 4. Wait for acceptance and approve final acceptEvent = await waitForAccept.future; final channel = await aliceSDK.approveConnectionRequest(channel: acceptEvent.channel); // 5. Initialize chat final chatSDK = await MeetingPlaceChatSDK.initialiseFromChannel( channel, coreSDK: aliceSDK, chatRepository: ChatRepositoryImpl(storage: InMemoryStorage()), options: ChatSDKOptions(chatPresenceSendInterval: Duration(seconds: 60)), ); await chatSDK.startChatSession(); print('Chat ready with ${channel.otherPartyContactCard?.contactInfo}'); } ``` -------------------------------- ### Create and Accept Out-of-Band (OOB) Invitations in Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Facilitates the creation and acceptance of Out-of-Band invitations using the MeetingPlaceCoreSDK, enabling secure connection offers via QR codes or URLs without a discovery mechanism. The 'createOobInvitation' function generates an invitation and provides a stream to listen for acceptance events. The 'acceptOobInvitation' function takes an OOB URL and contact details to establish a connection. ```dart import 'package:meeting_place_core/meeting_place_core.dart'; // Publisher creates OOB invitation Future createOobInvitation(MeetingPlaceCoreSDK sdk) async { final result = await sdk.createOobFlow( contactCard: ContactCard( did: 'did:test:alice', type: 'individual', contactInfo: {'n': {'given': 'Alice'}}, ), externalRef: 'invite-123', // Your app reference ); print('Share this URL: ${result.oobUrl}'); // Listen for acceptance result.streamSubscription.stream.listen((data) { print('Event type: ${data.eventType}'); if (data.channel != null) { print('Channel established: ${data.channel!.id}'); print('Connected with: ${data.channel!.otherPartyContactCard?.contactInfo}'); } }); } // Recipient accepts OOB invitation Future acceptOobInvitation( MeetingPlaceCoreSDK sdk, String oobUrl, ) async { final result = await sdk.acceptOobFlow( Uri.parse(oobUrl), contactCard: ContactCard( did: 'did:test:bob', type: 'individual', contactInfo: {'n': {'given': 'Bob'}}, ), ); print('Waiting for connection approval...'); print('Channel: ${result.channel.id}'); // Listen for approval result.streamSubscription.stream.listen((data) { if (data.eventType == EventType.connectionAccepted) { print('Connection accepted! Channel ready: ${data.channel!.status}'); } }); } ``` -------------------------------- ### Publish Connection Offer Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Publishes a connection offer (invitation) that others can discover and accept. Supports individual, group, and outreach invitations with customizable validity and usage limits. ```APIDOC ## POST /publishOffer ### Description Publishes a connection offer (invitation) that others can discover and accept. Supports individual invitations, group invitations, and outreach invitations with customizable validity and usage limits. ### Method POST ### Endpoint /publishOffer ### Parameters #### Query Parameters - **sdk** (MeetingPlaceCoreSDK) - Required - The SDK instance to use. #### Request Body - **offerName** (string) - Required - The name of the offer. - **offerDescription** (string) - Required - A description of the offer. - **type** (SDKConnectionOfferType) - Required - The type of offer (e.g., invitation, groupInvitation). - **contactCard** (ContactCard) - Required - The contact card associated with the offer. - **validUntil** (DateTime) - Optional - The expiration date of the offer. - **maximumUsage** (int) - Optional - The maximum number of times the offer can be used. - **customPhrase** (string) - Optional - A custom mnemonic phrase for the offer. ### Request Example ```dart await sdk.publishOffer( offerName: 'Connect with Alice', offerDescription: 'Personal connection invitation for friends.', type: SDKConnectionOfferType.invitation, contactCard: ContactCard( did: 'did:test:alice', type: 'individual', contactInfo: { 'n': {'given': 'Alice', 'family': 'Smith'}, }, ), validUntil: DateTime.now().toUtc().add(const Duration(days: 7)), maximumUsage: 10, customPhrase: 'alice-connect-2024', ); ``` ### Response #### Success Response (200) - **connectionOffer** (ConnectionOffer) - The published connection offer. - **publishedOfferDidManager** (string) - The DID manager of the published offer. #### Response Example ```json { "connectionOffer": { "mnemonic": "some-mnemonic", "name": "Connect with Alice", "description": "Personal connection invitation for friends.", "type": "invitation", "contactCard": { "did": "did:test:alice", "type": "individual", "contactInfo": { "n": {"given": "Alice", "family": "Smith"} } }, "validUntil": "2024-08-01T10:00:00Z", "maximumUsage": 10 }, "publishedOfferDidManager": "did:key:z6Mk..." } ``` ``` -------------------------------- ### Find and Accept Offer Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Discovers a published offer using its mnemonic phrase and accepts the connection. The accepting party provides their contact card and waits for approval from the offer publisher. ```APIDOC ## POST /findOffer and POST /acceptOffer ### Description Discovers a published offer using its mnemonic phrase and accepts the connection. The accepting party provides their contact card and waits for approval from the offer publisher. ### Method POST ### Endpoint /findOffer, /acceptOffer ### Parameters #### Query Parameters - **sdk** (MeetingPlaceCoreSDK) - Required - The SDK instance to use. - **mnemonic** (string) - Required - The mnemonic phrase of the offer to find. #### Request Body (acceptOffer) - **connectionOffer** (ConnectionOffer) - Required - The connection offer object obtained from `findOffer`. - **contactCard** (ContactCard) - Required - The contact card of the party accepting the offer. - **senderInfo** (string) - Required - Information about the sender, shown in notifications. ### Request Example (findOffer) ```dart final findResult = await sdk.findOffer(mnemonic: 'alice-connect-2024'); ``` ### Request Example (acceptOffer) ```dart final acceptResult = await sdk.acceptOffer( connectionOffer: findResult.connectionOffer!, contactCard: ContactCard( did: 'did:test:bob', type: 'individual', contactInfo: { 'n': {'given': 'Bob', 'family': 'Jones'}, }, ), senderInfo: 'Bob Jones', ); ``` ### Response #### Success Response (200) - findOffer - **connectionOffer** (ConnectionOffer | null) - The found connection offer, or null if not found or expired. - **errorCode** (string | null) - An error code if the offer was not found. #### Success Response (200) - acceptOffer - **acceptOfferDid** (string) - The DID of the accepted offer. - **permanentChannelDid** (string) - The DID of the permanent channel created. #### Response Example (findOffer) ```json { "connectionOffer": { "mnemonic": "alice-connect-2024", "name": "Connect with Alice", "description": "Personal connection invitation for friends.", "type": "invitation", "contactCard": { "did": "did:test:alice", "type": "individual", "contactInfo": { "n": {"given": "Alice", "family": "Smith"} } }, "validUntil": "2024-08-01T10:00:00Z", "maximumUsage": 10 }, "errorCode": null } ``` #### Response Example (acceptOffer) ```json { "acceptOfferDid": "did:key:z6MkB...", "permanentChannelDid": "did:key:z6MkJ..." } ``` ``` -------------------------------- ### Dart Connection Flow: Acceptor (Bob) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Bob's flow to accept a connection offer using a mnemonic, wait for finalization, and initialize a chat session. It requires the MeetingPlaceCoreSDK and MeetingPlaceChatSDK. ```dart import 'dart:async'; import 'package:meeting_place_core/meeting_place_core.dart'; import 'package:meeting_place_chat/meeting_place_chat.dart'; import 'package:ssi/ssi.dart'; // Bob (Acceptor) Flow Future bobAcceptorFlow(String mnemonic) async { final storage = InMemoryStorage(); final bobSDK = await MeetingPlaceCoreSDK.create( wallet: PersistentWallet(InMemoryKeyStore()), repositoryConfig: RepositoryConfig( connectionOfferRepository: ConnectionOfferRepositoryImpl(storage: storage), groupRepository: GroupRepositoryImpl(storage: storage), channelRepository: ChannelRepositoryImpl(storage: storage), keyRepository: KeyRepositoryImpl(storage: storage), ), mediatorDid: 'did:web:mediator.affinidi.io:.well-known', controlPlaneDid: 'did:web:controlplane.affinidi.io', ); // 1. Register and find offer final notification = await bobSDK.registerForDIDCommNotifications(); final notificationDid = (await notification.recipientDid.getDidDocument()).id; final findResult = await bobSDK.findOffer(mnemonic: mnemonic); print('Found offer: ${findResult.connectionOffer!.name}'); // 2. Accept offer final acceptResult = await bobSDK.acceptOffer( connectionOffer: findResult.connectionOffer!, contactCard: ContactCard(did: 'did:test:bob', type: 'individual', contactInfo: {}), senderInfo: 'Bob', ); // 3. Wait for approval final waitForFinalised = Completer(); bobSDK.controlPlaneEventsStream.listen((event) { if (event.type == ControlPlaneEventType.OfferFinalised) { waitForFinalised.complete(event); } }); final subscription = await bobSDK.subscribeToMediator(notificationDid); subscription.stream.listen((data) async { await bobSDK.processControlPlaneEvents(); }); final finalisedEvent = await waitForFinalised.future; // 4. Initialize chat and send message final chatSDK = await MeetingPlaceChatSDK.initialiseFromChannel( finalisedEvent.channel, coreSDK: bobSDK, chatRepository: ChatRepositoryImpl(storage: InMemoryStorage()), options: ChatSDKOptions(chatPresenceSendInterval: Duration(seconds: 60)), ); await chatSDK.startChatSession(); await chatSDK.sendTextMessage('Hello Alice!'); } ``` -------------------------------- ### Add Core SDK to pubspec.yaml - Dart Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Adds the core SDK and related packages to the pubspec.yaml file for dependency management in a Dart project. ```yaml dependencies: meeting_place_core: ^0.0.1-dev.27 meeting_place_chat: ^0.0.1-dev.29 meeting_place_drift_repository: ^0.0.1-dev.30 ``` -------------------------------- ### MeetingPlaceMediatorSDK - Direct Mediator Interactions Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Provides low-level SDK functionalities for direct interaction with a mediator, including authentication, OOB invitation creation, message sending, and fetching pending messages. ```APIDOC ## POST /mediator/authenticate ### Description Authenticates the client with the mediator using the provided DID manager. ### Method POST ### Endpoint /mediator/authenticate ### Parameters #### Request Body - **didManager** (object) - Required - An object implementing the DidManager interface for authentication. ### Response #### Success Response (200) - **session** (string) - An identifier for the authenticated session. #### Response Example ```json { "session": "session-token-123" } ``` ## POST /mediator/oob ### Description Creates an Out-of-Band (OOB) invitation URI for connecting through the mediator. ### Method POST ### Endpoint /mediator/oob ### Parameters #### Request Body - **ownerDidManager** (object) - Required - The DID manager for the owner initiating the OOB flow. - **recipientDid** (string) - Optional - The DID of the intended recipient. ### Response #### Success Response (200) - **oobUri** (string) - The generated OOB invitation URI. #### Response Example ```json { "oobUri": "https://mediator.example.com/oob?invitation=abc" } ``` ## POST /mediator/messages/send ### Method POST ### Endpoint /mediator/messages/send ### Description Sends a message through the mediator to one or more recipients. ### Parameters #### Request Body - **message** (object) - Required - The message payload to send. - **id** (string) - Required - Unique message identifier. - **type** (string) - Required - Message type URI. - **from** (string) - Required - Sender's DID. - **to** (array) - Required - Array of recipient DIDs. - **body** (object) - Required - Message content. - **senderDidManager** (object) - Required - The DID manager for the sender. - **recipientDidDocument** (object) - Required - The DID document of the recipient(s) for routing information. ### Response #### Success Response (200) - **status** (string) - Confirmation of message sending (e.g., 'sent'). #### Response Example ```json { "status": "sent" } ``` ## GET /mediator/messages/pending ### Description Fetches pending messages for the authenticated user from the mediator. ### Method GET ### Endpoint /mediator/messages/pending ### Parameters #### Query Parameters - **didManager** (object) - Required - The DID manager for the authenticated user. - **deleteOnRetrieve** (boolean) - Optional - If true, messages are deleted from the mediator after retrieval. ### Response #### Success Response (200) - **messages** (array) - An array of pending messages. - **message** (object) - The message content. #### Response Example ```json { "messages": [ { "message": { "id": "msg-456", "type": "https://example.com/message", "from": "did:test:sender", "to": ["did:test:recipient"], "body": {"content": "Hello again"} } } ] } ``` ``` -------------------------------- ### Apply SQLCipher Workaround for Old Android Versions Source: https://github.com/affinidi/affinidi-meetingplace-sdk-dart/blob/main/packages/meeting_place_drift_repository/README.md Applies a workaround to open SQLCipher on older Android versions, which can resolve issues with libsqlcipher.so availability. This method should be called before using APIs from package:sqlite3 or package:moor/ffi.dart. ```dart Future setupSqlCipher() async { await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions(); open.overrideFor(OperatingSystem.android, openCipherOnAndroid); } ``` -------------------------------- ### Listen for Events and Approve Connections (Dart) Source: https://context7.com/affinidi/affinidi-meetingplace-sdk-dart/llms.txt Listens to control plane events from the SDK, specifically for invitation acceptances and channel activities. It then approves an incoming connection request, returning the inaugurated channel. Requires an initialized SDK. ```dart import 'dart:async'; import 'package:meeting_place_core/meeting_place_core.dart'; Future listenAndApproveConnections(MeetingPlaceCoreSDK sdk) async { final waitForAccept = Completer(); final waitForActivity = Completer(); // Listen for control plane events sdk.controlPlaneEventsStream.listen((event) { switch (event.type) { case ControlPlaneEventType.InvitationAccept: print('Received invitation acceptance from: ${event.channel.otherPartyContactCard?.contactInfo}'); waitForAccept.complete(event); break; case ControlPlaneEventType.ChannelActivity: print('Channel inaugurated with: ${event.channel.otherPartyPermanentChannelDid}'); if (!waitForActivity.isCompleted) { waitForActivity.complete(event); } break; case ControlPlaneEventType.OfferFinalised: print('Connection offer finalised'); break; case ControlPlaneEventType.InvitationGroupAccept: print('Group invitation accepted'); break; } }); // Wait for someone to accept the offer final acceptEvent = await waitForAccept.future; // Approve the connection request final channel = await sdk.approveConnectionRequest( channel: acceptEvent.channel, ); print('Connection approved. Channel ID: ${channel.id}'); print('Channel status: ${channel.status}'); // ChannelStatus.inaugurated return channel; } ```