diff --git a/e2e-tests/build.gradle b/e2e-tests/build.gradle index cd2bd8ae..e4269169 100644 --- a/e2e-tests/build.gradle +++ b/e2e-tests/build.gradle @@ -61,11 +61,15 @@ dependencies { } } - cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-fungible-demo-app', configuration: 'cordaCPB') - cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-identifiable-demo-app', configuration: 'cordaCPB') - cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-issuable-demo-app', configuration: 'cordaCPB') - cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-chainable-demo-app', configuration: 'cordaCPB') - cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-ownable-demo-app', configuration: 'cordaCPB') + cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-fungible-test-app', configuration: 'cordaCPB') + cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-identifiable-test-app', configuration: 'cordaCPB') + cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-issuable-test-app', configuration: 'cordaCPB') + cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-chainable-test-app', configuration: 'cordaCPB') + cpis project(path: ':e2e-tests:cpbs:ledger-utxo-advanced-ownable-test-app', configuration: 'cordaCPB') + + cpis project(path: ':examples:ledger-utxo-advanced-fungible-demo-app', configuration: 'cordaCPB') + cpis project(path: ':examples:ledger-utxo-advanced-identifiable-demo-app', configuration: 'cordaCPB') + cpis project(path: ':examples:ledger-utxo-advanced-chainable-demo-app', configuration: 'cordaCPB') e2eTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" e2eTestImplementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/build.gradle similarity index 90% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/build.gradle index c319f9a1..6d129c5d 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion as Integer minimumPlatformVersion platformVersion as Integer workflow { - name "Advanced UTXO Ledger Demo Chainable Workflow" + name "Advanced UTXO Ledger Test Chainable Workflow" versionId 1 vendor "R3" } @@ -18,7 +18,7 @@ dependencies { cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' cordaProvided 'net.corda:corda-ledger-utxo' - cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-chainable-demo-contract') + cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-chainable-test-contract') // Common and API packages pulled in as transitive dependencies through client cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractCreateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractCreateTestFlow.kt new file mode 100644 index 00000000..bbdecab6 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractCreateTestFlow.kt @@ -0,0 +1,72 @@ +package com.r3.corda.test.utxo.chainable.workflow + +import com.r3.corda.ledger.utxo.base.StaticPointer +import com.r3.corda.test.utxo.chainable.contract.MyChainableContract +import com.r3.corda.test.utxo.chainable.contract.MyChainableState +import com.r3.corda.test.utxo.chainable.contract.MyContractState +import net.corda.v5.application.crypto.DigestService +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.crypto.DigestAlgorithmName +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class ChainableContractCreateTestFlow(private val rule: String) : SubFlow>> { + + @CordaInject + private lateinit var digestService: DigestService + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val outputs = when (rule) { + "CONTRACT_RULE_CREATE_OUTPUTS" -> listOf(MyContractState(UUID.randomUUID())) + "CONTRACT_RULE_CREATE_POINTERS" -> { + listOf( + MyChainableState( + UUID.randomUUID(), + key, + StaticPointer( + StateRef(digestService.hash(byteArrayOf(1, 2, 3, 4), DigestAlgorithmName.SHA2_256), 0), + MyChainableState::class.java + ) + ), + MyChainableState(UUID.randomUUID(), key, null) + ) + } + "VALID" -> { + listOf( + MyChainableState(UUID.randomUUID(), key, null), + MyChainableState(UUID.randomUUID(), key, null), + MyContractState(UUID.randomUUID()) + ) + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyChainableContract.Create()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractDeleteTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractDeleteTestFlow.kt new file mode 100644 index 00000000..6fa6d1ef --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractDeleteTestFlow.kt @@ -0,0 +1,53 @@ +package com.r3.corda.test.utxo.chainable.workflow + +import com.r3.corda.test.utxo.chainable.contract.MyChainableContract +import com.r3.corda.test.utxo.chainable.contract.MyChainableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit + +class ChainableContractDeleteTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val inputs = when (rule) { + "CONTRACT_RULE_DELETE_INPUTS" -> { + stateAndRefs + .filter { it.state.contractState !is MyChainableState } + .map { it.ref } + } + "VALID" -> { + stateAndRefs.map { it.ref } + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addSignatories(key) + .addCommand(MyChainableContract.Delete()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractTestFlow.kt new file mode 100644 index 00000000..a628d662 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractTestFlow.kt @@ -0,0 +1,37 @@ +package com.r3.corda.test.utxo.chainable.workflow + +import net.corda.v5.application.flows.ClientRequestBody +import net.corda.v5.application.flows.ClientStartableFlow +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.FlowEngine +import net.corda.v5.application.marshalling.JsonMarshallingService +import net.corda.v5.base.annotations.Suspendable + +class ChainableContractTestFlow : ClientStartableFlow { + + @CordaInject + private lateinit var flowEngine: FlowEngine + + @CordaInject + private lateinit var jsonMarshallingService: JsonMarshallingService + + @Suspendable + override fun call(requestBody: ClientRequestBody): String { + val request = requestBody.getRequestBodyAs(jsonMarshallingService, Request::class.java) + when (request.command) { + "CREATE" -> flowEngine.subFlow(ChainableContractCreateTestFlow(request.rule)) + "UPDATE" -> { + val outputs = flowEngine.subFlow(ChainableContractCreateTestFlow("VALID")) + flowEngine.subFlow(ChainableContractUpdateTestFlow(request.rule, outputs)) + } + "DELETE" -> { + val outputs = flowEngine.subFlow(ChainableContractCreateTestFlow("VALID")) + flowEngine.subFlow(ChainableContractDeleteTestFlow(request.rule, outputs)) + } + else -> throw IllegalArgumentException("Invalid command type passed in") + } + return "success" + } +} + +private class Request(val command: String, val rule: String) diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractUpdateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractUpdateTestFlow.kt new file mode 100644 index 00000000..5d2fafdf --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/ChainableContractUpdateTestFlow.kt @@ -0,0 +1,86 @@ +package com.r3.corda.test.utxo.chainable.workflow + +import com.r3.corda.ledger.utxo.base.StaticPointer +import com.r3.corda.test.utxo.chainable.contract.MyChainableContract +import com.r3.corda.test.utxo.chainable.contract.MyChainableState +import com.r3.corda.test.utxo.chainable.contract.MyContractState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class ChainableContractUpdateTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val (inputs, outputs) = when (rule) { + "CONTRACT_RULE_UPDATE_INPUTS" -> { + emptyList() to listOf(MyContractState(UUID.randomUUID())) + } + "CONTRACT_RULE_UPDATE_OUTPUTS" -> { + stateAndRefs.map { it.ref } to emptyList() + } + "CONTRACT_RULE_UPDATE_POINTERS" -> { + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyChainableState } + .map { (it.state.contractState as MyChainableState).copy(previousStatePointer = null) } + } + "CONTRACT_RULE_UPDATE_EXCLUSIVE_POINTERS" -> { + val stateRef = stateAndRefs.first().ref + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyChainableState } + .map { + (it.state.contractState as MyChainableState).copy( + previousStatePointer = StaticPointer( + stateRef, + MyChainableState::class.java + ) + ) + } + } + "VALID" -> { + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyChainableState } + .map { + (it.state.contractState as MyChainableState).copy( + previousStatePointer = StaticPointer( + it.ref, + MyChainableState::class.java + ) + ) + } + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyChainableContract.Update()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/MemberInfoExtensions.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/MemberInfoExtensions.kt new file mode 100644 index 00000000..8f3e00d0 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-app/src/main/kotlin/com/r3/corda/test/utxo/chainable/workflow/MemberInfoExtensions.kt @@ -0,0 +1,7 @@ +package com.r3.corda.test.utxo.chainable.workflow + +import net.corda.v5.membership.MemberInfo +import java.security.PublicKey + +internal val MemberInfo.firstLedgerKey: PublicKey + get() = ledgerKeys.first() diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/build.gradle new file mode 100644 index 00000000..12ae8f99 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/build.gradle @@ -0,0 +1,23 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpk2' +} + +cordapp { + targetPlatformVersion platformVersion.toInteger() + minimumPlatformVersion platformVersion.toInteger() + contract { + name "Advanced UTXO Ledger Test Chainable Contract" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(":chainable") + cordapp project(":ownable") +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableContract.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableContract.kt new file mode 100644 index 00000000..973481e6 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableContract.kt @@ -0,0 +1,52 @@ +package com.r3.corda.test.utxo.chainable.contract + +import com.r3.corda.ledger.utxo.chainable.ChainableContract +import com.r3.corda.ledger.utxo.chainable.ChainableContractCommand +import com.r3.corda.ledger.utxo.chainable.ChainableContractCreateCommand +import com.r3.corda.ledger.utxo.chainable.ChainableContractDeleteCommand +import com.r3.corda.ledger.utxo.chainable.ChainableContractUpdateCommand +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction + +class MyChainableContract : ChainableContract() { + + override fun getPermittedCommandTypes(): List>> { + return listOf(Create::class.java, Update::class.java, Delete::class.java) + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + + class Create : ChainableContractCreateCommand() { + + override fun getContractStateType(): Class { + return MyChainableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Update : ChainableContractUpdateCommand() { + + override fun getContractStateType(): Class { + return MyChainableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Delete : ChainableContractDeleteCommand() { + + override fun getContractStateType(): Class { + return MyChainableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableState.kt new file mode 100644 index 00000000..5c837679 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyChainableState.kt @@ -0,0 +1,28 @@ +package com.r3.corda.test.utxo.chainable.contract + +import com.r3.corda.ledger.utxo.base.StaticPointer +import com.r3.corda.ledger.utxo.chainable.ChainableState +import com.r3.corda.ledger.utxo.ownable.OwnableState +import net.corda.v5.ledger.utxo.BelongsToContract +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(MyChainableContract::class) +data class MyChainableState( + val id: UUID, + private val owner: PublicKey, + private val previousStatePointer: StaticPointer? +) : ChainableState, OwnableState { + + override fun getOwner(): PublicKey { + return owner + } + + override fun getParticipants(): List { + return listOf(owner) + } + + override fun getPreviousStatePointer(): StaticPointer? { + return previousStatePointer + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyContractState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyContractState.kt new file mode 100644 index 00000000..3b0f9640 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-chainable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/chainable/contract/MyContractState.kt @@ -0,0 +1,16 @@ +package com.r3.corda.test.utxo.chainable.contract + +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.ContractState +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(MyChainableContract::class) +data class MyContractState( + val id: UUID, +) : ContractState { + + override fun getParticipants(): List { + return emptyList() + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/build.gradle similarity index 90% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/build.gradle index afb4518a..513dd342 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion.toInteger() minimumPlatformVersion platformVersion.toInteger() workflow { - name "Advanced UTXO Ledger Demo Fungible Workflow" + name "Advanced UTXO Ledger Test Fungible Workflow" versionId 1 vendor "R3" } @@ -20,7 +20,7 @@ dependencies { cordapp project(":fungible") - cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-fungible-demo-contract') + cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-fungible-test-contract') // Common and API packages pulled in as transitive dependencies through client cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractCreateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractCreateTestFlow.kt new file mode 100644 index 00000000..67f08e3f --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractCreateTestFlow.kt @@ -0,0 +1,72 @@ +package com.r3.corda.test.utxo.fungible.workflow + +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import com.r3.corda.test.utxo.fungible.contract.MyContractState +import com.r3.corda.test.utxo.fungible.contract.MyFungibleContract +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateA +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateB +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class FungibleContractCreateTestFlow(private val rule: String) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val outputs = when (rule) { + "CONTRACT_RULE_CREATE_OUTPUTS" -> listOf(MyContractState(UUID.randomUUID())) + "CONTRACT_RULE_CREATE_POSITIVE_QUANTITIES" -> { + listOf( + MyFungibleStateA( + quantity = NumericInteger.ZERO, + owner = key + ), + MyFungibleStateB( + quantity = NumericInteger.TEN, + owner = key + ), + ) + } + "VALID" -> { + listOf( + MyFungibleStateA( + quantity = NumericInteger.ONE, + owner = key + ), + MyFungibleStateB( + quantity = NumericInteger.TEN, + owner = key + ), + MyContractState(UUID.randomUUID()) + ) + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyFungibleContract.Create()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractDeleteTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractDeleteTestFlow.kt new file mode 100644 index 00000000..7811e7ff --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractDeleteTestFlow.kt @@ -0,0 +1,83 @@ +package com.r3.corda.test.utxo.fungible.workflow + +import com.r3.corda.ledger.utxo.fungible.FungibleState +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import com.r3.corda.test.utxo.fungible.contract.MyFungibleContract +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateA +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateB +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.math.BigInteger +import java.time.Instant +import java.time.temporal.ChronoUnit + +class FungibleContractDeleteTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val states = stateAndRefs.map { it.state.contractState } + val fungibleStateAStateAndRef = states.filterIsInstance().single() + val fungibleStateBStateAndRef = states.filterIsInstance().single() + val (inputs, outputs) = when (rule) { + "CONTRACT_RULE_DELETE_INPUTS" -> { + stateAndRefs + .filter { it.state.contractState !is FungibleState<*> } + .map { it.ref } to emptyList() + } + "CONTRACT_RULE_DELETE_POSITIVE_QUANTITIES" -> { + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(quantity = NumericInteger.ZERO), + fungibleStateBStateAndRef.copy() + ) + } + "CONTRACT_RULE_DELETE_SUM" -> { + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(), + fungibleStateBStateAndRef.copy() + ) + } + // Must be more inputs (deleted) states than outputs (created) per group. + // Fungible state A has increased compared to the input of state A so fails the check. + "CONTRACT_RULE_DELETE_GROUP_SUM" -> { + val total = (fungibleStateAStateAndRef.quantity + fungibleStateBStateAndRef.quantity).unscaledValue.toLong() + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(quantity = fungibleStateAStateAndRef.quantity + NumericInteger.ONE), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf(total / 2 - 1))), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf((total / 2) - 1))), + ) + } + "VALID" -> { + stateAndRefs.map { it.ref } to emptyList() + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyFungibleContract.Delete()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractTestFlow.kt new file mode 100644 index 00000000..84c6a30f --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractTestFlow.kt @@ -0,0 +1,37 @@ +package com.r3.corda.test.utxo.fungible.workflow + +import net.corda.v5.application.flows.ClientRequestBody +import net.corda.v5.application.flows.ClientStartableFlow +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.FlowEngine +import net.corda.v5.application.marshalling.JsonMarshallingService +import net.corda.v5.base.annotations.Suspendable + +class FungibleContractTestFlow : ClientStartableFlow { + + @CordaInject + private lateinit var flowEngine: FlowEngine + + @CordaInject + private lateinit var jsonMarshallingService: JsonMarshallingService + + @Suspendable + override fun call(requestBody: ClientRequestBody): String { + val request = requestBody.getRequestBodyAs(jsonMarshallingService, Request::class.java) + when (request.command) { + "CREATE" -> flowEngine.subFlow(FungibleContractCreateTestFlow(request.rule)) + "UPDATE" -> { + val outputs = flowEngine.subFlow(FungibleContractCreateTestFlow("VALID")) + flowEngine.subFlow(FungibleContractUpdateTestFlow(request.rule, outputs)) + } + "DELETE" -> { + val outputs = flowEngine.subFlow(FungibleContractCreateTestFlow("VALID")) + flowEngine.subFlow(FungibleContractDeleteTestFlow(request.rule, outputs)) + } + else -> throw IllegalArgumentException("Invalid command type passed in") + } + return "success" + } +} + +private class Request(val command: String, val rule: String) diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractUpdateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractUpdateTestFlow.kt new file mode 100644 index 00000000..03859d11 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/FungibleContractUpdateTestFlow.kt @@ -0,0 +1,92 @@ +package com.r3.corda.test.utxo.fungible.workflow + +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import com.r3.corda.test.utxo.fungible.contract.MyContractState +import com.r3.corda.test.utxo.fungible.contract.MyFungibleContract +import com.r3.corda.test.utxo.fungible.contract.MyFungibleState +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateA +import com.r3.corda.test.utxo.fungible.contract.MyFungibleStateB +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.math.BigInteger +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class FungibleContractUpdateTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val states = stateAndRefs.map { it.state.contractState } + val fungibleStateAStateAndRef = states.filterIsInstance().single() + val fungibleStateBStateAndRef = states.filterIsInstance().single() + val (inputs, outputs) = when (rule) { + "CONTRACT_RULE_UPDATE_INPUTS" -> { + emptyList() to listOf(MyContractState(UUID.randomUUID())) + } + "CONTRACT_RULE_UPDATE_OUTPUTS" -> { + stateAndRefs.map { it.ref } to emptyList() + } + "CONTRACT_RULE_UPDATE_POSITIVE_QUANTITIES" -> { + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(quantity = NumericInteger.ZERO), + fungibleStateBStateAndRef.copy() + ) + } + "CONTRACT_RULE_UPDATE_SUM" -> { + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(quantity = fungibleStateAStateAndRef.quantity + NumericInteger(BigInteger.valueOf(100))), + fungibleStateBStateAndRef.copy() + ) + } + // Groups fungible with each other must be equal. + // Fungible state A has increased but it is not fungible with B so the check fails. + "CONTRACT_RULE_UPDATE_GROUP_SUM" -> { + val total = (fungibleStateAStateAndRef.quantity + fungibleStateBStateAndRef.quantity).unscaledValue.toLong() + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(quantity = fungibleStateAStateAndRef.quantity + NumericInteger.ONE), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf(total / 2))), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf((total / 2) - 1))), + ) + } + "VALID" -> { + val total = (fungibleStateAStateAndRef.quantity + fungibleStateBStateAndRef.quantity).unscaledValue.toLong() + stateAndRefs.map { it.ref } to listOf( + fungibleStateAStateAndRef.copy(), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf(total / 2))), + fungibleStateBStateAndRef.copy(quantity = NumericInteger(BigInteger.valueOf(total / 2))), + ) + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyFungibleContract.Update()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/MemberInfoExtensions.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/MemberInfoExtensions.kt similarity index 76% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/MemberInfoExtensions.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/MemberInfoExtensions.kt index a46090a0..306e9de4 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/MemberInfoExtensions.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-app/src/main/kotlin/com/r3/corda/test/utxo/fungible/workflow/MemberInfoExtensions.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.issuable.workflow +package com.r3.corda.test.utxo.fungible.workflow import net.corda.v5.membership.MemberInfo import java.security.PublicKey diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/build.gradle new file mode 100644 index 00000000..a49396af --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/build.gradle @@ -0,0 +1,24 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpk2' +} + +cordapp { + targetPlatformVersion platformVersion.toInteger() + minimumPlatformVersion platformVersion.toInteger() + contract { + name "Advanced UTXO Ledger Test Fungible Contract" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(":fungible") + cordapp project(":issuable") + cordapp project(":ownable") +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyContractState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyContractState.kt new file mode 100644 index 00000000..8788f046 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyContractState.kt @@ -0,0 +1,16 @@ +package com.r3.corda.test.utxo.fungible.contract + +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.ContractState +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(MyFungibleContract::class) +data class MyContractState( + val id: UUID, +) : ContractState { + + override fun getParticipants(): List { + return emptyList() + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleContract.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleContract.kt new file mode 100644 index 00000000..c2566515 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleContract.kt @@ -0,0 +1,52 @@ +package com.r3.corda.test.utxo.fungible.contract + +import com.r3.corda.ledger.utxo.fungible.FungibleContract +import com.r3.corda.ledger.utxo.fungible.FungibleContractCommand +import com.r3.corda.ledger.utxo.fungible.FungibleContractCreateCommand +import com.r3.corda.ledger.utxo.fungible.FungibleContractDeleteCommand +import com.r3.corda.ledger.utxo.fungible.FungibleContractUpdateCommand +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction + +class MyFungibleContract : FungibleContract() { + + override fun getPermittedCommandTypes(): List>> { + return listOf(Create::class.java, Update::class.java, Delete::class.java) + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + + class Create : FungibleContractCreateCommand() { + + override fun getContractStateType(): Class { + return MyFungibleState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Update : FungibleContractUpdateCommand() { + + override fun getContractStateType(): Class { + return MyFungibleState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Delete : FungibleContractDeleteCommand() { + + override fun getContractStateType(): Class { + return MyFungibleState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleState.kt new file mode 100644 index 00000000..f96b8d3e --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleState.kt @@ -0,0 +1,9 @@ +package com.r3.corda.test.utxo.fungible.contract + +import com.r3.corda.ledger.utxo.fungible.FungibleState +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import com.r3.corda.ledger.utxo.ownable.OwnableState +import net.corda.v5.ledger.utxo.BelongsToContract + +@BelongsToContract(MyFungibleContract::class) +interface MyFungibleState : FungibleState, OwnableState diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateA.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateA.kt new file mode 100644 index 00000000..8d060f9e --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateA.kt @@ -0,0 +1,29 @@ +package com.r3.corda.test.utxo.fungible.contract + +import com.r3.corda.ledger.utxo.fungible.FungibleState +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import net.corda.v5.ledger.utxo.BelongsToContract +import java.security.PublicKey + +@BelongsToContract(MyFungibleContract::class) +data class MyFungibleStateA( + private val quantity: NumericInteger, + private val owner: PublicKey +) : MyFungibleState { + + override fun getOwner(): PublicKey { + return owner + } + + override fun getParticipants(): List { + return listOf(owner) + } + + override fun getQuantity(): NumericInteger { + return quantity + } + + override fun isFungibleWith(other: FungibleState): Boolean { + return other is MyFungibleStateA + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateB.kt b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateB.kt new file mode 100644 index 00000000..69aad448 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-fungible-test-contract/src/main/kotlin/com/r3/corda/test/utxo/fungible/contract/MyFungibleStateB.kt @@ -0,0 +1,29 @@ +package com.r3.corda.test.utxo.fungible.contract + +import com.r3.corda.ledger.utxo.fungible.FungibleState +import com.r3.corda.ledger.utxo.fungible.NumericInteger +import net.corda.v5.ledger.utxo.BelongsToContract +import java.security.PublicKey + +@BelongsToContract(MyFungibleContract::class) +data class MyFungibleStateB( + private val quantity: NumericInteger, + private val owner: PublicKey +) : MyFungibleState { + + override fun getOwner(): PublicKey { + return owner + } + + override fun getParticipants(): List { + return listOf(owner) + } + + override fun getQuantity(): NumericInteger { + return quantity + } + + override fun isFungibleWith(other: FungibleState): Boolean { + return other is MyFungibleStateB + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/build.gradle similarity index 89% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/build.gradle index 35715b97..fd365bbc 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion.toInteger() minimumPlatformVersion platformVersion.toInteger() workflow { - name "Advanced UTXO Ledger Demo Identifiable Workflow" + name "Advanced UTXO Ledger Test Identifiable Workflow" versionId 1 vendor "R3" } @@ -18,7 +18,7 @@ dependencies { cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' cordaProvided 'net.corda:corda-ledger-utxo' - cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-identifiable-demo-contract') + cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-identifiable-test-contract') // Common and API packages pulled in as transitive dependencies through client cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractCreateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractCreateTestFlow.kt new file mode 100644 index 00000000..e2c76e5c --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractCreateTestFlow.kt @@ -0,0 +1,52 @@ +package com.r3.corda.test.utxo.identifiable.workflow + +import com.r3.corda.test.utxo.identifiable.contract.MyContractState +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableContract +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class IdentifiableContractCreateTestFlow(private val rule: String) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val outputs = when (rule) { + "CONTRACT_RULE_CREATE_OUTPUTS" -> listOf(MyContractState(UUID.randomUUID())) + "VALID" -> { + listOf( + MyIdentifiableState(id = null, owner = key), + MyIdentifiableState(id = null, owner = key), + MyContractState(UUID.randomUUID()) + ) + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyIdentifiableContract.Create()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractDeleteTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractDeleteTestFlow.kt new file mode 100644 index 00000000..b67e5b46 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractDeleteTestFlow.kt @@ -0,0 +1,53 @@ +package com.r3.corda.test.utxo.identifiable.workflow + +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableContract +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit + +class IdentifiableContractDeleteTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val inputs = when (rule) { + "CONTRACT_RULE_DELETE_INPUTS" -> { + stateAndRefs + .filter { it.state.contractState !is MyIdentifiableState } + .map { it.ref } + } + "VALID" -> { + stateAndRefs.map { it.ref } + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addSignatories(key) + .addCommand(MyIdentifiableContract.Delete()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractTestFlow.kt new file mode 100644 index 00000000..43cdccf9 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractTestFlow.kt @@ -0,0 +1,37 @@ +package com.r3.corda.test.utxo.identifiable.workflow + +import net.corda.v5.application.flows.ClientRequestBody +import net.corda.v5.application.flows.ClientStartableFlow +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.FlowEngine +import net.corda.v5.application.marshalling.JsonMarshallingService +import net.corda.v5.base.annotations.Suspendable + +class IdentifiableContractTestFlow : ClientStartableFlow { + + @CordaInject + private lateinit var flowEngine: FlowEngine + + @CordaInject + private lateinit var jsonMarshallingService: JsonMarshallingService + + @Suspendable + override fun call(requestBody: ClientRequestBody): String { + val request = requestBody.getRequestBodyAs(jsonMarshallingService, Request::class.java) + when (request.command) { + "CREATE" -> flowEngine.subFlow(IdentifiableContractCreateTestFlow(request.rule)) + "UPDATE" -> { + val outputs = flowEngine.subFlow(IdentifiableContractCreateTestFlow("VALID")) + flowEngine.subFlow(IdentifiableContractUpdateTestFlow(request.rule, outputs)) + } + "DELETE" -> { + val outputs = flowEngine.subFlow(IdentifiableContractCreateTestFlow("VALID")) + flowEngine.subFlow(IdentifiableContractDeleteTestFlow(request.rule, outputs)) + } + else -> throw IllegalArgumentException("Invalid command type passed in") + } + return "success" + } +} + +private class Request(val command: String, val rule: String) diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractUpdateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractUpdateTestFlow.kt new file mode 100644 index 00000000..355cc21c --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableContractUpdateTestFlow.kt @@ -0,0 +1,85 @@ +package com.r3.corda.test.utxo.identifiable.workflow + +import com.r3.corda.test.utxo.identifiable.contract.MyContractState +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableContract +import com.r3.corda.test.utxo.identifiable.contract.MyIdentifiableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +class IdentifiableContractUpdateTestFlow( + private val rule: String, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val (inputs, outputs) = when (rule) { + "CONTRACT_RULE_UPDATE_INPUTS" -> { + emptyList() to listOf(MyContractState(UUID.randomUUID())) + } + "CONTRACT_RULE_UPDATE_OUTPUTS" -> { + stateAndRefs.map { it.ref } to emptyList() + } + "CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY" -> { + val stateRef = stateAndRefs.first().ref + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyIdentifiableState } + .map { + (it.state.contractState as MyIdentifiableState).copy( + id = stateRef + ) + } + } + // TODO Currently broken fixed in CORE-13473 + "CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY MISSING_ID" -> { + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyIdentifiableState } + .let { stateAndRefs -> + val missingId = stateAndRefs.drop(1).map { it.state.contractState } + val hasId = stateAndRefs.take(1).map { (it.state.contractState as MyIdentifiableState).copy(id = it.ref) } + missingId + hasId + } + + } + "VALID" -> { + stateAndRefs.map { it.ref } to stateAndRefs + .filter { it.state.contractState is MyIdentifiableState } + .map { + (it.state.contractState as MyIdentifiableState).copy( + id = it.ref + ) + } + } + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(inputs) + .addOutputStates(outputs) + .addSignatories(key) + .addCommand(MyIdentifiableContract.Update()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + return utxoLedgerService.finalize(transaction, emptyList()).transaction.outputStateAndRefs + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiablePointerFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiablePointerFlow.kt similarity index 94% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiablePointerFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiablePointerFlow.kt index 8cf24332..dee17452 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiablePointerFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiablePointerFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.identifiable.workflow.query +package com.r3.corda.test.utxo.identifiable.workflow import com.r3.corda.ledger.utxo.identifiable.IdentifiablePointer import net.corda.v5.application.flows.ClientRequestBody @@ -9,9 +9,8 @@ import net.corda.v5.application.membership.MemberLookup import net.corda.v5.base.annotations.Suspendable import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.UtxoLedgerService -import com.r3.corda.demo.utxo.identifiable.contract.TestIdentifiableContract -import com.r3.corda.demo.utxo.identifiable.contract.TestIdentifiableState -import com.r3.corda.demo.utxo.identifiable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.identifiable.contract.TestIdentifiableContract +import com.r3.corda.test.utxo.identifiable.contract.TestIdentifiableState import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiableStateQueryFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableStateQueryFlow.kt similarity index 95% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiableStateQueryFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableStateQueryFlow.kt index e1134da7..eacd3fee 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/query/IdentifiableStateQueryFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/IdentifiableStateQueryFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.identifiable.workflow.query +package com.r3.corda.test.utxo.identifiable.workflow import com.r3.corda.ledger.utxo.identifiable.query.IdentifiableStateQueries import net.corda.v5.application.flows.ClientRequestBody @@ -11,9 +11,8 @@ import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.UtxoLedgerService import net.corda.v5.ledger.utxo.query.VaultNamedParameterizedQuery -import com.r3.corda.demo.utxo.identifiable.contract.TestIdentifiableContract -import com.r3.corda.demo.utxo.identifiable.contract.TestIdentifiableState -import com.r3.corda.demo.utxo.identifiable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.identifiable.contract.TestIdentifiableContract +import com.r3.corda.test.utxo.identifiable.contract.TestIdentifiableState import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/MemberInfoExtensions.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/MemberInfoExtensions.kt new file mode 100644 index 00000000..01a49841 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-app/src/main/kotlin/com/r3/corda/test/utxo/identifiable/workflow/MemberInfoExtensions.kt @@ -0,0 +1,7 @@ +package com.r3.corda.test.utxo.identifiable.workflow + +import net.corda.v5.membership.MemberInfo +import java.security.PublicKey + +internal val MemberInfo.firstLedgerKey: PublicKey + get() = ledgerKeys.first() diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/build.gradle new file mode 100644 index 00000000..2db3e374 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpk2' +} + +cordapp { + targetPlatformVersion platformVersion.toInteger() + minimumPlatformVersion platformVersion.toInteger() + contract { + name "Advanced UTXO Ledger Test Identifiable Contract" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(":identifiable") +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyContractState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyContractState.kt new file mode 100644 index 00000000..2cabde28 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyContractState.kt @@ -0,0 +1,16 @@ +package com.r3.corda.test.utxo.identifiable.contract + +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.ContractState +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(MyIdentifiableContract::class) +data class MyContractState( + val id: UUID, +) : ContractState { + + override fun getParticipants(): List { + return emptyList() + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableContract.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableContract.kt new file mode 100644 index 00000000..850462ef --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableContract.kt @@ -0,0 +1,52 @@ +package com.r3.corda.test.utxo.identifiable.contract + +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContract +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractCreateCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractDeleteCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractUpdateCommand +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction + +class MyIdentifiableContract : IdentifiableContract() { + + override fun getPermittedCommandTypes(): List>> { + return listOf(Create::class.java, Update::class.java, Delete::class.java) + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + + class Create : IdentifiableContractCreateCommand() { + + override fun getContractStateType(): Class { + return MyIdentifiableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Update : IdentifiableContractUpdateCommand() { + + override fun getContractStateType(): Class { + return MyIdentifiableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } + + class Delete : IdentifiableContractDeleteCommand() { + + override fun getContractStateType(): Class { + return MyIdentifiableState::class.java + } + + override fun onVerify(transaction: UtxoLedgerTransaction) { + + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableState.kt new file mode 100644 index 00000000..d56c251c --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/MyIdentifiableState.kt @@ -0,0 +1,21 @@ +package com.r3.corda.test.utxo.identifiable.contract + +import com.r3.corda.ledger.utxo.identifiable.IdentifiableState +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.StateRef +import java.security.PublicKey + +@BelongsToContract(MyIdentifiableContract::class) +data class MyIdentifiableState( + private val id: StateRef?, + val owner: PublicKey, +) : IdentifiableState { + + override fun getId(): StateRef? { + return id + } + + override fun getParticipants(): List { + return listOf(owner) + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/TestIdentifiableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/TestIdentifiableState.kt new file mode 100644 index 00000000..ceb9eb2b --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/identifiable/contract/TestIdentifiableState.kt @@ -0,0 +1,46 @@ +package com.r3.corda.test.utxo.identifiable.contract + +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContract +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractCreateCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractDeleteCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableContractUpdateCommand +import com.r3.corda.ledger.utxo.identifiable.IdentifiableState +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.StateRef +import java.security.PublicKey + +@BelongsToContract(TestIdentifiableContract::class) +data class TestIdentifiableState(private val id: StateRef?, private val participants: List) : IdentifiableState { + + override fun getParticipants(): List { + return participants + } + + override fun getId(): StateRef? { + return id + } +} + +class TestIdentifiableContract : IdentifiableContract() { + + class Create : IdentifiableContractCreateCommand() { + override fun getContractStateType(): Class { + return TestIdentifiableState::class.java + } + } + class Update: IdentifiableContractUpdateCommand() { + override fun getContractStateType(): Class { + return TestIdentifiableState::class.java + } + } + class Delete: IdentifiableContractDeleteCommand() { + override fun getContractStateType(): Class { + return TestIdentifiableState::class.java + } + } + + override fun getPermittedCommandTypes(): List>> { + return listOf(Create::class.java, Update::class.java, Delete::class.java) + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/build.gradle similarity index 89% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/build.gradle index 9feb87ba..5086da71 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion as Integer minimumPlatformVersion platformVersion as Integer workflow { - name "Advanced UTXO Ledger Demo Issuable Workflow" + name "Advanced UTXO Ledger Test Issuable Workflow" versionId 1 vendor "R3" } @@ -17,7 +17,7 @@ dependencies { cordaProvided platform("net.corda:corda-api:$cordaApiVersion") cordaProvided 'net.corda:corda-ledger-utxo' - cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-issuable-demo-contract') + cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-issuable-test-contract') // Common and API packages pulled in as transitive dependencies through client cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractCreateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractCreateTestFlow.kt new file mode 100644 index 00000000..88a860c6 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractCreateTestFlow.kt @@ -0,0 +1,81 @@ +package com.r3.corda.test.utxo.issuable.workflow + +import com.r3.corda.test.utxo.issuable.contract.MyContractState +import com.r3.corda.test.utxo.issuable.contract.MyIssuableContract +import com.r3.corda.test.utxo.issuable.contract.MyIssuableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatedBy +import net.corda.v5.application.flows.InitiatingFlow +import net.corda.v5.application.flows.ResponderFlow +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.security.PublicKey +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +@InitiatingFlow(protocol = "IssuableContractCreateTestFlow") +class IssuableContractCreateTestFlow( + private val rule: String, + private val issuer: PublicKey, + private val issuerName: MemberX500Name +) : SubFlow>> { + + @CordaInject + private lateinit var flowMessaging: FlowMessaging + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val signatories = when (rule) { + "CONTRACT_RULE_CREATE_SIGNATORIES" -> listOf(key) + "VALID" -> listOf(issuer, key) + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val outputs = listOf( + MyIssuableState(issuer, issuerName, participants = listOf(key)), + MyIssuableState(issuer, issuerName, participants = listOf(key)), + MyContractState(UUID.randomUUID()) + ) + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addOutputStates(outputs) + .addSignatories(signatories) + .addCommand(MyIssuableContract.Create()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + val session = flowMessaging.initiateFlow(issuerName) + return utxoLedgerService.finalize(transaction, listOf(session)).transaction.outputStateAndRefs + } +} + +@InitiatedBy(protocol = "IssuableContractCreateTestFlow") +class IssuableContractCreateTestResponderFlow : ResponderFlow { + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(session: FlowSession) { + utxoLedgerService.receiveFinality(session) { + // accept + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractDeleteTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractDeleteTestFlow.kt new file mode 100644 index 00000000..9041dddf --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractDeleteTestFlow.kt @@ -0,0 +1,74 @@ +package com.r3.corda.test.utxo.issuable.workflow + +import com.r3.corda.test.utxo.issuable.contract.MyIssuableContract +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatedBy +import net.corda.v5.application.flows.InitiatingFlow +import net.corda.v5.application.flows.ResponderFlow +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.security.PublicKey +import java.time.Instant +import java.time.temporal.ChronoUnit + +@InitiatingFlow(protocol = "IssuableContractDeleteTestFlow") +class IssuableContractDeleteTestFlow( + private val rule: String, + private val issuer: PublicKey, + private val issuerName: MemberX500Name, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var flowMessaging: FlowMessaging + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val signatories = when (rule) { + "CONTRACT_RULE_DELETE_SIGNATORIES" -> listOf(key) + "VALID" -> listOf(issuer, key) + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(stateAndRefs.map { it.ref }) + .addSignatories(signatories) + .addCommand(MyIssuableContract.Delete()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + val session = flowMessaging.initiateFlow(issuerName) + return utxoLedgerService.finalize(transaction, listOf(session)).transaction.outputStateAndRefs + } +} + +@InitiatedBy(protocol = "IssuableContractDeleteTestFlow") +class IssuableContractDeleteTestResponderFlow : ResponderFlow { + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(session: FlowSession) { + utxoLedgerService.receiveFinality(session) { + // accept + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractTestFlow.kt new file mode 100644 index 00000000..3e8b82f8 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableContractTestFlow.kt @@ -0,0 +1,42 @@ +package com.r3.corda.test.utxo.issuable.workflow + +import net.corda.v5.application.flows.ClientRequestBody +import net.corda.v5.application.flows.ClientStartableFlow +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.FlowEngine +import net.corda.v5.application.marshalling.JsonMarshallingService +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name + +class IssuableContractTestFlow : ClientStartableFlow { + + @CordaInject + private lateinit var flowEngine: FlowEngine + + @CordaInject + private lateinit var jsonMarshallingService: JsonMarshallingService + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @Suspendable + override fun call(requestBody: ClientRequestBody): String { + val request = requestBody.getRequestBodyAs(jsonMarshallingService, Request::class.java) + val issuerName = MemberX500Name.parse(request.issuer) + val issuer = requireNotNull(memberLookup.lookup(issuerName)) { + "Issuer $issuerName does not exist in the network" + }.firstLedgerKey + when (request.command) { + "CREATE" -> flowEngine.subFlow(IssuableContractCreateTestFlow(request.rule, issuer, issuerName)) + "DELETE" -> { + val outputs = flowEngine.subFlow(IssuableContractCreateTestFlow("VALID", issuer, issuerName)) + flowEngine.subFlow(IssuableContractDeleteTestFlow(request.rule, issuer, issuerName, outputs)) + } + else -> throw IllegalArgumentException("Invalid command type passed in") + } + return "success" + } +} + +private class Request(val command: String, val rule: String, val issuer: String) diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/IssuableStateQueryFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableStateQueryFlow.kt similarity index 95% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/IssuableStateQueryFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableStateQueryFlow.kt index 83cbd286..92de9024 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/IssuableStateQueryFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/IssuableStateQueryFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.issuable.workflow.query +package com.r3.corda.test.utxo.issuable.workflow import com.r3.corda.ledger.utxo.issuable.query.IssuableStateQueries import net.corda.v5.application.crypto.DigestService @@ -13,9 +13,8 @@ import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.UtxoLedgerService import net.corda.v5.ledger.utxo.query.VaultNamedParameterizedQuery -import com.r3.corda.demo.utxo.issuable.contract.TestIssuableContract -import com.r3.corda.demo.utxo.issuable.contract.TestIssuableState -import com.r3.corda.demo.utxo.issuable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.issuable.contract.TestIssuableContract +import com.r3.corda.test.utxo.issuable.contract.TestIssuableState import java.security.PublicKey import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/MemberInfoExtensions.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/MemberInfoExtensions.kt new file mode 100644 index 00000000..ba378155 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/MemberInfoExtensions.kt @@ -0,0 +1,7 @@ +package com.r3.corda.test.utxo.issuable.workflow + +import net.corda.v5.membership.MemberInfo +import java.security.PublicKey + +internal val MemberInfo.firstLedgerKey: PublicKey + get() = ledgerKeys.first() diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/WellKnownIssuableStateQueryFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/WellKnownIssuableStateQueryFlow.kt similarity index 95% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/WellKnownIssuableStateQueryFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/WellKnownIssuableStateQueryFlow.kt index 0a0fd3c5..da02d206 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/issuable/workflow/query/WellKnownIssuableStateQueryFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-app/src/main/kotlin/com/r3/corda/test/utxo/issuable/workflow/WellKnownIssuableStateQueryFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.issuable.workflow.query +package com.r3.corda.test.utxo.issuable.workflow import com.r3.corda.ledger.utxo.issuable.query.WellKnownIssuableStateQueries import net.corda.v5.application.flows.ClientRequestBody @@ -11,9 +11,8 @@ import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.UtxoLedgerService import net.corda.v5.ledger.utxo.query.VaultNamedParameterizedQuery -import com.r3.corda.demo.utxo.issuable.contract.TestIssuableContract -import com.r3.corda.demo.utxo.issuable.contract.TestIssuableState -import com.r3.corda.demo.utxo.issuable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.issuable.contract.TestIssuableContract +import com.r3.corda.test.utxo.issuable.contract.TestIssuableState import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/build.gradle similarity index 89% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/build.gradle index 58d36fb3..e05fa651 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion as Integer minimumPlatformVersion platformVersion as Integer contract { - name "Advanced UTXO Ledger Demo Issuable Contract" + name "Advanced UTXO Ledger Test Issuable Contract" versionId 1 vendor "R3" } diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyContractState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyContractState.kt new file mode 100644 index 00000000..1ba6fc01 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyContractState.kt @@ -0,0 +1,16 @@ +package com.r3.corda.test.utxo.issuable.contract + +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.ContractState +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(TestIssuableContract::class) +data class MyContractState( + val id: UUID, +) : ContractState { + + override fun getParticipants(): List { + return emptyList() + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyIssuableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyIssuableState.kt new file mode 100644 index 00000000..1bff43b0 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/MyIssuableState.kt @@ -0,0 +1,47 @@ +package com.r3.corda.test.utxo.issuable.contract + +import com.r3.corda.ledger.utxo.issuable.IssuableConstraints +import com.r3.corda.ledger.utxo.issuable.IssuableState +import com.r3.corda.ledger.utxo.issuable.WellKnownIssuableState +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.Command +import net.corda.v5.ledger.utxo.Contract +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction +import java.security.PublicKey + +@BelongsToContract(MyIssuableContract::class) +data class MyIssuableState( + private val issuer: PublicKey, + private val issuerName: MemberX500Name, + private val participants: List +) : IssuableState, WellKnownIssuableState { + + override fun getParticipants(): List { + return participants + } + + override fun getIssuer(): PublicKey { + return issuer + } + + override fun getIssuerName(): MemberX500Name { + return issuerName + } +} + +class MyIssuableContract : Contract { + + class Create : Command + class Delete : Command + + override fun verify(transaction: UtxoLedgerTransaction) { + val commands = transaction.commands + if (commands.any { it::class.java == Create::class.java }) { + IssuableConstraints.verifyCreate(transaction) + } + if (commands.any { it::class.java == Delete::class.java }) { + IssuableConstraints.verifyDelete(transaction) + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/TestIssuableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/TestIssuableState.kt similarity index 91% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/TestIssuableState.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/TestIssuableState.kt index 9421d8e5..fcb18b42 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/TestIssuableState.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/TestIssuableState.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.issuable.contract +package com.r3.corda.test.utxo.issuable.contract import com.r3.corda.ledger.utxo.issuable.IssuableState import com.r3.corda.ledger.utxo.issuable.WellKnownIssuableState @@ -25,14 +25,13 @@ data class TestIssuableState( } override fun getIssuerName(): MemberX500Name { - return issuerName + return issuerName } } class TestIssuableContract : Contract { class Create : Command - class Update : Command class Delete : Command override fun verify(transaction: UtxoLedgerTransaction) { diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt similarity index 79% rename from e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt index 83bb01eb..95e94b05 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-issuable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-issuable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/issuable/contract/query/json/TestIssuableStateVaultJsonFactory.kt @@ -1,8 +1,8 @@ -package com.r3.corda.demo.utxo.issuable.contract.query.json +package com.r3.corda.test.utxo.issuable.contract.query.json import net.corda.v5.application.marshalling.JsonMarshallingService import net.corda.v5.ledger.utxo.query.json.ContractStateVaultJsonFactory -import com.r3.corda.demo.utxo.issuable.contract.TestIssuableState +import com.r3.corda.test.utxo.issuable.contract.TestIssuableState class TestIssuableStateVaultJsonFactory : ContractStateVaultJsonFactory { diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/build.gradle similarity index 89% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/build.gradle index 7a8808c0..2be1157c 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion as Integer minimumPlatformVersion platformVersion as Integer workflow { - name "Advanced UTXO Ledger Demo Ownable Workflow" + name "Advanced UTXO Ledger Test Ownable Workflow" versionId 1 vendor "R3" } @@ -17,7 +17,7 @@ dependencies { cordaProvided platform("net.corda:corda-api:$cordaApiVersion") cordaProvided 'net.corda:corda-ledger-utxo' - cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-ownable-demo-contract') + cordapp project(':e2e-tests:cpbs:ledger-utxo-advanced-ownable-test-contract') // Common and API packages pulled in as transitive dependencies through client cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/MemberInfoExtensions.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/MemberInfoExtensions.kt similarity index 76% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/MemberInfoExtensions.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/MemberInfoExtensions.kt index c5084799..8fa5e983 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/MemberInfoExtensions.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/MemberInfoExtensions.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.ownable.workflow +package com.r3.corda.test.utxo.ownable.workflow import net.corda.v5.membership.MemberInfo import java.security.PublicKey diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractCreateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractCreateTestFlow.kt new file mode 100644 index 00000000..162ee930 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractCreateTestFlow.kt @@ -0,0 +1,80 @@ +package com.r3.corda.test.utxo.ownable.workflow + +import com.r3.corda.test.utxo.ownable.contract.MyContractState +import com.r3.corda.test.utxo.ownable.contract.MyOwnableContract +import com.r3.corda.test.utxo.ownable.contract.MyOwnableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatedBy +import net.corda.v5.application.flows.InitiatingFlow +import net.corda.v5.application.flows.ResponderFlow +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.security.PublicKey +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +@InitiatingFlow(protocol = "OwnableContractCreateTestFlow") +class OwnableContractCreateTestFlow( + private val rule: String, + private val owner: PublicKey, + private val ownerName: MemberX500Name +) : SubFlow>> { + + @CordaInject + private lateinit var flowMessaging: FlowMessaging + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val key = memberLookup.myInfo().firstLedgerKey + val signatories = when (rule) { + "VALID" -> listOf(owner, key) + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val outputs = listOf( + MyOwnableState(owner, ownerName, participants = listOf(key)), + MyOwnableState(owner, ownerName, participants = listOf(key)), + MyContractState(UUID.randomUUID()) + ) + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addOutputStates(outputs) + .addSignatories(signatories) + .addCommand(MyOwnableContract.Create()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + val session = flowMessaging.initiateFlow(ownerName) + return utxoLedgerService.finalize(transaction, listOf(session)).transaction.outputStateAndRefs + } +} + +@InitiatedBy(protocol = "OwnableContractCreateTestFlow") +class OwnableContractCreateTestResponderFlow : ResponderFlow { + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(session: FlowSession) { + utxoLedgerService.receiveFinality(session) { + // accept + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractTestFlow.kt new file mode 100644 index 00000000..66b58826 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractTestFlow.kt @@ -0,0 +1,41 @@ +package com.r3.corda.test.utxo.ownable.workflow + +import net.corda.v5.application.flows.ClientRequestBody +import net.corda.v5.application.flows.ClientStartableFlow +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.FlowEngine +import net.corda.v5.application.marshalling.JsonMarshallingService +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name + +class OwnableContractTestFlow : ClientStartableFlow { + + @CordaInject + private lateinit var flowEngine: FlowEngine + + @CordaInject + private lateinit var jsonMarshallingService: JsonMarshallingService + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @Suspendable + override fun call(requestBody: ClientRequestBody): String { + val request = requestBody.getRequestBodyAs(jsonMarshallingService, Request::class.java) + val ownerName = MemberX500Name.parse(request.owner) + val owner = requireNotNull(memberLookup.lookup(ownerName)) { + "owner $ownerName does not exist in the network" + }.firstLedgerKey + when (request.command) { + "UPDATE" -> { + val outputs = flowEngine.subFlow(OwnableContractCreateTestFlow("VALID", owner, ownerName)) + flowEngine.subFlow(OwnableContractUpdateTestFlow(request.rule, owner, ownerName, outputs)) + } + else -> throw IllegalArgumentException("Invalid command type passed in") + } + return "success" + } +} + +private class Request(val command: String, val rule: String, val owner: String) diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractUpdateTestFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractUpdateTestFlow.kt new file mode 100644 index 00000000..7683e261 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableContractUpdateTestFlow.kt @@ -0,0 +1,85 @@ +package com.r3.corda.test.utxo.ownable.workflow + +import com.r3.corda.test.utxo.ownable.contract.MyContractState +import com.r3.corda.test.utxo.ownable.contract.MyOwnableContract +import com.r3.corda.test.utxo.ownable.contract.MyOwnableState +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatedBy +import net.corda.v5.application.flows.InitiatingFlow +import net.corda.v5.application.flows.ResponderFlow +import net.corda.v5.application.flows.SubFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.common.NotaryLookup +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import java.security.PublicKey +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.UUID + +@InitiatingFlow(protocol = "OwnableContractUpdateTestFlow") +class OwnableContractUpdateTestFlow( + private val rule: String, + private val owner: PublicKey, + private val ownerName: MemberX500Name, + private val stateAndRefs: List> +) : SubFlow>> { + + @CordaInject + private lateinit var flowMessaging: FlowMessaging + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notaryLookup: NotaryLookup + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(): List> { + val info = memberLookup.myInfo() + val name = info.name + val key = info.firstLedgerKey + val signatories = when (rule) { + "CONTRACT_RULE_UPDATE_SIGNATORIES" -> listOf(key) + "VALID" -> listOf(owner, key) + else -> throw IllegalArgumentException("Invalid rule type passed in") + } + val outputs = listOf( + MyOwnableState(owner = key, ownerName = name, participants = listOf(key)), + MyOwnableState(owner = key, ownerName = name, participants = listOf(key)), + MyContractState(UUID.randomUUID()) + ) + val transaction = utxoLedgerService.createTransactionBuilder() + .setNotary(notaryLookup.notaryServices.first().name) + .addInputStates(stateAndRefs.map { it.ref }) + .addOutputStates(outputs) + .addSignatories(signatories) + .addCommand(MyOwnableContract.Update()) + .setTimeWindowUntil(Instant.now().plus(10, ChronoUnit.DAYS)) + .toSignedTransaction() + + val session = flowMessaging.initiateFlow(ownerName) + return utxoLedgerService.finalize(transaction, listOf(session)).transaction.outputStateAndRefs + } +} + +@InitiatedBy(protocol = "OwnableContractUpdateTestFlow") +class OwnableContractDeleteTestResponderFlow : ResponderFlow { + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @Suspendable + override fun call(session: FlowSession) { + utxoLedgerService.receiveFinality(session) { + // accept + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/OwnableStateQueryFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableStateQueryFlow.kt similarity index 95% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/OwnableStateQueryFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableStateQueryFlow.kt index c7601705..04c08923 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/OwnableStateQueryFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/OwnableStateQueryFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.ownable.workflow.query +package com.r3.corda.test.utxo.ownable.workflow import com.r3.corda.ledger.utxo.ownable.query.OwnableStateQueries import net.corda.v5.application.crypto.DigestService @@ -13,9 +13,8 @@ import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.UtxoLedgerService import net.corda.v5.ledger.utxo.query.VaultNamedParameterizedQuery -import com.r3.corda.demo.utxo.ownable.contract.TestOwnableContract -import com.r3.corda.demo.utxo.ownable.contract.TestOwnableState -import com.r3.corda.demo.utxo.ownable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.ownable.contract.TestOwnableContract +import com.r3.corda.test.utxo.ownable.contract.TestOwnableState import java.security.PublicKey import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/WellKnownOwnableStateQueryFlow.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/WellKnownOwnableStateQueryFlow.kt similarity index 95% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/WellKnownOwnableStateQueryFlow.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/WellKnownOwnableStateQueryFlow.kt index 47ec3e95..3ffd724e 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/ownable/workflow/query/WellKnownOwnableStateQueryFlow.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-app/src/main/kotlin/com/r3/corda/test/utxo/ownable/workflow/WellKnownOwnableStateQueryFlow.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.ownable.workflow.query +package com.r3.corda.test.utxo.ownable.workflow import com.r3.corda.ledger.utxo.ownable.query.WellKnownOwnableStateQueries import net.corda.v5.application.flows.ClientRequestBody @@ -11,9 +11,8 @@ import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.UtxoLedgerService import net.corda.v5.ledger.utxo.query.VaultNamedParameterizedQuery -import com.r3.corda.demo.utxo.ownable.contract.TestOwnableContract -import com.r3.corda.demo.utxo.ownable.contract.TestOwnableState -import com.r3.corda.demo.utxo.ownable.workflow.firstLedgerKey +import com.r3.corda.test.utxo.ownable.contract.TestOwnableContract +import com.r3.corda.test.utxo.ownable.contract.TestOwnableState import java.time.Instant import java.time.temporal.ChronoUnit diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/build.gradle b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/build.gradle similarity index 89% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/build.gradle rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/build.gradle index 9c3def4d..02619035 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/build.gradle +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/build.gradle @@ -7,7 +7,7 @@ cordapp { targetPlatformVersion platformVersion as Integer minimumPlatformVersion platformVersion as Integer contract { - name "Advanced UTXO Ledger Demo Ownable Contract" + name "Advanced UTXO Ledger Test Ownable Contract" versionId 1 vendor "R3" } diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyContractState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyContractState.kt new file mode 100644 index 00000000..32d2d100 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyContractState.kt @@ -0,0 +1,16 @@ +package com.r3.corda.test.utxo.ownable.contract + +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.ContractState +import java.security.PublicKey +import java.util.UUID + +@BelongsToContract(TestOwnableContract::class) +data class MyContractState( + val id: UUID, +) : ContractState { + + override fun getParticipants(): List { + return emptyList() + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyOwnableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyOwnableState.kt new file mode 100644 index 00000000..f7ea51d4 --- /dev/null +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/MyOwnableState.kt @@ -0,0 +1,44 @@ +package com.r3.corda.test.utxo.ownable.contract + +import com.r3.corda.ledger.utxo.ownable.OwnableConstraints +import com.r3.corda.ledger.utxo.ownable.OwnableState +import com.r3.corda.ledger.utxo.ownable.WellKnownOwnableState +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.ledger.utxo.BelongsToContract +import net.corda.v5.ledger.utxo.Command +import net.corda.v5.ledger.utxo.Contract +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction +import java.security.PublicKey + +@BelongsToContract(MyOwnableContract::class) +data class MyOwnableState( + private val owner: PublicKey, + private val ownerName: MemberX500Name, + private val participants: List +) : OwnableState, WellKnownOwnableState { + + override fun getParticipants(): List { + return participants + } + + override fun getOwner(): PublicKey { + return owner + } + + override fun getOwnerName(): MemberX500Name { + return ownerName + } +} + +class MyOwnableContract : Contract { + + class Create : Command + class Update : Command + + override fun verify(transaction: UtxoLedgerTransaction) { + val commands = transaction.commands + if (commands.any { it::class.java == Update::class.java }) { + OwnableConstraints.verifyUpdate(transaction) + } + } +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/TestOwnableState.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/TestOwnableState.kt similarity index 91% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/TestOwnableState.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/TestOwnableState.kt index a53800e4..c75d8901 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/TestOwnableState.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/TestOwnableState.kt @@ -1,4 +1,4 @@ -package com.r3.corda.demo.utxo.ownable.contract +package com.r3.corda.test.utxo.ownable.contract import com.r3.corda.ledger.utxo.ownable.OwnableState import com.r3.corda.ledger.utxo.ownable.WellKnownOwnableState @@ -25,14 +25,13 @@ data class TestOwnableState( } override fun getOwnerName(): MemberX500Name { - return ownerName + return ownerName } } class TestOwnableContract : Contract { class Create : Command - class Update : Command class Delete : Command override fun verify(transaction: UtxoLedgerTransaction) { diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt similarity index 79% rename from e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt rename to e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt index 30b00790..1055635c 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-ownable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt +++ b/e2e-tests/cpbs/ledger-utxo-advanced-ownable-test-contract/src/main/kotlin/com/r3/corda/test/utxo/ownable/contract/query/json/TestOwnableStateVaultJsonFactory.kt @@ -1,8 +1,8 @@ -package com.r3.corda.demo.utxo.ownable.contract.query.json +package com.r3.corda.test.utxo.ownable.contract.query.json import net.corda.v5.application.marshalling.JsonMarshallingService import net.corda.v5.ledger.utxo.query.json.ContractStateVaultJsonFactory -import com.r3.corda.demo.utxo.ownable.contract.TestOwnableState +import com.r3.corda.test.utxo.ownable.contract.TestOwnableState class TestOwnableStateVaultJsonFactory : ContractStateVaultJsonFactory { diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/ChainableTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/ChainableTests.kt index bb5eba8f..e6f2de5a 100644 --- a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/ChainableTests.kt +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/ChainableTests.kt @@ -2,6 +2,7 @@ package com.r3.corda.ledger.utxo.e2etest import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_FAILED import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME @@ -23,8 +24,8 @@ import java.util.UUID class ChainableTests { private companion object { - const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-chainable-demo-app" - const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-chainable-demo-app.cpb" + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-chainable-test-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-chainable-test-app.cpb" val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) @@ -76,66 +77,157 @@ class ChainableTests { } @Test - fun `Alice issues vehicle to Bob, bob transfers vehicle to Charlie`() { + fun `chainable contract create command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } - // Alice issues vehicle to Bob - val vehicleId = UUID.randomUUID() + @Test + fun `chainable contract create command CONTRACT_RULE_CREATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_OUTPUTS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On chainable state(s) creating, at least one chainable state must be created.") + } - val issueVehicleFlowRequestId = startRpcFlow( + @Test + fun `chainable contract create command CONTRACT_RULE_CREATE_POINTERS fails`() { + val request = startRpcFlow( aliceHoldingId, mapOf( - "make" to "reliant", - "model" to "robin", - "id" to vehicleId, - "manufacturer" to aliceX500, - "owner" to bobX500, - "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", - "observers" to emptyList() + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_POINTERS" ), - "com.r3.corda.demo.utxo.chainable.workflow.issue.IssueVehicleFlow\$Initiator" + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" ) - val issueVehicleFlowResult = awaitRpcFlowFinished(aliceHoldingId, issueVehicleFlowRequestId) - assertThat(issueVehicleFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(issueVehicleFlowResult.flowError).isNull() - - val issuedVehicleResponse = objectMapper - .readValue(issueVehicleFlowResult.flowResult, VehicleResponse::class.java) - - assertThat(issuedVehicleResponse.make).isEqualTo("reliant") - assertThat(issuedVehicleResponse.model).isEqualTo("robin") - assertThat(issuedVehicleResponse.id).isEqualTo(vehicleId) - assertThat(issuedVehicleResponse.manufacturer).isEqualTo(aliceX500) - assertThat(issuedVehicleResponse.owner).isEqualTo(bobX500) - - // Bob transfers vehicle to Charlie - val transferVehicleRequestId = startRpcFlow( - bobHoldingId, + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On chainable state(s) creating, the previous state pointer of every created chainable state must be null.") + } + + @Test + fun `chainable contract update command valid`() { + val request = startRpcFlow( + aliceHoldingId, mapOf( - "id" to vehicleId, - "owner" to charlieX500, - "observers" to emptyList() + "command" to "UPDATE", + "rule" to "VALID" ), - "com.r3.corda.demo.utxo.chainable.workflow.transfer.TransferVehicleFlow\$Initiator" + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" ) - val transferVehicleFlowResult = awaitRpcFlowFinished(bobHoldingId, transferVehicleRequestId) - assertThat(transferVehicleFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(transferVehicleFlowResult.flowError).isNull() - - val transferVehicleResponse = objectMapper - .readValue(transferVehicleFlowResult.flowResult, VehicleResponse::class.java) - - assertThat(transferVehicleResponse.make).isEqualTo("reliant") - assertThat(transferVehicleResponse.model).isEqualTo("robin") - assertThat(transferVehicleResponse.id).isEqualTo(vehicleId) - assertThat(transferVehicleResponse.manufacturer).isEqualTo(aliceX500) - assertThat(transferVehicleResponse.owner).isEqualTo(charlieX500) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() } - data class VehicleResponse( - val make: String, - val model: String, - val id: UUID, - val manufacturer: String, - val owner: String - ) + @Test + fun `chainable contract update command CONTRACT_RULE_UPDATE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_INPUTS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On chainable state(s) updating, at least one chainable state must be consumed.") + } + + @Test + fun `chainable contract update command CONTRACT_RULE_UPDATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_OUTPUTS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On chainable state(s) updating, at least one chainable state must be created.") + } + + @Test + fun `chainable contract update command CONTRACT_RULE_UPDATE_POINTERS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_POINTERS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On chainable state(s) updating, the previous state pointer of every created chainable state must not be null.") + } + + @Test + fun `chainable contract update command CONTRACT_RULE_UPDATE_EXCLUSIVE_POINTERS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_EXCLUSIVE_POINTERS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On chainable state(s) updating, the previous state pointer of every created chainable state must be pointing to exactly " + + "one consumed chainable state, exclusively." + ) + } + + @Test + fun `chainable contract delete command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `chainable contract delete command CONTRACT_RULE_DELETE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_INPUTS" + ), + "com.r3.corda.test.utxo.chainable.workflow.ChainableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On chainable state(s) deleting, at least one chainable state must be consumed.") + } } diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/FungibleTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/FungibleTests.kt index f83e3c8c..e087bc5a 100644 --- a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/FungibleTests.kt +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/FungibleTests.kt @@ -16,8 +16,8 @@ import java.util.* class FungibleTests { private companion object { - const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-fungible-demo-app" - const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-fungible-demo-app.cpb" + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-fungible-test-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-fungible-test-app.cpb" val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) @@ -73,86 +73,233 @@ class FungibleTests { } @Test - fun `Alice issues a token to Bob, Bob then transfers to Charlie, and then Bob burns some quantity of their token`() { - - // Alice issues tokens to Bob - val mintTokenFlowRequestId = startRpcFlow( + fun `fungible contract create command valid`() { + val request = startRpcFlow( aliceHoldingId, mapOf( - "issuer" to aliceX500, - "owner" to bobX500, - "quantity" to 123.45.toScaledBigDecimal(), - "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", - "observers" to emptyList() + "command" to "CREATE", + "rule" to "VALID" ), - "com.r3.corda.demo.utxo.fungible.workflow.mint.MintTokenFlow\$Initiator" + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" ) - val mintTokenFlowResult = awaitRpcFlowFinished(aliceHoldingId, mintTokenFlowRequestId) - assertThat(mintTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(mintTokenFlowResult.flowError).isNull() + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } - val mintTokenResponse = objectMapper.readValue(mintTokenFlowResult.flowResult, MintTokenResponse::class.java) + @Test + fun `fungible contract create command CONTRACT_RULE_CREATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_OUTPUTS" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On fungible state(s) creating, at least one fungible state must be created.") + } - assertThat(mintTokenResponse.balance.keys).hasSize(1) - assertThat(mintTokenResponse.balance.values).hasSize(1) + @Test + fun `fungible contract create command CONTRACT_RULE_CREATE_POSITIVE_QUANTITIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_POSITIVE_QUANTITIES" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains( + "On fungible state(s) creating, the quantity of every created fungible state must be greater than zero." + ) + } - val owner = mintTokenResponse.balance.keys.single() - val quantity = mintTokenResponse.balance.values.single() + @Test + fun `fungible contract update command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } - assertThat(owner).isEqualTo(bobX500) - assertThat(quantity).isEqualTo( 123.45.toScaledBigDecimal()) + @Test + fun `fungible contract update command CONTRACT_RULE_UPDATE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_INPUTS" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On fungible state(s) updating, at least one fungible state must be consumed.") + } - // Bob transfers tokens to Charlie and receives change - val moveTokenFlowRequestId = startRpcFlow( - bobHoldingId, + @Test + fun `fungible contract update command CONTRACT_RULE_UPDATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, mapOf( - "issuer" to aliceX500, - "owner" to bobX500, - "shares" to mapOf( - charlieX500 to 100.41.toScaledBigDecimal() - ), - "observers" to emptyList() + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_OUTPUTS" ), - "com.r3.corda.demo.utxo.fungible.workflow.move.MoveTokenFlow\$Initiator" + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" ) - val moveTokenFlowResult = awaitRpcFlowFinished(bobHoldingId, moveTokenFlowRequestId) - assertThat(moveTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(moveTokenFlowResult.flowError).isNull() + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On fungible state(s) updating, at least one fungible state must be created.") + } - val moveTokenResponse = objectMapper.readValue(moveTokenFlowResult.flowResult, MoveTokenResponse::class.java) + @Test + fun `fungible contract update command CONTRACT_RULE_UPDATE_POSITIVE_QUANTITIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_POSITIVE_QUANTITIES" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On fungible state(s) updating, the quantity of every created fungible state must be greater than zero.") + } - assertThat(moveTokenResponse.balance.keys).hasSize(2) - assertThat(moveTokenResponse.balance.values).hasSize(2) + @Test + fun `fungible contract update command CONTRACT_RULE_UPDATE_SUM fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_SUM" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On fungible state(s) updating, the sum of the unscaled values of the consumed states must be equal to the sum of the " + + "unscaled values of the created states." + ) + } - assertThat(moveTokenResponse.balance.keys).containsExactlyInAnyOrder(bobX500, charlieX500) - assertThat(moveTokenResponse.balance.values).containsExactlyInAnyOrder( - 100.41.toScaledBigDecimal(), - 23.04.toScaledBigDecimal() + @Test + fun `fungible contract update command CONTRACT_RULE_UPDATE_GROUP_SUM fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_GROUP_SUM" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On fungible state(s) updating, the sum of the consumed states that are fungible with each other must be equal to the " + + "sum of the created states that are fungible with each other." + ) + } - // Bob redeems tokens - val burnTokenFlowRequestId = startRpcFlow( - bobHoldingId, + @Test + fun `fungible contract delete command valid`() { + val request = startRpcFlow( + aliceHoldingId, mapOf( - "issuer" to aliceX500, - "owner" to bobX500, - "quantity" to 20.01.toScaledBigDecimal(), - "observers" to emptyList() + "command" to "DELETE", + "rule" to "VALID" ), - "com.r3.corda.demo.utxo.fungible.workflow.burn.BurnTokenFlow\$Initiator" + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } - val burnTokenFlowResult = awaitRpcFlowFinished(bobHoldingId, burnTokenFlowRequestId) - assertThat(burnTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(burnTokenFlowResult.flowError).isNull() + @Test + fun `fungible contract delete command CONTRACT_RULE_DELETE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_INPUTS" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains("On fungible state(s) deleting, at least one fungible state input must be consumed.") + } - val burnTokenResponse = objectMapper.readValue(burnTokenFlowResult.flowResult, BurnTokenResponse::class.java) + @Test + fun `fungible contract delete command CONTRACT_RULE_DELETE_POSITIVE_QUANTITIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_POSITIVE_QUANTITIES" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message).contains( + "On fungible state(s) deleting, the quantity of every created fungible state must be greater than zero." + ) + } - assertThat(burnTokenResponse.burned).isEqualTo(20.01.toScaledBigDecimal()) - assertThat(burnTokenResponse.change).isEqualTo(3.03.toScaledBigDecimal()) + @Test + fun `fungible contract delete command CONTRACT_RULE_DELETE_SUM fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_SUM" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On fungible state(s) deleting, the sum of the unscaled values of the consumed states must be greater than the sum of " + + "the unscaled values of the created states." + ) } - data class MintTokenResponse(val balance: Map) - data class MoveTokenResponse(val balance: Map) - data class BurnTokenResponse(val quantities: Collection, val burned: BigDecimal, val change: BigDecimal) + @Test + fun `fungible contract delete command CONTRACT_RULE_DELETE_GROUP_SUM fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_GROUP_SUM" + ), + "com.r3.corda.test.utxo.fungible.workflow.FungibleContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On fungible state(s) deleting, the sum of consumed states that are fungible with each other must be greater than the " + + "sum of the created states that are fungible with each other." + ) + } } diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IdentifiableTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IdentifiableTests.kt index 31d551b9..df6e2ae8 100644 --- a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IdentifiableTests.kt +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IdentifiableTests.kt @@ -2,6 +2,7 @@ package com.r3.corda.ledger.utxo.e2etest import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_FAILED import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME @@ -13,6 +14,7 @@ import net.corda.e2etest.utilities.registerStaticMember import net.corda.e2etest.utilities.startRpcFlow import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS @@ -23,8 +25,8 @@ import java.util.UUID class IdentifiableTests { private companion object { - const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-identifiable-demo-app" - const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-identifiable-demo-app.cpb" + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-identifiable-test-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-identifiable-test-app.cpb" val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) @@ -69,96 +71,13 @@ class IdentifiableTests { registerStaticMember(notaryHoldingId, true) } - @Test - fun `Alice issues a support ticket to Bob, Bob opens and completes the ticket, Alice closes the ticket`() { - - val issueSupportTicketRequestId = startRpcFlow( - aliceHoldingId, - mapOf( - "title" to "Build Corda 5", - "description" to "Build super-duper DLT and call it Corda 5", - "reporter" to aliceX500, - "assignee" to bobX500, - "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", - "observers" to emptyList() - ), - "com.r3.corda.demo.utxo.identifiable.workflow.create.CreateSupportTicketFlow\$Initiator" - ) - val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, issueSupportTicketRequestId) - assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(createFlowResponse.flowError).isNull() - - val createSupportTicketResponse = objectMapper - .readValue(createFlowResponse.flowResult, CreateSupportTicketResponse::class.java) - - val openSupportTicketRequestId = startRpcFlow( - bobHoldingId, - mapOf( - "id" to createSupportTicketResponse.id, - "reporter" to aliceX500, - "status" to "OPEN", - "observers" to emptyList() - ), - "com.r3.corda.demo.utxo.identifiable.workflow.update.UpdateSupportTicketFlow\$Initiator" - ) - val openFlowResult = awaitRpcFlowFinished(bobHoldingId, openSupportTicketRequestId) - assertThat(openFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(openFlowResult.flowError).isNull() - - val openSupportTicketResponse = objectMapper - .readValue(openFlowResult.flowResult, UpdateSupportTicketResponse::class.java) - - assertThat(openSupportTicketResponse.id).isEqualTo(createSupportTicketResponse.id) - assertThat(openSupportTicketResponse.title).isEqualTo(createSupportTicketResponse.title) - - val doneSupportTicketRequestId = startRpcFlow( - bobHoldingId, - mapOf( - "id" to openSupportTicketResponse.id, - "reporter" to aliceX500, - "status" to "DONE", - "observers" to emptyList() - ), - "com.r3.corda.demo.utxo.identifiable.workflow.update.UpdateSupportTicketFlow\$Initiator" - ) - val doneFlowResult = awaitRpcFlowFinished(bobHoldingId, doneSupportTicketRequestId) - assertThat(doneFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(doneFlowResult.flowError).isNull() - - val doneSupportTicketResponse = objectMapper - .readValue(doneFlowResult.flowResult, UpdateSupportTicketResponse::class.java) - - assertThat(doneSupportTicketResponse.id).isEqualTo(openSupportTicketResponse.id) - assertThat(doneSupportTicketResponse.title).isEqualTo(openSupportTicketResponse.title) - - val deleteSupportTicketRequestId = startRpcFlow( - aliceHoldingId, - mapOf( - "id" to doneSupportTicketResponse.id, - "assignee" to bobX500, - "observers" to emptyList() - ), - "com.r3.corda.demo.utxo.identifiable.workflow.delete.DeleteSupportTicketFlow\$Initiator" - ) - - val deleteSupportTicketResult = awaitRpcFlowFinished(aliceHoldingId, deleteSupportTicketRequestId) - assertThat(deleteSupportTicketResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) - assertThat(deleteSupportTicketResult.flowError).isNull() - - val deleteSupportTicketResponse = objectMapper - .readValue(doneFlowResult.flowResult, DeleteSupportTicketResponse::class.java) - - assertThat(deleteSupportTicketResponse.id).isEqualTo(doneSupportTicketResponse.id) - assertThat(deleteSupportTicketResponse.title).isEqualTo(doneSupportTicketResponse.title) - } - @Test fun `query identifiable states`() { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.identifiable.workflow.query.IdentifiableStateQueryFlow" + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableStateQueryFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -185,7 +104,7 @@ class IdentifiableTests { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.identifiable.workflow.query.IdentifiablePointerFlow" + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiablePointerFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -206,9 +125,155 @@ class IdentifiableTests { assertThat(response.consumed).isEmpty() } - data class CreateSupportTicketResponse(val id: String, val title: String) - data class UpdateSupportTicketResponse(val id: String, val title: String) - data class DeleteSupportTicketResponse(val id: String, val title: String) + @Test + fun `Identifiable contract create command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Identifiable contract create command CONTRACT_RULE_CREATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_OUTPUTS" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On identifiable state(s) creating, at least one identifiable state must be created.") + } + + @Test + fun `Identifiable contract update command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Identifiable contract update command CONTRACT_RULE_UPDATE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_INPUTS" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On identifiable state(s) updating, at least one identifiable state must be consumed.") + } + + @Test + fun `Identifiable contract update command CONTRACT_RULE_UPDATE_OUTPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_OUTPUTS" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On identifiable state(s) updating, at least one identifiable state must be created.") + } + + @Test + fun `Identifiable contract update command CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On identifiable state(s) updating, each created identifiable state's identifier must match one consumed identifiable " + + "state's state ref or identifier, exclusively." + ) + } + + // TODO Currently broken fixed in CORE-13473 + @Test + @Disabled + fun `Identifiable contract update command CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY MISSING_ID fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_IDENTIFIER_EXCLUSIVITY MISSING_ID" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains( + "On identifiable state(s) updating, each created identifiable state's identifier must match one consumed identifiable " + + "state's state ref or identifier, exclusively." + ) + } + + @Test + fun `Identifiable contract delete command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "VALID" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Identifiable contract delete command CONTRACT_RULE_DELETE_INPUTS fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_INPUTS" + ), + "com.r3.corda.test.utxo.identifiable.workflow.IdentifiableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On identifiable state(s) deleting, at least one identifiable state must be consumed.") + } + data class IdentifiableStateQueryResponse( val before: List, val after: List, diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IssuableTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IssuableTests.kt index 72e40064..cba5bd7b 100644 --- a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IssuableTests.kt +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/IssuableTests.kt @@ -2,6 +2,7 @@ package com.r3.corda.ledger.utxo.e2etest import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_FAILED import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME @@ -23,8 +24,8 @@ import java.util.UUID class IssuableTests { private companion object { - const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-issuable-demo-app" - const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-issuable-demo-app.cpb" + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-issuable-test-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-issuable-test-app.cpb" val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) @@ -75,7 +76,7 @@ class IssuableTests { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.issuable.workflow.query.IssuableStateQueryFlow" + "com.r3.corda.test.utxo.issuable.workflow.IssuableStateQueryFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -95,7 +96,7 @@ class IssuableTests { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.issuable.workflow.query.WellKnownIssuableStateQueryFlow" + "com.r3.corda.test.utxo.issuable.workflow.WellKnownIssuableStateQueryFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -109,6 +110,72 @@ class IssuableTests { assertThat(response.consumed).isEmpty() } + @Test + fun `Issuable contract create command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "VALID", + "issuer" to bobX500 + ), + "com.r3.corda.test.utxo.issuable.workflow.IssuableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Issuable contract create command CONTRACT_RULE_CREATE_SIGNATORIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "CREATE", + "rule" to "CONTRACT_RULE_CREATE_SIGNATORIES", + "issuer" to bobX500 + ), + "com.r3.corda.test.utxo.issuable.workflow.IssuableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On issuable state(s) creating, the issuer of every created issuable state must sign the transaction.") + } + + @Test + fun `Issuable contract delete command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "VALID", + "issuer" to bobX500 + ), + "com.r3.corda.test.utxo.issuable.workflow.IssuableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Issuable contract delete command CONTRACT_RULE_DELETE_SIGNATORIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "DELETE", + "rule" to "CONTRACT_RULE_DELETE_SIGNATORIES", + "issuer" to bobX500 + ), + "com.r3.corda.test.utxo.issuable.workflow.IssuableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On issuable state(s) deleting, the issuer of every consumed issuable state must sign the transaction.") + } + data class IssuableStateQueryResponse( val before: List, val after: List, diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/OwnableTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/OwnableTests.kt index 8295baea..36b70f22 100644 --- a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/OwnableTests.kt +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/OwnableTests.kt @@ -2,6 +2,7 @@ package com.r3.corda.ledger.utxo.e2etest import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_FAILED import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME @@ -23,8 +24,8 @@ import java.util.UUID class OwnableTests { private companion object { - const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-ownable-demo-app" - const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-ownable-demo-app.cpb" + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-ownable-test-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-ownable-test-app.cpb" val objectMapper = ObjectMapper().apply { registerModule(KotlinModule.Builder().build()) @@ -75,7 +76,7 @@ class OwnableTests { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.ownable.workflow.query.OwnableStateQueryFlow" + "com.r3.corda.test.utxo.ownable.workflow.OwnableStateQueryFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -95,7 +96,7 @@ class OwnableTests { val request = startRpcFlow( aliceHoldingId, mapOf(), - "com.r3.corda.demo.utxo.ownable.workflow.query.WellKnownOwnableStateQueryFlow" + "com.r3.corda.test.utxo.ownable.workflow.WellKnownOwnableStateQueryFlow" ) val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, request) assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) @@ -109,6 +110,39 @@ class OwnableTests { assertThat(response.consumed).isEmpty() } + @Test + fun `Ownable contract update command valid`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "VALID", + "owner" to bobX500 + ), + "com.r3.corda.test.utxo.ownable.workflow.OwnableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(response.flowError).isNull() + } + + @Test + fun `Ownable contract update command CONTRACT_RULE_UPDATE_SIGNATORIES fails`() { + val request = startRpcFlow( + aliceHoldingId, + mapOf( + "command" to "UPDATE", + "rule" to "CONTRACT_RULE_UPDATE_SIGNATORIES", + "owner" to bobX500 + ), + "com.r3.corda.test.utxo.ownable.workflow.OwnableContractTestFlow" + ) + val response = awaitRpcFlowFinished(aliceHoldingId, request) + assertThat(response.flowStatus).isEqualTo(RPC_FLOW_STATUS_FAILED) + assertThat(response.flowError?.message) + .contains("On ownable state(s) updating, the owner of every consumed ownable state must sign the transaction.") + } + data class OwnableStateQueryResponse( val before: List, val after: List, diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/ChainableDemoTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/ChainableDemoTests.kt new file mode 100644 index 00000000..e6c16fa1 --- /dev/null +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/ChainableDemoTests.kt @@ -0,0 +1,142 @@ +package com.r3.corda.ledger.utxo.e2etest.demo + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.r3.corda.ledger.utxo.e2etest.uploadTrustedCertificate +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS +import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION +import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME +import net.corda.e2etest.utilities.awaitRpcFlowFinished +import net.corda.e2etest.utilities.conditionallyUploadCordaPackage +import net.corda.e2etest.utilities.getHoldingIdShortHash +import net.corda.e2etest.utilities.getOrCreateVirtualNodeFor +import net.corda.e2etest.utilities.registerStaticMember +import net.corda.e2etest.utilities.startRpcFlow +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import java.util.UUID + +@Suppress("Unused", "FunctionName") +@TestInstance(PER_CLASS) +class ChainableDemoTests { + + private companion object { + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-chainable-demo-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-chainable-demo-app.cpb" + + val objectMapper = ObjectMapper().apply { + registerModule(KotlinModule.Builder().build()) + } + } + + private val testRunUniqueId = UUID.randomUUID() + private val groupId = UUID.randomUUID().toString() + private val cpiName = "${TEST_CPI_NAME}_$testRunUniqueId" + private val notaryCpiName = "${TEST_NOTARY_CPI_NAME}_$testRunUniqueId" + + private val aliceX500 = "CN=Alice-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val bobX500 = "CN=Bob-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val charlieX500 = "CN=Charlie-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val notaryX500 = "CN=Notary-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + + private val aliceHoldingId: String = getHoldingIdShortHash(aliceX500, groupId) + private val bobHoldingId: String = getHoldingIdShortHash(bobX500, groupId) + private val charlieHoldingId: String = getHoldingIdShortHash(charlieX500, groupId) + private val notaryHoldingId: String = getHoldingIdShortHash(notaryX500, groupId) + + private val staticMemberList = listOf( + aliceX500, + bobX500, + charlieX500, + notaryX500 + ) + + @BeforeAll + fun beforeAll() { + uploadTrustedCertificate() + conditionallyUploadCordaPackage(cpiName, TEST_CPB_LOCATION, groupId, staticMemberList) + conditionallyUploadCordaPackage(notaryCpiName, TEST_NOTARY_CPB_LOCATION, groupId, staticMemberList) + + val aliceActualHoldingId = getOrCreateVirtualNodeFor(aliceX500, cpiName) + val bobActualHoldingId = getOrCreateVirtualNodeFor(bobX500, cpiName) + val charlieActualHoldingId = getOrCreateVirtualNodeFor(charlieX500, cpiName) + val notaryActualHoldingId = getOrCreateVirtualNodeFor(notaryX500, notaryCpiName) + + assertThat(aliceActualHoldingId).isEqualTo(aliceHoldingId) + assertThat(bobActualHoldingId).isEqualTo(bobHoldingId) + assertThat(charlieActualHoldingId).isEqualTo(charlieHoldingId) + assertThat(notaryActualHoldingId).isEqualTo(notaryHoldingId) + + registerStaticMember(aliceHoldingId) + registerStaticMember(bobHoldingId) + registerStaticMember(charlieHoldingId) + registerStaticMember(notaryHoldingId, true) + } + + @Test + fun `Alice issues vehicle to Bob, bob transfers vehicle to Charlie`() { + + // Alice issues vehicle to Bob + val vehicleId = UUID.randomUUID() + + val issueVehicleFlowRequestId = startRpcFlow( + aliceHoldingId, + mapOf( + "make" to "reliant", + "model" to "robin", + "id" to vehicleId, + "manufacturer" to aliceX500, + "owner" to bobX500, + "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.chainable.workflow.issue.IssueVehicleFlow\$Initiator" + ) + val issueVehicleFlowResult = awaitRpcFlowFinished(aliceHoldingId, issueVehicleFlowRequestId) + assertThat(issueVehicleFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(issueVehicleFlowResult.flowError).isNull() + + val issuedVehicleResponse = objectMapper + .readValue(issueVehicleFlowResult.flowResult, VehicleResponse::class.java) + + assertThat(issuedVehicleResponse.make).isEqualTo("reliant") + assertThat(issuedVehicleResponse.model).isEqualTo("robin") + assertThat(issuedVehicleResponse.id).isEqualTo(vehicleId) + assertThat(issuedVehicleResponse.manufacturer).isEqualTo(aliceX500) + assertThat(issuedVehicleResponse.owner).isEqualTo(bobX500) + + // Bob transfers vehicle to Charlie + val transferVehicleRequestId = startRpcFlow( + bobHoldingId, + mapOf( + "id" to vehicleId, + "owner" to charlieX500, + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.chainable.workflow.transfer.TransferVehicleFlow\$Initiator" + ) + val transferVehicleFlowResult = awaitRpcFlowFinished(bobHoldingId, transferVehicleRequestId) + assertThat(transferVehicleFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(transferVehicleFlowResult.flowError).isNull() + + val transferVehicleResponse = objectMapper + .readValue(transferVehicleFlowResult.flowResult, VehicleResponse::class.java) + + assertThat(transferVehicleResponse.make).isEqualTo("reliant") + assertThat(transferVehicleResponse.model).isEqualTo("robin") + assertThat(transferVehicleResponse.id).isEqualTo(vehicleId) + assertThat(transferVehicleResponse.manufacturer).isEqualTo(aliceX500) + assertThat(transferVehicleResponse.owner).isEqualTo(charlieX500) + } + + data class VehicleResponse( + val make: String, + val model: String, + val id: UUID, + val manufacturer: String, + val owner: String + ) +} diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/FungibleDemoTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/FungibleDemoTests.kt new file mode 100644 index 00000000..f1fe56bf --- /dev/null +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/FungibleDemoTests.kt @@ -0,0 +1,159 @@ +package com.r3.corda.ledger.utxo.e2etest.demo + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.r3.corda.ledger.utxo.e2etest.uploadTrustedCertificate +import net.corda.e2etest.utilities.* +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import java.math.BigDecimal +import java.util.* + +@Suppress("Unused", "FunctionName") +@TestInstance(PER_CLASS) +class FungibleDemoTests { + + private companion object { + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-fungible-demo-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-fungible-demo-app.cpb" + + val objectMapper = ObjectMapper().apply { + registerModule(KotlinModule.Builder().build()) + } + } + + private val testRunUniqueId = UUID.randomUUID() + private val groupId = UUID.randomUUID().toString() + private val cpiName = "${TEST_CPI_NAME}_$testRunUniqueId" + private val notaryCpiName = "${TEST_NOTARY_CPI_NAME}_$testRunUniqueId" + + private val aliceX500 = "CN=Alice-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val bobX500 = "CN=Bob-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val charlieX500 = "CN=Charlie-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val notaryX500 = "CN=Notary-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + + private val aliceHoldingId: String = getHoldingIdShortHash(aliceX500, groupId) + private val bobHoldingId: String = getHoldingIdShortHash(bobX500, groupId) + private val charlieHoldingId: String = getHoldingIdShortHash(charlieX500, groupId) + private val notaryHoldingId: String = getHoldingIdShortHash(notaryX500, groupId) + + private val staticMemberList = listOf( + aliceX500, + bobX500, + charlieX500, + notaryX500 + ) + + private fun Double.toScaledBigDecimal(scale: Int = 2): BigDecimal { + return this.toBigDecimal().setScale(scale) + } + + @BeforeAll + fun beforeAll() { + uploadTrustedCertificate() + conditionallyUploadCordaPackage(cpiName, TEST_CPB_LOCATION, groupId, staticMemberList) + conditionallyUploadCordaPackage(notaryCpiName, TEST_NOTARY_CPB_LOCATION, groupId, staticMemberList) + + val aliceActualHoldingId = getOrCreateVirtualNodeFor(aliceX500, cpiName) + val bobActualHoldingId = getOrCreateVirtualNodeFor(bobX500, cpiName) + val charlieActualHoldingId = getOrCreateVirtualNodeFor(charlieX500, cpiName) + val notaryActualHoldingId = getOrCreateVirtualNodeFor(notaryX500, notaryCpiName) + + assertThat(aliceActualHoldingId).isEqualTo(aliceHoldingId) + assertThat(bobActualHoldingId).isEqualTo(bobHoldingId) + assertThat(charlieActualHoldingId).isEqualTo(charlieHoldingId) + assertThat(notaryActualHoldingId).isEqualTo(notaryHoldingId) + + registerStaticMember(aliceHoldingId) + registerStaticMember(bobHoldingId) + registerStaticMember(charlieHoldingId) + registerStaticMember(notaryHoldingId, true) + } + + @Test + fun `Alice issues a token to Bob, Bob then transfers to Charlie, and then Bob burns some quantity of their token`() { + + // Alice issues tokens to Bob + val mintTokenFlowRequestId = startRpcFlow( + aliceHoldingId, + mapOf( + "issuer" to aliceX500, + "owner" to bobX500, + "quantity" to 123.45.toScaledBigDecimal(), + "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.fungible.workflow.mint.MintTokenFlow\$Initiator" + ) + val mintTokenFlowResult = awaitRpcFlowFinished(aliceHoldingId, mintTokenFlowRequestId) + assertThat(mintTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(mintTokenFlowResult.flowError).isNull() + + val mintTokenResponse = objectMapper.readValue(mintTokenFlowResult.flowResult, MintTokenResponse::class.java) + + assertThat(mintTokenResponse.balance.keys).hasSize(1) + assertThat(mintTokenResponse.balance.values).hasSize(1) + + val owner = mintTokenResponse.balance.keys.single() + val quantity = mintTokenResponse.balance.values.single() + + assertThat(owner).isEqualTo(bobX500) + assertThat(quantity).isEqualTo(123.45.toScaledBigDecimal()) + + // Bob transfers tokens to Charlie and receives change + val moveTokenFlowRequestId = startRpcFlow( + bobHoldingId, + mapOf( + "issuer" to aliceX500, + "owner" to bobX500, + "shares" to mapOf( + charlieX500 to 100.41.toScaledBigDecimal() + ), + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.fungible.workflow.move.MoveTokenFlow\$Initiator" + ) + val moveTokenFlowResult = awaitRpcFlowFinished(bobHoldingId, moveTokenFlowRequestId) + assertThat(moveTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(moveTokenFlowResult.flowError).isNull() + + val moveTokenResponse = objectMapper.readValue(moveTokenFlowResult.flowResult, MoveTokenResponse::class.java) + + assertThat(moveTokenResponse.balance.keys).hasSize(2) + assertThat(moveTokenResponse.balance.values).hasSize(2) + + assertThat(moveTokenResponse.balance.keys).containsExactlyInAnyOrder(bobX500, charlieX500) + assertThat(moveTokenResponse.balance.values).containsExactlyInAnyOrder( + 100.41.toScaledBigDecimal(), + 23.04.toScaledBigDecimal() + ) + + // Bob redeems tokens + val burnTokenFlowRequestId = startRpcFlow( + bobHoldingId, + mapOf( + "issuer" to aliceX500, + "owner" to bobX500, + "quantity" to 20.01.toScaledBigDecimal(), + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.fungible.workflow.burn.BurnTokenFlow\$Initiator" + ) + + val burnTokenFlowResult = awaitRpcFlowFinished(bobHoldingId, burnTokenFlowRequestId) + assertThat(burnTokenFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(burnTokenFlowResult.flowError).isNull() + + val burnTokenResponse = objectMapper.readValue(burnTokenFlowResult.flowResult, BurnTokenResponse::class.java) + + assertThat(burnTokenResponse.burned).isEqualTo(20.01.toScaledBigDecimal()) + assertThat(burnTokenResponse.change).isEqualTo(3.03.toScaledBigDecimal()) + } + + data class MintTokenResponse(val balance: Map) + data class MoveTokenResponse(val balance: Map) + data class BurnTokenResponse(val quantities: Collection, val burned: BigDecimal, val change: BigDecimal) +} diff --git a/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/IdentifiableDemoTests.kt b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/IdentifiableDemoTests.kt new file mode 100644 index 00000000..70b464ba --- /dev/null +++ b/e2e-tests/src/e2eTest/kotlin/com/r3/corda/ledger/utxo/e2etest/demo/IdentifiableDemoTests.kt @@ -0,0 +1,159 @@ +package com.r3.corda.ledger.utxo.e2etest.demo + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.r3.corda.ledger.utxo.e2etest.uploadTrustedCertificate +import net.corda.e2etest.utilities.RPC_FLOW_STATUS_SUCCESS +import net.corda.e2etest.utilities.TEST_NOTARY_CPB_LOCATION +import net.corda.e2etest.utilities.TEST_NOTARY_CPI_NAME +import net.corda.e2etest.utilities.awaitRpcFlowFinished +import net.corda.e2etest.utilities.conditionallyUploadCordaPackage +import net.corda.e2etest.utilities.getHoldingIdShortHash +import net.corda.e2etest.utilities.getOrCreateVirtualNodeFor +import net.corda.e2etest.utilities.registerStaticMember +import net.corda.e2etest.utilities.startRpcFlow +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import java.util.UUID + +@Suppress("Unused", "FunctionName") +@TestInstance(PER_CLASS) +class IdentifiableDemoTests { + + private companion object { + const val TEST_CPI_NAME = "corda-ledger-extensions-ledger-utxo-advanced-identifiable-demo-app" + const val TEST_CPB_LOCATION = "/META-INF/corda-ledger-extensions-ledger-utxo-advanced-identifiable-demo-app.cpb" + + val objectMapper = ObjectMapper().apply { + registerModule(KotlinModule.Builder().build()) + } + } + + private val testRunUniqueId = UUID.randomUUID() + private val groupId = UUID.randomUUID().toString() + private val cpiName = "${TEST_CPI_NAME}_$testRunUniqueId" + private val notaryCpiName = "${TEST_NOTARY_CPI_NAME}_$testRunUniqueId" + + private val aliceX500 = "CN=Alice-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val bobX500 = "CN=Bob-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + private val notaryX500 = "CN=Notary-${testRunUniqueId}, OU=Application, O=R3, L=London, C=GB" + + private val aliceHoldingId: String = getHoldingIdShortHash(aliceX500, groupId) + private val bobHoldingId: String = getHoldingIdShortHash(bobX500, groupId) + private val notaryHoldingId: String = getHoldingIdShortHash(notaryX500, groupId) + + private val staticMemberList = listOf( + aliceX500, + bobX500, + notaryX500 + ) + + @BeforeAll + fun beforeAll() { + uploadTrustedCertificate() + conditionallyUploadCordaPackage(cpiName, TEST_CPB_LOCATION, groupId, staticMemberList) + conditionallyUploadCordaPackage(notaryCpiName, TEST_NOTARY_CPB_LOCATION, groupId, staticMemberList) + + val aliceActualHoldingId = getOrCreateVirtualNodeFor(aliceX500, cpiName) + val bobActualHoldingId = getOrCreateVirtualNodeFor(bobX500, cpiName) + val notaryActualHoldingId = getOrCreateVirtualNodeFor(notaryX500, notaryCpiName) + + assertThat(aliceActualHoldingId).isEqualTo(aliceHoldingId) + assertThat(bobActualHoldingId).isEqualTo(bobHoldingId) + assertThat(notaryActualHoldingId).isEqualTo(notaryHoldingId) + + registerStaticMember(aliceHoldingId) + registerStaticMember(bobHoldingId) + registerStaticMember(notaryHoldingId, true) + } + + @Test + fun `Alice issues a support ticket to Bob, Bob opens and completes the ticket, Alice closes the ticket`() { + + val issueSupportTicketRequestId = startRpcFlow( + aliceHoldingId, + mapOf( + "title" to "Build Corda 5", + "description" to "Build super-duper DLT and call it Corda 5", + "reporter" to aliceX500, + "assignee" to bobX500, + "notary" to "O=MyNotaryService-$notaryHoldingId, L=London, C=GB", + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.identifiable.workflow.create.CreateSupportTicketFlow\$Initiator" + ) + val createFlowResponse = awaitRpcFlowFinished(aliceHoldingId, issueSupportTicketRequestId) + assertThat(createFlowResponse.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(createFlowResponse.flowError).isNull() + + val createSupportTicketResponse = objectMapper + .readValue(createFlowResponse.flowResult, CreateSupportTicketResponse::class.java) + + val openSupportTicketRequestId = startRpcFlow( + bobHoldingId, + mapOf( + "id" to createSupportTicketResponse.id, + "reporter" to aliceX500, + "status" to "OPEN", + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.identifiable.workflow.update.UpdateSupportTicketFlow\$Initiator" + ) + val openFlowResult = awaitRpcFlowFinished(bobHoldingId, openSupportTicketRequestId) + assertThat(openFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(openFlowResult.flowError).isNull() + + val openSupportTicketResponse = objectMapper + .readValue(openFlowResult.flowResult, UpdateSupportTicketResponse::class.java) + + assertThat(openSupportTicketResponse.id).isEqualTo(createSupportTicketResponse.id) + assertThat(openSupportTicketResponse.title).isEqualTo(createSupportTicketResponse.title) + + val doneSupportTicketRequestId = startRpcFlow( + bobHoldingId, + mapOf( + "id" to openSupportTicketResponse.id, + "reporter" to aliceX500, + "status" to "DONE", + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.identifiable.workflow.update.UpdateSupportTicketFlow\$Initiator" + ) + val doneFlowResult = awaitRpcFlowFinished(bobHoldingId, doneSupportTicketRequestId) + assertThat(doneFlowResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(doneFlowResult.flowError).isNull() + + val doneSupportTicketResponse = objectMapper + .readValue(doneFlowResult.flowResult, UpdateSupportTicketResponse::class.java) + + assertThat(doneSupportTicketResponse.id).isEqualTo(openSupportTicketResponse.id) + assertThat(doneSupportTicketResponse.title).isEqualTo(openSupportTicketResponse.title) + + val deleteSupportTicketRequestId = startRpcFlow( + aliceHoldingId, + mapOf( + "id" to doneSupportTicketResponse.id, + "assignee" to bobX500, + "observers" to emptyList() + ), + "com.r3.corda.demo.utxo.identifiable.workflow.delete.DeleteSupportTicketFlow\$Initiator" + ) + + val deleteSupportTicketResult = awaitRpcFlowFinished(aliceHoldingId, deleteSupportTicketRequestId) + assertThat(deleteSupportTicketResult.flowStatus).isEqualTo(RPC_FLOW_STATUS_SUCCESS) + assertThat(deleteSupportTicketResult.flowError).isNull() + + val deleteSupportTicketResponse = objectMapper + .readValue(doneFlowResult.flowResult, DeleteSupportTicketResponse::class.java) + + assertThat(deleteSupportTicketResponse.id).isEqualTo(doneSupportTicketResponse.id) + assertThat(deleteSupportTicketResponse.title).isEqualTo(doneSupportTicketResponse.title) + } + + data class CreateSupportTicketResponse(val id: String, val title: String) + data class UpdateSupportTicketResponse(val id: String, val title: String) + data class DeleteSupportTicketResponse(val id: String, val title: String) +} diff --git a/examples/ledger-utxo-advanced-chainable-demo-app/build.gradle b/examples/ledger-utxo-advanced-chainable-demo-app/build.gradle new file mode 100644 index 00000000..61134994 --- /dev/null +++ b/examples/ledger-utxo-advanced-chainable-demo-app/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpb2' +} + +cordapp { + targetPlatformVersion platformVersion as Integer + minimumPlatformVersion platformVersion as Integer + workflow { + name "Advanced UTXO Ledger Demo Chainable Workflow" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(':examples:ledger-utxo-advanced-chainable-demo-contract') + + // Common and API packages pulled in as transitive dependencies through client + cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/AppLogger.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/AppLogger.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/AppLogger.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/AppLogger.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberInfoExtensions.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberInfoExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberInfoExtensions.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberInfoExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberLookupExtensions.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberLookupExtensions.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/MemberLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/NotaryLookupExtensions.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/NotaryLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/NotaryLookupExtensions.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/NotaryLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/UtxoTransactionBuilderExtensions.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/UtxoTransactionBuilderExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/UtxoTransactionBuilderExtensions.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/UtxoTransactionBuilderExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlow.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlow.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlowResponder.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlowResponder.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleRequest.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleRequest.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleResponse.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleResponse.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/issue/IssueVehicleResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlow.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlow.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlowResponder.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlowResponder.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleRequest.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleRequest.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleResponse.kt b/examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleResponse.kt rename to examples/ledger-utxo-advanced-chainable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/chainable/workflow/transfer/TransferVehicleResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/build.gradle b/examples/ledger-utxo-advanced-chainable-demo-contract/build.gradle similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/build.gradle rename to examples/ledger-utxo-advanced-chainable-demo-contract/build.gradle diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/StateAndRefExtensions.kt b/examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/StateAndRefExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/StateAndRefExtensions.kt rename to examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/StateAndRefExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/Vehicle.kt b/examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/Vehicle.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/Vehicle.kt rename to examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/Vehicle.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/VehicleContract.kt b/examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/VehicleContract.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/VehicleContract.kt rename to examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/VehicleContract.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/query/json/VehicleVaultJsonFactory.kt b/examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/query/json/VehicleVaultJsonFactory.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/query/json/VehicleVaultJsonFactory.kt rename to examples/ledger-utxo-advanced-chainable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/chainable/contract/query/json/VehicleVaultJsonFactory.kt diff --git a/examples/ledger-utxo-advanced-fungible-demo-app/build.gradle b/examples/ledger-utxo-advanced-fungible-demo-app/build.gradle new file mode 100644 index 00000000..72c61b4d --- /dev/null +++ b/examples/ledger-utxo-advanced-fungible-demo-app/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpb2' +} + +cordapp { + targetPlatformVersion platformVersion.toInteger() + minimumPlatformVersion platformVersion.toInteger() + workflow { + name "Advanced UTXO Ledger Demo Fungible Workflow" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(":fungible") + + cordapp project(':examples:ledger-utxo-advanced-fungible-demo-contract') + + // Common and API packages pulled in as transitive dependencies through client + cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/AppLogger.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/AppLogger.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/AppLogger.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/AppLogger.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberInfoExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberInfoExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberInfoExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberInfoExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberLookupExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberLookupExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/MemberLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NotaryLookupExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NotaryLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NotaryLookupExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NotaryLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NumericExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NumericExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NumericExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/NumericExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoLedgerServiceExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoLedgerServiceExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoLedgerServiceExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoLedgerServiceExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoTransactionBuilderExtensions.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoTransactionBuilderExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoTransactionBuilderExtensions.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/UtxoTransactionBuilderExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlow.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlow.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlowResponder.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlowResponder.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenRequest.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenRequest.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenResponse.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenResponse.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenSelector.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenSelector.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenSelector.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/burn/BurnTokenSelector.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlow.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlow.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlowResponder.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlowResponder.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenRequest.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenRequest.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenResponse.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenResponse.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/mint/MintTokenResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlow.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlow.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlowResponder.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlowResponder.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenRequest.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenRequest.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenResponse.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenResponse.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenSelector.kt b/examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenSelector.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenSelector.kt rename to examples/ledger-utxo-advanced-fungible-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/fungible/workflow/move/MoveTokenSelector.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/build.gradle b/examples/ledger-utxo-advanced-fungible-demo-contract/build.gradle similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/build.gradle rename to examples/ledger-utxo-advanced-fungible-demo-contract/build.gradle diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/Token.kt b/examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/Token.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/Token.kt rename to examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/Token.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/TokenContract.kt b/examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/TokenContract.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/TokenContract.kt rename to examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/TokenContract.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/query/json/TokenVaultJsonFactory.kt b/examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/query/json/TokenVaultJsonFactory.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/query/json/TokenVaultJsonFactory.kt rename to examples/ledger-utxo-advanced-fungible-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/fungible/contract/query/json/TokenVaultJsonFactory.kt diff --git a/examples/ledger-utxo-advanced-identifiable-demo-app/build.gradle b/examples/ledger-utxo-advanced-identifiable-demo-app/build.gradle new file mode 100644 index 00000000..3d16b014 --- /dev/null +++ b/examples/ledger-utxo-advanced-identifiable-demo-app/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'net.corda.plugins.cordapp-cpb2' +} + +cordapp { + targetPlatformVersion platformVersion.toInteger() + minimumPlatformVersion platformVersion.toInteger() + workflow { + name "Advanced UTXO Ledger Demo Identifiable Workflow" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'net.corda:corda-ledger-utxo' + + cordapp project(':examples:ledger-utxo-advanced-identifiable-demo-contract') + + // Common and API packages pulled in as transitive dependencies through client + cordapp "com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-client:$cordaNotaryPluginsVersion" +} diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/AppLogger.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/AppLogger.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/AppLogger.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/AppLogger.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberInfoExtensions.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberInfoExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberInfoExtensions.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberInfoExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberLookupExtensions.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberLookupExtensions.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/MemberLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/NotaryLookupExtensions.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/NotaryLookupExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/NotaryLookupExtensions.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/NotaryLookupExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/UtxoTransactionBuilderExtensions.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/UtxoTransactionBuilderExtensions.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/UtxoTransactionBuilderExtensions.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/UtxoTransactionBuilderExtensions.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlow.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlow.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlow.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlow.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlowResponder.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlowResponder.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketRequest.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketRequest.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketRequest.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketRequest.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketResponse.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketResponse.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/create/CreateSupportTicketResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt similarity index 98% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt index 706c7316..c6e75df5 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt +++ b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlow.kt @@ -1,6 +1,5 @@ package com.r3.corda.demo.utxo.identifiable.workflow.delete -import net.corda.v5.application.crypto.DigestService import net.corda.v5.application.flows.ClientRequestBody import net.corda.v5.application.flows.ClientStartableFlow import net.corda.v5.application.flows.CordaInject diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlowResponder.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlowResponder.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt similarity index 93% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt index dfe67334..e02c48cd 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt +++ b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketRequest.kt @@ -1,13 +1,11 @@ package com.r3.corda.demo.utxo.identifiable.workflow.delete import com.r3.corda.ledger.utxo.identifiable.query.IdentifiableStateQueries -import net.corda.v5.application.crypto.DigestService import net.corda.v5.application.messaging.FlowMessaging import net.corda.v5.application.messaging.FlowSession import net.corda.v5.base.annotations.Suspendable import net.corda.v5.base.types.MemberX500Name import net.corda.v5.ledger.utxo.StateAndRef -import net.corda.v5.ledger.utxo.StateRef import net.corda.v5.ledger.utxo.UtxoLedgerService import com.r3.corda.demo.utxo.identifiable.contract.SupportTicket import java.time.Instant diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketResponse.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketResponse.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/delete/DeleteSupportTicketResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt similarity index 98% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt index e8e53621..00ac264a 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt +++ b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlow.kt @@ -1,6 +1,5 @@ package com.r3.corda.demo.utxo.identifiable.workflow.update -import net.corda.v5.application.crypto.DigestService import net.corda.v5.application.flows.ClientRequestBody import net.corda.v5.application.flows.ClientStartableFlow import net.corda.v5.application.flows.CordaInject diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlowResponder.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlowResponder.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlowResponder.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketFlowResponder.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt similarity index 94% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt index d61327a7..56d00db0 100644 --- a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt +++ b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketRequest.kt @@ -1,13 +1,11 @@ package com.r3.corda.demo.utxo.identifiable.workflow.update import com.r3.corda.ledger.utxo.identifiable.query.IdentifiableStateQueries -import net.corda.v5.application.crypto.DigestService import net.corda.v5.application.messaging.FlowMessaging import net.corda.v5.application.messaging.FlowSession import net.corda.v5.base.annotations.Suspendable import net.corda.v5.base.types.MemberX500Name import net.corda.v5.ledger.utxo.StateAndRef -import net.corda.v5.ledger.utxo.StateRef import net.corda.v5.ledger.utxo.UtxoLedgerService import com.r3.corda.demo.utxo.identifiable.contract.SupportTicket import com.r3.corda.demo.utxo.identifiable.contract.SupportTicketStatus diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketResponse.kt b/examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketResponse.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketResponse.kt rename to examples/ledger-utxo-advanced-identifiable-demo-app/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/workflow/update/UpdateSupportTicketResponse.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/build.gradle b/examples/ledger-utxo-advanced-identifiable-demo-contract/build.gradle similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/build.gradle rename to examples/ledger-utxo-advanced-identifiable-demo-contract/build.gradle diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicket.kt b/examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicket.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicket.kt rename to examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicket.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketContract.kt b/examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketContract.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketContract.kt rename to examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketContract.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketStatus.kt b/examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketStatus.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketStatus.kt rename to examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/SupportTicketStatus.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/TestIdentifiableState.kt b/examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/TestIdentifiableState.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/TestIdentifiableState.kt rename to examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/TestIdentifiableState.kt diff --git a/e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/query/json/SupportTicketVaultJsonFactory.kt b/examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/query/json/SupportTicketVaultJsonFactory.kt similarity index 100% rename from e2e-tests/cpbs/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/query/json/SupportTicketVaultJsonFactory.kt rename to examples/ledger-utxo-advanced-identifiable-demo-contract/src/main/kotlin/com/r3/corda/demo/utxo/identifiable/contract/query/json/SupportTicketVaultJsonFactory.kt diff --git a/fungible/src/main/java/com/r3/corda/ledger/utxo/fungible/FungibleConstraints.java b/fungible/src/main/java/com/r3/corda/ledger/utxo/fungible/FungibleConstraints.java index fe9caf2b..8aef9840 100644 --- a/fungible/src/main/java/com/r3/corda/ledger/utxo/fungible/FungibleConstraints.java +++ b/fungible/src/main/java/com/r3/corda/ledger/utxo/fungible/FungibleConstraints.java @@ -115,7 +115,11 @@ public static > void verifyUpdate(@NotNull final Utxo Check.isNotEmpty(inputs, CONTRACT_RULE_UPDATE_INPUTS); Check.isNotEmpty(outputs, CONTRACT_RULE_UPDATE_OUTPUTS); Check.all(outputs, it -> it.getQuantity().getUnscaledValue().compareTo(BigInteger.ZERO) > 0, CONTRACT_RULE_UPDATE_POSITIVE_QUANTITIES); - Check.isEqual(FungibleUtils.sum(inputs), FungibleUtils.sum(outputs), CONTRACT_RULE_UPDATE_SUM); + + BigInteger inputsSum = FungibleUtils.sum(inputs); + BigInteger outputsSum = FungibleUtils.sum(outputs); + + Check.isEqual(inputsSum, outputsSum, CONTRACT_RULE_UPDATE_SUM); for (final T input : inputs) { @@ -174,6 +178,7 @@ public static > void verifyDelete(@NotNull final Utxo Check.isNotEmpty(inputs, CONTRACT_RULE_DELETE_INPUTS); Check.all(outputs, it -> it.getQuantity().getUnscaledValue().compareTo(BigInteger.ZERO) > 0, CONTRACT_RULE_DELETE_POSITIVE_QUANTITIES); + Check.isGreaterThan(FungibleUtils.sum(inputs), FungibleUtils.sum(outputs), CONTRACT_RULE_DELETE_SUM); // We have to check all inputs and outputs, because we might create an extra output for which there is no input. diff --git a/settings.gradle b/settings.gradle index 049327f8..cc92b28f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -71,22 +71,27 @@ rootProject.name = 'corda-utxo-ledger-extensions' include 'base' include 'chainable' +include 'examples:ledger-utxo-advanced-chainable-demo-app' +include 'examples:ledger-utxo-advanced-chainable-demo-contract' +include 'examples:ledger-utxo-advanced-fungible-demo-app' +include 'examples:ledger-utxo-advanced-fungible-demo-contract' +include 'examples:ledger-utxo-advanced-identifiable-demo-app' +include 'examples:ledger-utxo-advanced-identifiable-demo-contract' include 'e2e-tests' -include 'e2e-tests:cpbs:ledger-utxo-advanced-chainable-demo-app' -include 'e2e-tests:cpbs:ledger-utxo-advanced-chainable-demo-contract' -include 'e2e-tests:cpbs:ledger-utxo-advanced-fungible-demo-app' -include 'e2e-tests:cpbs:ledger-utxo-advanced-fungible-demo-contract' -include 'e2e-tests:cpbs:ledger-utxo-advanced-identifiable-demo-app' -include 'e2e-tests:cpbs:ledger-utxo-advanced-identifiable-demo-contract' -include 'e2e-tests:cpbs:ledger-utxo-advanced-issuable-demo-app' -include 'e2e-tests:cpbs:ledger-utxo-advanced-issuable-demo-contract' -include 'e2e-tests:cpbs:ledger-utxo-advanced-ownable-demo-app' -include 'e2e-tests:cpbs:ledger-utxo-advanced-ownable-demo-contract' +include 'e2e-tests:cpbs:ledger-utxo-advanced-chainable-test-app' +include 'e2e-tests:cpbs:ledger-utxo-advanced-chainable-test-contract' +include 'e2e-tests:cpbs:ledger-utxo-advanced-fungible-test-app' +include 'e2e-tests:cpbs:ledger-utxo-advanced-fungible-test-contract' +include 'e2e-tests:cpbs:ledger-utxo-advanced-identifiable-test-app' +include 'e2e-tests:cpbs:ledger-utxo-advanced-identifiable-test-contract' +include 'e2e-tests:cpbs:ledger-utxo-advanced-issuable-test-app' +include 'e2e-tests:cpbs:ledger-utxo-advanced-issuable-test-contract' +include 'e2e-tests:cpbs:ledger-utxo-advanced-ownable-test-app' +include 'e2e-tests:cpbs:ledger-utxo-advanced-ownable-test-contract' include 'fungible' include 'identifiable' include 'issuable' include 'ownable' - include 'testing' gradleEnterprise {