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.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import net.corda.client.jfx.utils.filterNotNull
|
||||
import net.corda.client.jfx.utils.fold
|
||||
import net.corda.client.jfx.utils.map
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import java.security.PublicKey
|
||||
|
||||
class NetworkIdentityModel {
|
||||
private val networkIdentityObservable by observable(NodeMonitorModel::networkMap)
|
||||
|
||||
val networkIdentities: ObservableList<NodeInfo> =
|
||||
private val networkIdentities: ObservableList<NodeInfo> =
|
||||
networkIdentityObservable.fold(FXCollections.observableArrayList()) { list, update ->
|
||||
list.removeIf {
|
||||
when (update) {
|
||||
@ -32,13 +33,15 @@ class NetworkIdentityModel {
|
||||
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||
|
||||
private val identityCache = CacheBuilder.newBuilder()
|
||||
.build<PublicKey, ObservableValue<NodeInfo?>>(CacheLoader.from {
|
||||
publicKey ->
|
||||
.build<PublicKey, ObservableValue<NodeInfo?>>(CacheLoader.from { publicKey ->
|
||||
publicKey?.let { rpcProxy.map { it?.nodeInfoFromParty(AnonymousParty(publicKey)) } }
|
||||
})
|
||||
|
||||
val notaries: ObservableList<Party> = FXCollections.observableList(rpcProxy.value?.notaryIdentities())
|
||||
val notaryNodes: ObservableList<NodeInfo> = FXCollections.observableList(notaries.map { rpcProxy.value?.nodeInfoFromParty(it) })
|
||||
val notaries: ObservableList<Party> = networkIdentities.map {
|
||||
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 myIdentity = rpcProxy.map { it?.nodeInfo()?.legalIdentitiesAndCerts?.first()?.party }
|
||||
|
||||
|
@ -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.FlowPermissionAuditEvent
|
||||
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.utilities.CordaPersistence
|
||||
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
|
||||
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(
|
||||
serviceHub.clock.instant(),
|
||||
flowInitiator,
|
||||
|
@ -69,6 +69,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||
['username' : "bankUser",
|
||||
'password' : "test",
|
||||
'permissions': ["StartFlow.net.corda.finance.flows.CashPaymentFlow",
|
||||
"StartFlow.net.corda.finance.flows.CashConfigDataFlow",
|
||||
"StartFlow.net.corda.finance.flows.CashExitFlow",
|
||||
"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.USD
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.flows.AbstractCashFlow
|
||||
import net.corda.finance.flows.CashExitFlow
|
||||
import net.corda.finance.flows.*
|
||||
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.CashPaymentFlow
|
||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.ServiceInfo
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.ALICE
|
||||
import net.corda.testing.BOB
|
||||
@ -39,12 +36,14 @@ import java.util.*
|
||||
|
||||
class ExplorerSimulation(val options: OptionSet) {
|
||||
private val user = User("user1", "test", permissions = setOf(
|
||||
startFlowPermission<CashPaymentFlow>()
|
||||
startFlowPermission<CashPaymentFlow>(),
|
||||
startFlowPermission<CashConfigDataFlow>()
|
||||
))
|
||||
private val manager = User("manager", "test", permissions = setOf(
|
||||
startFlowPermission<CashIssueAndPaymentFlow>(),
|
||||
startFlowPermission<CashPaymentFlow>(),
|
||||
startFlowPermission<CashExitFlow>())
|
||||
startFlowPermission<CashExitFlow>(),
|
||||
startFlowPermission<CashConfigDataFlow>())
|
||||
)
|
||||
|
||||
private lateinit var notaryNode: NodeHandle
|
||||
@ -122,7 +121,7 @@ class ExplorerSimulation(val options: OptionSet) {
|
||||
val issuerRPCGBP = issuerGBPConnection.proxy
|
||||
|
||||
val issuerClientUSD = issuerNodeUSD.rpcClientToNode()
|
||||
val issuerUSDConnection =issuerClientUSD.start(manager.username, manager.password)
|
||||
val issuerUSDConnection = issuerClientUSD.start(manager.username, manager.password)
|
||||
val issuerRPCUSD = issuerUSDConnection.proxy
|
||||
|
||||
RPCConnections.addAll(listOf(aliceConnection, bobConnection, issuerGBPConnection, issuerUSDConnection))
|
||||
|
@ -1,34 +1,25 @@
|
||||
package net.corda.explorer.model
|
||||
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import net.corda.client.jfx.model.NetworkIdentityModel
|
||||
import net.corda.client.jfx.model.observableList
|
||||
import net.corda.client.jfx.model.NodeMonitorModel
|
||||
import net.corda.client.jfx.model.observableValue
|
||||
import net.corda.client.jfx.utils.ChosenList
|
||||
import net.corda.client.jfx.utils.map
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.finance.flows.CashConfigDataFlow
|
||||
import tornadofx.*
|
||||
|
||||
val ISSUER_SERVICE_TYPE = Regex("corda.issuer.(USD|GBP|CHF|EUR)")
|
||||
|
||||
class IssuerModel {
|
||||
// TODO Explorer will be fixed as separate PR.
|
||||
private val networkIdentities by observableList(NetworkIdentityModel::networkIdentities)
|
||||
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
||||
private val supportedCurrencies by observableList(ReportingCurrencyModel::supportedCurrencies)
|
||||
private val proxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||
private val cashAppConfiguration = proxy.map { it?.startFlow(::CashConfigDataFlow)?.returnValue?.getOrThrow() }
|
||||
val supportedCurrencies = ChosenList(cashAppConfiguration.map { it?.supportedCurrencies?.observable() ?: FXCollections.emptyObservableList() })
|
||||
val currencyTypes = ChosenList(cashAppConfiguration.map { it?.issuableCurrencies?.observable() ?: FXCollections.emptyObservableList() })
|
||||
|
||||
val issuers: ObservableList<NodeInfo> = FXCollections.observableList(networkIdentities)
|
||||
|
||||
val currencyTypes = ChosenList(myIdentity.map { supportedCurrencies })
|
||||
|
||||
val transactionTypes = ChosenList(myIdentity.map {
|
||||
if (it?.isIssuerNode() ?: false)
|
||||
val transactionTypes = ChosenList(cashAppConfiguration.map {
|
||||
if (it?.issuableCurrencies?.isNotEmpty() == true)
|
||||
CashTransaction.values().asList().observable()
|
||||
else
|
||||
listOf(CashTransaction.Pay).observable()
|
||||
})
|
||||
|
||||
private fun Party.isIssuerNode() = true
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ import java.util.*
|
||||
|
||||
class ReportingCurrencyModel {
|
||||
private val exchangeRate: ObservableValue<ExchangeRate> by observableValue(ExchangeRateModel::exchangeRate)
|
||||
val reportingCurrency by observableValue(SettingsModel::reportingCurrencyProperty)
|
||||
val supportedCurrencies = setOf(USD, GBP, CHF, EUR).toList().observable()
|
||||
private val reportingCurrency by observableValue(SettingsModel::reportingCurrencyProperty)
|
||||
|
||||
/**
|
||||
* 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.collections.FXCollections
|
||||
import javafx.geometry.Bounds
|
||||
import javafx.geometry.Insets
|
||||
import javafx.geometry.Point2D
|
||||
import javafx.scene.Parent
|
||||
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.ScreenCoordinate
|
||||
import net.corda.finance.utils.WorldMapLocation
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import tornadofx.*
|
||||
|
||||
class Network : CordaView() {
|
||||
@ -91,15 +93,19 @@ class Network : CordaView() {
|
||||
val node = this
|
||||
val identities = node.legalIdentitiesAndCerts.sortedBy { it.owningKey.toBase58String() }
|
||||
return button {
|
||||
minWidth = 300.0
|
||||
padding = Insets(10.0)
|
||||
useMaxWidth = true
|
||||
graphic = vbox {
|
||||
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
|
||||
vgap = 5.0
|
||||
for (identity in identities) {
|
||||
row(PartyNameFormatter.short.format(identity.name)) {
|
||||
copyableLabel(SimpleObjectProperty(identity.owningKey.toBase58String())).apply { minWidth = 400.0 }
|
||||
val isNotary = identity.name.commonName?.let { ServiceType.parse(it).isNotary() } ?: false
|
||||
row("${if (isNotary) "Notary " else ""}Public Key :") {
|
||||
copyableLabel(SimpleObjectProperty(identity.owningKey.toBase58String()))
|
||||
}
|
||||
}
|
||||
node.getWorldMapLocation()?.apply { row("Location :") { label(this@apply.description) } }
|
||||
@ -114,7 +120,7 @@ class Network : CordaView() {
|
||||
private fun NodeInfo.render(): MapViewComponents {
|
||||
val node = this
|
||||
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)
|
||||
// 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.
|
||||
|
@ -12,6 +12,7 @@ import net.corda.client.jfx.model.objectProperty
|
||||
import net.corda.client.jfx.model.observableList
|
||||
import net.corda.client.jfx.utils.map
|
||||
import net.corda.explorer.model.CordaView
|
||||
import net.corda.explorer.model.IssuerModel
|
||||
import net.corda.explorer.model.ReportingCurrencyModel
|
||||
import net.corda.explorer.model.SettingsModel
|
||||
import java.util.*
|
||||
@ -22,7 +23,7 @@ class Settings : CordaView() {
|
||||
override val icon = FontAwesomeIcon.COGS
|
||||
|
||||
// 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 rememberMe by objectProperty(SettingsModel::rememberMeProperty)
|
||||
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.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.utilities.toBase58String
|
||||
import net.corda.explorer.AmountDiff
|
||||
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.CordaWidget
|
||||
import net.corda.explorer.model.ReportingCurrencyModel
|
||||
import net.corda.explorer.model.SettingsModel
|
||||
import net.corda.explorer.sign
|
||||
import net.corda.explorer.ui.setCustomCellFactory
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
@ -52,7 +52,7 @@ class TransactionViewer : CordaView("Transactions") {
|
||||
// Inject data
|
||||
private val transactions by observableListReadOnly(TransactionDataModel::partiallyResolvedTransactions)
|
||||
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)
|
||||
|
||||
override val widgets = listOf(CordaWidget(title, TransactionWidget(), icon)).observable()
|
||||
@ -260,7 +260,7 @@ class TransactionViewer : CordaView("Transactions") {
|
||||
vgap = 10.0
|
||||
hgap = 10.0
|
||||
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)
|
||||
tooltip = identiconToolTip(contractState.ref.txhash)
|
||||
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.stage.Window
|
||||
import net.corda.client.jfx.model.*
|
||||
import net.corda.client.jfx.utils.ChosenList
|
||||
import net.corda.client.jfx.utils.isNotNull
|
||||
import net.corda.client.jfx.utils.map
|
||||
import net.corda.client.jfx.utils.unique
|
||||
import net.corda.client.jfx.utils.*
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.Amount.Companion.sumOrNull
|
||||
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.model.CashTransaction
|
||||
import net.corda.explorer.model.IssuerModel
|
||||
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.explorer.views.toKnownParty
|
||||
import net.corda.finance.flows.AbstractCashFlow
|
||||
import net.corda.finance.flows.CashExitFlow
|
||||
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.CashPaymentFlow
|
||||
import net.corda.finance.flows.CashPaymentFlow.PaymentRequest
|
||||
import net.corda.testing.chooseIdentity
|
||||
import net.corda.testing.chooseIdentityAndCert
|
||||
import org.controlsfx.dialog.ExceptionDialog
|
||||
import tornadofx.*
|
||||
@ -71,15 +67,15 @@ class NewTransaction : Fragment() {
|
||||
private val issueRef = SimpleObjectProperty<Byte>()
|
||||
// Inject data
|
||||
private val parties by observableList(NetworkIdentityModel::parties)
|
||||
private val issuers by observableList(IssuerModel::issuers)
|
||||
private val rpcProxy by observableValue(NodeMonitorModel::proxyObservable)
|
||||
private val myIdentity by observableValue(NetworkIdentityModel::myIdentity)
|
||||
private val notaries by observableList(NetworkIdentityModel::notaries)
|
||||
private val cash by observableList(ContractStateModel::cash)
|
||||
private val executeButton = ButtonType("Execute", ButtonBar.ButtonData.APPLY)
|
||||
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 issuers = cash.map { it.token.issuer }
|
||||
|
||||
private val currencyItems = ChosenList(transactionTypeCB.valueProperty().map {
|
||||
when (it) {
|
||||
@ -156,7 +152,7 @@ class NewTransaction : Fragment() {
|
||||
val issueRef = if (issueRef.value != null) OpaqueBytes.of(issueRef.value) else defaultRef
|
||||
when (it) {
|
||||
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.Exit -> ExitRequest(Amount.fromDecimal(amount.value, currencyChoiceBox.value), issueRef)
|
||||
else -> null
|
||||
@ -192,7 +188,7 @@ class NewTransaction : Fragment() {
|
||||
issuerLabel.visibleProperty().bind(transactionTypeCB.valueProperty().isNotNull)
|
||||
// TODO This concept should burn (after services removal...)
|
||||
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) }
|
||||
visibleProperty().bind(transactionTypeCB.valueProperty().map { it == CashTransaction.Pay })
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
<Insets bottom="25" left="5" right="5" top="5"/>
|
||||
</StackPane.margin>
|
||||
<TitledPane styleClass="networkTile" text="My Identity">
|
||||
<BorderPane fx:id="myIdentityPane" minHeight="150"/>
|
||||
<BorderPane fx:id="myIdentityPane"/>
|
||||
</TitledPane>
|
||||
<TitledPane styleClass="networkTile" text="Notaries">
|
||||
<BorderPane minHeight="150">
|
||||
|
Loading…
Reference in New Issue
Block a user