diff --git a/client/src/integration-test/kotlin/net/corda/client/CordaRPCClientTest.kt b/client/src/integration-test/kotlin/net/corda/client/CordaRPCClientTest.kt index db5092e396..27d3a7eb40 100644 --- a/client/src/integration-test/kotlin/net/corda/client/CordaRPCClientTest.kt +++ b/client/src/integration-test/kotlin/net/corda/client/CordaRPCClientTest.kt @@ -65,4 +65,14 @@ class CordaRPCClientTest : DriverBasedTest() { } println("Result: ${flowHandle.returnValue.toBlocking().first()}") } + + @Test + fun `get cash balances`() { + println("Starting client") + client.start(rpcUser.username, rpcUser.password) + println("Creating proxy") + val proxy = client.proxy() + val cash = proxy.getCashBalances() + println("Cash Balances: $cash") + } } diff --git a/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt b/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt index e4d43df5d9..1f657f64de 100644 --- a/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt +++ b/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt @@ -1,5 +1,6 @@ package net.corda.core.messaging +import net.corda.core.contracts.Amount import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.crypto.CompositeKey @@ -15,6 +16,7 @@ import net.corda.core.transactions.SignedTransaction import rx.Observable import java.io.InputStream import java.time.Instant +import java.util.* data class StateMachineInfo( val id: StateMachineRunId, @@ -92,6 +94,12 @@ interface CordaRPCOps : RPCOps { */ fun getVaultTransactionNotes(txnId: SecureHash): Iterable + /* + * 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> + /** * Checks whether an attachment with the given hash is stored on the node. */ diff --git a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt index b05388b5f5..ec002c245d 100644 --- a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt +++ b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt @@ -1,5 +1,6 @@ package net.corda.node.internal +import net.corda.core.contracts.Amount import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.crypto.CompositeKey @@ -27,6 +28,7 @@ import org.jetbrains.exposed.sql.Database import rx.Observable import java.io.InputStream import java.time.Instant +import java.util.* /** * 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> { + return databaseTransaction(database) { + services.vaultService.cashBalances + } + } + // TODO: Check that this flow is annotated as being intended for RPC invocation override fun startFlowDynamic(logicType: Class>, vararg args: Any?): FlowHandle { requirePermission(startFlowPermission(logicType)) diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt index ca2954e5cb..d3f1f98727 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt @@ -175,6 +175,7 @@ private class RPCKryo(observableSerializer: Serializer>? = null) register(UUID::class.java) register(UniqueIdentifier::class.java) register(LinkedHashSet::class.java) + register(HashMap::class.java) register(StateAndRef::class.java) register(setOf().javaClass) // EmptySet register(StateRef::class.java)