Merged in get-cash-balances (pull request #21)

CORPRIV-687: Implement new RPCOp getCashBalances().

* CORPRIV-687: Implement new RPCOp getCashBalances().

* Use proper assertTrue().

Approved-by: Shams Asari
This commit is contained in:
Chris Rankin 2017-02-22 12:17:35 +00:00
parent 453d1d8c2b
commit 63cebb3c96
4 changed files with 52 additions and 3 deletions

View File

@ -10,9 +10,6 @@ import net.corda.core.random63BitValue
import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.OpaqueBytes
import net.corda.flows.CashIssueFlow import net.corda.flows.CashIssueFlow
import net.corda.flows.CashPaymentFlow 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.internal.Node
import net.corda.node.services.User import net.corda.node.services.User
import net.corda.node.services.config.configureTestSSL import net.corda.node.services.config.configureTestSSL
@ -22,8 +19,12 @@ import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class CordaRPCClientTest : NodeBasedTest() { class CordaRPCClientTest : NodeBasedTest() {
private val rpcUser = User("user1", "test", permissions = setOf( private val rpcUser = User("user1", "test", permissions = setOf(
@ -39,6 +40,11 @@ class CordaRPCClientTest : NodeBasedTest() {
client = CordaRPCClient(node.configuration.artemisAddress, configureTestSSL()) client = CordaRPCClient(node.configuration.artemisAddress, configureTestSSL())
} }
@After
fun done() {
client.close()
}
@Test @Test
fun `log in with valid username and password`() { fun `log in with valid username and password`() {
client.start(rpcUser.username, rpcUser.password) client.start(rpcUser.username, rpcUser.password)
@ -88,4 +94,30 @@ class CordaRPCClientTest : NodeBasedTest() {
handle.returnValue.getOrThrow() handle.returnValue.getOrThrow()
} }
} }
@Test
fun `get cash balances`() {
println("Starting client")
client.start(rpcUser.username, rpcUser.password)
println("Creating proxy")
val proxy = client.proxy()
val startCash = proxy.getCashBalances()
assertTrue(startCash.isEmpty(), "Should not start with any cash")
val flowHandle = proxy.startFlow(::CashIssueFlow,
123.DOLLARS, OpaqueBytes.of(0),
node.info.legalIdentity, node.info.legalIdentity
)
println("Started issuing cash, waiting on result")
flowHandle.progress.subscribe {
println("CashIssue PROGRESS $it")
}
val finishCash = proxy.getCashBalances()
println("Cash Balances: $finishCash")
assertEquals(1, finishCash.size)
assertEquals(123.DOLLARS, finishCash.get(Currency.getInstance("USD")))
}
} }

View File

@ -1,6 +1,7 @@
package net.corda.core.messaging package net.corda.core.messaging
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.contracts.Amount
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.UpgradedContract import net.corda.core.contracts.UpgradedContract
@ -17,6 +18,7 @@ import net.corda.core.transactions.SignedTransaction
import rx.Observable import rx.Observable
import java.io.InputStream import java.io.InputStream
import java.time.Instant import java.time.Instant
import java.util.*
data class StateMachineInfo( data class StateMachineInfo(
val id: StateMachineRunId, val id: StateMachineRunId,
@ -94,6 +96,12 @@ interface CordaRPCOps : RPCOps {
*/ */
fun getVaultTransactionNotes(txnId: SecureHash): Iterable<String> fun getVaultTransactionNotes(txnId: SecureHash): Iterable<String>
/*
* Returns a map of how much cash we have in each currency, ignoring details like issuer. Note: currencies for
* which we have no cash evaluate to null (not present in map), not 0.
*/
fun getCashBalances(): Map<Currency, Amount<Currency>>
/** /**
* Checks whether an attachment with the given hash is stored on the node. * Checks whether an attachment with the given hash is stored on the node.
*/ */

View File

@ -1,5 +1,6 @@
package net.corda.node.internal package net.corda.node.internal
import net.corda.core.contracts.Amount
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.UpgradedContract import net.corda.core.contracts.UpgradedContract
@ -27,6 +28,7 @@ import org.jetbrains.exposed.sql.Database
import rx.Observable import rx.Observable
import java.io.InputStream import java.io.InputStream
import java.time.Instant import java.time.Instant
import java.util.*
/** /**
* Server side implementations of RPCs available to MQ based client tools. Execution takes place on the server * Server side implementations of RPCs available to MQ based client tools. Execution takes place on the server
@ -90,6 +92,12 @@ class CordaRPCOpsImpl(
} }
} }
override fun getCashBalances(): Map<Currency, Amount<Currency>> {
return databaseTransaction(database) {
services.vaultService.cashBalances
}
}
// TODO: Check that this flow is annotated as being intended for RPC invocation // TODO: Check that this flow is annotated as being intended for RPC invocation
override fun <T : Any> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T> { override fun <T : Any> startFlowDynamic(logicType: Class<out FlowLogic<T>>, vararg args: Any?): FlowHandle<T> {
requirePermission(startFlowPermission(logicType)) requirePermission(startFlowPermission(logicType))

View File

@ -183,6 +183,7 @@ private class RPCKryo(observableSerializer: Serializer<Observable<Any>>? = null)
register(UUID::class.java) register(UUID::class.java)
register(UniqueIdentifier::class.java) register(UniqueIdentifier::class.java)
register(LinkedHashSet::class.java) register(LinkedHashSet::class.java)
register(HashMap::class.java)
register(StateAndRef::class.java) register(StateAndRef::class.java)
register(setOf<Unit>().javaClass) // EmptySet register(setOf<Unit>().javaClass) // EmptySet
register(StateRef::class.java) register(StateRef::class.java)