Welcome to Agent Framework’s documentation!¶
AgentFramework is a .NET Core library for building Sovrin interoperable agent services. It is an abstraction on top of Indy SDK that provides a set of API’s for building Indy Agents. The framework runs on any .NET Standard target, including ASP.NET Core and Xamarin.
Installation and configuration¶
Using NuGet¶
Install-Package AgentFramework.Core -Source https://www.myget.org/F/agent-framework/api/v3/index.json
The framework will be moved to nuget.org soon. For the time being, stable and pre-release packages are available at https://www.myget.org/F/agent-framework/api/v3/index.json
.
You can add nuget.config anywhere in your project path with the myget.org repo.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="myget.org" value="https://www.myget.org/F/agent-framework/api/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
Setting up development environment¶
Agent Framework uses Indy SDK wrapper for .NET which requires platform specific native libraries of libindy to be available in the running environment. Check the [Indy SDK project page](https://github.com/hyperledger/indy-sdk) for details on installing libindy for different platforms or read the brief instructions below.
Make sure you have [.NET Core SDK](https://dotnet.microsoft.com/download) installed for your platform.
Windows¶
You can download binaries of libindy and all dependencies from the [Sovrin repo](https://repo.sovrin.org/windows/libindy/). The dependcies are under deps folder and libindy under one of streams (rc, master, stable). There are two options to link the DLLs
- Unzip all files in a directory and add that to your PATH variable (recommended for development)
- Or copy all DLL files in the publish directory (recommended for published deployments)
More details at the [Indy documentation for setting up Windows environment](https://github.com/hyperledger/indy-sdk/blob/master/doc/windows-build.md)
MacOS¶
Linux¶
Build instructions for [Ubuntu based distros](https://github.com/hyperledger/indy-sdk/blob/master/doc/ubuntu-build.md) and [RHEL based distros](https://github.com/hyperledger/indy-sdk/blob/master/doc/rhel-build.md).
Agent Workflows¶
Before you begin reading any of the topics below, please familiarize youself with the core idea behind Hyperledger Indy. We suggest that you go over the Indy SDK Getting Started Guide.
Roles and players¶
Mobile Agents with Xamarin¶
Using Indy with Xamarin¶
When working with Xamarin, we can fully leverage the offical Indy wrapper for dotnet, since the package is fully compatible with Xamarin runtime. The wrapper uses DllImport
to invoke the native Indy library which exposes all functionality as C callable functions.
In order to make the library work in Xamarin, we need to make libindy available for Android and iOS, which requires bundling static libraries of libindy and it’s dependencies built for each platform.
Instructions for Android¶
To setup Indy on Android you need to add the native libindy references and dependencies. The process is described in detail at the official Xamarin documentation Using Native Libraries with Xamarin.Android.
Below are a few additional things that are not covered by the documentation that are Indy specific.
Download static libraries¶
- Our repo (includes libgnustl_shared.so) - samples/xamarin/libs-android
- Sovrin repo - https://repo.sovrin.org/android/libindy/
For Android the entire library and its dependencies are compiled into a single shared object (libindy.so). In order for libindy.so
to be executable we must also include libgnustl_shared.so
.
Note
You can find libgnustl_shared.so
in your android-ndk
installation directory under \sources\cxx-stl\gnu-libstdc++\4.9\libs
.
Depending on the target abi(s) for the resulting app, not all of the artifacts need to be included, for ease of use below we document including all abi(s).
Setup native references¶
In Visual Studio (for Windows or Mac) create new Xamarin Android project. If you want to use Xamarin Forms, the instructions are the same. Apply the changes to your Android project in Xamarin Forms.
The required files can be added via your IDE by clicking Add-Item and setting the build action to AndroidNativeLibrary
. However when dealing with multiple ABI targets it is easier to manually add the references via the android projects .csproj. Note - if the path contains the abi i.e ..x86library.so then the build process automatically infers the target ABI.
If you are adding all the target ABI’s to you android project add the following snippet to your .csproj.
<ItemGroup>
<AndroidNativeLibrary Include="..\libs-android\armeabi\libindy.so" />
<AndroidNativeLibrary Include="..\libs-android\arm64-v8a\libindy.so" />
<AndroidNativeLibrary Include="..\libs-android\armeabi-v7a\libindy.so" />
<AndroidNativeLibrary Include="..\libs-android\x86\libindy.so" />
<AndroidNativeLibrary Include="..\libs-android\x86_64\libindy.so" />
<AndroidNativeLibrary Include="..\libs-android\armeabi\libgnustl_shared.so" />
<AndroidNativeLibrary Include="..\libs-android\arm64-v8a\libgnustl_shared.so" />
<AndroidNativeLibrary Include="..\libs-android\armeabi-v7a\libgnustl_shared.so" />
<AndroidNativeLibrary Include="..\libs-android\x86\libgnustl_shared.so" />
<AndroidNativeLibrary Include="..\libs-android\x86_64\libgnustl_shared.so" />
</ItemGroup>
Note
Paths listed above will vary project to project.
Load runtime dependencies¶
Load these dependencies at runtime. To do this add the following to your MainActivity.cs
JavaSystem.LoadLibrary("gnustl_shared");
JavaSystem.LoadLibrary("indy");
Setup Android permissions¶
In order to use most of libindy’s functionality, the following permissions must be granted to your app, you can do this by adjusting your AndroidManifest.xml, located under properties in your project.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
If you are running your android app at API level 23 and above, these permissions also must be requested at runtime, in order to do this add the following to your MainActivity.cs
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
RequestPermissions(new[] { Manifest.Permission.ReadExternalStorage }, 10);
RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 10);
RequestPermissions(new[] { Manifest.Permission.Internet }, 10);
}
Instructions for iOS¶
To setup Indy on iOS you need to add the native libindy references and dependencies. The process is described in detail at the official Xamarin documentation Native References in iOS, Mac, and Bindings Projects.
Below are a few additional things that are not covered by the documentation that are Indy specific.
Download static libraries¶
In order to enable the Indy SDK package to recognize the DllImport calls to the native static libraries, we need to include them in our solution.
These includes the following static libraries:
- libindy.a
- libssl.a
- libsodium.a
- libcrypto.a
- libzmq.a
Pre-built libraries¶
Can be found in the iOS sample project.
Build your own libs¶
The Indy team doesn’t provide static libraries for all of the dependencies for iOS. Here are some helpful instructions on building the dependencies for iOS should you decide to build your own.
The above links should help you build the 4 static libraries that libindy depends on. To build libindy for iOS, check out the offical Indy SDK repo or [download the library from the Sovrin repo](https://repo.sovrin.org/ios/libindy/).
Setup native references¶
In Visual Studio (for Windows or Mac) create new Xamarin iOS project. If you want to use Xamarin Forms, the instructions are the same. Apply the changes to your iOS project in Xamarin Forms.
Add each library as native reference, either by right clicking the project and Add Native Reference, or add them directly in the project file.
Note
Make sure libraries are set to Static
in the properties window and Is C++
is selected for libzmq.a
only.
The final project file should look like this (paths will vary per project):
<ItemGroup>
<NativeReference Include="..\libs-ios\libcrypto.a">
<Kind>Static</Kind>
</NativeReference>
<NativeReference Include="..\libs-ios\libsodium.a">
<Kind>Static</Kind>
</NativeReference>
<NativeReference Include="..\libs-ios\libssl.a">
<Kind>Static</Kind>
</NativeReference>
<NativeReference Include="..\libs-ios\libzmq.a">
<Kind>Static</Kind>
<IsCxx>True</IsCxx>
</NativeReference>
<NativeReference Include="..\libs-ios\libindy.a">
<Kind>Static</Kind>
</NativeReference>
</ItemGroup>
Update MTouch arguments¶
In your project options under iOS Build add the following to Additional mtouch arguments
-gcc_flags -dead_strip -v
If you prefer to add them directly in the project file, add the following line:
<MtouchExtraArgs>-gcc_flags -dead_strip -v</MtouchExtraArgs>
Warning
This step is mandatory, otherwise you won’t be able to build the project. It prevents linking unused symbols in the static libraries. Make sure you add these arguments for all configurations. See example project file.
Install NuGet packages¶
Install the Nuget packages for Indy SDK and/or Agent Framework and build your solution. Everything should work and run just fine.
dotnet add package AgentFramework.Core --source https://www.myget.org/F/agent-framework/api/v3/index.json
If you run into any errors or need help setting up, please open an issue in this repo.
Finally, check the Xamarin Sample we have included for a fully configured project.
Agent services with ASP.NET Core¶
Installation¶
A package with extensions and default implementations for use with ASP.NET Core is available.
Configure required services¶
Inside your Startup.cs
fine in ConfigureServices(IServiceCollection services)
use the extension methods to add all dependent services and optionally pass configuration data.
public void ConfigureServices(IServiceCollection services)
{
// other configuration
services.AddAgent();
}
Configure options manually¶
You can customize the wallet and pool configuration options using
services.AddAgent(config =>
{
config.SetPoolOptions(new PoolOptions { GenesisFilename = Path.GetFullPath("pool_genesis.txn") });
config.SetWalletOptions(new WalletOptions
{
WalletConfiguration = new WalletConfiguration { Id = "MyAgentWallet" },
WalletCredentials = new WalletCredentials { Key = "SecretWalletEncryptionKeyPhrase" }
});
});
Use options pattern¶
Alternatively, options be configured using APS.NET Core IOptions<T>
pattern.
services.Configure<PoolOptions>(Configuration.GetSection("PoolOptions"));
services.Configure<WalletOptions>(Configuration.GetSection("WalletOptions"));
Set any fields you’d like to configure in your appsettings.json
.
{
// config options
"WalletOptions": {
"WalletConfiguration": {
"Id": "MyAgentWallet",
"StorageConfiguration": { "Path": "[path to wallet storage]" }
},
"WalletCredentials": { "Key": "SecretWalletEncryptionKeyPhrase" }
},
"PoolOptions": {
"GenesisFilename": "[path to genesis file]",
"PoolName": "DefaultPool",
"ProtocolVersion": 2
}
}
Initialize agent middleware¶
In Configure(IApplicationBuilder app, IHostingEnvironment env)
start the default agent middleware
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// Endpoint can be any address you'd like to bind to this middleware
app.UseAgent("http://localhost:5000/agent");
// .. other services like app.UseMvc()
}
The default agent middleware is a simple implementation. You can create your middleware and use that instead if you’d like to customize the message handling.
app.UseAgent<CustomAgentMiddlware>("http://localhost:5000/agent");
See AgentMiddleware.cs for example implementation.
Tip
In ASP.NET Core, the order of middleware registration is important, so you might want to add the agent middleware before any other middlewares, like MVC.
Calling services from controllers¶
Use dependency injection to get a reference to each service in your controllers.
public class HomeController : Controller
{
private readonly IConnectionService _connectionService;
private readonly IWalletService _walletService;
private readonly WalletOptions _walletOptions;
public HomeController(
IConnectionService connectionService,
IWalletService walletService,
IOptions<WalletOptions> walletOptions)
{
_connectionService = connectionService;
_walletService = walletService;
_walletOptions = walletOptions.Value;
}
// ...
}
Hosting agents in docker containers¶
Hosting agents in docker container is the easiest way to ensure your running environment has all dependencies required by the framework. We provide images with libindy and dotnet-sdk preinstalled.
Usage¶
FROM streetcred/dotnet-indy:latest
The images are based on ubuntu:16.04. You can check the docker repo if you want to build your own image or require specific version of .NET Core or libindy.
Example build¶
Check the web agent docker file for an example of building and running ASP.NET Core project inside docker container with libindy support.
Samples¶
ASP.NET Core Agents¶
A sample agent running in ASP.NET Core that runs the default agent middleware can be found in samples/aspnetcore. This agent is also used in the Docker sample.
ddotnet run --project samples/aspnetcore/WebAgent.csproj
Running multiple instances¶
To run multiple agent instances that can communicate, you can specify the binding address and port by setting the ASPNETCORE_URLS
environment variable
# Unix/Mac:
ASPNETCORE_URLS="http://localhost:5001" dotnet run --no-launch-profile --project samples/aspnetcore/WebAgent.csproj
# Windows PowerShell:
$env:ASPNETCORE_URLS="http://localhost:5001" ; dotnet run --no-launch-profile --project samples/aspnetcore/WebAgent.csproj
# Windows CMD (note: no quotes):
SET ASPNETCORE_URLS=http://localhost:5001 && dotnet run --no-launch-profile --project samples/aspnetcore/WebAgent.csproj
Note
The sample web agent doesn’t use any functionality that requires a local indy node, but if you’d like to extend the sample and test interaction with the ledger, you can run a local node using the instructions below.
Run a local Indy node with Docker¶
The repo contains a docker image that can be used to run a local pool with 4 nodes.
docker build -f docker/indy-pool.dockerfile -t indy_pool .
docker run -itd -p 9701-9709:9701-9709 indy_pool
Mobile Agent with Xamarin Forms¶
Docker container example¶
Running the example¶
At the root of the repo run:
docker-compose up
This will create an agent network with a pool and three identical agents able to communicate with each other in the network. Navigate to http://localhost:7001/, http://localhost:7002/ and http://localhost:7003/ to create and accept connection invitations between the different agents.
Running the unit tests¶
docker-compose -f docker-compose.test.yaml up --build --remove-orphans --abort-on-container-exit --exit-code-from test-agent
Note: You may need to cleanup previous docker network created using docker network prune