We are using GitHub Actions for Lint check. See .github/workflows for details. Run swiftlint at the root of the repo to check linting locally.
- aries-uniffi-wrappers: Provides wrappers for three libraries, Aries Askar, AnonCreds and Indy VDR.
- WebSockets: Provides WebSocket API used in
WsOutboundTransport
. This library requires iOS 15.0+. - CollectionConcurrencyKit: Provides concurrent map APIs used in
ProofService
andRevocationService
. - BigInt: Provides big interger types used in the
CredentialValues
struct to encode credential attributes as big integers. Note thatBigInt
is in the dependency ofBase58Swift
. - Base58Swift: Provides Base58 encoding/decoding used in
DIDParser
to handle did:key in out-of-band invitation. - Criollo: Provides HTTP server that can be used in unit tests. We use this library to implement a backchannel for AATH.
- Semaphore: AsyncSemaphore used in
WsOutboundTransport
. This can lock asynchrononous functions safely and hide compile warnings.
Aries Framework Swift refers to Aries Framework JavaScript a lot, so the structure is similar to it.
Take a look at the diagrams in the doc to understand the basics of Aries and the framework.
Agent is the main class of Aries Framework Swift. Mobile apps will use this class to create a connection, receive a credential, and so on. It helps mobile apps to become Aries agents. Agent class holds all the commands, services, repositories, and wallet instances. Agent also has a message sender and a receiver along with a dispatcher. Dispatcher dispatches messages to the corresponding MessageHandler
by its type and sends the outbound messages back when the message handlers return them.
Aries Framework Swift only provides outbound transports, not inbound transports. It provides HttpOutboundTransport
and WsOutboundTransport
for HTTP and WebSocket, respectively. Agent selects the outbound transport automatically by the endpoint of the counterparty agent. HTTP outbound transport can be used when the agent uses a mediator. WebSocket outbound transport can be used with or without a mediator. SubjectOutboundTransport
is for testing.
Repository classes provide APIs to store and retrieve records. The operation is done using Aries Askar which uses sqlite as a storage. Records can have custom tags and can be searched by the tags.
Aries Framework Swift uses Codable
protocol for JSON encoding and decoding. AgentMessage
types, BaseRecord
types, and model types used in these types should conform to Codable
protocol. AgentMessage
types are classes which inherit Codable
class AgentMessage
, so they should implement encode(to: Encoder)
and init(from: Decoder)
methods. BaseRecord
types and other model types are structures, so they don't need to implement these methods.
Aries agents make connections to exchange encrypted messages with each other. The connection here does not refer to the actual internet connection, but an information about the agents involved in the communication. ConnectionRecord
is created through Connection Protocol and contains data such as did, keys, endpoints, label, etc.
Aries agents find the existing connection by the keys in the message, so each connection must be created with a unique key. Agents know where to send messages by the endpoint stored in the connection records. Mobile agents using Aries Framework Swift do not have reachable endpoints, then how the counterpart agents can send messages to us? There are 2 solutions for this.
- Using mediator. Agents use mediator's endpoints as their endpoints when creating a connection, then the messages for the agents will be sent to the mediator and agents can fetch the messages from the mediator later.
- Using WebSocket and keep the WebSocket connection open. Agents using Aries Framework Javascript use the WebSocket session to send messages if the session is open, and they do not close the session when
return-route
is specified. This solution has limitations because the communication is possible only when the WebSocket session is open, and it's not guaranteed that other Aries Frameworks would not close the session. But, this could be a convenient solution depending on the situation.
AgentConfig.mediatorConnectionsInvite
is a connection invitation url from a mediator. An agent connects to the mediator when it is initialized. After the connection is made, it starts mediation protocol with the mediator. The mediation protocol is performed only once if successful, and the result is saved as an MediationRecord
. Agent.isInitialized()
becomes true
when this process is done. Agents pick up messages from the mediator periodically.
Aries Framework Swift supports only one mediator. If the AgentConfig.mediatorConnectionsInvite
is changed, agent will remove the existing MediationRecord
and do the mediation protocol again.
Agents can specify return-route
for messages using the transport decorator. Aries Framework Swift is specifing return-route
as all
for all outbound messages in the MessageSender
class.
There are several types of unit tests:
- BasicTests: This is the default test plan. We can run it without any setup and it will finish in a second.
- AllTests: This is the test plan for all the tests including credential tests, proof tests, and out-of-band tests. We need a local indy pool to run this test plan.
- AgentTest: This test requires other agents to run. We run this test manually one by one.
AllTests
plan requires a local indy pool. We need Docker Desktop or colima to run the pool.
$ git clone https://github.com/conanoc/aries-framework-javascript.git
$ cd aries-framework-javascript
$ docker build -f network/indy-pool-arm.dockerfile -t indy_pool .
$ docker run -itd -p 9701-9708:9701-9708 indy_pool
Select AriesFrameworkTests
scheme in XCode, select AllTests
test plan in Test navigator and run the tests. You also can run it from the command line.
$ swift test --skip AgentTest | xcpretty
AgentTest
requires a mediator and another agent to offer credentials. We use Aries Framework Javascript for this purpose.
Clone the Aries Framework Javascript repository and checkout the demo_swift
branch.
git clone https://github.com/conanoc/aries-framework-javascript.git
git checkout demo_swift
Build and run the mediator. It requires nodejs, yarn and npx.
$ cd aries-framework-javascript
$ yarn install
$ cd samples
$ npx ts-node mediator.ts
testDemoFaber()
tests the credential exchange flow.
Run the faber agent in demo directory.
$ cd aries-framework-javascript/demo
$ yarn install
$ yarn faber
Then, get the invitation urls from the mediator and faber agent.
Run testDemoFaber()
with these urls and operate the faber agent to issue a credential.
You can also use the Sample app to interact with the faber agent.
You can see debug messages of faber agent by adding the following option to the agent config in BaseAgent.ts
:
logger: new ConsoleLogger(LogLevel.debug),