Skip to content

Trust Registry

In many real-world credential exchange scenarios, a credential holder or verifier has the question “How do I know the issuer of this credential is trustworthy?”

Credential holders may also be uneasy about sharing information with a verifier if trust in the verifier has not been established.

These problems can be solved by having a trusted third party vouch for the trustworthiness of a credential exchange participant.

A trust registry is a list of authorized issuers and verifiers in the ecosystem and the types of credentials and passes they are authorized to issue and verify.

Specification

The Trust over IP Foundation has a specification for an interoperable trust registry. This defines an API interface so that trust registries can be queried in the same way. Our implementation is based off of this trust registry spec.

API Reference

Create a Ecosystem Governance Framework

An ecosystem governance framework is useful because it provides a good basis for verifying issuers and verifiers. It's a json-ld document that lists the issuers and verifiers. These issuers and verifiers are identified by a decentralized identifier. The governance framework is signified by an identifier as well. This can be used to represent the governance framework outside in the credential that it comes in.

trinsic trust-registry register-efg
var schemaUri = "https://schema.org/Card";
var frameworkUri = "https://example.com";
var registerFrameworkResponse = await service.AddFrameworkAsync(new() {
    Name = $"Demo framework-{Guid.NewGuid()}",
    GovernanceFrameworkUri = frameworkUri,
    Description = schemaUri
});
register_framework_response = await service.register_governance_framework(
    request=AddFrameworkRequest(
        governance_framework_uri=https_example_com,
        description="Demo framework",
        name=framework_name,
    )
)
newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
    GovernanceFrameworkUri: frameworkURI,
    Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
})
var frameworkResponse = service.registerGovernanceFramework(TrustRegistryOuterClass.AddFrameworkRequest.newBuilder().setGovernanceFrameworkUri(frameworkUri).setName("Example Framework" + UUID.randomUUID()).build()).get();

Register Issuers

Each entity on the governance framework, whether an issuer or a verifier, is represented by a decentralized identifier. These entities are registered to either issue or verify specific credential types. A credential type is represented as a fully qualified type URI, of the kind found in a JSON-LD Verifiable Credential. Finally, each entity must be registered on a specific governance framework.

trinsic trust-registry register-issuer \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
var didUri = "did:example:test";
var registerMemberResponse = await service.RegisterMemberAsync(new() {
    DidUri = didUri,
    FrameworkId = registerFrameworkResponse.Id,
    SchemaUri = schemaUri
});
await service.register_member(
    request=RegisterMemberRequest(
        did_uri=did_example_test,
        framework_id=register_framework_response.id,
        schema_uri=https_schema_org,
    )
)
package services

import (
    "context"
    "fmt"
    "io/ioutil"
    "path/filepath"
    "runtime"
    "testing"

    "github.com/google/uuid"
    "github.com/stretchr/testify/assert"
    sdk "github.com/trinsic-id/sdk/go/proto"
)

// pathData() {
func GetBasePath() string {
    _, fileName, _, _ := runtime.Caller(1)
    path := filepath.Clean(filepath.Join(filepath.Dir(fileName), "..", "..", "devops", "testdata"))
    return path
}
func GetVaccineCertUnsignedPath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-unsigned.jsonld")
}
func GetVaccineCertFramePath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-frame.jsonld")
}

// }

func TestServiceOptions(t *testing.T) {
    assert := assert.New(t)

    opts, err := NewServiceOptions()
    assert.Nil(err)

    prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}}
    err = WithProductionEnv()(prodOpts)
    assert.Nil(err, "production options should return")

    prodOpts.ServiceOptions.DefaultEcosystem = "default"
    assert.Equal(prodOpts, opts, "should default to production env")
    assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url")

    err = WithAuthToken("test token")(opts)
    assert.Nil(err, "should not error on test token")
    assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied")

    err = WithDevEnv()(opts)
    assert.Nil(err, "should not error on dev env")
    assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url")

    err = WithStagingEnv()(opts)
    assert.Nil(err, "should not error on staging env")
    assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url")

    err = WithDefaultEcosystem("test1")(opts)
    assert.Nil(err, "should not error on setting default ecosystem")
    assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated")
}

func TestVaccineCredentialsDemo(t *testing.T) {
    assert2 := assert.New(t)

    // Open in background
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return
    }

    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return
    }

    // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) {
    //  t.Fail()
    // }

    // SETUP ACTORS
    // Create 3 different profiles for each participant in the scenario
    // setupActors() {
    allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(allison) {
        return
    }

    clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(clinic) {
        return
    }

    airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(airline) {
        return
    }
    // }

    // storeAndRecallProfile() {
    // Store profile for later use
    // File.WriteAllBytes("allison.bin", allison.ToByteString().ToByteArray());

    // Create profile from existing data
    // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin"));
    // }

    walletService, err := NewWalletService(opts)
    failError(t, "error creating wallet service", err)

    credentialService, err := NewCredentialService(opts)
    failError(t, "error creating credential service", err)

    // ISSUE CREDENTIAL
    // Sign a credential as the clinic and send it to Allison
    // issueCredential() {
    fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath())
    failError(t, "error reading file", err)

    credentialService.SetToken(clinic)
    // issueCredentialSample() {
    credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)})
    // }
    failError(t, "error issuing credential", err)
    fmt.Printf("Credential:%s\n", credential)
    // }

    // sendCredential() {
    err = credentialService.Send(context.Background(), &sdk.SendRequest{DocumentJson: credential.SignedDocumentJson,
        DeliveryMethod: &sdk.SendRequest_Email{Email: "[email protected]"}})
    // }
    // We ignore errors because we don't expect this email account to exist.
    err = nil

    // STORE CREDENTIAL
    // Alice stores the credential in her cloud wallet.
    // storeCredential() {
    walletService.SetToken(allison)
    failError(t, "error setting profile", err)
    // insertItemWallet() {
    itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson})
    // }
    failError(t, "error inserting item", err)
    fmt.Println("item id", itemID)
    // }

    // searchWalletBasic() {
    items, err := walletService.Search(context.Background(), &sdk.SearchRequest{})
    // }
    // searchWalletSQL() {
    items2, err := walletService.Search(context.Background(), &sdk.SearchRequest{Query: "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"})
    // }
    if items != nil && items2 != nil {
    }

    // SHARE CREDENTIAL
    // Allison shares the credential with the venue.
    // The venue has communicated with Allison the details of the credential
    // that they require expressed as a JSON-LD frame.
    // shareCredential() {
    walletService.SetToken(allison)
    failError(t, "error reading file", err)

    fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath())
    failError(t, "error reading file", err)

    req := &sdk.CreateProofRequest{
        RevealDocumentJson: string(fileContent2),
        Proof:              &sdk.CreateProofRequest_ItemId{ItemId: itemID},
    }

    credentialService.SetToken(allison)
    // createProof() {
    credentialProof, err := credentialService.CreateProof(context.Background(), req)
    // }
    failError(t, "error creating proof", err)
    fmt.Println("Credential proof", credentialProof)
    // }

    // VERIFY CREDENTIAL
    // The airline verifies the credential
    // verifyCredential() {
    walletService.SetToken(airline)
    failError(t, "error setting profile", err)
    // verifyProof() {
    valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson})
    // }
    failError(t, "error verifying proof", err)
    fmt.Println("Validation result", valid)
    if valid != true {
        t.Fail()
    }
    // }
}

func TestTrustRegistryDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, _ := NewTrustRegistryService(opts)

    // register issuer
    didURI := "did:example:test"
    schemaUri := "https://schema.org/Card"
    frameworkURI := fmt.Sprintf("https://example.com/%s", uuid.New())

    // registerGovernanceFramework() {
    newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
        GovernanceFrameworkUri: frameworkURI,
        Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // registerMemberSample() {
    registerMemberResponse, err := service.RegisterMember(context.Background(), &sdk.RegisterMemberRequest{
        FrameworkId: newFramework.Id,
        SchemaUri:   schemaUri,
        Member:      &sdk.RegisterMemberRequest_DidUri{DidUri: didURI},
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // getMembershipStatus() {
    getMembershipStatusResponse, err := service.GetMembershipStatus(context.Background(), &sdk.GetMembershipStatusRequest{
        GovernanceFrameworkUri: frameworkURI,
        Member:                 &sdk.GetMembershipStatusRequest_DidUri{DidUri: didURI},
        SchemaUri:              schemaUri,
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.Equal(sdk.RegistrationStatus_CURRENT, getMembershipStatusResponse.Status, "Member status should be current")

    // searchTrustRegistry() {
    ecosystemList, err := service.SearchRegistry(context.Background(), nil)
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(ecosystemList)
    assert2.NotEmpty(ecosystemList)

    // unregisterIssuer() {
    unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
        SchemaUri:   schemaUri,
        FrameworkId: newFramework.Id,
    })
    // }

    // This is for the variables used for demos above, so they appear "used".
    if unregisterMemberResponse == nil || registerMemberResponse == nil || getMembershipStatusResponse == nil {
        // Do absolutely nothing
    }
}

func createAccountAndSignIn(t *testing.T) (*assert.Assertions, string, error) {
    assert2 := assert.New(t)
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    // Open in background
    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    if !assert2.Nil(err) {
        fmt.Println(err)
        return assert2, "", err
    }
    return assert2, authtoken, nil
}

func createRandomEcosystem() error {
    opts, err := NewServiceOptions(WithTestEnv())
    if err != nil {
        return err
    }

    ps, err := NewProviderService(opts)
    if err != nil {
        return err
    }

    _, err = ps.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{Name: "test-sdk-" + uuid.New().String()})

    return err
}
func TestEcosystemDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, err := NewProviderService(opts)
    if !assert2.Nil(err) {
        return
    }

    // createEcosystem() {
    actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{
        Description: "My ecosystem",
        Uri:         "https://example.com",
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(actualCreate)
    // assert2.NotNil(actualCreate.Id)
    // assert2.True(strings.HasPrefix(actualCreate.Id, "urn:trinsic:ecosystems:"))

    // inviteParticipant() {
    inviteResponse, err := service.InviteParticipant(context.Background(),
        &sdk.InviteRequest{Participant: sdk.ParticipantType_participant_type_individual,
            Details: &sdk.AccountDetails{Email: "[email protected]"}})
    // }
    if inviteResponse == nil {
        inviteResponse = &sdk.InviteResponse{InvitationId: "NA"}
    }
    // invitationStatus() {
    inviteStatus, err := service.InvitationStatus(context.Background(), &sdk.InvitationStatusRequest{InvitationId: inviteResponse.InvitationId})
    // }
    if inviteStatus != nil {
    }

}

// func TestCreateChannelUrlFromConfig(t *testing.T) {
//  assert2 := assert.New(t)
//  if !assert2.Equalf(CreateChannelUrlFromConfig(TrinsicProductionConfig()), CreateChannelUrlFromConfig(nil), "Default is production stack") {
//      return
//  }
// }

func failError(t *testing.T, message string, err error) {
    if err != nil {
        t.Helper()
        t.Errorf("%s: %v", message, err)
        t.FailNow()
    }
}
service.registerMember(TrustRegistryOuterClass.RegisterMemberRequest.newBuilder().setDidUri(didUri).setFrameworkId(frameworkResponse.getId()).setSchemaUri(typeUri).build());

Register Verifiers

trinsic trust-registry register-verifier \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Trinsic;
using Trinsic.Sdk.Options.V1;
using Trinsic.Services.Common.V1;
using Trinsic.Services.Provider.V1;
using Trinsic.Services.TrustRegistry.V1;
using Trinsic.Services.VerifiableCredentials.Templates.V1;
using Xunit;
using Xunit.Abstractions;
using JsonSerializer = System.Text.Json.JsonSerializer;

#pragma warning disable CS0618

namespace Tests;

[SuppressMessage("ReSharper", "MethodHasAsyncOverload")]
public class Tests
{
#if DEBUG
    private const string DefaultEndpoint = "localhost";
    private const int DefaultPort = 5000;
    private const bool DefaultUseTls = false;
#else
    private const string DefaultEndpoint = "staging-internal.trinsic.cloud";
    private const int DefaultPort = 443;
    private const bool DefaultUseTls = true;
#endif

    private readonly ITestOutputHelper _testOutputHelper;
    private readonly ServiceOptions _options;

    public Tests(ITestOutputHelper testOutputHelper) {
        _testOutputHelper = testOutputHelper;

        _options = new() {
            ServerEndpoint = Environment.GetEnvironmentVariable("TEST_SERVER_ENDPOINT") ?? DefaultEndpoint,
            ServerPort = int.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_PORT"), out var port) ? port : DefaultPort,
            ServerUseTls = bool.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_USE_TLS"), out var tls) ? tls : DefaultUseTls
        };

        _testOutputHelper.WriteLine($"Testing endpoint: {_options.FormatUrl()}");
    }

    private const string VaccinationCertificateUnsigned = "TestData/vaccination-certificate-unsigned.jsonld";
    private const string VaccinationCertificateFrame = "TestData/vaccination-certificate-frame.jsonld";

    [Fact(DisplayName = "Demo: wallet and credential sample")]
    public async Task TestWalletService() {
        // createAccountService() {
        var providerService = new ProviderService(_options.Clone());
        var accountService = new AccountService(_options.Clone());
        var (ecosystem, _) = providerService.CreateEcosystem(new());
        var ecosystemId = ecosystem.Id;
        // }

        // SETUP ACTORS
        // Create 3 different profiles for each participant in the scenario
        // setupActors() {
        var allison = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var clinic = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var airline = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        // }

        accountService.Options.AuthToken = clinic;
        var info = await accountService.GetInfoAsync();
        info.Should().NotBeNull();

        // createService() {
        var walletService = new WalletService(_options.CloneWithAuthToken(allison));
        var credentialsService = new CredentialsService(_options.CloneWithAuthToken(clinic));
        // }

        // ISSUE CREDENTIAL
        // Sign a credential as the clinic and send it to Allison
        // issueCredential() {
        // Set active profile to 'clinic' so we can issue credential signed
        // with the clinic's signing keys
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = clinic;

        // Read the JSON credential data
        var credentialJson = await File.ReadAllTextAsync(VaccinationCertificateUnsigned);
        // Sign the credential using BBS+ signature scheme
        // issueCredentialSample() {
        var credential = await credentialsService.IssueCredentialAsync(new() {DocumentJson = credentialJson});
        _testOutputHelper.WriteLine($"Credential:\n{credential.SignedDocumentJson}");
        // }
        // }

        // storeAndRecallProfile {
        // Serialize auth token by exporting it to file
        File.WriteAllText("allison.txt", allison);
        // Create auth token from existing data
        allison = File.ReadAllText("allison.txt");
        // }

        try {
            // sendCredential() {
            await credentialsService.SendAsync(new() {Email = "[email protected]"});
            // }
        } catch { } // We expect this to fail

        // STORE CREDENTIAL
        // Allison stores the credential in her cloud wallet.

        // storeCredential() {
        // Set active profile to 'allison' so we can manage her cloud wallet
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credential.SignedDocumentJson});
        var itemId = insertItemResponse.ItemId;
        // }
        // searchWalletBasic() {
        var walletItems = await walletService.SearchAsync(new());
        // }
        _testOutputHelper.WriteLine($"Last wallet item:\n{walletItems.Items.Last()}");

        // searchWalletSQL() { 
        var walletItems2 = await walletService.SearchAsync(new() {Query = "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"});
        // }

        // SHARE CREDENTIAL
        // Allison shares the credential with the venue.
        // The venue has communicated with Allison the details of the credential
        // that they require expressed as a JSON-LD frame.
        // shareCredential() {
        // We'll read the request frame from a file and communicate this with Allison
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var proofRequestJson = await File.ReadAllTextAsync(VaccinationCertificateFrame);

        // Build a proof for the given request and the `itemId` we previously received
        // which points to the stored credential
        var credentialProof = await credentialsService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = proofRequestJson
        });
        _testOutputHelper.WriteLine("Proof:");
        _testOutputHelper.WriteLine(credentialProof.ProofDocumentJson);
        // }


        // VERIFY CREDENTIAL
        // verifyCredential() {
        // The airline verifies the credential
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = airline;

        // Check for valid signature
        var valid = await credentialsService.VerifyProofAsync(new() {
            ProofDocumentJson = credentialProof.ProofDocumentJson
        });
        _testOutputHelper.WriteLine($"Verification result: {valid.IsValid}");
        Assert.True(valid.IsValid);
        // }
    }

    [Fact(DisplayName = "Demo: trust registries")]
    public async Task TestTrustRegistry() {
        var governanceUri = $"https://example.com/{Guid.NewGuid():N}";

        // setup
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var service = new TrustRegistryService(_options.CloneWithAuthToken(authToken));

        // registerGovernanceFramework() {
        var schemaUri = "https://schema.org/Card";
        var frameworkUri = "https://example.com";
        var registerFrameworkResponse = await service.AddFrameworkAsync(new() {
            Name = $"Demo framework-{Guid.NewGuid()}",
            GovernanceFrameworkUri = frameworkUri,
            Description = schemaUri
        });
        // }


        // registerIssuerSample() {
        var didUri = "did:example:test";
        var registerMemberResponse = await service.RegisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }

        // checkIssuerStatus() {
        var issuerStatus = await service.GetMembershipStatusAsync(new() {
            DidUri = didUri,
            GovernanceFrameworkUri = frameworkUri,
            SchemaUri = schemaUri
        });
        // }
        issuerStatus.Should().NotBeNull();
        issuerStatus.Status.Should().Be(RegistrationStatus.Current);

        // searchTrustRegistry() {
        var searchResult = await service.SearchRegistryAsync(new());
        // }

        searchResult.Should().NotBeNull();
        searchResult.ItemsJson.Should().NotBeNull().And.NotBeEmpty();

        // unregisterIssuer() {
        await service.UnregisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }
    }

    [Fact(DisplayName = "Demo: ecosystem creation and listing")]
    public async Task EcosystemTests() {
        // setup
        var accountService = new AccountService(_options);
        var account = await accountService.SignInAsync(new());
        var service = new ProviderService(_options.CloneWithAuthToken(account));

        // test create ecosystem
        // createEcosystem() {
        var (actualCreate, _) = await service.CreateEcosystemAsync(new() {
            Description = "My ecosystem",
            Uri = "https://example.com"
        });
        // }

        actualCreate.Should().NotBeNull();
        actualCreate.Id.Should().NotBeNull();
        actualCreate.Id.Should().StartWith("urn:trinsic:ecosystems:");

        try {
            // inviteParticipant() {
            var inviteResponse = await service.InviteParticipantAsync(new() {
                Participant = ParticipantType.Individual,
                Description = "Doc sample",
                Details = new() {
                    Email = "[email protected]"
                }
            });
            // }
        } catch(Exception) { } // This is expected as a doc sample

        var invitationId = "N/A";
        try {
            // invitationStatus() {
            var inviteStatus = await service.InvitationStatusAsync(new() {InvitationId = invitationId});
            // }
        } catch(Exception) { } // This is expected as a doc sample
    }

    [Fact]
    public async Task TestProtectUnprotectProfile() {
        // testSignInAndGetInfo() {
        // accountServiceConstructor() {
        var myAccountService = new AccountService(_options);
        // }
        // accountServiceSignIn() {
        var myProfile = await myAccountService.SignInAsync(new());
        // }
        myAccountService.Options.AuthToken = myProfile;
        // accountServiceGetInfo() {
        var output = await myAccountService.GetInfoAsync();
        // }
        Assert.NotNull(output);
        // }

        // protectUnprotectProfile() {
        var securityCode = "1234";
        var myProtectedProfile = AccountService.Protect(myProfile, securityCode);
        var myUnprotectedProfile = AccountService.Unprotect(myProtectedProfile, securityCode);
        // }
        myAccountService.Options.AuthToken = myProtectedProfile;
        await Assert.ThrowsAsync<Exception>(myAccountService.GetInfoAsync);
        myAccountService.Options.AuthToken = myUnprotectedProfile;
        Assert.NotNull(await myAccountService.GetInfoAsync());
        Assert.NotNull(myAccountService.GetInfo());
    }

    [Fact]
    public async Task TestInvitationIdSet() {
        var providerService = new ProviderService(_options.Clone());
        _ = await providerService.CreateEcosystemAsync(new());

        var invitationResponse = await providerService.InviteParticipantAsync(new());

        invitationResponse.Should().NotBeNull();
        invitationResponse.InvitationCode.Should().NotBeEmpty();

        await Assert.ThrowsAsync<Exception>(async () => await providerService.InvitationStatusAsync(new()));
    }

    [Fact(Skip = "Ecosystem support not complete yet")]
    public async Task TestInviteParticipant() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myProviderService = new ProviderService(_options.CloneWithAuthToken(myProfile));
        var invite = new InviteRequest {Description = "Test invitation"};
        var response = await myProviderService.InviteParticipantAsync(invite);
        Assert.NotNull(response);

        var statusResponse = await myProviderService.InvitationStatusAsync(new() {InvitationId = response.InvitationId});
        Assert.NotNull(statusResponse);
    }

    [Fact]
    public async Task TestGovernanceFrameworkUriParse() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myTrustRegistryService = new TrustRegistryService(_options.CloneWithAuthToken(myProfile));
        await Assert.ThrowsAsync<Exception>(async () => await myTrustRegistryService.AddFrameworkAsync(new() {
            Description = "invalid uri",
            GovernanceFrameworkUri = ""
        }));
    }

    [Fact(DisplayName = "Demo: template management and credential issuance from template")]
    public async Task DemoTemplatesWithIssuance() {
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var options = _options.CloneWithAuthToken(authToken);

        var templateService = new TemplateService(options);
        var credentialService = new CredentialsService(options);
        var walletService = new WalletService(options);

        // create example template
        // createTemplate() {
        CreateCredentialTemplateRequest templateRequest = new() {
            Name = "An Example Credential",
            AllowAdditionalFields = false
        };
        templateRequest.Fields.Add("firstName", new() {Description = "Given name"});
        templateRequest.Fields.Add("lastName", new());
        templateRequest.Fields.Add("age", new() {Optional = true}); // TODO - use FieldType.NUMBER once schema validation is fixed.

        var template = await templateService.CreateAsync(templateRequest);
        // }

        template.Should().NotBeNull();
        template.Data.Should().NotBeNull();
        template.Data.Id.Should().NotBeNull();
        template.Data.SchemaUri.Should().NotBeNull();

        // issue credential from this template
        var values = JsonSerializer.Serialize(new {
            firstName = "Jane",
            lastName = "Doe",
            age = "42"
        });

        // issueFromTemplate() {
        var credentialJson = await credentialService.IssueFromTemplateAsync(new() {
            TemplateId = template.Data.Id,
            ValuesJson = values
        });
        // }

        credentialJson.Should().NotBeNull();

        var jsonDocument = JsonDocument.Parse(credentialJson.DocumentJson).RootElement.EnumerateObject();

        jsonDocument.Should().Contain(x => x.Name == "id");
        jsonDocument.Should().Contain(x => x.Name == "credentialSubject");

        // insertItemWallet() {
        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credentialJson.DocumentJson});
        // }
        var itemId = insertItemResponse.ItemId;

        var frame = new JObject {
            {"@context", "https://www.w3.org/2018/credentials/v1"},
            {"type", new JArray("VerifiableCredential")}
        };

        // Create proof from input document
        // createProof() {
        var proof = await credentialService.CreateProofAsync(new() {
            DocumentJson = credentialJson.DocumentJson,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });
        // }
        // verifyProof() {
        var valid = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof.ProofDocumentJson});
        // }
        valid.IsValid.Should().BeTrue();

        // Create proof from item id
        var proof2 = await credentialService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });

        var valid2 = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof2.ProofDocumentJson});

        valid2.IsValid.Should().BeTrue();

        try {
            // checkCredentialStatus() {
            var checkResponse = await credentialService.CheckStatusAsync(new() {CredentialStatusId = ""});
            // }
        } catch { } // We expect this to fail

        try {
            // updateCredentialStatus() {
            await credentialService.UpdateStatusAsync(new() {CredentialStatusId = "", Revoked = true});
            // }
        } catch { } // We expect this to fail

        // getCredentialTemplate() {
        var getTemplateResponse = await templateService.GetAsync(new() {Id = template.Data.Id});
        // }
        // searchCredentialTemplate() {
        var searchTemplateResponse = await templateService.SearchAsync(new() {Query = "SELECT * FROM c"});
        // }
        // deleteCredentialTemplate() {
        var deleteTemplateResponse = await templateService.DeleteAsync(new() {Id = template.Data.Id});
        // }
    }

    [Fact(DisplayName = "Decode base64 url encoded string")]
    public void DecodeBase64UrlString() {
        const string encoded =
            "CiVodHRwczovL3RyaW5zaWMuaWQvc2VjdXJpdHkvdjEvb2Jlcm9uEnIKKnVybjp0cmluc2ljOndhbGxldHM6Vzl1dG9pVmhDZHp2RXJZRGVyOGlrRxIkODBkMTVlYTYtMTIxOS00MGZmLWE4NTQtZGI1NmZhOTlmNjMwIh51cm46dHJpbnNpYzplY29zeXN0ZW1zOmRlZmF1bHQaMJRXhevRbornRpA-HJ86WaTLGmQlOuoXSnDT_W2O3u3bV5rS5nKpgrfGKFEbRtIgjyIA";

        var actual = Base64Url.Decode(encoded);

        actual.Should().NotBeEmpty();
    }
}
import asyncio
import uuid

from trinsic.account_service import AccountService
from trinsic.proto.services.trustregistry.v1 import (
    RegistrationStatus,
    AddFrameworkRequest,
    UnregisterMemberRequest,
    GetMembershipStatusRequest,
    RegisterMemberRequest,
)
from trinsic.trinsic_util import trinsic_config
from trinsic.trustregistry_service import TrustRegistryService


async def trustregistry_demo():
    # setup
    account_service = AccountService(server_config=trinsic_config())
    account = await account_service.sign_in()
    service = TrustRegistryService(server_config=trinsic_config(account))

    # data
    https_schema_org = "https://schema.org/Card"
    https_example_com = f"https://example.com/{uuid.uuid4()}"
    did_example_test = "did:example:test"
    framework_name = f"Example Framework: {uuid.uuid4()}"

    # registerGovernanceFramework() {
    register_framework_response = await service.register_governance_framework(
        request=AddFrameworkRequest(
            governance_framework_uri=https_example_com,
            description="Demo framework",
            name=framework_name,
        )
    )
    # }

    # registerIssuerSample() {
    await service.register_member(
        request=RegisterMemberRequest(
            did_uri=did_example_test,
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
        )
    )
    # }

    # checkIssuerStatus() {
    check_response = await service.get_membership_status(
        request=GetMembershipStatusRequest(
            did_uri=did_example_test,
            governance_framework_uri=https_example_com,
            schema_uri=https_schema_org,
        )
    )
    # }
    issuer_status = check_response.status
    assert issuer_status == RegistrationStatus.CURRENT

    # searchTrustRegistry() {
    search_result = await service.search_registry()
    # }
    assert search_result is not None
    assert search_result.items_json is not None
    assert len(search_result.items_json) > 0

    # unregisterIssuer() {
    unregister_issuer_response = await service.unregister_member(
        request=UnregisterMemberRequest(
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
            did_uri=did_example_test,
        )
    )
    # }


if __name__ == "__main__":
    asyncio.run(trustregistry_demo())
package services

import (
    "context"
    "fmt"
    "io/ioutil"
    "path/filepath"
    "runtime"
    "testing"

    "github.com/google/uuid"
    "github.com/stretchr/testify/assert"
    sdk "github.com/trinsic-id/sdk/go/proto"
)

// pathData() {
func GetBasePath() string {
    _, fileName, _, _ := runtime.Caller(1)
    path := filepath.Clean(filepath.Join(filepath.Dir(fileName), "..", "..", "devops", "testdata"))
    return path
}
func GetVaccineCertUnsignedPath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-unsigned.jsonld")
}
func GetVaccineCertFramePath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-frame.jsonld")
}

// }

func TestServiceOptions(t *testing.T) {
    assert := assert.New(t)

    opts, err := NewServiceOptions()
    assert.Nil(err)

    prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}}
    err = WithProductionEnv()(prodOpts)
    assert.Nil(err, "production options should return")

    prodOpts.ServiceOptions.DefaultEcosystem = "default"
    assert.Equal(prodOpts, opts, "should default to production env")
    assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url")

    err = WithAuthToken("test token")(opts)
    assert.Nil(err, "should not error on test token")
    assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied")

    err = WithDevEnv()(opts)
    assert.Nil(err, "should not error on dev env")
    assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url")

    err = WithStagingEnv()(opts)
    assert.Nil(err, "should not error on staging env")
    assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url")

    err = WithDefaultEcosystem("test1")(opts)
    assert.Nil(err, "should not error on setting default ecosystem")
    assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated")
}

func TestVaccineCredentialsDemo(t *testing.T) {
    assert2 := assert.New(t)

    // Open in background
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return
    }

    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return
    }

    // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) {
    //  t.Fail()
    // }

    // SETUP ACTORS
    // Create 3 different profiles for each participant in the scenario
    // setupActors() {
    allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(allison) {
        return
    }

    clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(clinic) {
        return
    }

    airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(airline) {
        return
    }
    // }

    // storeAndRecallProfile() {
    // Store profile for later use
    // File.WriteAllBytes("allison.bin", allison.ToByteString().ToByteArray());

    // Create profile from existing data
    // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin"));
    // }

    walletService, err := NewWalletService(opts)
    failError(t, "error creating wallet service", err)

    credentialService, err := NewCredentialService(opts)
    failError(t, "error creating credential service", err)

    // ISSUE CREDENTIAL
    // Sign a credential as the clinic and send it to Allison
    // issueCredential() {
    fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath())
    failError(t, "error reading file", err)

    credentialService.SetToken(clinic)
    // issueCredentialSample() {
    credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)})
    // }
    failError(t, "error issuing credential", err)
    fmt.Printf("Credential:%s\n", credential)
    // }

    // sendCredential() {
    err = credentialService.Send(context.Background(), &sdk.SendRequest{DocumentJson: credential.SignedDocumentJson,
        DeliveryMethod: &sdk.SendRequest_Email{Email: "[email protected]"}})
    // }
    // We ignore errors because we don't expect this email account to exist.
    err = nil

    // STORE CREDENTIAL
    // Alice stores the credential in her cloud wallet.
    // storeCredential() {
    walletService.SetToken(allison)
    failError(t, "error setting profile", err)
    // insertItemWallet() {
    itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson})
    // }
    failError(t, "error inserting item", err)
    fmt.Println("item id", itemID)
    // }

    // searchWalletBasic() {
    items, err := walletService.Search(context.Background(), &sdk.SearchRequest{})
    // }
    // searchWalletSQL() {
    items2, err := walletService.Search(context.Background(), &sdk.SearchRequest{Query: "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"})
    // }
    if items != nil && items2 != nil {
    }

    // SHARE CREDENTIAL
    // Allison shares the credential with the venue.
    // The venue has communicated with Allison the details of the credential
    // that they require expressed as a JSON-LD frame.
    // shareCredential() {
    walletService.SetToken(allison)
    failError(t, "error reading file", err)

    fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath())
    failError(t, "error reading file", err)

    req := &sdk.CreateProofRequest{
        RevealDocumentJson: string(fileContent2),
        Proof:              &sdk.CreateProofRequest_ItemId{ItemId: itemID},
    }

    credentialService.SetToken(allison)
    // createProof() {
    credentialProof, err := credentialService.CreateProof(context.Background(), req)
    // }
    failError(t, "error creating proof", err)
    fmt.Println("Credential proof", credentialProof)
    // }

    // VERIFY CREDENTIAL
    // The airline verifies the credential
    // verifyCredential() {
    walletService.SetToken(airline)
    failError(t, "error setting profile", err)
    // verifyProof() {
    valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson})
    // }
    failError(t, "error verifying proof", err)
    fmt.Println("Validation result", valid)
    if valid != true {
        t.Fail()
    }
    // }
}

func TestTrustRegistryDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, _ := NewTrustRegistryService(opts)

    // register issuer
    didURI := "did:example:test"
    schemaUri := "https://schema.org/Card"
    frameworkURI := fmt.Sprintf("https://example.com/%s", uuid.New())

    // registerGovernanceFramework() {
    newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
        GovernanceFrameworkUri: frameworkURI,
        Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // registerMemberSample() {
    registerMemberResponse, err := service.RegisterMember(context.Background(), &sdk.RegisterMemberRequest{
        FrameworkId: newFramework.Id,
        SchemaUri:   schemaUri,
        Member:      &sdk.RegisterMemberRequest_DidUri{DidUri: didURI},
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // getMembershipStatus() {
    getMembershipStatusResponse, err := service.GetMembershipStatus(context.Background(), &sdk.GetMembershipStatusRequest{
        GovernanceFrameworkUri: frameworkURI,
        Member:                 &sdk.GetMembershipStatusRequest_DidUri{DidUri: didURI},
        SchemaUri:              schemaUri,
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.Equal(sdk.RegistrationStatus_CURRENT, getMembershipStatusResponse.Status, "Member status should be current")

    // searchTrustRegistry() {
    ecosystemList, err := service.SearchRegistry(context.Background(), nil)
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(ecosystemList)
    assert2.NotEmpty(ecosystemList)

    // unregisterIssuer() {
    unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
        SchemaUri:   schemaUri,
        FrameworkId: newFramework.Id,
    })
    // }

    // This is for the variables used for demos above, so they appear "used".
    if unregisterMemberResponse == nil || registerMemberResponse == nil || getMembershipStatusResponse == nil {
        // Do absolutely nothing
    }
}

func createAccountAndSignIn(t *testing.T) (*assert.Assertions, string, error) {
    assert2 := assert.New(t)
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    // Open in background
    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    if !assert2.Nil(err) {
        fmt.Println(err)
        return assert2, "", err
    }
    return assert2, authtoken, nil
}

func createRandomEcosystem() error {
    opts, err := NewServiceOptions(WithTestEnv())
    if err != nil {
        return err
    }

    ps, err := NewProviderService(opts)
    if err != nil {
        return err
    }

    _, err = ps.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{Name: "test-sdk-" + uuid.New().String()})

    return err
}
func TestEcosystemDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, err := NewProviderService(opts)
    if !assert2.Nil(err) {
        return
    }

    // createEcosystem() {
    actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{
        Description: "My ecosystem",
        Uri:         "https://example.com",
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(actualCreate)
    // assert2.NotNil(actualCreate.Id)
    // assert2.True(strings.HasPrefix(actualCreate.Id, "urn:trinsic:ecosystems:"))

    // inviteParticipant() {
    inviteResponse, err := service.InviteParticipant(context.Background(),
        &sdk.InviteRequest{Participant: sdk.ParticipantType_participant_type_individual,
            Details: &sdk.AccountDetails{Email: "[email protected]"}})
    // }
    if inviteResponse == nil {
        inviteResponse = &sdk.InviteResponse{InvitationId: "NA"}
    }
    // invitationStatus() {
    inviteStatus, err := service.InvitationStatus(context.Background(), &sdk.InvitationStatusRequest{InvitationId: inviteResponse.InvitationId})
    // }
    if inviteStatus != nil {
    }

}

// func TestCreateChannelUrlFromConfig(t *testing.T) {
//  assert2 := assert.New(t)
//  if !assert2.Equalf(CreateChannelUrlFromConfig(TrinsicProductionConfig()), CreateChannelUrlFromConfig(nil), "Default is production stack") {
//      return
//  }
// }

func failError(t *testing.T, message string, err error) {
    if err != nil {
        t.Helper()
        t.Errorf("%s: %v", message, err)
        t.FailNow()
    }
}
package trinsic;

import org.junit.jupiter.api.Assertions;
import trinsic.okapi.DidException;
import trinsic.services.AccountService;
import trinsic.services.TrustRegistryService;
import trinsic.services.trustregistry.v1.TrustRegistryOuterClass;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

public class TrustRegistryDemo {
    public static void main(String[] args) throws IOException, DidException, ExecutionException, InterruptedException {
        run();
    }

    public static void run() throws IOException, DidException, ExecutionException, InterruptedException {
        var accountService = new AccountService(TrinsicUtilities.getTrinsicServiceOptions());
        var account = accountService.signIn().get();
        var service = new TrustRegistryService(TrinsicUtilities.getTrinsicServiceOptions(account));

        final String didUri = "did:example:test";
        final String frameworkUri = "https://example.com/" + UUID.randomUUID();
        final String typeUri = "https://schema.org/Card";

        // registerGovernanceFramework() {
        var frameworkResponse = service.registerGovernanceFramework(TrustRegistryOuterClass.AddFrameworkRequest.newBuilder().setGovernanceFrameworkUri(frameworkUri).setName("Example Framework" + UUID.randomUUID()).build()).get();
        // }

        // registerIssuerSample() {
        service.registerMember(TrustRegistryOuterClass.RegisterMemberRequest.newBuilder().setDidUri(didUri).setFrameworkId(frameworkResponse.getId()).setSchemaUri(typeUri).build());
        // }
        // checkIssuerStatus() {
        var issuerStatus = service.checkIssuerStatus(TrustRegistryOuterClass.GetMembershipStatusRequest.newBuilder().setDidUri(didUri).setGovernanceFrameworkUri(frameworkUri).setSchemaUri(typeUri).build()).get();
        // }
        Assertions.assertEquals(TrustRegistryOuterClass.RegistrationStatus.CURRENT, issuerStatus.getStatus());

        // searchTrustRegistry() {
        var searchResult = service.searchRegistry().get();
        // }
        Assertions.assertNotNull(searchResult);
        Assertions.assertNotNull(searchResult.getItemsJson());
        Assertions.assertTrue(searchResult.getItemsJson().length() > 0);

        // unregisterIssuer() {
        service.unregisterIssuer(TrustRegistryOuterClass.UnregisterMemberRequest.newBuilder().setFrameworkId(frameworkResponse.getId()).setDidUri(didUri).setSchemaUri(typeUri).build());
        // }
    }
}

Unregister Issuers

To unregister an issuer, include the credential type, the did, and the ecosystem governance framework. The credential type will be unregistered from that issuer.

trinsic trust-registry unregister-issuer \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
await service.UnregisterMemberAsync(new() {
    DidUri = didUri,
    FrameworkId = registerFrameworkResponse.Id,
    SchemaUri = schemaUri
});
unregister_issuer_response = await service.unregister_member(
    request=UnregisterMemberRequest(
        framework_id=register_framework_response.id,
        schema_uri=https_schema_org,
        did_uri=did_example_test,
    )
)
unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
    SchemaUri:   schemaUri,
    FrameworkId: newFramework.Id,
})
service.unregisterIssuer(TrustRegistryOuterClass.UnregisterMemberRequest.newBuilder().setFrameworkId(frameworkResponse.getId()).setDidUri(didUri).setSchemaUri(typeUri).build());

Unregister Verifiers

To unregister a verifier, include the credential type, the did, and the ecosystem governance framework. The credential type will be unregistered from that verifier.

trinsic trust-registry unregister-verifier \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Trinsic;
using Trinsic.Sdk.Options.V1;
using Trinsic.Services.Common.V1;
using Trinsic.Services.Provider.V1;
using Trinsic.Services.TrustRegistry.V1;
using Trinsic.Services.VerifiableCredentials.Templates.V1;
using Xunit;
using Xunit.Abstractions;
using JsonSerializer = System.Text.Json.JsonSerializer;

#pragma warning disable CS0618

namespace Tests;

[SuppressMessage("ReSharper", "MethodHasAsyncOverload")]
public class Tests
{
#if DEBUG
    private const string DefaultEndpoint = "localhost";
    private const int DefaultPort = 5000;
    private const bool DefaultUseTls = false;
#else
    private const string DefaultEndpoint = "staging-internal.trinsic.cloud";
    private const int DefaultPort = 443;
    private const bool DefaultUseTls = true;
#endif

    private readonly ITestOutputHelper _testOutputHelper;
    private readonly ServiceOptions _options;

    public Tests(ITestOutputHelper testOutputHelper) {
        _testOutputHelper = testOutputHelper;

        _options = new() {
            ServerEndpoint = Environment.GetEnvironmentVariable("TEST_SERVER_ENDPOINT") ?? DefaultEndpoint,
            ServerPort = int.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_PORT"), out var port) ? port : DefaultPort,
            ServerUseTls = bool.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_USE_TLS"), out var tls) ? tls : DefaultUseTls
        };

        _testOutputHelper.WriteLine($"Testing endpoint: {_options.FormatUrl()}");
    }

    private const string VaccinationCertificateUnsigned = "TestData/vaccination-certificate-unsigned.jsonld";
    private const string VaccinationCertificateFrame = "TestData/vaccination-certificate-frame.jsonld";

    [Fact(DisplayName = "Demo: wallet and credential sample")]
    public async Task TestWalletService() {
        // createAccountService() {
        var providerService = new ProviderService(_options.Clone());
        var accountService = new AccountService(_options.Clone());
        var (ecosystem, _) = providerService.CreateEcosystem(new());
        var ecosystemId = ecosystem.Id;
        // }

        // SETUP ACTORS
        // Create 3 different profiles for each participant in the scenario
        // setupActors() {
        var allison = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var clinic = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var airline = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        // }

        accountService.Options.AuthToken = clinic;
        var info = await accountService.GetInfoAsync();
        info.Should().NotBeNull();

        // createService() {
        var walletService = new WalletService(_options.CloneWithAuthToken(allison));
        var credentialsService = new CredentialsService(_options.CloneWithAuthToken(clinic));
        // }

        // ISSUE CREDENTIAL
        // Sign a credential as the clinic and send it to Allison
        // issueCredential() {
        // Set active profile to 'clinic' so we can issue credential signed
        // with the clinic's signing keys
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = clinic;

        // Read the JSON credential data
        var credentialJson = await File.ReadAllTextAsync(VaccinationCertificateUnsigned);
        // Sign the credential using BBS+ signature scheme
        // issueCredentialSample() {
        var credential = await credentialsService.IssueCredentialAsync(new() {DocumentJson = credentialJson});
        _testOutputHelper.WriteLine($"Credential:\n{credential.SignedDocumentJson}");
        // }
        // }

        // storeAndRecallProfile {
        // Serialize auth token by exporting it to file
        File.WriteAllText("allison.txt", allison);
        // Create auth token from existing data
        allison = File.ReadAllText("allison.txt");
        // }

        try {
            // sendCredential() {
            await credentialsService.SendAsync(new() {Email = "[email protected]"});
            // }
        } catch { } // We expect this to fail

        // STORE CREDENTIAL
        // Allison stores the credential in her cloud wallet.

        // storeCredential() {
        // Set active profile to 'allison' so we can manage her cloud wallet
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credential.SignedDocumentJson});
        var itemId = insertItemResponse.ItemId;
        // }
        // searchWalletBasic() {
        var walletItems = await walletService.SearchAsync(new());
        // }
        _testOutputHelper.WriteLine($"Last wallet item:\n{walletItems.Items.Last()}");

        // searchWalletSQL() { 
        var walletItems2 = await walletService.SearchAsync(new() {Query = "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"});
        // }

        // SHARE CREDENTIAL
        // Allison shares the credential with the venue.
        // The venue has communicated with Allison the details of the credential
        // that they require expressed as a JSON-LD frame.
        // shareCredential() {
        // We'll read the request frame from a file and communicate this with Allison
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var proofRequestJson = await File.ReadAllTextAsync(VaccinationCertificateFrame);

        // Build a proof for the given request and the `itemId` we previously received
        // which points to the stored credential
        var credentialProof = await credentialsService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = proofRequestJson
        });
        _testOutputHelper.WriteLine("Proof:");
        _testOutputHelper.WriteLine(credentialProof.ProofDocumentJson);
        // }


        // VERIFY CREDENTIAL
        // verifyCredential() {
        // The airline verifies the credential
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = airline;

        // Check for valid signature
        var valid = await credentialsService.VerifyProofAsync(new() {
            ProofDocumentJson = credentialProof.ProofDocumentJson
        });
        _testOutputHelper.WriteLine($"Verification result: {valid.IsValid}");
        Assert.True(valid.IsValid);
        // }
    }

    [Fact(DisplayName = "Demo: trust registries")]
    public async Task TestTrustRegistry() {
        var governanceUri = $"https://example.com/{Guid.NewGuid():N}";

        // setup
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var service = new TrustRegistryService(_options.CloneWithAuthToken(authToken));

        // registerGovernanceFramework() {
        var schemaUri = "https://schema.org/Card";
        var frameworkUri = "https://example.com";
        var registerFrameworkResponse = await service.AddFrameworkAsync(new() {
            Name = $"Demo framework-{Guid.NewGuid()}",
            GovernanceFrameworkUri = frameworkUri,
            Description = schemaUri
        });
        // }


        // registerIssuerSample() {
        var didUri = "did:example:test";
        var registerMemberResponse = await service.RegisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }

        // checkIssuerStatus() {
        var issuerStatus = await service.GetMembershipStatusAsync(new() {
            DidUri = didUri,
            GovernanceFrameworkUri = frameworkUri,
            SchemaUri = schemaUri
        });
        // }
        issuerStatus.Should().NotBeNull();
        issuerStatus.Status.Should().Be(RegistrationStatus.Current);

        // searchTrustRegistry() {
        var searchResult = await service.SearchRegistryAsync(new());
        // }

        searchResult.Should().NotBeNull();
        searchResult.ItemsJson.Should().NotBeNull().And.NotBeEmpty();

        // unregisterIssuer() {
        await service.UnregisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }
    }

    [Fact(DisplayName = "Demo: ecosystem creation and listing")]
    public async Task EcosystemTests() {
        // setup
        var accountService = new AccountService(_options);
        var account = await accountService.SignInAsync(new());
        var service = new ProviderService(_options.CloneWithAuthToken(account));

        // test create ecosystem
        // createEcosystem() {
        var (actualCreate, _) = await service.CreateEcosystemAsync(new() {
            Description = "My ecosystem",
            Uri = "https://example.com"
        });
        // }

        actualCreate.Should().NotBeNull();
        actualCreate.Id.Should().NotBeNull();
        actualCreate.Id.Should().StartWith("urn:trinsic:ecosystems:");

        try {
            // inviteParticipant() {
            var inviteResponse = await service.InviteParticipantAsync(new() {
                Participant = ParticipantType.Individual,
                Description = "Doc sample",
                Details = new() {
                    Email = "[email protected]"
                }
            });
            // }
        } catch(Exception) { } // This is expected as a doc sample

        var invitationId = "N/A";
        try {
            // invitationStatus() {
            var inviteStatus = await service.InvitationStatusAsync(new() {InvitationId = invitationId});
            // }
        } catch(Exception) { } // This is expected as a doc sample
    }

    [Fact]
    public async Task TestProtectUnprotectProfile() {
        // testSignInAndGetInfo() {
        // accountServiceConstructor() {
        var myAccountService = new AccountService(_options);
        // }
        // accountServiceSignIn() {
        var myProfile = await myAccountService.SignInAsync(new());
        // }
        myAccountService.Options.AuthToken = myProfile;
        // accountServiceGetInfo() {
        var output = await myAccountService.GetInfoAsync();
        // }
        Assert.NotNull(output);
        // }

        // protectUnprotectProfile() {
        var securityCode = "1234";
        var myProtectedProfile = AccountService.Protect(myProfile, securityCode);
        var myUnprotectedProfile = AccountService.Unprotect(myProtectedProfile, securityCode);
        // }
        myAccountService.Options.AuthToken = myProtectedProfile;
        await Assert.ThrowsAsync<Exception>(myAccountService.GetInfoAsync);
        myAccountService.Options.AuthToken = myUnprotectedProfile;
        Assert.NotNull(await myAccountService.GetInfoAsync());
        Assert.NotNull(myAccountService.GetInfo());
    }

    [Fact]
    public async Task TestInvitationIdSet() {
        var providerService = new ProviderService(_options.Clone());
        _ = await providerService.CreateEcosystemAsync(new());

        var invitationResponse = await providerService.InviteParticipantAsync(new());

        invitationResponse.Should().NotBeNull();
        invitationResponse.InvitationCode.Should().NotBeEmpty();

        await Assert.ThrowsAsync<Exception>(async () => await providerService.InvitationStatusAsync(new()));
    }

    [Fact(Skip = "Ecosystem support not complete yet")]
    public async Task TestInviteParticipant() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myProviderService = new ProviderService(_options.CloneWithAuthToken(myProfile));
        var invite = new InviteRequest {Description = "Test invitation"};
        var response = await myProviderService.InviteParticipantAsync(invite);
        Assert.NotNull(response);

        var statusResponse = await myProviderService.InvitationStatusAsync(new() {InvitationId = response.InvitationId});
        Assert.NotNull(statusResponse);
    }

    [Fact]
    public async Task TestGovernanceFrameworkUriParse() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myTrustRegistryService = new TrustRegistryService(_options.CloneWithAuthToken(myProfile));
        await Assert.ThrowsAsync<Exception>(async () => await myTrustRegistryService.AddFrameworkAsync(new() {
            Description = "invalid uri",
            GovernanceFrameworkUri = ""
        }));
    }

    [Fact(DisplayName = "Demo: template management and credential issuance from template")]
    public async Task DemoTemplatesWithIssuance() {
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var options = _options.CloneWithAuthToken(authToken);

        var templateService = new TemplateService(options);
        var credentialService = new CredentialsService(options);
        var walletService = new WalletService(options);

        // create example template
        // createTemplate() {
        CreateCredentialTemplateRequest templateRequest = new() {
            Name = "An Example Credential",
            AllowAdditionalFields = false
        };
        templateRequest.Fields.Add("firstName", new() {Description = "Given name"});
        templateRequest.Fields.Add("lastName", new());
        templateRequest.Fields.Add("age", new() {Optional = true}); // TODO - use FieldType.NUMBER once schema validation is fixed.

        var template = await templateService.CreateAsync(templateRequest);
        // }

        template.Should().NotBeNull();
        template.Data.Should().NotBeNull();
        template.Data.Id.Should().NotBeNull();
        template.Data.SchemaUri.Should().NotBeNull();

        // issue credential from this template
        var values = JsonSerializer.Serialize(new {
            firstName = "Jane",
            lastName = "Doe",
            age = "42"
        });

        // issueFromTemplate() {
        var credentialJson = await credentialService.IssueFromTemplateAsync(new() {
            TemplateId = template.Data.Id,
            ValuesJson = values
        });
        // }

        credentialJson.Should().NotBeNull();

        var jsonDocument = JsonDocument.Parse(credentialJson.DocumentJson).RootElement.EnumerateObject();

        jsonDocument.Should().Contain(x => x.Name == "id");
        jsonDocument.Should().Contain(x => x.Name == "credentialSubject");

        // insertItemWallet() {
        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credentialJson.DocumentJson});
        // }
        var itemId = insertItemResponse.ItemId;

        var frame = new JObject {
            {"@context", "https://www.w3.org/2018/credentials/v1"},
            {"type", new JArray("VerifiableCredential")}
        };

        // Create proof from input document
        // createProof() {
        var proof = await credentialService.CreateProofAsync(new() {
            DocumentJson = credentialJson.DocumentJson,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });
        // }
        // verifyProof() {
        var valid = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof.ProofDocumentJson});
        // }
        valid.IsValid.Should().BeTrue();

        // Create proof from item id
        var proof2 = await credentialService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });

        var valid2 = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof2.ProofDocumentJson});

        valid2.IsValid.Should().BeTrue();

        try {
            // checkCredentialStatus() {
            var checkResponse = await credentialService.CheckStatusAsync(new() {CredentialStatusId = ""});
            // }
        } catch { } // We expect this to fail

        try {
            // updateCredentialStatus() {
            await credentialService.UpdateStatusAsync(new() {CredentialStatusId = "", Revoked = true});
            // }
        } catch { } // We expect this to fail

        // getCredentialTemplate() {
        var getTemplateResponse = await templateService.GetAsync(new() {Id = template.Data.Id});
        // }
        // searchCredentialTemplate() {
        var searchTemplateResponse = await templateService.SearchAsync(new() {Query = "SELECT * FROM c"});
        // }
        // deleteCredentialTemplate() {
        var deleteTemplateResponse = await templateService.DeleteAsync(new() {Id = template.Data.Id});
        // }
    }

    [Fact(DisplayName = "Decode base64 url encoded string")]
    public void DecodeBase64UrlString() {
        const string encoded =
            "CiVodHRwczovL3RyaW5zaWMuaWQvc2VjdXJpdHkvdjEvb2Jlcm9uEnIKKnVybjp0cmluc2ljOndhbGxldHM6Vzl1dG9pVmhDZHp2RXJZRGVyOGlrRxIkODBkMTVlYTYtMTIxOS00MGZmLWE4NTQtZGI1NmZhOTlmNjMwIh51cm46dHJpbnNpYzplY29zeXN0ZW1zOmRlZmF1bHQaMJRXhevRbornRpA-HJ86WaTLGmQlOuoXSnDT_W2O3u3bV5rS5nKpgrfGKFEbRtIgjyIA";

        var actual = Base64Url.Decode(encoded);

        actual.Should().NotBeEmpty();
    }
}
import asyncio
import uuid

from trinsic.account_service import AccountService
from trinsic.proto.services.trustregistry.v1 import (
    RegistrationStatus,
    AddFrameworkRequest,
    UnregisterMemberRequest,
    GetMembershipStatusRequest,
    RegisterMemberRequest,
)
from trinsic.trinsic_util import trinsic_config
from trinsic.trustregistry_service import TrustRegistryService


async def trustregistry_demo():
    # setup
    account_service = AccountService(server_config=trinsic_config())
    account = await account_service.sign_in()
    service = TrustRegistryService(server_config=trinsic_config(account))

    # data
    https_schema_org = "https://schema.org/Card"
    https_example_com = f"https://example.com/{uuid.uuid4()}"
    did_example_test = "did:example:test"
    framework_name = f"Example Framework: {uuid.uuid4()}"

    # registerGovernanceFramework() {
    register_framework_response = await service.register_governance_framework(
        request=AddFrameworkRequest(
            governance_framework_uri=https_example_com,
            description="Demo framework",
            name=framework_name,
        )
    )
    # }

    # registerIssuerSample() {
    await service.register_member(
        request=RegisterMemberRequest(
            did_uri=did_example_test,
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
        )
    )
    # }

    # checkIssuerStatus() {
    check_response = await service.get_membership_status(
        request=GetMembershipStatusRequest(
            did_uri=did_example_test,
            governance_framework_uri=https_example_com,
            schema_uri=https_schema_org,
        )
    )
    # }
    issuer_status = check_response.status
    assert issuer_status == RegistrationStatus.CURRENT

    # searchTrustRegistry() {
    search_result = await service.search_registry()
    # }
    assert search_result is not None
    assert search_result.items_json is not None
    assert len(search_result.items_json) > 0

    # unregisterIssuer() {
    unregister_issuer_response = await service.unregister_member(
        request=UnregisterMemberRequest(
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
            did_uri=did_example_test,
        )
    )
    # }


if __name__ == "__main__":
    asyncio.run(trustregistry_demo())
package services

import (
    "context"
    "fmt"
    "io/ioutil"
    "path/filepath"
    "runtime"
    "testing"

    "github.com/google/uuid"
    "github.com/stretchr/testify/assert"
    sdk "github.com/trinsic-id/sdk/go/proto"
)

// pathData() {
func GetBasePath() string {
    _, fileName, _, _ := runtime.Caller(1)
    path := filepath.Clean(filepath.Join(filepath.Dir(fileName), "..", "..", "devops", "testdata"))
    return path
}
func GetVaccineCertUnsignedPath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-unsigned.jsonld")
}
func GetVaccineCertFramePath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-frame.jsonld")
}

// }

func TestServiceOptions(t *testing.T) {
    assert := assert.New(t)

    opts, err := NewServiceOptions()
    assert.Nil(err)

    prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}}
    err = WithProductionEnv()(prodOpts)
    assert.Nil(err, "production options should return")

    prodOpts.ServiceOptions.DefaultEcosystem = "default"
    assert.Equal(prodOpts, opts, "should default to production env")
    assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url")

    err = WithAuthToken("test token")(opts)
    assert.Nil(err, "should not error on test token")
    assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied")

    err = WithDevEnv()(opts)
    assert.Nil(err, "should not error on dev env")
    assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url")

    err = WithStagingEnv()(opts)
    assert.Nil(err, "should not error on staging env")
    assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url")

    err = WithDefaultEcosystem("test1")(opts)
    assert.Nil(err, "should not error on setting default ecosystem")
    assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated")
}

func TestVaccineCredentialsDemo(t *testing.T) {
    assert2 := assert.New(t)

    // Open in background
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return
    }

    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return
    }

    // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) {
    //  t.Fail()
    // }

    // SETUP ACTORS
    // Create 3 different profiles for each participant in the scenario
    // setupActors() {
    allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(allison) {
        return
    }

    clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(clinic) {
        return
    }

    airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(airline) {
        return
    }
    // }

    // storeAndRecallProfile() {
    // Store profile for later use
    // File.WriteAllBytes("allison.bin", allison.ToByteString().ToByteArray());

    // Create profile from existing data
    // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin"));
    // }

    walletService, err := NewWalletService(opts)
    failError(t, "error creating wallet service", err)

    credentialService, err := NewCredentialService(opts)
    failError(t, "error creating credential service", err)

    // ISSUE CREDENTIAL
    // Sign a credential as the clinic and send it to Allison
    // issueCredential() {
    fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath())
    failError(t, "error reading file", err)

    credentialService.SetToken(clinic)
    // issueCredentialSample() {
    credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)})
    // }
    failError(t, "error issuing credential", err)
    fmt.Printf("Credential:%s\n", credential)
    // }

    // sendCredential() {
    err = credentialService.Send(context.Background(), &sdk.SendRequest{DocumentJson: credential.SignedDocumentJson,
        DeliveryMethod: &sdk.SendRequest_Email{Email: "[email protected]"}})
    // }
    // We ignore errors because we don't expect this email account to exist.
    err = nil

    // STORE CREDENTIAL
    // Alice stores the credential in her cloud wallet.
    // storeCredential() {
    walletService.SetToken(allison)
    failError(t, "error setting profile", err)
    // insertItemWallet() {
    itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson})
    // }
    failError(t, "error inserting item", err)
    fmt.Println("item id", itemID)
    // }

    // searchWalletBasic() {
    items, err := walletService.Search(context.Background(), &sdk.SearchRequest{})
    // }
    // searchWalletSQL() {
    items2, err := walletService.Search(context.Background(), &sdk.SearchRequest{Query: "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"})
    // }
    if items != nil && items2 != nil {
    }

    // SHARE CREDENTIAL
    // Allison shares the credential with the venue.
    // The venue has communicated with Allison the details of the credential
    // that they require expressed as a JSON-LD frame.
    // shareCredential() {
    walletService.SetToken(allison)
    failError(t, "error reading file", err)

    fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath())
    failError(t, "error reading file", err)

    req := &sdk.CreateProofRequest{
        RevealDocumentJson: string(fileContent2),
        Proof:              &sdk.CreateProofRequest_ItemId{ItemId: itemID},
    }

    credentialService.SetToken(allison)
    // createProof() {
    credentialProof, err := credentialService.CreateProof(context.Background(), req)
    // }
    failError(t, "error creating proof", err)
    fmt.Println("Credential proof", credentialProof)
    // }

    // VERIFY CREDENTIAL
    // The airline verifies the credential
    // verifyCredential() {
    walletService.SetToken(airline)
    failError(t, "error setting profile", err)
    // verifyProof() {
    valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson})
    // }
    failError(t, "error verifying proof", err)
    fmt.Println("Validation result", valid)
    if valid != true {
        t.Fail()
    }
    // }
}

func TestTrustRegistryDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, _ := NewTrustRegistryService(opts)

    // register issuer
    didURI := "did:example:test"
    schemaUri := "https://schema.org/Card"
    frameworkURI := fmt.Sprintf("https://example.com/%s", uuid.New())

    // registerGovernanceFramework() {
    newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
        GovernanceFrameworkUri: frameworkURI,
        Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // registerMemberSample() {
    registerMemberResponse, err := service.RegisterMember(context.Background(), &sdk.RegisterMemberRequest{
        FrameworkId: newFramework.Id,
        SchemaUri:   schemaUri,
        Member:      &sdk.RegisterMemberRequest_DidUri{DidUri: didURI},
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // getMembershipStatus() {
    getMembershipStatusResponse, err := service.GetMembershipStatus(context.Background(), &sdk.GetMembershipStatusRequest{
        GovernanceFrameworkUri: frameworkURI,
        Member:                 &sdk.GetMembershipStatusRequest_DidUri{DidUri: didURI},
        SchemaUri:              schemaUri,
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.Equal(sdk.RegistrationStatus_CURRENT, getMembershipStatusResponse.Status, "Member status should be current")

    // searchTrustRegistry() {
    ecosystemList, err := service.SearchRegistry(context.Background(), nil)
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(ecosystemList)
    assert2.NotEmpty(ecosystemList)

    // unregisterIssuer() {
    unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
        SchemaUri:   schemaUri,
        FrameworkId: newFramework.Id,
    })
    // }

    // This is for the variables used for demos above, so they appear "used".
    if unregisterMemberResponse == nil || registerMemberResponse == nil || getMembershipStatusResponse == nil {
        // Do absolutely nothing
    }
}

func createAccountAndSignIn(t *testing.T) (*assert.Assertions, string, error) {
    assert2 := assert.New(t)
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    // Open in background
    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    if !assert2.Nil(err) {
        fmt.Println(err)
        return assert2, "", err
    }
    return assert2, authtoken, nil
}

func createRandomEcosystem() error {
    opts, err := NewServiceOptions(WithTestEnv())
    if err != nil {
        return err
    }

    ps, err := NewProviderService(opts)
    if err != nil {
        return err
    }

    _, err = ps.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{Name: "test-sdk-" + uuid.New().String()})

    return err
}
func TestEcosystemDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, err := NewProviderService(opts)
    if !assert2.Nil(err) {
        return
    }

    // createEcosystem() {
    actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{
        Description: "My ecosystem",
        Uri:         "https://example.com",
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(actualCreate)
    // assert2.NotNil(actualCreate.Id)
    // assert2.True(strings.HasPrefix(actualCreate.Id, "urn:trinsic:ecosystems:"))

    // inviteParticipant() {
    inviteResponse, err := service.InviteParticipant(context.Background(),
        &sdk.InviteRequest{Participant: sdk.ParticipantType_participant_type_individual,
            Details: &sdk.AccountDetails{Email: "[email protected]"}})
    // }
    if inviteResponse == nil {
        inviteResponse = &sdk.InviteResponse{InvitationId: "NA"}
    }
    // invitationStatus() {
    inviteStatus, err := service.InvitationStatus(context.Background(), &sdk.InvitationStatusRequest{InvitationId: inviteResponse.InvitationId})
    // }
    if inviteStatus != nil {
    }

}

// func TestCreateChannelUrlFromConfig(t *testing.T) {
//  assert2 := assert.New(t)
//  if !assert2.Equalf(CreateChannelUrlFromConfig(TrinsicProductionConfig()), CreateChannelUrlFromConfig(nil), "Default is production stack") {
//      return
//  }
// }

func failError(t *testing.T, message string, err error) {
    if err != nil {
        t.Helper()
        t.Errorf("%s: %v", message, err)
        t.FailNow()
    }
}
package trinsic;

import org.junit.jupiter.api.Assertions;
import trinsic.okapi.DidException;
import trinsic.services.AccountService;
import trinsic.services.TrustRegistryService;
import trinsic.services.trustregistry.v1.TrustRegistryOuterClass;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

public class TrustRegistryDemo {
    public static void main(String[] args) throws IOException, DidException, ExecutionException, InterruptedException {
        run();
    }

    public static void run() throws IOException, DidException, ExecutionException, InterruptedException {
        var accountService = new AccountService(TrinsicUtilities.getTrinsicServiceOptions());
        var account = accountService.signIn().get();
        var service = new TrustRegistryService(TrinsicUtilities.getTrinsicServiceOptions(account));

        final String didUri = "did:example:test";
        final String frameworkUri = "https://example.com/" + UUID.randomUUID();
        final String typeUri = "https://schema.org/Card";

        // registerGovernanceFramework() {
        var frameworkResponse = service.registerGovernanceFramework(TrustRegistryOuterClass.AddFrameworkRequest.newBuilder().setGovernanceFrameworkUri(frameworkUri).setName("Example Framework" + UUID.randomUUID()).build()).get();
        // }

        // registerIssuerSample() {
        service.registerMember(TrustRegistryOuterClass.RegisterMemberRequest.newBuilder().setDidUri(didUri).setFrameworkId(frameworkResponse.getId()).setSchemaUri(typeUri).build());
        // }
        // checkIssuerStatus() {
        var issuerStatus = service.checkIssuerStatus(TrustRegistryOuterClass.GetMembershipStatusRequest.newBuilder().setDidUri(didUri).setGovernanceFrameworkUri(frameworkUri).setSchemaUri(typeUri).build()).get();
        // }
        Assertions.assertEquals(TrustRegistryOuterClass.RegistrationStatus.CURRENT, issuerStatus.getStatus());

        // searchTrustRegistry() {
        var searchResult = service.searchRegistry().get();
        // }
        Assertions.assertNotNull(searchResult);
        Assertions.assertNotNull(searchResult.getItemsJson());
        Assertions.assertTrue(searchResult.getItemsJson().length() > 0);

        // unregisterIssuer() {
        service.unregisterIssuer(TrustRegistryOuterClass.UnregisterMemberRequest.newBuilder().setFrameworkId(frameworkResponse.getId()).setDidUri(didUri).setSchemaUri(typeUri).build());
        // }
    }
}

Check Issuer Status

Check the status of an issuer for a credential type within a given governance framework. Returns all historical data for the given input parameter.

trinsic trust-registry check-issuer \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
var issuerStatus = await service.GetMembershipStatusAsync(new() {
    DidUri = didUri,
    GovernanceFrameworkUri = frameworkUri,
    SchemaUri = schemaUri
});
check_response = await service.get_membership_status(
    request=GetMembershipStatusRequest(
        did_uri=did_example_test,
        governance_framework_uri=https_example_com,
        schema_uri=https_schema_org,
    )
)
package services

import (
    "context"
    "fmt"
    "io/ioutil"
    "path/filepath"
    "runtime"
    "testing"

    "github.com/google/uuid"
    "github.com/stretchr/testify/assert"
    sdk "github.com/trinsic-id/sdk/go/proto"
)

// pathData() {
func GetBasePath() string {
    _, fileName, _, _ := runtime.Caller(1)
    path := filepath.Clean(filepath.Join(filepath.Dir(fileName), "..", "..", "devops", "testdata"))
    return path
}
func GetVaccineCertUnsignedPath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-unsigned.jsonld")
}
func GetVaccineCertFramePath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-frame.jsonld")
}

// }

func TestServiceOptions(t *testing.T) {
    assert := assert.New(t)

    opts, err := NewServiceOptions()
    assert.Nil(err)

    prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}}
    err = WithProductionEnv()(prodOpts)
    assert.Nil(err, "production options should return")

    prodOpts.ServiceOptions.DefaultEcosystem = "default"
    assert.Equal(prodOpts, opts, "should default to production env")
    assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url")

    err = WithAuthToken("test token")(opts)
    assert.Nil(err, "should not error on test token")
    assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied")

    err = WithDevEnv()(opts)
    assert.Nil(err, "should not error on dev env")
    assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url")

    err = WithStagingEnv()(opts)
    assert.Nil(err, "should not error on staging env")
    assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url")

    err = WithDefaultEcosystem("test1")(opts)
    assert.Nil(err, "should not error on setting default ecosystem")
    assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated")
}

func TestVaccineCredentialsDemo(t *testing.T) {
    assert2 := assert.New(t)

    // Open in background
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return
    }

    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return
    }

    // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) {
    //  t.Fail()
    // }

    // SETUP ACTORS
    // Create 3 different profiles for each participant in the scenario
    // setupActors() {
    allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(allison) {
        return
    }

    clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(clinic) {
        return
    }

    airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(airline) {
        return
    }
    // }

    // storeAndRecallProfile() {
    // Store profile for later use
    // File.WriteAllBytes("allison.bin", allison.ToByteString().ToByteArray());

    // Create profile from existing data
    // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin"));
    // }

    walletService, err := NewWalletService(opts)
    failError(t, "error creating wallet service", err)

    credentialService, err := NewCredentialService(opts)
    failError(t, "error creating credential service", err)

    // ISSUE CREDENTIAL
    // Sign a credential as the clinic and send it to Allison
    // issueCredential() {
    fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath())
    failError(t, "error reading file", err)

    credentialService.SetToken(clinic)
    // issueCredentialSample() {
    credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)})
    // }
    failError(t, "error issuing credential", err)
    fmt.Printf("Credential:%s\n", credential)
    // }

    // sendCredential() {
    err = credentialService.Send(context.Background(), &sdk.SendRequest{DocumentJson: credential.SignedDocumentJson,
        DeliveryMethod: &sdk.SendRequest_Email{Email: "[email protected]"}})
    // }
    // We ignore errors because we don't expect this email account to exist.
    err = nil

    // STORE CREDENTIAL
    // Alice stores the credential in her cloud wallet.
    // storeCredential() {
    walletService.SetToken(allison)
    failError(t, "error setting profile", err)
    // insertItemWallet() {
    itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson})
    // }
    failError(t, "error inserting item", err)
    fmt.Println("item id", itemID)
    // }

    // searchWalletBasic() {
    items, err := walletService.Search(context.Background(), &sdk.SearchRequest{})
    // }
    // searchWalletSQL() {
    items2, err := walletService.Search(context.Background(), &sdk.SearchRequest{Query: "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"})
    // }
    if items != nil && items2 != nil {
    }

    // SHARE CREDENTIAL
    // Allison shares the credential with the venue.
    // The venue has communicated with Allison the details of the credential
    // that they require expressed as a JSON-LD frame.
    // shareCredential() {
    walletService.SetToken(allison)
    failError(t, "error reading file", err)

    fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath())
    failError(t, "error reading file", err)

    req := &sdk.CreateProofRequest{
        RevealDocumentJson: string(fileContent2),
        Proof:              &sdk.CreateProofRequest_ItemId{ItemId: itemID},
    }

    credentialService.SetToken(allison)
    // createProof() {
    credentialProof, err := credentialService.CreateProof(context.Background(), req)
    // }
    failError(t, "error creating proof", err)
    fmt.Println("Credential proof", credentialProof)
    // }

    // VERIFY CREDENTIAL
    // The airline verifies the credential
    // verifyCredential() {
    walletService.SetToken(airline)
    failError(t, "error setting profile", err)
    // verifyProof() {
    valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson})
    // }
    failError(t, "error verifying proof", err)
    fmt.Println("Validation result", valid)
    if valid != true {
        t.Fail()
    }
    // }
}

func TestTrustRegistryDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, _ := NewTrustRegistryService(opts)

    // register issuer
    didURI := "did:example:test"
    schemaUri := "https://schema.org/Card"
    frameworkURI := fmt.Sprintf("https://example.com/%s", uuid.New())

    // registerGovernanceFramework() {
    newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
        GovernanceFrameworkUri: frameworkURI,
        Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // registerMemberSample() {
    registerMemberResponse, err := service.RegisterMember(context.Background(), &sdk.RegisterMemberRequest{
        FrameworkId: newFramework.Id,
        SchemaUri:   schemaUri,
        Member:      &sdk.RegisterMemberRequest_DidUri{DidUri: didURI},
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // getMembershipStatus() {
    getMembershipStatusResponse, err := service.GetMembershipStatus(context.Background(), &sdk.GetMembershipStatusRequest{
        GovernanceFrameworkUri: frameworkURI,
        Member:                 &sdk.GetMembershipStatusRequest_DidUri{DidUri: didURI},
        SchemaUri:              schemaUri,
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.Equal(sdk.RegistrationStatus_CURRENT, getMembershipStatusResponse.Status, "Member status should be current")

    // searchTrustRegistry() {
    ecosystemList, err := service.SearchRegistry(context.Background(), nil)
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(ecosystemList)
    assert2.NotEmpty(ecosystemList)

    // unregisterIssuer() {
    unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
        SchemaUri:   schemaUri,
        FrameworkId: newFramework.Id,
    })
    // }

    // This is for the variables used for demos above, so they appear "used".
    if unregisterMemberResponse == nil || registerMemberResponse == nil || getMembershipStatusResponse == nil {
        // Do absolutely nothing
    }
}

func createAccountAndSignIn(t *testing.T) (*assert.Assertions, string, error) {
    assert2 := assert.New(t)
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    // Open in background
    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    if !assert2.Nil(err) {
        fmt.Println(err)
        return assert2, "", err
    }
    return assert2, authtoken, nil
}

func createRandomEcosystem() error {
    opts, err := NewServiceOptions(WithTestEnv())
    if err != nil {
        return err
    }

    ps, err := NewProviderService(opts)
    if err != nil {
        return err
    }

    _, err = ps.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{Name: "test-sdk-" + uuid.New().String()})

    return err
}
func TestEcosystemDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, err := NewProviderService(opts)
    if !assert2.Nil(err) {
        return
    }

    // createEcosystem() {
    actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{
        Description: "My ecosystem",
        Uri:         "https://example.com",
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(actualCreate)
    // assert2.NotNil(actualCreate.Id)
    // assert2.True(strings.HasPrefix(actualCreate.Id, "urn:trinsic:ecosystems:"))

    // inviteParticipant() {
    inviteResponse, err := service.InviteParticipant(context.Background(),
        &sdk.InviteRequest{Participant: sdk.ParticipantType_participant_type_individual,
            Details: &sdk.AccountDetails{Email: "[email protected]"}})
    // }
    if inviteResponse == nil {
        inviteResponse = &sdk.InviteResponse{InvitationId: "NA"}
    }
    // invitationStatus() {
    inviteStatus, err := service.InvitationStatus(context.Background(), &sdk.InvitationStatusRequest{InvitationId: inviteResponse.InvitationId})
    // }
    if inviteStatus != nil {
    }

}

// func TestCreateChannelUrlFromConfig(t *testing.T) {
//  assert2 := assert.New(t)
//  if !assert2.Equalf(CreateChannelUrlFromConfig(TrinsicProductionConfig()), CreateChannelUrlFromConfig(nil), "Default is production stack") {
//      return
//  }
// }

func failError(t *testing.T, message string, err error) {
    if err != nil {
        t.Helper()
        t.Errorf("%s: %v", message, err)
        t.FailNow()
    }
}
var issuerStatus = service.checkIssuerStatus(TrustRegistryOuterClass.GetMembershipStatusRequest.newBuilder().setDidUri(didUri).setGovernanceFrameworkUri(frameworkUri).setSchemaUri(typeUri).build()).get();

Check Verifier Status

Check the status of an issuer for a credential type within a given governance framework. Returns all historical data for the given input parameter.

trinsic trust-registry check-issuer \
    --egf http://hl7.org/fhir \
    --credential-type https://w3id.org/vaccination#VaccinationCertificate \
    --did did:example:fabre
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Trinsic;
using Trinsic.Sdk.Options.V1;
using Trinsic.Services.Common.V1;
using Trinsic.Services.Provider.V1;
using Trinsic.Services.TrustRegistry.V1;
using Trinsic.Services.VerifiableCredentials.Templates.V1;
using Xunit;
using Xunit.Abstractions;
using JsonSerializer = System.Text.Json.JsonSerializer;

#pragma warning disable CS0618

namespace Tests;

[SuppressMessage("ReSharper", "MethodHasAsyncOverload")]
public class Tests
{
#if DEBUG
    private const string DefaultEndpoint = "localhost";
    private const int DefaultPort = 5000;
    private const bool DefaultUseTls = false;
#else
    private const string DefaultEndpoint = "staging-internal.trinsic.cloud";
    private const int DefaultPort = 443;
    private const bool DefaultUseTls = true;
#endif

    private readonly ITestOutputHelper _testOutputHelper;
    private readonly ServiceOptions _options;

    public Tests(ITestOutputHelper testOutputHelper) {
        _testOutputHelper = testOutputHelper;

        _options = new() {
            ServerEndpoint = Environment.GetEnvironmentVariable("TEST_SERVER_ENDPOINT") ?? DefaultEndpoint,
            ServerPort = int.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_PORT"), out var port) ? port : DefaultPort,
            ServerUseTls = bool.TryParse(Environment.GetEnvironmentVariable("TEST_SERVER_USE_TLS"), out var tls) ? tls : DefaultUseTls
        };

        _testOutputHelper.WriteLine($"Testing endpoint: {_options.FormatUrl()}");
    }

    private const string VaccinationCertificateUnsigned = "TestData/vaccination-certificate-unsigned.jsonld";
    private const string VaccinationCertificateFrame = "TestData/vaccination-certificate-frame.jsonld";

    [Fact(DisplayName = "Demo: wallet and credential sample")]
    public async Task TestWalletService() {
        // createAccountService() {
        var providerService = new ProviderService(_options.Clone());
        var accountService = new AccountService(_options.Clone());
        var (ecosystem, _) = providerService.CreateEcosystem(new());
        var ecosystemId = ecosystem.Id;
        // }

        // SETUP ACTORS
        // Create 3 different profiles for each participant in the scenario
        // setupActors() {
        var allison = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var clinic = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        var airline = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
        // }

        accountService.Options.AuthToken = clinic;
        var info = await accountService.GetInfoAsync();
        info.Should().NotBeNull();

        // createService() {
        var walletService = new WalletService(_options.CloneWithAuthToken(allison));
        var credentialsService = new CredentialsService(_options.CloneWithAuthToken(clinic));
        // }

        // ISSUE CREDENTIAL
        // Sign a credential as the clinic and send it to Allison
        // issueCredential() {
        // Set active profile to 'clinic' so we can issue credential signed
        // with the clinic's signing keys
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = clinic;

        // Read the JSON credential data
        var credentialJson = await File.ReadAllTextAsync(VaccinationCertificateUnsigned);
        // Sign the credential using BBS+ signature scheme
        // issueCredentialSample() {
        var credential = await credentialsService.IssueCredentialAsync(new() {DocumentJson = credentialJson});
        _testOutputHelper.WriteLine($"Credential:\n{credential.SignedDocumentJson}");
        // }
        // }

        // storeAndRecallProfile {
        // Serialize auth token by exporting it to file
        File.WriteAllText("allison.txt", allison);
        // Create auth token from existing data
        allison = File.ReadAllText("allison.txt");
        // }

        try {
            // sendCredential() {
            await credentialsService.SendAsync(new() {Email = "[email protected]"});
            // }
        } catch { } // We expect this to fail

        // STORE CREDENTIAL
        // Allison stores the credential in her cloud wallet.

        // storeCredential() {
        // Set active profile to 'allison' so we can manage her cloud wallet
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credential.SignedDocumentJson});
        var itemId = insertItemResponse.ItemId;
        // }
        // searchWalletBasic() {
        var walletItems = await walletService.SearchAsync(new());
        // }
        _testOutputHelper.WriteLine($"Last wallet item:\n{walletItems.Items.Last()}");

        // searchWalletSQL() { 
        var walletItems2 = await walletService.SearchAsync(new() {Query = "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"});
        // }

        // SHARE CREDENTIAL
        // Allison shares the credential with the venue.
        // The venue has communicated with Allison the details of the credential
        // that they require expressed as a JSON-LD frame.
        // shareCredential() {
        // We'll read the request frame from a file and communicate this with Allison
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = allison;

        var proofRequestJson = await File.ReadAllTextAsync(VaccinationCertificateFrame);

        // Build a proof for the given request and the `itemId` we previously received
        // which points to the stored credential
        var credentialProof = await credentialsService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = proofRequestJson
        });
        _testOutputHelper.WriteLine("Proof:");
        _testOutputHelper.WriteLine(credentialProof.ProofDocumentJson);
        // }


        // VERIFY CREDENTIAL
        // verifyCredential() {
        // The airline verifies the credential
        walletService.Options.AuthToken = credentialsService.Options.AuthToken = airline;

        // Check for valid signature
        var valid = await credentialsService.VerifyProofAsync(new() {
            ProofDocumentJson = credentialProof.ProofDocumentJson
        });
        _testOutputHelper.WriteLine($"Verification result: {valid.IsValid}");
        Assert.True(valid.IsValid);
        // }
    }

    [Fact(DisplayName = "Demo: trust registries")]
    public async Task TestTrustRegistry() {
        var governanceUri = $"https://example.com/{Guid.NewGuid():N}";

        // setup
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var service = new TrustRegistryService(_options.CloneWithAuthToken(authToken));

        // registerGovernanceFramework() {
        var schemaUri = "https://schema.org/Card";
        var frameworkUri = "https://example.com";
        var registerFrameworkResponse = await service.AddFrameworkAsync(new() {
            Name = $"Demo framework-{Guid.NewGuid()}",
            GovernanceFrameworkUri = frameworkUri,
            Description = schemaUri
        });
        // }


        // registerIssuerSample() {
        var didUri = "did:example:test";
        var registerMemberResponse = await service.RegisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }

        // checkIssuerStatus() {
        var issuerStatus = await service.GetMembershipStatusAsync(new() {
            DidUri = didUri,
            GovernanceFrameworkUri = frameworkUri,
            SchemaUri = schemaUri
        });
        // }
        issuerStatus.Should().NotBeNull();
        issuerStatus.Status.Should().Be(RegistrationStatus.Current);

        // searchTrustRegistry() {
        var searchResult = await service.SearchRegistryAsync(new());
        // }

        searchResult.Should().NotBeNull();
        searchResult.ItemsJson.Should().NotBeNull().And.NotBeEmpty();

        // unregisterIssuer() {
        await service.UnregisterMemberAsync(new() {
            DidUri = didUri,
            FrameworkId = registerFrameworkResponse.Id,
            SchemaUri = schemaUri
        });
        // }
    }

    [Fact(DisplayName = "Demo: ecosystem creation and listing")]
    public async Task EcosystemTests() {
        // setup
        var accountService = new AccountService(_options);
        var account = await accountService.SignInAsync(new());
        var service = new ProviderService(_options.CloneWithAuthToken(account));

        // test create ecosystem
        // createEcosystem() {
        var (actualCreate, _) = await service.CreateEcosystemAsync(new() {
            Description = "My ecosystem",
            Uri = "https://example.com"
        });
        // }

        actualCreate.Should().NotBeNull();
        actualCreate.Id.Should().NotBeNull();
        actualCreate.Id.Should().StartWith("urn:trinsic:ecosystems:");

        try {
            // inviteParticipant() {
            var inviteResponse = await service.InviteParticipantAsync(new() {
                Participant = ParticipantType.Individual,
                Description = "Doc sample",
                Details = new() {
                    Email = "[email protected]"
                }
            });
            // }
        } catch(Exception) { } // This is expected as a doc sample

        var invitationId = "N/A";
        try {
            // invitationStatus() {
            var inviteStatus = await service.InvitationStatusAsync(new() {InvitationId = invitationId});
            // }
        } catch(Exception) { } // This is expected as a doc sample
    }

    [Fact]
    public async Task TestProtectUnprotectProfile() {
        // testSignInAndGetInfo() {
        // accountServiceConstructor() {
        var myAccountService = new AccountService(_options);
        // }
        // accountServiceSignIn() {
        var myProfile = await myAccountService.SignInAsync(new());
        // }
        myAccountService.Options.AuthToken = myProfile;
        // accountServiceGetInfo() {
        var output = await myAccountService.GetInfoAsync();
        // }
        Assert.NotNull(output);
        // }

        // protectUnprotectProfile() {
        var securityCode = "1234";
        var myProtectedProfile = AccountService.Protect(myProfile, securityCode);
        var myUnprotectedProfile = AccountService.Unprotect(myProtectedProfile, securityCode);
        // }
        myAccountService.Options.AuthToken = myProtectedProfile;
        await Assert.ThrowsAsync<Exception>(myAccountService.GetInfoAsync);
        myAccountService.Options.AuthToken = myUnprotectedProfile;
        Assert.NotNull(await myAccountService.GetInfoAsync());
        Assert.NotNull(myAccountService.GetInfo());
    }

    [Fact]
    public async Task TestInvitationIdSet() {
        var providerService = new ProviderService(_options.Clone());
        _ = await providerService.CreateEcosystemAsync(new());

        var invitationResponse = await providerService.InviteParticipantAsync(new());

        invitationResponse.Should().NotBeNull();
        invitationResponse.InvitationCode.Should().NotBeEmpty();

        await Assert.ThrowsAsync<Exception>(async () => await providerService.InvitationStatusAsync(new()));
    }

    [Fact(Skip = "Ecosystem support not complete yet")]
    public async Task TestInviteParticipant() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myProviderService = new ProviderService(_options.CloneWithAuthToken(myProfile));
        var invite = new InviteRequest {Description = "Test invitation"};
        var response = await myProviderService.InviteParticipantAsync(invite);
        Assert.NotNull(response);

        var statusResponse = await myProviderService.InvitationStatusAsync(new() {InvitationId = response.InvitationId});
        Assert.NotNull(statusResponse);
    }

    [Fact]
    public async Task TestGovernanceFrameworkUriParse() {
        var myAccountService = new AccountService(_options);
        var myProfile = await myAccountService.SignInAsync(new());
        var myTrustRegistryService = new TrustRegistryService(_options.CloneWithAuthToken(myProfile));
        await Assert.ThrowsAsync<Exception>(async () => await myTrustRegistryService.AddFrameworkAsync(new() {
            Description = "invalid uri",
            GovernanceFrameworkUri = ""
        }));
    }

    [Fact(DisplayName = "Demo: template management and credential issuance from template")]
    public async Task DemoTemplatesWithIssuance() {
        var providerService = new ProviderService(_options.Clone());
        var (_, authToken) = await providerService.CreateEcosystemAsync(new());
        var options = _options.CloneWithAuthToken(authToken);

        var templateService = new TemplateService(options);
        var credentialService = new CredentialsService(options);
        var walletService = new WalletService(options);

        // create example template
        // createTemplate() {
        CreateCredentialTemplateRequest templateRequest = new() {
            Name = "An Example Credential",
            AllowAdditionalFields = false
        };
        templateRequest.Fields.Add("firstName", new() {Description = "Given name"});
        templateRequest.Fields.Add("lastName", new());
        templateRequest.Fields.Add("age", new() {Optional = true}); // TODO - use FieldType.NUMBER once schema validation is fixed.

        var template = await templateService.CreateAsync(templateRequest);
        // }

        template.Should().NotBeNull();
        template.Data.Should().NotBeNull();
        template.Data.Id.Should().NotBeNull();
        template.Data.SchemaUri.Should().NotBeNull();

        // issue credential from this template
        var values = JsonSerializer.Serialize(new {
            firstName = "Jane",
            lastName = "Doe",
            age = "42"
        });

        // issueFromTemplate() {
        var credentialJson = await credentialService.IssueFromTemplateAsync(new() {
            TemplateId = template.Data.Id,
            ValuesJson = values
        });
        // }

        credentialJson.Should().NotBeNull();

        var jsonDocument = JsonDocument.Parse(credentialJson.DocumentJson).RootElement.EnumerateObject();

        jsonDocument.Should().Contain(x => x.Name == "id");
        jsonDocument.Should().Contain(x => x.Name == "credentialSubject");

        // insertItemWallet() {
        var insertItemResponse = await walletService.InsertItemAsync(new() {ItemJson = credentialJson.DocumentJson});
        // }
        var itemId = insertItemResponse.ItemId;

        var frame = new JObject {
            {"@context", "https://www.w3.org/2018/credentials/v1"},
            {"type", new JArray("VerifiableCredential")}
        };

        // Create proof from input document
        // createProof() {
        var proof = await credentialService.CreateProofAsync(new() {
            DocumentJson = credentialJson.DocumentJson,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });
        // }
        // verifyProof() {
        var valid = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof.ProofDocumentJson});
        // }
        valid.IsValid.Should().BeTrue();

        // Create proof from item id
        var proof2 = await credentialService.CreateProofAsync(new() {
            ItemId = itemId,
            RevealDocumentJson = frame.ToString(Formatting.None)
        });

        var valid2 = await credentialService.VerifyProofAsync(new() {ProofDocumentJson = proof2.ProofDocumentJson});

        valid2.IsValid.Should().BeTrue();

        try {
            // checkCredentialStatus() {
            var checkResponse = await credentialService.CheckStatusAsync(new() {CredentialStatusId = ""});
            // }
        } catch { } // We expect this to fail

        try {
            // updateCredentialStatus() {
            await credentialService.UpdateStatusAsync(new() {CredentialStatusId = "", Revoked = true});
            // }
        } catch { } // We expect this to fail

        // getCredentialTemplate() {
        var getTemplateResponse = await templateService.GetAsync(new() {Id = template.Data.Id});
        // }
        // searchCredentialTemplate() {
        var searchTemplateResponse = await templateService.SearchAsync(new() {Query = "SELECT * FROM c"});
        // }
        // deleteCredentialTemplate() {
        var deleteTemplateResponse = await templateService.DeleteAsync(new() {Id = template.Data.Id});
        // }
    }

    [Fact(DisplayName = "Decode base64 url encoded string")]
    public void DecodeBase64UrlString() {
        const string encoded =
            "CiVodHRwczovL3RyaW5zaWMuaWQvc2VjdXJpdHkvdjEvb2Jlcm9uEnIKKnVybjp0cmluc2ljOndhbGxldHM6Vzl1dG9pVmhDZHp2RXJZRGVyOGlrRxIkODBkMTVlYTYtMTIxOS00MGZmLWE4NTQtZGI1NmZhOTlmNjMwIh51cm46dHJpbnNpYzplY29zeXN0ZW1zOmRlZmF1bHQaMJRXhevRbornRpA-HJ86WaTLGmQlOuoXSnDT_W2O3u3bV5rS5nKpgrfGKFEbRtIgjyIA";

        var actual = Base64Url.Decode(encoded);

        actual.Should().NotBeEmpty();
    }
}
import asyncio
import uuid

from trinsic.account_service import AccountService
from trinsic.proto.services.trustregistry.v1 import (
    RegistrationStatus,
    AddFrameworkRequest,
    UnregisterMemberRequest,
    GetMembershipStatusRequest,
    RegisterMemberRequest,
)
from trinsic.trinsic_util import trinsic_config
from trinsic.trustregistry_service import TrustRegistryService


async def trustregistry_demo():
    # setup
    account_service = AccountService(server_config=trinsic_config())
    account = await account_service.sign_in()
    service = TrustRegistryService(server_config=trinsic_config(account))

    # data
    https_schema_org = "https://schema.org/Card"
    https_example_com = f"https://example.com/{uuid.uuid4()}"
    did_example_test = "did:example:test"
    framework_name = f"Example Framework: {uuid.uuid4()}"

    # registerGovernanceFramework() {
    register_framework_response = await service.register_governance_framework(
        request=AddFrameworkRequest(
            governance_framework_uri=https_example_com,
            description="Demo framework",
            name=framework_name,
        )
    )
    # }

    # registerIssuerSample() {
    await service.register_member(
        request=RegisterMemberRequest(
            did_uri=did_example_test,
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
        )
    )
    # }

    # checkIssuerStatus() {
    check_response = await service.get_membership_status(
        request=GetMembershipStatusRequest(
            did_uri=did_example_test,
            governance_framework_uri=https_example_com,
            schema_uri=https_schema_org,
        )
    )
    # }
    issuer_status = check_response.status
    assert issuer_status == RegistrationStatus.CURRENT

    # searchTrustRegistry() {
    search_result = await service.search_registry()
    # }
    assert search_result is not None
    assert search_result.items_json is not None
    assert len(search_result.items_json) > 0

    # unregisterIssuer() {
    unregister_issuer_response = await service.unregister_member(
        request=UnregisterMemberRequest(
            framework_id=register_framework_response.id,
            schema_uri=https_schema_org,
            did_uri=did_example_test,
        )
    )
    # }


if __name__ == "__main__":
    asyncio.run(trustregistry_demo())
package services

import (
    "context"
    "fmt"
    "io/ioutil"
    "path/filepath"
    "runtime"
    "testing"

    "github.com/google/uuid"
    "github.com/stretchr/testify/assert"
    sdk "github.com/trinsic-id/sdk/go/proto"
)

// pathData() {
func GetBasePath() string {
    _, fileName, _, _ := runtime.Caller(1)
    path := filepath.Clean(filepath.Join(filepath.Dir(fileName), "..", "..", "devops", "testdata"))
    return path
}
func GetVaccineCertUnsignedPath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-unsigned.jsonld")
}
func GetVaccineCertFramePath() string {
    return filepath.Join(GetBasePath(), "vaccination-certificate-frame.jsonld")
}

// }

func TestServiceOptions(t *testing.T) {
    assert := assert.New(t)

    opts, err := NewServiceOptions()
    assert.Nil(err)

    prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}}
    err = WithProductionEnv()(prodOpts)
    assert.Nil(err, "production options should return")

    prodOpts.ServiceOptions.DefaultEcosystem = "default"
    assert.Equal(prodOpts, opts, "should default to production env")
    assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url")

    err = WithAuthToken("test token")(opts)
    assert.Nil(err, "should not error on test token")
    assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied")

    err = WithDevEnv()(opts)
    assert.Nil(err, "should not error on dev env")
    assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url")

    err = WithStagingEnv()(opts)
    assert.Nil(err, "should not error on staging env")
    assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url")

    err = WithDefaultEcosystem("test1")(opts)
    assert.Nil(err, "should not error on setting default ecosystem")
    assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated")
}

func TestVaccineCredentialsDemo(t *testing.T) {
    assert2 := assert.New(t)

    // Open in background
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return
    }

    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return
    }

    // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) {
    //  t.Fail()
    // }

    // SETUP ACTORS
    // Create 3 different profiles for each participant in the scenario
    // setupActors() {
    allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(allison) {
        return
    }

    clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(clinic) {
        return
    }

    airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    failError(t, "error creating profile", err)
    if !assert2.NotNil(airline) {
        return
    }
    // }

    // storeAndRecallProfile() {
    // Store profile for later use
    // File.WriteAllBytes("allison.bin", allison.ToByteString().ToByteArray());

    // Create profile from existing data
    // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin"));
    // }

    walletService, err := NewWalletService(opts)
    failError(t, "error creating wallet service", err)

    credentialService, err := NewCredentialService(opts)
    failError(t, "error creating credential service", err)

    // ISSUE CREDENTIAL
    // Sign a credential as the clinic and send it to Allison
    // issueCredential() {
    fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath())
    failError(t, "error reading file", err)

    credentialService.SetToken(clinic)
    // issueCredentialSample() {
    credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)})
    // }
    failError(t, "error issuing credential", err)
    fmt.Printf("Credential:%s\n", credential)
    // }

    // sendCredential() {
    err = credentialService.Send(context.Background(), &sdk.SendRequest{DocumentJson: credential.SignedDocumentJson,
        DeliveryMethod: &sdk.SendRequest_Email{Email: "[email protected]"}})
    // }
    // We ignore errors because we don't expect this email account to exist.
    err = nil

    // STORE CREDENTIAL
    // Alice stores the credential in her cloud wallet.
    // storeCredential() {
    walletService.SetToken(allison)
    failError(t, "error setting profile", err)
    // insertItemWallet() {
    itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson})
    // }
    failError(t, "error inserting item", err)
    fmt.Println("item id", itemID)
    // }

    // searchWalletBasic() {
    items, err := walletService.Search(context.Background(), &sdk.SearchRequest{})
    // }
    // searchWalletSQL() {
    items2, err := walletService.Search(context.Background(), &sdk.SearchRequest{Query: "SELECT c.id, c.type, c.data FROM c WHERE c.type = 'VerifiableCredential'"})
    // }
    if items != nil && items2 != nil {
    }

    // SHARE CREDENTIAL
    // Allison shares the credential with the venue.
    // The venue has communicated with Allison the details of the credential
    // that they require expressed as a JSON-LD frame.
    // shareCredential() {
    walletService.SetToken(allison)
    failError(t, "error reading file", err)

    fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath())
    failError(t, "error reading file", err)

    req := &sdk.CreateProofRequest{
        RevealDocumentJson: string(fileContent2),
        Proof:              &sdk.CreateProofRequest_ItemId{ItemId: itemID},
    }

    credentialService.SetToken(allison)
    // createProof() {
    credentialProof, err := credentialService.CreateProof(context.Background(), req)
    // }
    failError(t, "error creating proof", err)
    fmt.Println("Credential proof", credentialProof)
    // }

    // VERIFY CREDENTIAL
    // The airline verifies the credential
    // verifyCredential() {
    walletService.SetToken(airline)
    failError(t, "error setting profile", err)
    // verifyProof() {
    valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson})
    // }
    failError(t, "error verifying proof", err)
    fmt.Println("Validation result", valid)
    if valid != true {
        t.Fail()
    }
    // }
}

func TestTrustRegistryDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, _ := NewTrustRegistryService(opts)

    // register issuer
    didURI := "did:example:test"
    schemaUri := "https://schema.org/Card"
    frameworkURI := fmt.Sprintf("https://example.com/%s", uuid.New())

    // registerGovernanceFramework() {
    newFramework, err := service.RegisterGovernanceFramework(context.Background(), &sdk.AddFrameworkRequest{
        GovernanceFrameworkUri: frameworkURI,
        Name:                   fmt.Sprintf("Example Framework - %s", uuid.New()),
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // registerMemberSample() {
    registerMemberResponse, err := service.RegisterMember(context.Background(), &sdk.RegisterMemberRequest{
        FrameworkId: newFramework.Id,
        SchemaUri:   schemaUri,
        Member:      &sdk.RegisterMemberRequest_DidUri{DidUri: didURI},
    })
    // }
    if !assert2.Nil(err) {
        return
    }

    // getMembershipStatus() {
    getMembershipStatusResponse, err := service.GetMembershipStatus(context.Background(), &sdk.GetMembershipStatusRequest{
        GovernanceFrameworkUri: frameworkURI,
        Member:                 &sdk.GetMembershipStatusRequest_DidUri{DidUri: didURI},
        SchemaUri:              schemaUri,
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.Equal(sdk.RegistrationStatus_CURRENT, getMembershipStatusResponse.Status, "Member status should be current")

    // searchTrustRegistry() {
    ecosystemList, err := service.SearchRegistry(context.Background(), nil)
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(ecosystemList)
    assert2.NotEmpty(ecosystemList)

    // unregisterIssuer() {
    unregisterMemberResponse, err := service.UnregisterMember(context.Background(), &sdk.UnregisterMemberRequest{
        SchemaUri:   schemaUri,
        FrameworkId: newFramework.Id,
    })
    // }

    // This is for the variables used for demos above, so they appear "used".
    if unregisterMemberResponse == nil || registerMemberResponse == nil || getMembershipStatusResponse == nil {
        // Do absolutely nothing
    }
}

func createAccountAndSignIn(t *testing.T) (*assert.Assertions, string, error) {
    assert2 := assert.New(t)
    opts, err := NewServiceOptions(WithTestEnv())
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    // Open in background
    accountService, err := NewAccountService(opts)
    if !assert2.Nil(err) {
        return assert2, "", err
    }
    authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{})
    if !assert2.Nil(err) {
        fmt.Println(err)
        return assert2, "", err
    }
    return assert2, authtoken, nil
}

func createRandomEcosystem() error {
    opts, err := NewServiceOptions(WithTestEnv())
    if err != nil {
        return err
    }

    ps, err := NewProviderService(opts)
    if err != nil {
        return err
    }

    _, err = ps.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{Name: "test-sdk-" + uuid.New().String()})

    return err
}
func TestEcosystemDemo(t *testing.T) {
    assert2, authtoken, err := createAccountAndSignIn(t)
    if !assert2.Nil(err) {
        return
    }

    opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken))
    if !assert2.Nil(err) {
        return
    }

    service, err := NewProviderService(opts)
    if !assert2.Nil(err) {
        return
    }

    // createEcosystem() {
    actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{
        Description: "My ecosystem",
        Uri:         "https://example.com",
    })
    // }
    if !assert2.Nil(err) {
        return
    }
    assert2.NotNil(actualCreate)
    // assert2.NotNil(actualCreate.Id)
    // assert2.True(strings.HasPrefix(actualCreate.Id, "urn:trinsic:ecosystems:"))

    // inviteParticipant() {
    inviteResponse, err := service.InviteParticipant(context.Background(),
        &sdk.InviteRequest{Participant: sdk.ParticipantType_participant_type_individual,
            Details: &sdk.AccountDetails{Email: "[email protected]"}})
    // }
    if inviteResponse == nil {
        inviteResponse = &sdk.InviteResponse{InvitationId: "NA"}
    }
    // invitationStatus() {
    inviteStatus, err := service.InvitationStatus(context.Background(), &sdk.InvitationStatusRequest{InvitationId: inviteResponse.InvitationId})
    // }
    if inviteStatus != nil {
    }

}

// func TestCreateChannelUrlFromConfig(t *testing.T) {
//  assert2 := assert.New(t)
//  if !assert2.Equalf(CreateChannelUrlFromConfig(TrinsicProductionConfig()), CreateChannelUrlFromConfig(nil), "Default is production stack") {
//      return
//  }
// }

func failError(t *testing.T, message string, err error) {
    if err != nil {
        t.Helper()
        t.Errorf("%s: %v", message, err)
        t.FailNow()
    }
}
package trinsic;

import org.junit.jupiter.api.Assertions;
import trinsic.okapi.DidException;
import trinsic.services.AccountService;
import trinsic.services.TrustRegistryService;
import trinsic.services.trustregistry.v1.TrustRegistryOuterClass;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

public class TrustRegistryDemo {
    public static void main(String[] args) throws IOException, DidException, ExecutionException, InterruptedException {
        run();
    }

    public static void run() throws IOException, DidException, ExecutionException, InterruptedException {
        var accountService = new AccountService(TrinsicUtilities.getTrinsicServiceOptions());
        var account = accountService.signIn().get();
        var service = new TrustRegistryService(TrinsicUtilities.getTrinsicServiceOptions(account));

        final String didUri = "did:example:test";
        final String frameworkUri = "https://example.com/" + UUID.randomUUID();
        final String typeUri = "https://schema.org/Card";

        // registerGovernanceFramework() {
        var frameworkResponse = service.registerGovernanceFramework(TrustRegistryOuterClass.AddFrameworkRequest.newBuilder().setGovernanceFrameworkUri(frameworkUri).setName("Example Framework" + UUID.randomUUID()).build()).get();
        // }

        // registerIssuerSample() {
        service.registerMember(TrustRegistryOuterClass.RegisterMemberRequest.newBuilder().setDidUri(didUri).setFrameworkId(frameworkResponse.getId()).setSchemaUri(typeUri).build());
        // }
        // checkIssuerStatus() {
        var issuerStatus = service.checkIssuerStatus(TrustRegistryOuterClass.GetMembershipStatusRequest.newBuilder().setDidUri(didUri).setGovernanceFrameworkUri(frameworkUri).setSchemaUri(typeUri).build()).get();
        // }
        Assertions.assertEquals(TrustRegistryOuterClass.RegistrationStatus.CURRENT, issuerStatus.getStatus());

        // searchTrustRegistry() {
        var searchResult = service.searchRegistry().get();
        // }
        Assertions.assertNotNull(searchResult);
        Assertions.assertNotNull(searchResult.getItemsJson());
        Assertions.assertTrue(searchResult.getItemsJson().length() > 0);

        // unregisterIssuer() {
        service.unregisterIssuer(TrustRegistryOuterClass.UnregisterMemberRequest.newBuilder().setFrameworkId(frameworkResponse.getId()).setDidUri(didUri).setSchemaUri(typeUri).build());
        // }
    }
}

Search the registry for authoritative issuer and verifiers using a custom query in a SQL format.

trinsic trust-registry search --query <SQL query>
var searchResult = await service.SearchRegistryAsync(new());
search_result = await service.search_registry()
ecosystemList, err := service.SearchRegistry(context.Background(), nil)
var searchResult = service.searchRegistry().get();

Cache Offline Registry File

trinsic trust-registry download