Messaging

Receive, send, and manage text messages exchanged between the Edge Agent connections.

After establishing a DIDComm connection with a peer, one of many supported interactions is the ability to exchange text messages back and forth along the E2EE channel. The Edge Agent supports Aries Basic Message Protocol (RFC 0095) to accomplish this.

The MessagingModule contains the methods to receive, send and manage these messages. It is accessed via the agent's fields: agent.connections.messaging.

Subscribe to Inbound Messages

As described in the Subscribe to Events section, subscription to new incoming Basic Messages is supported via the subscribeToAgentEvents API. The subscriber will be invoked once for each new message, and will include the inbound message data, such as the content, the receivedTime and the ID of the Connection who sent it.

class MessageSubscriber : AgentEventSubscriber {
    func inboundBasicMessage(basicMessage: BasicMessage.Inbound) {
        // the following will be invoked whenever a new basic message is received.
        print("new message: \(basicMessage)")
    }
    
    func connectionExchangeStateChanged(connectionExchange: ConnectionExchange) {}
    func credentialExchangeStateChanged(credentialExchange: CredentialExchange) {}
    func proofExchangeStateChanged(proofExchange: ProofExchange) {}
    func messageProcessed(messageId: String) {}
}

let customSubscriber = MessageSubscriber()
let subscriberId = agent.subscribeToAgentEvents(subscriber: customSubscriber)

See Subscribe to Events for more subscription management details.

Send Messages

To send a basic message to a connection, the sendBasicMessage API can simply be used. On success, the outbound basic message that was sent to the peer will be returned.

let agent: SudoDIEdgeAgent
let connectionId: String // the identifier of the [Connection] to message

do {
    let sentMessage = try await agent.connections.messaging.sendBasicMessage(
        connectionId: connectionId,
        content: "hello world"
    )
} catch {
    // handle error
}

Query Messages

The SDK features one API for listing basic messages in a variety of ways: listBasicMessages. The API is designed to support common peer to peer messaging use cases.

The method takes a ListBasicMessagesOptions object as input as a way to configure pagination, sorting and filtering. It has the following fields within it:

  • filters - A ListBasicMessagesFilter object with configurations for how results should be filtered

    • filters.connectionId - if provided, the resulting list of messages will only contain messages from the given connection

    • filters.limitMessagesPerConnection - if provided, the resulting list of messages will limit the number of messages from a single connection. Useful for "conversation list views": "list recent messages, limited to 1 per connection".

  • paging - A common Paging object, configuring the limit of items to fetch, and the current cursor position (if any)

  • sorting - A ListBasicMessagesSorting object specifying how the results should be sorted (pre filtering and paging). Currently chronological sorting (ascending and descending) is supported

The value returned is a PageResult<BasicMessage>, which contains a list of items and a string cursor, nextToken, if there is more items to fetch. This nextToken can be passed into the paging item when performing the next listBasicMessages operation to fetch the next page of items from where the cursor was up to.

List All Recent Messages

let agent: SudoDIEdgeAgent
let pageSize: UInt = 10

do {
    let page1 = try await agent.connections.messaging.listBasicMessages(
        options: .init(
            paging: .init(limit: pageSize)
        )
    )
    let pageItems1 = page1.items
    
    // fetch next page if nextToken is not nil
    let page2 = try await agent.connections.messaging.listBasicMessages(
        options: .init(
            paging: .init(limit: pageSize, nextToken: page1.nextToken)
        )
    )
    let pageItems2 = page2.items
    
    // continue..
} catch {
    // handle error
}

List Oldest Messages

let agent: SudoDIEdgeAgent
let pageSize: UInt = 10

do {
    let page = try await agent.connections.messaging.listBasicMessages(
        options: .init(
            paging: .init(limit: pageSize),
            sorting: .chronological(direction: .ascending)
        )
    )
    let pageItems = page.items
} catch {
    // handle error
}

List Recent Messages with a Connection

let agent: SudoDIEdgeAgent
let connectionId: String
let pageSize: UInt = 10

do {
    let page = try await agent.connections.messaging.listBasicMessages(
        options: .init(
            filters: .init(connectionId: connectionId),
            paging: .init(limit: pageSize)
        )
    )
    let pageItems = page.items
} catch {
    // handle error
}

List Most Recent Connection Conversations

To support use cases like a "recent conversations" list view, the list API may be used like so:

let agent: SudoDIEdgeAgent
let pageSize: UInt = 10

do {
    let page = try await agent.connections.messaging.listBasicMessages(
        options: .init(
            filters: .init(limitMessagesPerConnection: 1),
            paging: .init(limit: pageSize)
        )
    )
    let pageItems = page.items
} catch {
    // handle error
}

Delete Messages

Delete All Messages with a Connection

All basic messages to/from a connection can be deleted from storage with the deleteBasicMessagesForConnection API.

let agent: SudoDIEdgeAgent
let connectionId: String

do {
    try await agent.connections.messaging.deleteBasicMessagesForConnection(
        connectionId: connectionId
    )
} catch {
// handle error
}

Delete Basic Messages by IDs

Alternatively, a known set of message IDs (BasicMessage.id) can be passed into the deleteBasicMessages API to delete them.

let agent: SudoDIEdgeAgent
let messageIds: [String]

do {
    try await agent.connections.messaging.deleteBasicMessages(
        ids: messageIds
    )
} catch {
// handle error
}

Opt Out of Message Storage

Some Edge Agent SDK consumers may wish to handle Basic Message storage themselves, for instance, to add their own indexes and data schema. Or even to just avoid message storage all together. If that is the case, the SDKs managed storage of Basic Messages can be opt out of with the AgentConfiguration's messagingConfiguration.storeBasicMessages field. By default this is true, setting the configuration field to false will disable storage of Basic Messages.

See Agent Management for details on managing the agent's configuration.

With storage disabled, Basic Messages will still be processed and will still invoke the subscription (see Subscribe to Inbound Messages), but nothing will be put into the agent's database. Meaning the above APIs (list, delete) will have limited functionality.

Last updated