diff --git a/src/test/java/org/hyperledger/aries/IntegrationTestBase.java b/src/test/java/org/hyperledger/aries/IntegrationTestBase.java index 53210c96..7b638375 100644 --- a/src/test/java/org/hyperledger/aries/IntegrationTestBase.java +++ b/src/test/java/org/hyperledger/aries/IntegrationTestBase.java @@ -22,6 +22,7 @@ public abstract class IntegrationTestBase { private final Logger log = LoggerFactory.getLogger(IntegrationTestBase.class); public static final String ARIES_VERSION = "bcgovimages/aries-cloudagent:py36-1.16-1_0.7.3"; + public static final Integer ARIES_ENDPOINT_PORT = 8030; public static final Integer ARIES_ADMIN_PORT = 8031; protected AriesClient ac; @@ -30,7 +31,7 @@ public abstract class IntegrationTestBase { protected GenericContainer ariesContainer = new GenericContainer<>(ARIES_VERSION) .withExposedPorts(ARIES_ADMIN_PORT) .withCommand("start" - + " -it http 0.0.0.0 8030" + + " -it http 0.0.0.0 " + ARIES_ENDPOINT_PORT + " -ot http --admin 0.0.0.0 " + ARIES_ADMIN_PORT + " --admin-insecure-mode" + " --log-level debug" diff --git a/src/test/java/org/hyperledger/aries/LedgerClient.java b/src/test/java/org/hyperledger/aries/LedgerClient.java new file mode 100644 index 00000000..b98f8c25 --- /dev/null +++ b/src/test/java/org/hyperledger/aries/LedgerClient.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020-2022 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import lombok.Builder; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.apache.commons.lang3.StringUtils; + +import org.hyperledger.aries.util.ledger.LedgerDIDCreate; +import org.hyperledger.aries.util.ledger.LedgerDIDResponse; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.lang.reflect.Type; +import java.time.Duration; +import java.time.Instant; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * ACA-PY client + */ +@Slf4j +@SuppressWarnings("unused") +public class LedgerClient extends BaseClient { + + public static final String LEDGER_GENESIS_TXN_URL = "/genesis"; + public static final String LEDGER_DID_REGISTRATION_URL = "/register"; + public static final String LEDGER_DID_ENDORSER_ROLE = "ENDORSER"; + + private final String url; + + /** + * @param url The ledger URL without a path e.g. protocol://host:[port] + * @param client {@link OkHttpClient} if null a default client is created + */ + @Builder + public LedgerClient(@NonNull String url, + @Nullable OkHttpClient client) { + super(client); + this.url = StringUtils.trim(url); + } + + // ---------------------------------------------------- + // Register a new public DID on the ledger + // ---------------------------------------------------- + + /** + * Create a public DID + * @param didCreate {@link DIDCreate} + * @return {@link DID} + * @throws IOException if the request could not be executed due to cancellation, a connectivity problem or timeout. + */ + public Optional ledgerDidCreate(@NonNull LedgerDIDCreate didCreate) throws IOException { + Request req = buildPost(url + LEDGER_DID_REGISTRATION_URL, didCreate); + return call(req, LedgerDIDResponse.class); + } + + + // ---------------------------------------------------- + // Internal + // ---------------------------------------------------- + + private Request buildPost(String u, Object body) { + return request(u) + .post(jsonBody(gson.toJson(body))) + .build(); + } + + private Request.Builder request(String u) { + Request.Builder b = new Request.Builder() + .url(u); + return b; + } +} diff --git a/src/test/java/org/hyperledger/aries/MultiIntegrationTestBase.java b/src/test/java/org/hyperledger/aries/MultiIntegrationTestBase.java new file mode 100644 index 00000000..e7fa5cef --- /dev/null +++ b/src/test/java/org/hyperledger/aries/MultiIntegrationTestBase.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020-2022 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries; + +import org.junit.jupiter.api.BeforeEach; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +public abstract class MultiIntegrationTestBase { + + private final Logger log = LoggerFactory.getLogger(MultiIntegrationTestBase.class); + + public static final String ARIES_VERSION = IntegrationTestBase.ARIES_VERSION; + public static final Integer ARIES_ENDPOINT_PORT = IntegrationTestBase.ARIES_ENDPOINT_PORT; + public static final Integer ARIES_ADMIN_PORT = IntegrationTestBase.ARIES_ADMIN_PORT; + public static final Integer ARIES_ENDPOINT_PORT_2 = 8040; + public static final Integer ARIES_ADMIN_PORT_2 = 8041; + + protected LedgerClient lc; + protected AriesClient ac; + protected AriesClient ac2; + + Network network = Network.newNetwork(); + + @Container + protected GenericContainer ariesContainer = new GenericContainer<>(ARIES_VERSION) + .withNetwork(network) + .withNetworkAliases("agent_1") + .withExposedPorts(ARIES_ADMIN_PORT) + .withCommand("start" + + " -it http 0.0.0.0 " + ARIES_ENDPOINT_PORT + + " -ot http" + + " --admin 0.0.0.0 " + ARIES_ADMIN_PORT + + " --admin-insecure-mode" + + " --log-level debug" + + " -e http://agent_1:" + ARIES_ENDPOINT_PORT + + " --plugin aries_cloudagent.messaging.jsonld" + + this.extraAgentArgs(1)) + .waitingFor(Wait.defaultWaitStrategy()) + .withLogConsumer(new Slf4jLogConsumer(log)) + ; + + @Container + protected GenericContainer ariesContainer2 = new GenericContainer<>(ARIES_VERSION) + .withExposedPorts(ARIES_ADMIN_PORT_2) + .withNetwork(network) + .withNetworkAliases("agent_2") + .withCommand("start" + + " -it http 0.0.0.0 " + ARIES_ENDPOINT_PORT_2 + + " -ot http" + + " --admin 0.0.0.0 " + ARIES_ADMIN_PORT_2 + + " --admin-insecure-mode" + + " --log-level debug" + + " -e http://agent_2:" + ARIES_ENDPOINT_PORT_2 + + " --plugin aries_cloudagent.messaging.jsonld" + + this.extraAgentArgs(2)) + .waitingFor(Wait.defaultWaitStrategy()) + .withLogConsumer(new Slf4jLogConsumer(log)) + ; + + protected String extraAgentArgs(int agentNum) { + return " --no-ledger"; + } + + @BeforeEach + void setup() { + ac = AriesClient.builder() + .url("http://" + ariesContainer.getHost() + ":" + ariesContainer.getMappedPort(ARIES_ADMIN_PORT)) + .build(); + ac2 = AriesClient.builder() + .url("http://" + ariesContainer2.getHost() + ":" + ariesContainer2.getMappedPort(ARIES_ADMIN_PORT_2)) + .build(); + } +} diff --git a/src/test/java/org/hyperledger/aries/api/connection/EndorserConnectionRecordTest.java b/src/test/java/org/hyperledger/aries/api/connection/EndorserConnectionRecordTest.java new file mode 100644 index 00000000..66177cf9 --- /dev/null +++ b/src/test/java/org/hyperledger/aries/api/connection/EndorserConnectionRecordTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2020-2022 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries.api.connection; + +import lombok.extern.slf4j.Slf4j; +import org.hyperledger.aries.MultiIntegrationTestBase; +import org.hyperledger.aries.api.credential_definition.CredentialDefinition; +import org.hyperledger.aries.api.credential_definition.CredentialDefinition.CredentialDefinitionRequest; +import org.hyperledger.aries.api.credential_definition.CredentialDefinition.CredentialDefinitionsCreated; +import org.hyperledger.aries.api.exception.AriesException; +import org.hyperledger.aries.api.endorser.EndorserInfoFilter; +import org.hyperledger.aries.api.endorser.SetEndorserRoleFilter; +import org.hyperledger.aries.api.endorser.SetEndorserInfoFilter; +import org.hyperledger.aries.api.schema.SchemaSendRequest; +import org.hyperledger.acy_py.generated.model.ConnectionInvitation; +import org.hyperledger.acy_py.generated.model.DID; +import org.hyperledger.acy_py.generated.model.DIDCreate; +import org.hyperledger.acy_py.generated.model.EndorserInfo; +import org.hyperledger.acy_py.generated.model.TransactionJobs; +import org.hyperledger.acy_py.generated.model.TxnOrCredentialDefinitionSendResult; +import org.hyperledger.acy_py.generated.model.TxnOrSchemaSendResult; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import org.hyperledger.aries.LedgerClient; +import org.hyperledger.aries.util.ledger.LedgerDIDCreate; +import org.hyperledger.aries.util.ledger.LedgerDIDResponse; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +@Slf4j +public class EndorserConnectionRecordTest extends MultiIntegrationTestBase { + + public static final String INDY_LEDGER_URL = "https://indy-test.bosch-digital.de"; + public static final String ENDORSER_CONNECTION_ALIAS = "endorser"; + + protected String getLedgerUrl() { + return INDY_LEDGER_URL; + } + + protected String extraAgentArgs(int agentNum) { + switch (agentNum) { + case 1: + // agent 1 is the Author + return " --genesis-url " + INDY_LEDGER_URL + "/genesis" + + " --auto-ping-connection" + + " --wallet-type indy" + + " --wallet-name agent1" + + " --wallet-key agent1key" + + " --auto-provision" + + " --endorser-protocol-role author" + + " --endorser-alias " + ENDORSER_CONNECTION_ALIAS + + " --auto-request-endorsement" + + " --auto-write-transactions"; + case 2: + // agent 2 is the Endorser + return " --genesis-url " + INDY_LEDGER_URL + "/genesis" + + " --auto-ping-connection" + + " --wallet-type indy" + + " --wallet-name agent2" + + " --wallet-key agent2key" + + " --auto-provision" + + " --endorser-protocol-role endorser" + + " --auto-endorse-transactions"; + default: + return super.extraAgentArgs(agentNum); + } + } + + @Test + @Tag("IntegrationTest") + void testCreateConnectionBetweenAuthorAndEndorser() throws Exception { + String alias_1 = "my_agent_1"; + String alias_2 = "my_agent_2"; + + // create a DID for each agent and make public + lc = LedgerClient.builder() + .url(INDY_LEDGER_URL) + .build(); + + DID localDid1 = ac.walletDidCreate(DIDCreate + .builder() + .build()) + .orElseThrow(); + assertNotNull(localDid1.getVerkey()); + Optional agent1Did = lc.ledgerDidCreate( + LedgerDIDCreate + .builder() + .alias(alias_1) + .did(localDid1.getDid()) + .verkey(localDid1.getVerkey()) + .build()); + assertTrue(agent1Did.isPresent()); + assertNotNull(agent1Did.get().getDid()); + Optional localPublicDid1 = ac.walletDidPublic(localDid1.getDid()); + assertTrue(localPublicDid1.isPresent()); + assertNotNull(localPublicDid1.get().getVerkey()); + + DID localDid2 = ac2.walletDidCreate(DIDCreate + .builder() + .build()) + .orElseThrow(); + assertNotNull(localDid2.getVerkey()); + Optional agent2Did = lc.ledgerDidCreate( + LedgerDIDCreate + .builder() + .alias(alias_2) + .role(LedgerClient.LEDGER_DID_ENDORSER_ROLE) + .did(localDid2.getDid()) + .verkey(localDid2.getVerkey()) + .build()); + assertTrue(agent2Did.isPresent()); + assertNotNull(agent2Did.get().getDid()); + Optional localPublicDid2 = ac2.walletDidPublic(localDid2.getDid()); + assertTrue(localPublicDid2.isPresent()); + assertNotNull(localPublicDid2.get().getVerkey()); + + // get (verify) public DID for each agent + final Optional agent1PublicDid = ac.walletDidPublic(); + assertTrue(agent1PublicDid.isPresent()); + assertNotNull(agent1PublicDid.get().getDid()); + final Optional agent2PublicDid = ac2.walletDidPublic(); + assertTrue(agent2PublicDid.isPresent()); + assertNotNull(agent2PublicDid.get().getDid()); + + // establish Endorser/Author connection for endorsements + final Optional inv = ac.connectionsCreateInvitation( + CreateInvitationRequest + .builder() + .recipientKeys(List.of()) + .build(), + CreateInvitationParams + .builder() + .autoAccept(Boolean.TRUE) + .alias(ENDORSER_CONNECTION_ALIAS) + .build()); + assertTrue(inv.isPresent()); + assertNotNull(inv.get().getInvitationUrl()); + + ConnectionInvitation conn_inv = inv.get().getInvitation(); + final Optional conn2 = ac2.connectionsReceiveInvitation( + ReceiveInvitationRequest + .builder() + .id(conn_inv.getAtId()) + .type(conn_inv.getAtType()) + .did(conn_inv.getDid()) + .imageUrl(conn_inv.getImageUrl()) + .label(conn_inv.getLabel()) + .recipientKeys(conn_inv.getRecipientKeys()) + .routingKeys(conn_inv.getRoutingKeys()) + .serviceEndpoint(conn_inv.getServiceEndpoint()) + .build(), + ConnectionReceiveInvitationFilter + .builder() + .alias(alias_2) + .autoAccept(false) + .build()); + assertTrue(conn2.isPresent()); + + final Optional conn2_updated = ac2.connectionsAcceptInvitation( + conn2.get().getConnectionId(), + null); + assertTrue(conn2_updated.isPresent()); + + // pause to allow the agent chatter to complete + Thread.sleep(4000); + + // now fetch connections and confirm everything completed successfully + final Optional> connections = ac.connections( + ConnectionFilter.builder().alias(ENDORSER_CONNECTION_ALIAS).build()); + assertTrue(connections.isPresent()); + assertEquals(1, connections.get().size()); + assertEquals(ENDORSER_CONNECTION_ALIAS, connections.get().get(0).getAlias()); + assertEquals(ConnectionState.ACTIVE, connections.get().get(0).getState()); + ConnectionRecord authorConnection = connections.get().get(0); + + final Optional> connections2 = ac2.connections( + ConnectionFilter.builder().alias(alias_2).build()); + assertTrue(connections2.isPresent()); + assertEquals(1, connections2.get().size()); + assertEquals(alias_2, connections2.get().get(0).getAlias()); + assertEquals(ConnectionState.ACTIVE, connections2.get().get(0).getState()); + ConnectionRecord endorserConnection = connections2.get().get(0); + + // add endorser metadata to connections + Optional endorserJob = ac2.endorseTransactionSetEndorserRole( + endorserConnection.getConnectionId(), + SetEndorserRoleFilter + .builder() + .transactionMyJob(TransactionJobs.TransactionMyJobEnum.TRANSACTION_ENDORSER.getValue()) + .build()); + assertTrue(endorserJob.isPresent()); + Thread.sleep(1000); + Optional authorJob = ac.endorseTransactionSetEndorserRole( + authorConnection.getConnectionId(), + SetEndorserRoleFilter + .builder() + .transactionMyJob(TransactionJobs.TransactionMyJobEnum.TRANSACTION_AUTHOR.getValue()) + .build()); + assertTrue(authorJob.isPresent()); + Thread.sleep(1000); + Optional endorserInfo = ac.endorseTransactionSetEndorserInfo( + authorConnection.getConnectionId(), + SetEndorserInfoFilter + .builder() + .endorserDid(agent1PublicDid.get().getDid()) + .endorserName(ENDORSER_CONNECTION_ALIAS) + .build()); + assertTrue(endorserInfo.isPresent()); + + // confirm author has no schemas or cred defs + Optional> schemasPre = ac.schemasCreated(null); + assertTrue(schemasPre.isPresent()); + assertEquals(0, schemasPre.get().size()); + Optional credDefsPre = ac.credentialDefinitionsCreated(null); + assertTrue(credDefsPre.isPresent()); + assertEquals(0, credDefsPre.get().getCredentialDefinitionIds().size()); + + // author - create schema and credential definition + // (all auto flags are on so the endorsement and ledger write should happen automatically) + Optional schemaResult = ac.schemas( + SchemaSendRequest + .builder() + .schemaName("author_test_schema") + .schemaVersion("1.0.0") + .attributes(List.of("test_attribute")) + .build(), + EndorserInfoFilter + .builder() + .build()); + assertTrue(schemaResult.isPresent()); + assertNotNull(schemaResult.get().getTxn()); + Thread.sleep(4000); // wait for endorsement + + // check that schema is created + Optional> schemasPost = ac.schemasCreated(null); + assertTrue(schemasPost.isPresent()); + assertEquals(1, schemasPost.get().size()); + String schemaId = schemasPost.get().get(0); + + // create cred def + Optional credDefResult = ac.credentialDefinitionsCreate( + CredentialDefinitionRequest + .builder() + .schemaId(schemaId) + .tag("tester") + .supportRevocation(false) + .build(), + EndorserInfoFilter + .builder() + .build()); + assertTrue(credDefResult.isPresent()); + assertNotNull(credDefResult.get().getTxn()); + Thread.sleep(4000); // wait for endorsement + + // check that cred def is created + Optional credDefsPost = ac.credentialDefinitionsCreated(null); + assertTrue(credDefsPost.isPresent()); + assertEquals(1, credDefsPost.get().getCredentialDefinitionIds().size()); + } +} diff --git a/src/test/java/org/hyperledger/aries/api/connection/MultiConnectionRecordTest.java b/src/test/java/org/hyperledger/aries/api/connection/MultiConnectionRecordTest.java new file mode 100644 index 00000000..f5be58ba --- /dev/null +++ b/src/test/java/org/hyperledger/aries/api/connection/MultiConnectionRecordTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020-2022 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries.api.connection; + +import lombok.extern.slf4j.Slf4j; +import org.hyperledger.aries.MultiIntegrationTestBase; +import org.hyperledger.aries.api.exception.AriesException; +import org.hyperledger.acy_py.generated.model.ConnectionInvitation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +@Slf4j +public class MultiConnectionRecordTest extends MultiIntegrationTestBase { + + protected String extraAgentArgs(int agentNum) { + switch (agentNum) { + case 1: + return " --genesis-url https://indy-test.bosch-digital.de/genesis" + + " --auto-ping-connection" + + " --wallet-type indy" + + " --wallet-name agent1" + + " --wallet-key agent1key" + + " --auto-provision"; + case 2: + return " --genesis-url https://indy-test.bosch-digital.de/genesis" + + " --auto-ping-connection" + + " --wallet-type indy" + + " --wallet-name agent2" + + " --wallet-key agent2key" + + " --auto-provision"; + default: + return super.extraAgentArgs(agentNum); + } + } + + @Test + @Tag("IntegrationTest") + void testCreateConnectionBetweenAgents() throws Exception { + String alias_1 = "my_test_1"; + String alias_2 = "my_test_2"; + final Optional inv = ac.connectionsCreateInvitation( + CreateInvitationRequest + .builder() + .recipientKeys(List.of()) + .build(), + CreateInvitationParams + .builder() + .autoAccept(Boolean.TRUE) + .alias(alias_1) + .build()); + assertTrue(inv.isPresent()); + assertNotNull(inv.get().getInvitationUrl()); + + ConnectionInvitation conn_inv = inv.get().getInvitation(); + final Optional conn2 = ac2.connectionsReceiveInvitation( + ReceiveInvitationRequest + .builder() + .id(conn_inv.getAtId()) + .type(conn_inv.getAtType()) + .did(conn_inv.getDid()) + .imageUrl(conn_inv.getImageUrl()) + .label(conn_inv.getLabel()) + .recipientKeys(conn_inv.getRecipientKeys()) + .routingKeys(conn_inv.getRoutingKeys()) + .serviceEndpoint(conn_inv.getServiceEndpoint()) + .build(), + ConnectionReceiveInvitationFilter + .builder() + .alias(alias_2) + .autoAccept(Boolean.FALSE) + .build()); + assertTrue(conn2.isPresent()); + + final Optional conn2_updated = ac2.connectionsAcceptInvitation( + conn2.get().getConnectionId(), + null); + assertTrue(conn2_updated.isPresent()); + + // pause to allow the agent chatter to complete + Thread.sleep(4000); + + // now fetch connections and confirm everything completed successfully + final Optional> connections = ac.connections( + ConnectionFilter.builder().alias(alias_1).build()); + assertTrue(connections.isPresent()); + assertEquals(1, connections.get().size()); + assertEquals(alias_1, connections.get().get(0).getAlias()); + assertEquals(ConnectionState.ACTIVE, connections.get().get(0).getState()); + + final Optional> connections2 = ac2.connections( + ConnectionFilter.builder().alias(alias_2).build()); + assertTrue(connections2.isPresent()); + assertEquals(1, connections2.get().size()); + assertEquals(alias_2, connections2.get().get(0).getAlias()); + assertEquals(ConnectionState.ACTIVE, connections2.get().get(0).getState()); + } +} diff --git a/src/test/java/org/hyperledger/aries/api/did_exchange/MultiDidExchangeTest.java b/src/test/java/org/hyperledger/aries/api/did_exchange/MultiDidExchangeTest.java new file mode 100644 index 00000000..6b778798 --- /dev/null +++ b/src/test/java/org/hyperledger/aries/api/did_exchange/MultiDidExchangeTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020-2021 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries.api.did_exchange; + +import lombok.extern.slf4j.Slf4j; +import org.hyperledger.acy_py.generated.model.DID; +import org.hyperledger.acy_py.generated.model.DIDCreate; +import org.hyperledger.aries.MultiIntegrationTestBase; +import org.hyperledger.aries.api.connection.ConnectionAcceptRequestFilter; +import org.hyperledger.aries.api.connection.ConnectionFilter; +import org.hyperledger.aries.api.connection.ConnectionRecord; +import org.hyperledger.aries.api.connection.ConnectionState; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import org.hyperledger.aries.LedgerClient; +import org.hyperledger.aries.util.ledger.LedgerDIDCreate; +import org.hyperledger.aries.util.ledger.LedgerDIDResponse; + +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +@Slf4j +class MultiDidExchangeTest extends MultiIntegrationTestBase { + + public static final String INDY_LEDGER_URL = "https://indy-test.bosch-digital.de"; + + protected String getLedgerUrl() { + return INDY_LEDGER_URL; + } + + protected String extraAgentArgs(int agentNum) { + switch (agentNum) { + case 1: + return " --genesis-url https://indy-test.bosch-digital.de/genesis" + + " --auto-ping-connection" + + " --public-invites" + + " --wallet-type indy" + + " --wallet-name agent1" + + " --wallet-key agent1key" + + " --auto-provision"; + case 2: + return " --genesis-url https://indy-test.bosch-digital.de/genesis" + + " --auto-ping-connection" + + " --public-invites" + + " --wallet-type indy" + + " --wallet-name agent2" + + " --wallet-key agent2key" + + " --auto-provision"; + default: + return super.extraAgentArgs(agentNum); + } + } + + @Test + void testCreateRequest() throws Exception { + String alias_1 = "my_didex_test_1"; + String alias_2 = "my_didex_test_2"; + + // create a DID for one agent and make it public + lc = LedgerClient.builder() + .url(INDY_LEDGER_URL) + .build(); + + DID localDid1 = ac.walletDidCreate(DIDCreate + .builder() + .build()) + .orElseThrow(); + assertNotNull(localDid1.getVerkey()); + Optional agent1Did = lc.ledgerDidCreate( + LedgerDIDCreate + .builder() + .alias(alias_1) + .did(localDid1.getDid()) + .verkey(localDid1.getVerkey()) + .build()); + assertTrue(agent1Did.isPresent()); + assertNotNull(agent1Did.get().getDid()); + Optional localPublicDid1 = ac.walletDidPublic(localDid1.getDid()); + assertTrue(localPublicDid1.isPresent()); + assertNotNull(localPublicDid1.get().getVerkey()); + + final Optional agent1PublicDid = ac.walletDidPublic(); + assertTrue(agent1PublicDid.isPresent()); + assertNotNull(agent1PublicDid.get().getDid()); + String theirDid = agent1PublicDid.get().getDid(); + + // agent 2 makes an implicit connection request using agent 1's public DID + // TODO include the "alias" parameter when available in aca-py + final Optional c = ac2.didExchangeCreateRequest(DidExchangeCreateRequestFilter + .builder() + .theirPublicDid(theirDid) + .build()); + Assertions.assertTrue(c.isPresent()); + Assertions.assertEquals(ConnectionRecord.ConnectionProtocol.DID_EXCHANGE_V1, c.get().getConnectionProtocol()); + + // wait for the connection to complete and then verify each agent has an active connection + Thread.sleep(1000); + + // now fetch connections and confirm everything completed successfully + // TODO include the "alias" parameter when available in aca-py + final Optional> connections = ac.connections( + ConnectionFilter.builder()/*.alias(alias_1)*/.build()); + assertTrue(connections.isPresent()); + assertEquals(1, connections.get().size()); + //assertEquals(alias_1, connections.get().get(0).getAlias()); + assertEquals(ConnectionState.REQUEST, connections.get().get(0).getState()); + + // accept request (can't "auto"?) + final Optional connection1 = ac.connectionsAcceptRequest( + connections.get().get(0).getConnectionId(), + ConnectionAcceptRequestFilter.builder().build()); + Thread.sleep(2000); + + final Optional> connections2 = ac2.connections( + ConnectionFilter.builder()/*.alias(alias_2)*/.build()); + assertTrue(connections2.isPresent()); + assertEquals(1, connections2.get().size()); + //assertEquals(alias_2, connections2.get().get(0).getAlias()); + assertEquals(ConnectionState.ACTIVE, connections2.get().get(0).getState()); + } +} diff --git a/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDCreate.java b/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDCreate.java new file mode 100644 index 00000000..7bef5300 --- /dev/null +++ b/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDCreate.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries.util.ledger; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; + +/** + * DID + */ + +@lombok.Data +@lombok.AllArgsConstructor +@lombok.NoArgsConstructor +@lombok.Builder +public class LedgerDIDCreate { + public static final String SERIALIZED_NAME_ALIAS = "alias"; + @SerializedName(SERIALIZED_NAME_ALIAS) + private String alias; + + public static final String SERIALIZED_NAME_DID = "did"; + @SerializedName(SERIALIZED_NAME_DID) + private String did; + + public static final String SERIALIZED_NAME_ROLE = "role"; + @SerializedName(SERIALIZED_NAME_ROLE) + private String role; + + public static final String SERIALIZED_NAME_SEED = "seed"; + @SerializedName(SERIALIZED_NAME_SEED) + private String seed; + + public static final String SERIALIZED_NAME_VERKEY = "verkey"; + @SerializedName(SERIALIZED_NAME_VERKEY) + private String verkey; +} diff --git a/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDResponse.java b/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDResponse.java new file mode 100644 index 00000000..10ded435 --- /dev/null +++ b/src/test/java/org/hyperledger/aries/util/ledger/LedgerDIDResponse.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/acapy-java-client + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.aries.util.ledger; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; + +/** + * DID + */ + +@lombok.Data +@lombok.AllArgsConstructor +@lombok.NoArgsConstructor +@lombok.Builder +public class LedgerDIDResponse { + public static final String SERIALIZED_NAME_DID = "did"; + @SerializedName(SERIALIZED_NAME_DID) + private String did; + + public static final String SERIALIZED_NAME_SEED = "seed"; + @SerializedName(SERIALIZED_NAME_SEED) + private String seed; + + public static final String SERIALIZED_NAME_VERKEY = "verkey"; + @SerializedName(SERIALIZED_NAME_VERKEY) + private String verkey; +}