mirror of
https://github.com/corda/corda.git
synced 2025-01-24 13:28:07 +00:00
Explorer advertising service fix (#1576)
* WIP added a helper method to convert ObservableValue<List> to ObservableList (cherry picked from commit 75306aa) * Fix for cash explorer after advertising service removal (cherry picked from commit 59d0278) * remove unused changes * address PR issues * fixup after rebase * fix CashState name rendering issue added flow permission to gradle config
This commit is contained in:
parent
33421bdd44
commit
80b3411fa5
@ -5,19 +5,20 @@ import com.google.common.cache.CacheLoader
|
|||||||
import javafx.beans.value.ObservableValue
|
import javafx.beans.value.ObservableValue
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.collections.ObservableList
|
import javafx.collections.ObservableList
|
||||||
|
import net.corda.client.jfx.utils.filterNotNull
|
||||||
import net.corda.client.jfx.utils.fold
|
import net.corda.client.jfx.utils.fold
|
||||||
import net.corda.client.jfx.utils.map
|
import net.corda.client.jfx.utils.map
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||||
|
import net.corda.nodeapi.ServiceType
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
class NetworkIdentityModel {
|
class NetworkIdentityModel {
|
||||||
private val networkIdentityObservable by observable(NodeMonitorModel::networkMap)
|
private val networkIdentityObservable by observable(NodeMonitorModel::networkMap)
|
||||||
|
|
||||||
val networkIdentities: ObservableList<NodeInfo> =
|
private val networkIdentities: ObservableList<NodeInfo> =
|
||||||
networkIdentityObservable.fold(FXCollections.observableArrayList()) { list, update ->
|
networkIdentityObservable.fold(FXCollections.observableArrayList()) { list, update ->
|
||||||
list.removeIf {
|
list.removeIf {
|
||||||
when (update) {
|
when (update) {
|
||||||
@ -32,13 +33,15 @@ class NetworkIdentityModel {
|
|||||||
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||||
|
|
||||||
private val identityCache = CacheBuilder.newBuilder()
|
private val identityCache = CacheBuilder.newBuilder()
|
||||||
.build<PublicKey, ObservableValue<NodeInfo?>>(CacheLoader.from {
|
.build<PublicKey, ObservableValue<NodeInfo?>>(CacheLoader.from { publicKey ->
|
||||||
publicKey ->
|
|
||||||
publicKey?.let { rpcProxy.map { it?.nodeInfoFromParty(AnonymousParty(publicKey)) } }
|
publicKey?.let { rpcProxy.map { it?.nodeInfoFromParty(AnonymousParty(publicKey)) } }
|
||||||
})
|
})
|
||||||
|
|
||||||
val notaries: ObservableList<Party> = FXCollections.observableList(rpcProxy.value?.notaryIdentities())
|
val notaries: ObservableList<Party> = networkIdentities.map {
|
||||||
val notaryNodes: ObservableList<NodeInfo> = FXCollections.observableList(notaries.map { rpcProxy.value?.nodeInfoFromParty(it) })
|
it.legalIdentitiesAndCerts.find { it.name.commonName?.let { ServiceType.parse(it).isNotary() } ?: false }
|
||||||
|
}.map { it?.party }.filterNotNull()
|
||||||
|
|
||||||
|
val notaryNodes: ObservableList<NodeInfo> = notaries.map { rpcProxy.value?.nodeInfoFromParty(it) }.filterNotNull()
|
||||||
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { it.legalIdentities.all { it !in notaries } }
|
val parties: ObservableList<NodeInfo> = networkIdentities.filtered { it.legalIdentities.all { it !in notaries } }
|
||||||
val myIdentity = rpcProxy.map { it?.nodeInfo()?.legalIdentitiesAndCerts?.first()?.party }
|
val myIdentity = rpcProxy.map { it?.nodeInfo()?.legalIdentitiesAndCerts?.first()?.party }
|
||||||
|
|
||||||
|
@ -353,4 +353,4 @@ fun <T : ContractState> DataFeed<Vault.Page<T>, Vault.Update<T>>.toFXListOfState
|
|||||||
*/
|
*/
|
||||||
fun <T : ContractState> DataFeed<Vault.Page<T>, Vault.Update<T>>.toFXListOfStates(): ObservableList<T> {
|
fun <T : ContractState> DataFeed<Vault.Page<T>, Vault.Update<T>>.toFXListOfStates(): ObservableList<T> {
|
||||||
return toFXListOfStateRefs().map { it.state.data }
|
return toFXListOfStateRefs().map { it.state.data }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package net.corda.finance.flows
|
||||||
|
|
||||||
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import net.corda.core.flows.FlowException
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.finance.CHF
|
||||||
|
import net.corda.finance.EUR
|
||||||
|
import net.corda.finance.GBP
|
||||||
|
import net.corda.finance.USD
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flow to obtain cash cordapp app configuration.
|
||||||
|
*/
|
||||||
|
@StartableByRPC
|
||||||
|
class CashConfigDataFlow : FlowLogic<CashConfiguration>() {
|
||||||
|
companion object {
|
||||||
|
private val supportedCurrencies = listOf(USD, GBP, CHF, EUR)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): CashConfiguration {
|
||||||
|
val issuableCurrencies = supportedCurrencies.mapNotNull {
|
||||||
|
try {
|
||||||
|
// Currently it uses checkFlowPermission to determine the list of issuable currency as a temporary hack.
|
||||||
|
// TODO: get the config from proper configuration source.
|
||||||
|
checkFlowPermission("corda.issuer.$it", emptyMap())
|
||||||
|
it
|
||||||
|
} catch (e: FlowException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CashConfiguration(issuableCurrencies, supportedCurrencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
data class CashConfiguration(val issuableCurrencies: List<Currency>, val supportedCurrencies: List<Currency>)
|
@ -23,6 +23,7 @@ import net.corda.core.utilities.*
|
|||||||
import net.corda.node.services.api.FlowAppAuditEvent
|
import net.corda.node.services.api.FlowAppAuditEvent
|
||||||
import net.corda.node.services.api.FlowPermissionAuditEvent
|
import net.corda.node.services.api.FlowPermissionAuditEvent
|
||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
import net.corda.node.services.statemachine.FlowSessionState.Initiating
|
import net.corda.node.services.statemachine.FlowSessionState.Initiating
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.DatabaseTransaction
|
import net.corda.node.utilities.DatabaseTransaction
|
||||||
@ -260,7 +261,10 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
|
|||||||
|
|
||||||
// TODO Dummy implementation of access to application specific permission controls and audit logging
|
// TODO Dummy implementation of access to application specific permission controls and audit logging
|
||||||
override fun checkFlowPermission(permissionName: String, extraAuditData: Map<String, String>) {
|
override fun checkFlowPermission(permissionName: String, extraAuditData: Map<String, String>) {
|
||||||
val permissionGranted = true // TODO define permission control service on ServiceHubInternal and actually check authorization.
|
// This is a hack to allow cash app access list of permitted issuer currency.
|
||||||
|
// TODO: replace this with cordapp configuration.
|
||||||
|
val config = serviceHub.configuration as? FullNodeConfiguration
|
||||||
|
val permissionGranted = config?.extraAdvertisedServiceIds?.contains(permissionName) ?: true
|
||||||
val checkPermissionEvent = FlowPermissionAuditEvent(
|
val checkPermissionEvent = FlowPermissionAuditEvent(
|
||||||
serviceHub.clock.instant(),
|
serviceHub.clock.instant(),
|
||||||
flowInitiator,
|
flowInitiator,
|
||||||
|
@ -69,6 +69,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
['username' : "bankUser",
|
['username' : "bankUser",
|
||||||
'password' : "test",
|
'password' : "test",
|
||||||
'permissions': ["StartFlow.net.corda.finance.flows.CashPaymentFlow",
|
'permissions': ["StartFlow.net.corda.finance.flows.CashPaymentFlow",
|
||||||
|
"StartFlow.net.corda.finance.flows.CashConfigDataFlow",
|
||||||
"StartFlow.net.corda.finance.flows.CashExitFlow",
|
"StartFlow.net.corda.finance.flows.CashExitFlow",
|
||||||
"StartFlow.net.corda.finance.flows.CashIssueAndPaymentFlow"]]
|
"StartFlow.net.corda.finance.flows.CashIssueAndPaymentFlow"]]
|
||||||
]
|
]
|
||||||
|
@ -17,16 +17,13 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.GBP
|
import net.corda.finance.GBP
|
||||||
import net.corda.finance.USD
|
import net.corda.finance.USD
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.finance.flows.AbstractCashFlow
|
import net.corda.finance.flows.*
|
||||||
import net.corda.finance.flows.CashExitFlow
|
|
||||||
import net.corda.finance.flows.CashExitFlow.ExitRequest
|
import net.corda.finance.flows.CashExitFlow.ExitRequest
|
||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
|
||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest
|
import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
|
||||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||||
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
import net.corda.nodeapi.ServiceInfo
|
import net.corda.nodeapi.ServiceInfo
|
||||||
import net.corda.nodeapi.ServiceType
|
import net.corda.nodeapi.ServiceType
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.BOB
|
import net.corda.testing.BOB
|
||||||
@ -39,12 +36,14 @@ import java.util.*
|
|||||||
|
|
||||||
class ExplorerSimulation(val options: OptionSet) {
|
class ExplorerSimulation(val options: OptionSet) {
|
||||||
private val user = User("user1", "test", permissions = setOf(
|
private val user = User("user1", "test", permissions = setOf(
|
||||||
startFlowPermission<CashPaymentFlow>()
|
startFlowPermission<CashPaymentFlow>(),
|
||||||
|
startFlowPermission<CashConfigDataFlow>()
|
||||||
))
|
))
|
||||||
private val manager = User("manager", "test", permissions = setOf(
|
private val manager = User("manager", "test", permissions = setOf(
|
||||||
startFlowPermission<CashIssueAndPaymentFlow>(),
|
startFlowPermission<CashIssueAndPaymentFlow>(),
|
||||||
startFlowPermission<CashPaymentFlow>(),
|
startFlowPermission<CashPaymentFlow>(),
|
||||||
startFlowPermission<CashExitFlow>())
|
startFlowPermission<CashExitFlow>(),
|
||||||
|
startFlowPermission<CashConfigDataFlow>())
|
||||||
)
|
)
|
||||||
|
|
||||||
private lateinit var notaryNode: NodeHandle
|
private lateinit var notaryNode: NodeHandle
|
||||||
@ -122,7 +121,7 @@ class ExplorerSimulation(val options: OptionSet) {
|
|||||||
val issuerRPCGBP = issuerGBPConnection.proxy
|
val issuerRPCGBP = issuerGBPConnection.proxy
|
||||||
|
|
||||||
val issuerClientUSD = issuerNodeUSD.rpcClientToNode()
|
val issuerClientUSD = issuerNodeUSD.rpcClientToNode()
|
||||||
val issuerUSDConnection =issuerClientUSD.start(manager.username, manager.password)
|
val issuerUSDConnection = issuerClientUSD.start(manager.username, manager.password)
|
||||||
val issuerRPCUSD = issuerUSDConnection.proxy
|
val issuerRPCUSD = issuerUSDConnection.proxy
|
||||||
|
|
||||||
RPCConnections.addAll(listOf(aliceConnection, bobConnection, issuerGBPConnection, issuerUSDConnection))
|
RPCConnections.addAll(listOf(aliceConnection, bobConnection, issuerGBPConnection, issuerUSDConnection))
|
||||||
|
@ -1,34 +1,25 @@
|
|||||||
package net.corda.explorer.model
|
package net.corda.explorer.model
|
||||||
|
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.collections.ObservableList
|
import net.corda.client.jfx.model.NodeMonitorModel
|
||||||
import net.corda.client.jfx.model.NetworkIdentityModel
|
|
||||||
import net.corda.client.jfx.model.observableList
|
|
||||||
import net.corda.client.jfx.model.observableValue
|
import net.corda.client.jfx.model.observableValue
|
||||||
import net.corda.client.jfx.utils.ChosenList
|
import net.corda.client.jfx.utils.ChosenList
|
||||||
import net.corda.client.jfx.utils.map
|
import net.corda.client.jfx.utils.map
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.finance.flows.CashConfigDataFlow
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
val ISSUER_SERVICE_TYPE = Regex("corda.issuer.(USD|GBP|CHF|EUR)")
|
|
||||||
|
|
||||||
class IssuerModel {
|
class IssuerModel {
|
||||||
// TODO Explorer will be fixed as separate PR.
|
private val proxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||||
private val networkIdentities by observableList(NetworkIdentityModel::networkIdentities)
|
private val cashAppConfiguration = proxy.map { it?.startFlow(::CashConfigDataFlow)?.returnValue?.getOrThrow() }
|
||||||
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
val supportedCurrencies = ChosenList(cashAppConfiguration.map { it?.supportedCurrencies?.observable() ?: FXCollections.emptyObservableList() })
|
||||||
private val supportedCurrencies by observableList(ReportingCurrencyModel::supportedCurrencies)
|
val currencyTypes = ChosenList(cashAppConfiguration.map { it?.issuableCurrencies?.observable() ?: FXCollections.emptyObservableList() })
|
||||||
|
|
||||||
val issuers: ObservableList<NodeInfo> = FXCollections.observableList(networkIdentities)
|
val transactionTypes = ChosenList(cashAppConfiguration.map {
|
||||||
|
if (it?.issuableCurrencies?.isNotEmpty() == true)
|
||||||
val currencyTypes = ChosenList(myIdentity.map { supportedCurrencies })
|
|
||||||
|
|
||||||
val transactionTypes = ChosenList(myIdentity.map {
|
|
||||||
if (it?.isIssuerNode() ?: false)
|
|
||||||
CashTransaction.values().asList().observable()
|
CashTransaction.values().asList().observable()
|
||||||
else
|
else
|
||||||
listOf(CashTransaction.Pay).observable()
|
listOf(CashTransaction.Pay).observable()
|
||||||
})
|
})
|
||||||
|
|
||||||
private fun Party.isIssuerNode() = true
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,7 @@ import java.util.*
|
|||||||
|
|
||||||
class ReportingCurrencyModel {
|
class ReportingCurrencyModel {
|
||||||
private val exchangeRate: ObservableValue<ExchangeRate> by observableValue(ExchangeRateModel::exchangeRate)
|
private val exchangeRate: ObservableValue<ExchangeRate> by observableValue(ExchangeRateModel::exchangeRate)
|
||||||
val reportingCurrency by observableValue(SettingsModel::reportingCurrencyProperty)
|
private val reportingCurrency by observableValue(SettingsModel::reportingCurrencyProperty)
|
||||||
val supportedCurrencies = setOf(USD, GBP, CHF, EUR).toList().observable()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This stream provides a stream of exchange() functions that updates when either the reporting currency or the
|
* This stream provides a stream of exchange() functions that updates when either the reporting currency or the
|
||||||
|
@ -9,6 +9,7 @@ import javafx.beans.property.SimpleObjectProperty
|
|||||||
import javafx.beans.value.ObservableValue
|
import javafx.beans.value.ObservableValue
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.geometry.Bounds
|
import javafx.geometry.Bounds
|
||||||
|
import javafx.geometry.Insets
|
||||||
import javafx.geometry.Point2D
|
import javafx.geometry.Point2D
|
||||||
import javafx.scene.Parent
|
import javafx.scene.Parent
|
||||||
import javafx.scene.control.Button
|
import javafx.scene.control.Button
|
||||||
@ -35,6 +36,7 @@ import net.corda.explorer.model.CordaView
|
|||||||
import net.corda.finance.utils.CityDatabase
|
import net.corda.finance.utils.CityDatabase
|
||||||
import net.corda.finance.utils.ScreenCoordinate
|
import net.corda.finance.utils.ScreenCoordinate
|
||||||
import net.corda.finance.utils.WorldMapLocation
|
import net.corda.finance.utils.WorldMapLocation
|
||||||
|
import net.corda.nodeapi.ServiceType
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class Network : CordaView() {
|
class Network : CordaView() {
|
||||||
@ -91,15 +93,19 @@ class Network : CordaView() {
|
|||||||
val node = this
|
val node = this
|
||||||
val identities = node.legalIdentitiesAndCerts.sortedBy { it.owningKey.toBase58String() }
|
val identities = node.legalIdentitiesAndCerts.sortedBy { it.owningKey.toBase58String() }
|
||||||
return button {
|
return button {
|
||||||
|
minWidth = 300.0
|
||||||
|
padding = Insets(10.0)
|
||||||
useMaxWidth = true
|
useMaxWidth = true
|
||||||
graphic = vbox {
|
graphic = vbox {
|
||||||
label(PartyNameFormatter.short.format(identities[0].name)) { font = Font.font(font.family, FontWeight.BOLD, 15.0) }
|
label(PartyNameFormatter.short.format(identities[0].name)) { font = Font.font(font.family, FontWeight.BOLD, 15.0) }
|
||||||
gridpane { // TODO We lose node's main identity for display.
|
gridpane {
|
||||||
|
// TODO We lose node's main identity for display.
|
||||||
hgap = 5.0
|
hgap = 5.0
|
||||||
vgap = 5.0
|
vgap = 5.0
|
||||||
for (identity in identities) {
|
for (identity in identities) {
|
||||||
row(PartyNameFormatter.short.format(identity.name)) {
|
val isNotary = identity.name.commonName?.let { ServiceType.parse(it).isNotary() } ?: false
|
||||||
copyableLabel(SimpleObjectProperty(identity.owningKey.toBase58String())).apply { minWidth = 400.0 }
|
row("${if (isNotary) "Notary " else ""}Public Key :") {
|
||||||
|
copyableLabel(SimpleObjectProperty(identity.owningKey.toBase58String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.getWorldMapLocation()?.apply { row("Location :") { label(this@apply.description) } }
|
node.getWorldMapLocation()?.apply { row("Location :") { label(this@apply.description) } }
|
||||||
@ -114,7 +120,7 @@ class Network : CordaView() {
|
|||||||
private fun NodeInfo.render(): MapViewComponents {
|
private fun NodeInfo.render(): MapViewComponents {
|
||||||
val node = this
|
val node = this
|
||||||
val identities = node.legalIdentitiesAndCerts.sortedBy { it.owningKey.toBase58String() }
|
val identities = node.legalIdentitiesAndCerts.sortedBy { it.owningKey.toBase58String() }
|
||||||
val mapLabel = label(PartyNameFormatter.short.format(identities[0].name)) // We choose the first one for the name of the node on the map.
|
val mapLabel = label(PartyNameFormatter.short.format(identities.first().name)) // We choose the first one for the name of the node on the map.
|
||||||
mapPane.add(mapLabel)
|
mapPane.add(mapLabel)
|
||||||
// applyCss: This method does not normally need to be invoked directly but may be used in conjunction with Parent.layout()
|
// applyCss: This method does not normally need to be invoked directly but may be used in conjunction with Parent.layout()
|
||||||
// to size a Node before the next pulse, or if the Scene is not in a Stage.
|
// to size a Node before the next pulse, or if the Scene is not in a Stage.
|
||||||
|
@ -12,6 +12,7 @@ import net.corda.client.jfx.model.objectProperty
|
|||||||
import net.corda.client.jfx.model.observableList
|
import net.corda.client.jfx.model.observableList
|
||||||
import net.corda.client.jfx.utils.map
|
import net.corda.client.jfx.utils.map
|
||||||
import net.corda.explorer.model.CordaView
|
import net.corda.explorer.model.CordaView
|
||||||
|
import net.corda.explorer.model.IssuerModel
|
||||||
import net.corda.explorer.model.ReportingCurrencyModel
|
import net.corda.explorer.model.ReportingCurrencyModel
|
||||||
import net.corda.explorer.model.SettingsModel
|
import net.corda.explorer.model.SettingsModel
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -22,7 +23,7 @@ class Settings : CordaView() {
|
|||||||
override val icon = FontAwesomeIcon.COGS
|
override val icon = FontAwesomeIcon.COGS
|
||||||
|
|
||||||
// Inject Data.
|
// Inject Data.
|
||||||
private val currencies by observableList(ReportingCurrencyModel::supportedCurrencies)
|
private val currencies by observableList(IssuerModel::supportedCurrencies)
|
||||||
private val reportingCurrencies by objectProperty(SettingsModel::reportingCurrencyProperty)
|
private val reportingCurrencies by objectProperty(SettingsModel::reportingCurrencyProperty)
|
||||||
private val rememberMe by objectProperty(SettingsModel::rememberMeProperty)
|
private val rememberMe by objectProperty(SettingsModel::rememberMeProperty)
|
||||||
private val fullscreen by objectProperty(SettingsModel::fullscreenProperty)
|
private val fullscreen by objectProperty(SettingsModel::fullscreenProperty)
|
||||||
|
@ -26,7 +26,6 @@ import net.corda.core.crypto.toStringShort
|
|||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.NodeInfo
|
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.explorer.AmountDiff
|
import net.corda.explorer.AmountDiff
|
||||||
import net.corda.explorer.formatters.AmountFormatter
|
import net.corda.explorer.formatters.AmountFormatter
|
||||||
@ -37,6 +36,7 @@ import net.corda.explorer.identicon.identiconToolTip
|
|||||||
import net.corda.explorer.model.CordaView
|
import net.corda.explorer.model.CordaView
|
||||||
import net.corda.explorer.model.CordaWidget
|
import net.corda.explorer.model.CordaWidget
|
||||||
import net.corda.explorer.model.ReportingCurrencyModel
|
import net.corda.explorer.model.ReportingCurrencyModel
|
||||||
|
import net.corda.explorer.model.SettingsModel
|
||||||
import net.corda.explorer.sign
|
import net.corda.explorer.sign
|
||||||
import net.corda.explorer.ui.setCustomCellFactory
|
import net.corda.explorer.ui.setCustomCellFactory
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
@ -52,7 +52,7 @@ class TransactionViewer : CordaView("Transactions") {
|
|||||||
// Inject data
|
// Inject data
|
||||||
private val transactions by observableListReadOnly(TransactionDataModel::partiallyResolvedTransactions)
|
private val transactions by observableListReadOnly(TransactionDataModel::partiallyResolvedTransactions)
|
||||||
private val reportingExchange by observableValue(ReportingCurrencyModel::reportingExchange)
|
private val reportingExchange by observableValue(ReportingCurrencyModel::reportingExchange)
|
||||||
private val reportingCurrency by observableValue(ReportingCurrencyModel::reportingCurrency)
|
private val reportingCurrency by observableValue(SettingsModel::reportingCurrencyProperty)
|
||||||
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
||||||
|
|
||||||
override val widgets = listOf(CordaWidget(title, TransactionWidget(), icon)).observable()
|
override val widgets = listOf(CordaWidget(title, TransactionWidget(), icon)).observable()
|
||||||
@ -260,7 +260,7 @@ class TransactionViewer : CordaView("Transactions") {
|
|||||||
vgap = 10.0
|
vgap = 10.0
|
||||||
hgap = 10.0
|
hgap = 10.0
|
||||||
row {
|
row {
|
||||||
label("${contractState.contract().javaClass.simpleName} (${contractState.ref.toString().substring(0, 16)}...)[${contractState.ref.index}]") {
|
label("${contractState.contract()} (${contractState.ref.toString().substring(0, 16)}...)[${contractState.ref.index}]") {
|
||||||
graphic = identicon(contractState.ref.txhash, 30.0)
|
graphic = identicon(contractState.ref.txhash, 30.0)
|
||||||
tooltip = identiconToolTip(contractState.ref.txhash)
|
tooltip = identiconToolTip(contractState.ref.txhash)
|
||||||
gridpaneConstraints { columnSpan = 2 }
|
gridpaneConstraints { columnSpan = 2 }
|
||||||
@ -298,8 +298,7 @@ class TransactionViewer : CordaView("Transactions") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StateAndRef<ContractState>.contract() = this.state.contract
|
private fun StateAndRef<ContractState>.contract() = this.state.contract.split(".").last()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,10 +13,7 @@ import javafx.scene.text.Font
|
|||||||
import javafx.scene.text.FontWeight
|
import javafx.scene.text.FontWeight
|
||||||
import javafx.stage.Window
|
import javafx.stage.Window
|
||||||
import net.corda.client.jfx.model.*
|
import net.corda.client.jfx.model.*
|
||||||
import net.corda.client.jfx.utils.ChosenList
|
import net.corda.client.jfx.utils.*
|
||||||
import net.corda.client.jfx.utils.isNotNull
|
|
||||||
import net.corda.client.jfx.utils.map
|
|
||||||
import net.corda.client.jfx.utils.unique
|
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.contracts.Amount.Companion.sumOrNull
|
import net.corda.core.contracts.Amount.Companion.sumOrNull
|
||||||
import net.corda.core.contracts.withoutIssuer
|
import net.corda.core.contracts.withoutIssuer
|
||||||
@ -31,10 +28,10 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.explorer.formatters.PartyNameFormatter
|
import net.corda.explorer.formatters.PartyNameFormatter
|
||||||
import net.corda.explorer.model.CashTransaction
|
import net.corda.explorer.model.CashTransaction
|
||||||
import net.corda.explorer.model.IssuerModel
|
import net.corda.explorer.model.IssuerModel
|
||||||
import net.corda.explorer.model.ReportingCurrencyModel
|
|
||||||
import net.corda.explorer.views.bigDecimalFormatter
|
import net.corda.explorer.views.bigDecimalFormatter
|
||||||
import net.corda.explorer.views.byteFormatter
|
import net.corda.explorer.views.byteFormatter
|
||||||
import net.corda.explorer.views.stringConverter
|
import net.corda.explorer.views.stringConverter
|
||||||
|
import net.corda.explorer.views.toKnownParty
|
||||||
import net.corda.finance.flows.AbstractCashFlow
|
import net.corda.finance.flows.AbstractCashFlow
|
||||||
import net.corda.finance.flows.CashExitFlow
|
import net.corda.finance.flows.CashExitFlow
|
||||||
import net.corda.finance.flows.CashExitFlow.ExitRequest
|
import net.corda.finance.flows.CashExitFlow.ExitRequest
|
||||||
@ -42,7 +39,6 @@ import net.corda.finance.flows.CashIssueAndPaymentFlow
|
|||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest
|
import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
import net.corda.finance.flows.CashPaymentFlow.PaymentRequest
|
import net.corda.finance.flows.CashPaymentFlow.PaymentRequest
|
||||||
import net.corda.testing.chooseIdentity
|
|
||||||
import net.corda.testing.chooseIdentityAndCert
|
import net.corda.testing.chooseIdentityAndCert
|
||||||
import org.controlsfx.dialog.ExceptionDialog
|
import org.controlsfx.dialog.ExceptionDialog
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -71,15 +67,15 @@ class NewTransaction : Fragment() {
|
|||||||
private val issueRef = SimpleObjectProperty<Byte>()
|
private val issueRef = SimpleObjectProperty<Byte>()
|
||||||
// Inject data
|
// Inject data
|
||||||
private val parties by observableList(NetworkIdentityModel::parties)
|
private val parties by observableList(NetworkIdentityModel::parties)
|
||||||
private val issuers by observableList(IssuerModel::issuers)
|
|
||||||
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||||
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
||||||
private val notaries by observableList(NetworkIdentityModel::notaries)
|
private val notaries by observableList(NetworkIdentityModel::notaries)
|
||||||
private val cash by observableList(ContractStateModel::cash)
|
private val cash by observableList(ContractStateModel::cash)
|
||||||
private val executeButton = ButtonType("Execute", ButtonBar.ButtonData.APPLY)
|
private val executeButton = ButtonType("Execute", ButtonBar.ButtonData.APPLY)
|
||||||
private val currencyTypes by observableList(IssuerModel::currencyTypes)
|
private val currencyTypes by observableList(IssuerModel::currencyTypes)
|
||||||
private val supportedCurrencies by observableList(ReportingCurrencyModel::supportedCurrencies)
|
private val supportedCurrencies by observableList(IssuerModel::supportedCurrencies)
|
||||||
private val transactionTypes by observableList(IssuerModel::transactionTypes)
|
private val transactionTypes by observableList(IssuerModel::transactionTypes)
|
||||||
|
private val issuers = cash.map { it.token.issuer }
|
||||||
|
|
||||||
private val currencyItems = ChosenList(transactionTypeCB.valueProperty().map {
|
private val currencyItems = ChosenList(transactionTypeCB.valueProperty().map {
|
||||||
when (it) {
|
when (it) {
|
||||||
@ -156,7 +152,7 @@ class NewTransaction : Fragment() {
|
|||||||
val issueRef = if (issueRef.value != null) OpaqueBytes.of(issueRef.value) else defaultRef
|
val issueRef = if (issueRef.value != null) OpaqueBytes.of(issueRef.value) else defaultRef
|
||||||
when (it) {
|
when (it) {
|
||||||
executeButton -> when (transactionTypeCB.value) {
|
executeButton -> when (transactionTypeCB.value) {
|
||||||
CashTransaction.Issue -> IssueAndPaymentRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), issueRef, partyBChoiceBox.value.party, notaries.first(), anonymous)
|
CashTransaction.Issue -> IssueAndPaymentRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), issueRef, partyBChoiceBox.value.party, notaries.first().value!!, anonymous)
|
||||||
CashTransaction.Pay -> PaymentRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), partyBChoiceBox.value.party, anonymous = anonymous)
|
CashTransaction.Pay -> PaymentRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), partyBChoiceBox.value.party, anonymous = anonymous)
|
||||||
CashTransaction.Exit -> ExitRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), issueRef)
|
CashTransaction.Exit -> ExitRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), issueRef)
|
||||||
else -> null
|
else -> null
|
||||||
@ -192,7 +188,7 @@ class NewTransaction : Fragment() {
|
|||||||
issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull)
|
issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull)
|
||||||
// TODO This concept should burn (after services removal...)
|
// TODO This concept should burn (after services removal...)
|
||||||
issuerChoiceBox.apply {
|
issuerChoiceBox.apply {
|
||||||
items = issuers.map { it.chooseIdentity() }.unique().sorted()
|
items = issuers.map { it.party.owningKey.toKnownParty().value }.filterNotNull().unique().sorted()
|
||||||
converter = stringConverter { PartyNameFormatter.short.format(it.name) }
|
converter = stringConverter { PartyNameFormatter.short.format(it.name) }
|
||||||
visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay })
|
visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay })
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<Insets bottom="25" left="5" right="5" top="5"/>
|
<Insets bottom="25" left="5" right="5" top="5"/>
|
||||||
</StackPane.margin>
|
</StackPane.margin>
|
||||||
<TitledPane styleClass="networkTile" text="My Identity">
|
<TitledPane styleClass="networkTile" text="My Identity">
|
||||||
<BorderPane fx:id="myIdentityPane" minHeight="150"/>
|
<BorderPane fx:id="myIdentityPane"/>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<TitledPane styleClass="networkTile" text="Notaries">
|
<TitledPane styleClass="networkTile" text="Notaries">
|
||||||
<BorderPane minHeight="150">
|
<BorderPane minHeight="150">
|
||||||
|
Loading…
Reference in New Issue
Block a user