Remove CashFlow

Remove the CashFlow flow, replacing it with CashFlowCommand which can be used for the use-cases
with instructions passed around as an object.
This commit is contained in:
Ross Nicoll 2017-02-03 14:07:45 +00:00 committed by Chris Rankin
parent 04e41b5ed4
commit 56387a2831
14 changed files with 147 additions and 152 deletions

View File

@ -10,6 +10,9 @@ import net.corda.core.random63BitValue
import net.corda.core.serialization.OpaqueBytes
import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow
import net.corda.node.driver.DriverBasedTest
import net.corda.node.driver.NodeHandle
import net.corda.node.driver.driver
import net.corda.node.internal.Node
import net.corda.node.services.User
import net.corda.node.services.config.configureTestSSL

View File

@ -19,7 +19,9 @@ import net.corda.core.node.services.StateMachineTransactionMapping
import net.corda.core.node.services.Vault
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import net.corda.flows.CashFlow
import net.corda.flows.CashExitFlow
import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow
import net.corda.node.driver.DriverBasedTest
import net.corda.node.driver.driver
import net.corda.node.services.User
@ -48,7 +50,11 @@ class NodeMonitorModelTest : DriverBasedTest() {
lateinit var newNode: (String) -> NodeInfo
override fun setup() = driver {
val cashUser = User("user1", "test", permissions = setOf(startFlowPermission<CashFlow>()))
val cashUser = User("user1", "test", permissions = setOf(
startFlowPermission<CashIssueFlow>(),
startFlowPermission<CashPaymentFlow>(),
startFlowPermission<CashExitFlow>())
)
val aliceNodeFuture = startNode("Alice", rpcUsers = listOf(cashUser))
val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
@ -93,12 +99,12 @@ class NodeMonitorModelTest : DriverBasedTest() {
@Test
fun `cash issue works end to end`() {
rpc.startFlow(::CashFlow, CashFlow.Command.IssueCash(
amount = Amount(100, USD),
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
recipient = aliceNode.legalIdentity,
notary = notaryNode.notaryIdentity
))
rpc.startFlow(::CashIssueFlow,
Amount(100, USD),
OpaqueBytes(ByteArray(1, { 1 })),
aliceNode.legalIdentity,
notaryNode.notaryIdentity
)
vaultUpdates.expectEvents(isStrict = false) {
sequence(
@ -118,17 +124,17 @@ class NodeMonitorModelTest : DriverBasedTest() {
@Test
fun `cash issue and move`() {
rpc.startFlow(::CashFlow, CashFlow.Command.IssueCash(
amount = Amount(100, USD),
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
recipient = aliceNode.legalIdentity,
notary = notaryNode.notaryIdentity
)).returnValue.getOrThrow()
rpc.startFlow(::CashIssueFlow,
Amount(100, USD),
OpaqueBytes(ByteArray(1, { 1 })),
aliceNode.legalIdentity,
notaryNode.notaryIdentity
).returnValue.getOrThrow()
rpc.startFlow(::CashFlow, CashFlow.Command.PayCash(
amount = Amount(100, Issued(PartyAndReference(aliceNode.legalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
recipient = aliceNode.legalIdentity
))
rpc.startFlow(::CashPaymentFlow,
Amount(100, Issued(PartyAndReference(aliceNode.legalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
aliceNode.legalIdentity
)
var issueSmId: StateMachineRunId? = null
var moveSmId: StateMachineRunId? = null

View File

@ -5,7 +5,7 @@ import net.corda.core.contracts.*
import net.corda.core.crypto.Party
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.transactions.TransactionBuilder
import net.corda.flows.CashFlow
import net.corda.flows.CashFlowCommand
import java.util.*
/**
@ -64,7 +64,7 @@ class EventGenerator(
val issueCashGenerator =
amountGenerator.combine(partyGenerator, issueRefGenerator) { amount, to, issueRef ->
CashFlow.Command.IssueCash(
CashFlowCommand.IssueCash(
amount,
issueRef,
to,
@ -76,7 +76,7 @@ class EventGenerator(
amountIssuedGenerator.combine(
partyGenerator
) { amountIssued, recipient ->
CashFlow.Command.PayCash(
CashFlowCommand.PayCash(
amount = amountIssued,
recipient = recipient
)
@ -84,7 +84,7 @@ class EventGenerator(
val exitCashGenerator =
amountIssuedGenerator.map {
CashFlow.Command.ExitCash(
CashFlowCommand.ExitCash(
it.withoutIssuer(),
it.token.issuer.reference
)

View File

@ -8,7 +8,7 @@ import net.corda.core.crypto.SecureHash
import net.corda.core.getOrThrow
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.utilities.Emoji
import net.corda.flows.CashFlow
import net.corda.flows.CashIssueFlow
import net.corda.flows.ContractUpgradeFlow
import net.corda.flows.FinalityFlow
import net.corda.node.utilities.databaseTransaction
@ -90,7 +90,7 @@ class ContractUpgradeFlowTest {
@Test
fun `upgrade Cash to v2`() {
// Create some cash.
val result = a.services.startFlow(CashFlow(CashFlow.Command.IssueCash(Amount(1000, USD), OpaqueBytes.of(1), a.info.legalIdentity, notary))).resultFuture
val result = a.services.startFlow(CashIssueFlow(Amount(1000, USD), OpaqueBytes.of(1), a.info.legalIdentity, notary)).resultFuture
mockNet.runNetwork()
val stateAndRef = result.getOrThrow().tx.outRef<Cash.State>(0)
// Starts contract upgrade flow.

View File

@ -10,7 +10,8 @@ import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.Vault
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.toFuture
import net.corda.flows.CashFlow
import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow
import net.corda.node.driver.driver
import net.corda.node.services.User
import net.corda.node.services.startFlowPermission
@ -28,7 +29,10 @@ class IntegrationTestingTutorial {
fun `alice bob cash exchange example`() {
// START 1
driver {
val testUser = User("testUser", "testPassword", permissions = setOf(startFlowPermission<CashFlow>()))
val testUser = User("testUser", "testPassword", permissions = setOf(
startFlowPermission<CashIssueFlow>(),
startFlowPermission<CashPaymentFlow>()
))
val (alice, bob, notary) = Futures.allAsList(
startNode("Alice", rpcUsers = listOf(testUser)),
startNode("Bob", rpcUsers = listOf(testUser)),
@ -56,12 +60,12 @@ class IntegrationTestingTutorial {
val issueRef = OpaqueBytes.of(0)
for (i in 1 .. 10) {
thread {
aliceProxy.startFlow(::CashFlow, CashFlow.Command.IssueCash(
amount = i.DOLLARS,
issueRef = issueRef,
recipient = bob.nodeInfo.legalIdentity,
notary = notary.nodeInfo.notaryIdentity
))
aliceProxy.startFlow(::CashIssueFlow,
i.DOLLARS,
issueRef,
bob.nodeInfo.legalIdentity,
notary.nodeInfo.notaryIdentity
)
}
}
@ -82,10 +86,10 @@ class IntegrationTestingTutorial {
// START 5
for (i in 1 .. 10) {
val flowHandle = bobProxy.startFlow(::CashFlow, CashFlow.Command.PayCash(
amount = i.DOLLARS.issuedBy(alice.nodeInfo.legalIdentity.ref(issueRef)),
recipient = alice.nodeInfo.legalIdentity
))
val flowHandle = bobProxy.startFlow(::CashPaymentFlow,
i.DOLLARS.issuedBy(alice.nodeInfo.legalIdentity.ref(issueRef)),
alice.nodeInfo.legalIdentity
)
flowHandle.returnValue.getOrThrow()
}

View File

@ -9,6 +9,9 @@ Milestone 9
* API:
* Pseudonymous ``AnonymousParty`` class added as a superclass of ``Party``.
* Split ``CashFlow`` into individual ``CashIssueFlow``, ``CashPaymentFlow`` and ``CashExitFlow`` flows, so that fine
grained permissions can be applied. Added ``CashFlowCommand`` for use-cases where cash flow triggers need to be
captured in an object that can be passed around.
Milestone 8
-----------

View File

@ -1,67 +0,0 @@
package net.corda.flows
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.crypto.Party
import net.corda.core.flows.FlowLogic
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.ProgressTracker
import java.util.*
/**
* Initiates a flow that produces an Issue/Move or Exit Cash transaction.
*
* @param command Indicates what Cash transaction to create with what parameters.
*/
class CashFlow(val command: CashFlow.Command, override val progressTracker: ProgressTracker) : FlowLogic<SignedTransaction>() {
constructor(command: CashFlow.Command) : this(command, tracker())
companion object {
object ISSUING : ProgressTracker.Step("Issuing cash")
object PAYING : ProgressTracker.Step("Paying cash")
object EXITING : ProgressTracker.Step("Exiting cash")
fun tracker() = ProgressTracker(ISSUING, PAYING, EXITING)
}
@Suspendable
@Throws(CashException::class)
override fun call(): SignedTransaction {
return when (command) {
is CashFlow.Command.IssueCash -> subFlow(CashIssueFlow(command.amount, command.issueRef, command.recipient, command.notary))
is CashFlow.Command.PayCash -> subFlow(CashPaymentFlow(command.amount, command.recipient))
is CashFlow.Command.ExitCash -> subFlow(CashExitFlow(command.amount, command.issueRef))
}
}
/**
* A command to initiate the Cash flow with.
*/
sealed class Command {
/**
* A command to initiate the Cash flow with.
*/
class IssueCash(val amount: Amount<Currency>,
val issueRef: OpaqueBytes,
val recipient: Party,
val notary: Party) : CashFlow.Command()
/**
* Pay cash to someone else.
*
* @param amount the amount of currency to issue on to the ledger.
* @param recipient the party to issue the cash to.
*/
class PayCash(val amount: Amount<Issued<Currency>>, val recipient: Party) : CashFlow.Command()
/**
* Exit cash from the ledger.
*
* @param amount the amount of currency to exit from the ledger.
* @param issueRef the reference previously specified on the issuance.
*/
class ExitCash(val amount: Amount<Currency>, val issueRef: OpaqueBytes) : CashFlow.Command()
}
}

View File

@ -0,0 +1,48 @@
package net.corda.flows
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.crypto.Party
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.FlowHandle
import net.corda.core.messaging.startFlow
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.transactions.SignedTransaction
import java.util.*
/**
* A command to initiate the Cash flow with.
*/
sealed class CashFlowCommand {
abstract fun startFlow(proxy: CordaRPCOps): FlowHandle<SignedTransaction>
/**
* A command to initiate the Cash flow with.
*/
class IssueCash(val amount: Amount<Currency>,
val issueRef: OpaqueBytes,
val recipient: Party,
val notary: Party) : CashFlowCommand() {
override fun startFlow(proxy: CordaRPCOps) = proxy.startFlow(::CashIssueFlow, amount, issueRef, recipient, notary)
}
/**
* Pay cash to someone else.
*
* @param amount the amount of currency to issue on to the ledger.
* @param recipient the party to issue the cash to.
*/
class PayCash(val amount: Amount<Issued<Currency>>, val recipient: Party) : CashFlowCommand() {
override fun startFlow(proxy: CordaRPCOps) = proxy.startFlow(::CashPaymentFlow, amount, recipient)
}
/**
* Exit cash from the ledger.
*
* @param amount the amount of currency to exit from the ledger.
* @param issueRef the reference previously specified on the issuance.
*/
class ExitCash(val amount: Amount<Currency>, val issueRef: OpaqueBytes) : CashFlowCommand() {
override fun startFlow(proxy: CordaRPCOps) = proxy.startFlow(::CashExitFlow, amount, issueRef)
}
}

View File

@ -81,9 +81,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
val PUBLIC_IDENTITY_FILE_NAME = "identity-public"
val defaultFlowWhiteList: Map<Class<out FlowLogic<*>>, Set<Class<*>>> = mapOf(
CashFlow::class.java to setOf(CashFlow.Command.IssueCash::class.java,
CashFlow.Command.PayCash::class.java,
CashFlow.Command.ExitCash::class.java),
CashExitFlow::class.java to setOf(Amount::class.java, PartyAndReference::class.java),
CashIssueFlow::class.java to setOf(Amount::class.java, OpaqueBytes::class.java, Party::class.java),
CashPaymentFlow::class.java to setOf(Amount::class.java, Party::class.java),

View File

@ -21,7 +21,9 @@ import net.corda.explorer.model.CordaViewModel
import net.corda.explorer.model.SettingsModel
import net.corda.explorer.views.*
import net.corda.explorer.views.cordapps.cash.CashViewer
import net.corda.flows.CashFlow
import net.corda.flows.CashExitFlow
import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow
import net.corda.flows.IssuerFlow.IssuanceRequester
import net.corda.node.driver.PortAllocation
import net.corda.node.driver.driver
@ -107,8 +109,15 @@ class Main : App(MainView::class) {
fun main(args: Array<String>) {
val portAllocation = PortAllocation.Incremental(20000)
driver(portAllocation = portAllocation) {
val user = User("user1", "test", permissions = setOf(startFlowPermission<CashFlow>()))
val manager = User("manager", "test", permissions = setOf(startFlowPermission<CashFlow>(), startFlowPermission<IssuanceRequester>()))
val user = User("user1", "test", permissions = setOf(
startFlowPermission<CashPaymentFlow>()
))
val manager = User("manager", "test", permissions = setOf(
startFlowPermission<CashIssueFlow>(),
startFlowPermission<CashPaymentFlow>(),
startFlowPermission<CashExitFlow>(),
startFlowPermission<IssuanceRequester>())
)
// TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo.
val notary = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)),
customOverrides = mapOf("nearestCity" to "Zurich"))
@ -178,34 +187,26 @@ fun main(args: Array<String>) {
// Party pay requests
listOf(aliceRPC, bobRPC).forEach {
eventGenerator.clientCommandGenerator.map { command ->
it.startFlow(::CashFlow, command)
command.startFlow(it)
Unit
}.generate(SplittableRandom())
}
// Exit requests
issuerGBPEventGenerator.bankOfCordaExitGenerator.map { command ->
issuerRPCGBP.startFlow(::CashFlow, command)
command.startFlow(issuerRPCGBP)
Unit
}.generate(SplittableRandom())
issuerUSDEventGenerator.bankOfCordaExitGenerator.map { command ->
issuerRPCUSD.startFlow(::CashFlow, command)
command.startFlow(issuerRPCUSD)
Unit
}.generate(SplittableRandom())
// Issuer requests
issuerGBPEventGenerator.bankOfCordaIssueGenerator.map { command ->
issuerRPCGBP.startFlow(::IssuanceRequester,
command.amount,
command.recipient,
command.issueRef,
issuerNodeGBP.nodeInfo.legalIdentity)
command.startFlow(issuerRPCGBP)
Unit
}.generate(SplittableRandom())
issuerUSDEventGenerator.bankOfCordaIssueGenerator.map { command ->
issuerRPCUSD.startFlow(::IssuanceRequester,
command.amount,
command.recipient,
command.issueRef,
issuerNodeUSD.nodeInfo.legalIdentity)
command.startFlow(issuerRPCUSD)
Unit
}.generate(SplittableRandom())
}
@ -216,4 +217,4 @@ fun main(args: Array<String>) {
}
waitForAllNodesToFinish()
}
}
}

View File

@ -28,7 +28,7 @@ import net.corda.explorer.model.ReportingCurrencyModel
import net.corda.explorer.views.bigDecimalFormatter
import net.corda.explorer.views.byteFormatter
import net.corda.explorer.views.stringConverter
import net.corda.flows.CashFlow
import net.corda.flows.CashFlowCommand
import net.corda.flows.IssuerFlow.IssuanceRequester
import org.controlsfx.dialog.ExceptionDialog
import tornadofx.Fragment
@ -87,7 +87,7 @@ class NewTransaction : Fragment() {
}
dialog.show()
runAsync {
val handle = if (it is CashFlow.Command.IssueCash) {
val handle = if (it is CashFlowCommand.IssueCash) {
myIdentity.value?.let { myIdentity ->
rpcProxy.value!!.startFlow(::IssuanceRequester,
it.amount,
@ -96,7 +96,7 @@ class NewTransaction : Fragment() {
myIdentity.legalIdentity)
}
} else {
rpcProxy.value!!.startFlow(::CashFlow, it)
it.startFlow(rpcProxy.value!!)
}
val response = try {
handle?.returnValue?.getOrThrow()
@ -110,9 +110,9 @@ class NewTransaction : Fragment() {
Alert.AlertType.ERROR to response.message
} else {
val type = when (command) {
is CashFlow.Command.IssueCash -> "Cash Issued"
is CashFlow.Command.ExitCash -> "Cash Exited"
is CashFlow.Command.PayCash -> "Cash Paid"
is CashFlowCommand.IssueCash -> "Cash Issued"
is CashFlowCommand.ExitCash -> "Cash Exited"
is CashFlowCommand.PayCash -> "Cash Paid"
}
Alert.AlertType.INFORMATION to "$type \nTransaction ID : ${(response as SignedTransaction).id}"
}
@ -127,7 +127,7 @@ class NewTransaction : Fragment() {
}
}
private fun dialog(window: Window) = Dialog<CashFlow.Command>().apply {
private fun dialog(window: Window) = Dialog<CashFlowCommand>().apply {
dialogPane = root
initOwner(window)
setResultConverter {
@ -136,10 +136,10 @@ class NewTransaction : Fragment() {
when (it) {
executeButton -> when (transactionTypeCB.value) {
CashTransaction.Issue -> {
CashFlow.Command.IssueCash(Amount(amount.value, currencyChoiceBox.value), issueRef, partyBChoiceBox.value.legalIdentity, notaries.first().notaryIdentity)
CashFlowCommand.IssueCash(Amount(amount.value, currencyChoiceBox.value), issueRef, partyBChoiceBox.value.legalIdentity, notaries.first().notaryIdentity)
}
CashTransaction.Pay -> CashFlow.Command.PayCash(Amount(amount.value, Issued(PartyAndReference(issuerChoiceBox.value, issueRef), currencyChoiceBox.value)), partyBChoiceBox.value.legalIdentity)
CashTransaction.Exit -> CashFlow.Command.ExitCash(Amount(amount.value, currencyChoiceBox.value), issueRef)
CashTransaction.Pay -> CashFlowCommand.PayCash(Amount(amount.value, Issued(PartyAndReference(issuerChoiceBox.value, issueRef), currencyChoiceBox.value)), partyBChoiceBox.value.legalIdentity)
CashTransaction.Exit -> CashFlowCommand.ExitCash(Amount(amount.value, currencyChoiceBox.value), issueRef)
else -> null
}
else -> null

View File

@ -14,7 +14,7 @@ import net.corda.core.messaging.startFlow
import net.corda.core.serialization.OpaqueBytes
import net.corda.core.toFuture
import net.corda.flows.CashException
import net.corda.flows.CashFlow
import net.corda.flows.CashFlowCommand
import net.corda.loadtest.LoadTest
import net.corda.loadtest.NodeHandle
import org.slf4j.LoggerFactory
@ -29,18 +29,18 @@ private val log = LoggerFactory.getLogger("CrossCash")
*/
data class CrossCashCommand(
val command: CashFlow.Command,
val command: CashFlowCommand,
val node: NodeHandle
) {
override fun toString(): String {
return when (command) {
is CashFlow.Command.IssueCash -> {
is CashFlowCommand.IssueCash -> {
"ISSUE ${node.info.legalIdentity} -> ${command.recipient} : ${command.amount}"
}
is CashFlow.Command.PayCash -> {
is CashFlowCommand.PayCash -> {
"MOVE ${node.info.legalIdentity} -> ${command.recipient} : ${command.amount}"
}
is CashFlow.Command.ExitCash -> {
is CashFlowCommand.ExitCash -> {
"EXIT ${node.info.legalIdentity} : ${command.amount}"
}
}
@ -146,7 +146,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
interpret = { state, command ->
when (command.command) {
is CashFlow.Command.IssueCash -> {
is CashFlowCommand.IssueCash -> {
val newDiffQueues = state.copyQueues()
val originators = newDiffQueues.getOrPut(command.command.recipient, { HashMap() })
val issuer = command.node.info.legalIdentity
@ -156,7 +156,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
queue.add(Pair(issuer, quantity))
CrossCashState(state.nodeVaults, newDiffQueues)
}
is CashFlow.Command.PayCash -> {
is CashFlowCommand.PayCash -> {
val newNodeVaults = state.copyVaults()
val newDiffQueues = state.copyQueues()
val recipientOriginators = newDiffQueues.getOrPut(command.command.recipient, { HashMap() })
@ -183,7 +183,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
recipientQueue.add(Pair(issuer, quantity))
CrossCashState(newNodeVaults, newDiffQueues)
}
is CashFlow.Command.ExitCash -> {
is CashFlowCommand.ExitCash -> {
val newNodeVaults = state.copyVaults()
val issuer = command.node.info.legalIdentity
val quantity = command.command.amount.quantity
@ -209,7 +209,7 @@ val crossCashTest = LoadTest<CrossCashCommand, CrossCashState>(
execute = { command ->
try {
val result = command.node.connection.proxy.startFlow(::CashFlow, command.command).returnValue.getOrThrow()
val result = command.command.startFlow(command.node.connection.proxy).returnValue.getOrThrow()
log.info("Success: $result")
} catch (e: FlowException) {
log.error("Failure", e)

View File

@ -8,7 +8,7 @@ import net.corda.core.contracts.PartyAndReference
import net.corda.core.crypto.AnonymousParty
import net.corda.core.crypto.Party
import net.corda.core.serialization.OpaqueBytes
import net.corda.flows.CashFlow
import net.corda.flows.CashFlowCommand
import java.util.*
fun generateIssue(
@ -16,12 +16,12 @@ fun generateIssue(
currency: Currency,
notary: Party,
possibleRecipients: List<Party>
): Generator<CashFlow.Command.IssueCash> {
): Generator<CashFlowCommand.IssueCash> {
return generateAmount(0, max, Generator.pure(currency)).combine(
Generator.pure(OpaqueBytes.of(0)),
Generator.pickOne(possibleRecipients)
) { amount, ref, recipient ->
CashFlow.Command.IssueCash(amount, ref, recipient, notary)
CashFlowCommand.IssueCash(amount, ref, recipient, notary)
}
}
@ -30,19 +30,19 @@ fun generateMove(
currency: Currency,
issuer: AnonymousParty,
possibleRecipients: List<Party>
): Generator<CashFlow.Command.PayCash> {
): Generator<CashFlowCommand.PayCash> {
return generateAmount(1, max, Generator.pure(Issued(PartyAndReference(issuer, OpaqueBytes.of(0)), currency))).combine(
Generator.pickOne(possibleRecipients)
) { amount, recipient ->
CashFlow.Command.PayCash(amount, recipient)
CashFlowCommand.PayCash(amount, recipient)
}
}
fun generateExit(
max: Long,
currency: Currency
): Generator<CashFlow.Command.ExitCash> {
): Generator<CashFlowCommand.ExitCash> {
return generateAmount(1, max, Generator.pure(currency)).map { amount ->
CashFlow.Command.ExitCash(amount, OpaqueBytes.of(0))
CashFlowCommand.ExitCash(amount, OpaqueBytes.of(0))
}
}

View File

@ -13,7 +13,7 @@ import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow
import net.corda.core.toFuture
import net.corda.flows.CashException
import net.corda.flows.CashFlow
import net.corda.flows.CashFlowCommand
import net.corda.loadtest.LoadTest
import net.corda.loadtest.NodeHandle
import org.slf4j.LoggerFactory
@ -23,7 +23,7 @@ private val log = LoggerFactory.getLogger("SelfIssue")
// DOCS START 1
data class SelfIssueCommand(
val command: CashFlow.Command.IssueCash,
val command: CashFlowCommand.IssueCash,
val node: NodeHandle
)
@ -64,7 +64,7 @@ val selfIssueTest = LoadTest<SelfIssueCommand, SelfIssueState>(
execute = { command ->
try {
val result = command.node.connection.proxy.startFlow(::CashFlow, command.command).returnValue.getOrThrow()
val result = command.command.startFlow(command.node.connection.proxy).returnValue.getOrThrow()
log.info("Success: $result")
} catch (e: FlowException) {
log.error("Failure", e)