mirror of
https://github.com/corda/corda.git
synced 2025-05-21 17:57:43 +00:00
explorer: Add input/output states and signers to tx screen
This commit is contained in:
parent
db9eb060b9
commit
26aed70e24
@ -1,7 +1,7 @@
|
|||||||
package com.r3corda.client.model
|
package com.r3corda.client.model
|
||||||
|
|
||||||
import com.r3corda.client.fxutils.foldToObservableList
|
import com.r3corda.client.fxutils.foldToObservableList
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.LedgerTransaction
|
||||||
import com.r3corda.node.services.monitor.ServiceToClientEvent
|
import com.r3corda.node.services.monitor.ServiceToClientEvent
|
||||||
import com.r3corda.node.services.monitor.TransactionBuildResult
|
import com.r3corda.node.services.monitor.TransactionBuildResult
|
||||||
import com.r3corda.node.utilities.AddOrRemove
|
import com.r3corda.node.utilities.AddOrRemove
|
||||||
@ -18,7 +18,7 @@ interface GatheredTransactionData {
|
|||||||
val uuid: ObservableValue<UUID?>
|
val uuid: ObservableValue<UUID?>
|
||||||
val protocolName: ObservableValue<String?>
|
val protocolName: ObservableValue<String?>
|
||||||
val protocolStatus: ObservableValue<ProtocolStatus?>
|
val protocolStatus: ObservableValue<ProtocolStatus?>
|
||||||
val transaction: ObservableValue<SignedTransaction?>
|
val transaction: ObservableValue<LedgerTransaction?>
|
||||||
val status: ObservableValue<TransactionCreateStatus?>
|
val status: ObservableValue<TransactionCreateStatus?>
|
||||||
val lastUpdate: ObservableValue<Instant>
|
val lastUpdate: ObservableValue<Instant>
|
||||||
val allEvents: ObservableList<out ServiceToClientEvent>
|
val allEvents: ObservableList<out ServiceToClientEvent>
|
||||||
@ -42,7 +42,7 @@ data class GatheredTransactionDataWritable(
|
|||||||
override val uuid: SimpleObjectProperty<UUID?> = SimpleObjectProperty(null),
|
override val uuid: SimpleObjectProperty<UUID?> = SimpleObjectProperty(null),
|
||||||
override val protocolName: SimpleObjectProperty<String?> = SimpleObjectProperty(null),
|
override val protocolName: SimpleObjectProperty<String?> = SimpleObjectProperty(null),
|
||||||
override val protocolStatus: SimpleObjectProperty<ProtocolStatus?> = SimpleObjectProperty(null),
|
override val protocolStatus: SimpleObjectProperty<ProtocolStatus?> = SimpleObjectProperty(null),
|
||||||
override val transaction: SimpleObjectProperty<SignedTransaction?> = SimpleObjectProperty(null),
|
override val transaction: SimpleObjectProperty<LedgerTransaction?> = SimpleObjectProperty(null),
|
||||||
override val status: SimpleObjectProperty<TransactionCreateStatus?> = SimpleObjectProperty(null),
|
override val status: SimpleObjectProperty<TransactionCreateStatus?> = SimpleObjectProperty(null),
|
||||||
override val lastUpdate: SimpleObjectProperty<Instant>,
|
override val lastUpdate: SimpleObjectProperty<Instant>,
|
||||||
override val allEvents: ObservableList<ServiceToClientEvent> = FXCollections.observableArrayList()
|
override val allEvents: ObservableList<ServiceToClientEvent> = FXCollections.observableArrayList()
|
||||||
|
26
explorer/src/main/kotlin/com/r3corda/explorer/AmountDiff.kt
Normal file
26
explorer/src/main/kotlin/com/r3corda/explorer/AmountDiff.kt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package com.r3corda.explorer
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.Amount
|
||||||
|
|
||||||
|
enum class Positivity {
|
||||||
|
Positive,
|
||||||
|
Negative
|
||||||
|
}
|
||||||
|
|
||||||
|
val Positivity.sign: String get() = when (this) {
|
||||||
|
Positivity.Positive -> ""
|
||||||
|
Positivity.Negative -> "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class AmountDiff<T>(
|
||||||
|
val positivity: Positivity,
|
||||||
|
val amount: Amount<T>
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun <T> fromLong(quantity: Long, token: T) =
|
||||||
|
AmountDiff(
|
||||||
|
positivity = if (quantity < 0) Positivity.Negative else Positivity.Positive,
|
||||||
|
amount = Amount(Math.abs(quantity), token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.r3corda.explorer.ui
|
||||||
|
|
||||||
|
import com.r3corda.explorer.formatters.Formatter
|
||||||
|
import javafx.scene.control.ListCell
|
||||||
|
import javafx.scene.control.ListView
|
||||||
|
import javafx.util.Callback
|
||||||
|
|
||||||
|
fun <T> Formatter<T>.toListCellFactory() = Callback<ListView<T?>, ListCell<T?>> {
|
||||||
|
object : ListCell<T?>() {
|
||||||
|
override fun updateItem(value: T?, empty: Boolean) {
|
||||||
|
super.updateItem(value, empty)
|
||||||
|
text = if (value == null || empty) {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
format(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,18 @@ import com.r3corda.core.contracts.Amount
|
|||||||
import com.r3corda.core.contracts.CommandData
|
import com.r3corda.core.contracts.CommandData
|
||||||
import com.r3corda.core.contracts.withoutIssuer
|
import com.r3corda.core.contracts.withoutIssuer
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
|
import com.r3corda.core.contracts.*
|
||||||
|
import com.r3corda.core.crypto.Party
|
||||||
|
import com.r3corda.core.crypto.toStringShort
|
||||||
|
import com.r3corda.core.transactions.LedgerTransaction
|
||||||
|
import com.r3corda.explorer.AmountDiff
|
||||||
import com.r3corda.explorer.formatters.AmountFormatter
|
import com.r3corda.explorer.formatters.AmountFormatter
|
||||||
|
import com.r3corda.explorer.formatters.Formatter
|
||||||
|
import com.r3corda.explorer.formatters.NumberFormatter
|
||||||
|
import com.r3corda.explorer.model.IdentityModel
|
||||||
import com.r3corda.explorer.model.ReportingCurrencyModel
|
import com.r3corda.explorer.model.ReportingCurrencyModel
|
||||||
import com.r3corda.explorer.ui.SingleRowSelection
|
import com.r3corda.explorer.sign
|
||||||
import com.r3corda.explorer.ui.setColumnPrefWidthPolicy
|
import com.r3corda.explorer.ui.*
|
||||||
import com.r3corda.explorer.ui.singleRowSelection
|
|
||||||
import com.r3corda.explorer.ui.toTableCellFactory
|
|
||||||
import com.r3corda.node.services.monitor.ServiceToClientEvent
|
import com.r3corda.node.services.monitor.ServiceToClientEvent
|
||||||
import javafx.beans.binding.Bindings
|
import javafx.beans.binding.Bindings
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper
|
import javafx.beans.property.ReadOnlyObjectWrapper
|
||||||
@ -20,10 +26,8 @@ import javafx.beans.value.ObservableValue
|
|||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.collections.ObservableList
|
import javafx.collections.ObservableList
|
||||||
import javafx.geometry.Insets
|
import javafx.geometry.Insets
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.Node
|
||||||
import javafx.scene.control.TableCell
|
import javafx.scene.control.*
|
||||||
import javafx.scene.control.TableColumn
|
|
||||||
import javafx.scene.control.TableView
|
|
||||||
import javafx.scene.layout.Background
|
import javafx.scene.layout.Background
|
||||||
import javafx.scene.layout.BackgroundFill
|
import javafx.scene.layout.BackgroundFill
|
||||||
import javafx.scene.layout.CornerRadii
|
import javafx.scene.layout.CornerRadii
|
||||||
@ -31,12 +35,15 @@ import javafx.scene.layout.VBox
|
|||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
import org.fxmisc.easybind.EasyBind
|
import org.fxmisc.easybind.EasyBind
|
||||||
import tornadofx.View
|
import tornadofx.View
|
||||||
|
import java.security.PublicKey
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class TransactionViewer: View() {
|
class TransactionViewer: View() {
|
||||||
override val root: VBox by fxml()
|
override val root: VBox by fxml()
|
||||||
|
|
||||||
|
val topSplitPane: SplitPane by fxid("TopSplitPane")
|
||||||
|
|
||||||
// Top half (transactions table)
|
// Top half (transactions table)
|
||||||
private val transactionViewTable: TableView<ViewerNode> by fxid("TransactionViewTable")
|
private val transactionViewTable: TableView<ViewerNode> by fxid("TransactionViewTable")
|
||||||
private val transactionViewTransactionId: TableColumn<ViewerNode, String> by fxid("TransactionViewTransactionId")
|
private val transactionViewTransactionId: TableColumn<ViewerNode, String> by fxid("TransactionViewTransactionId")
|
||||||
@ -44,9 +51,31 @@ class TransactionViewer: View() {
|
|||||||
private val transactionViewTransactionStatus: TableColumn<ViewerNode, Pair<TransactionCreateStatus?, ProtocolStatus?>> by fxid("TransactionViewTransactionStatus")
|
private val transactionViewTransactionStatus: TableColumn<ViewerNode, Pair<TransactionCreateStatus?, ProtocolStatus?>> by fxid("TransactionViewTransactionStatus")
|
||||||
private val transactionViewStatusUpdated: TableColumn<ViewerNode, Instant> by fxid("TransactionViewStatusUpdated")
|
private val transactionViewStatusUpdated: TableColumn<ViewerNode, Instant> by fxid("TransactionViewStatusUpdated")
|
||||||
private val transactionViewCommandTypes: TableColumn<ViewerNode, String> by fxid("TransactionViewCommandTypes")
|
private val transactionViewCommandTypes: TableColumn<ViewerNode, String> by fxid("TransactionViewCommandTypes")
|
||||||
private val transactionViewTotalValueEquiv: TableColumn<ViewerNode, Amount<Currency>> by fxid("TransactionViewTotalValueEquiv")
|
private val transactionViewTotalValueEquiv: TableColumn<ViewerNode, AmountDiff<Currency>> by fxid("TransactionViewTotalValueEquiv")
|
||||||
|
|
||||||
// Bottom half (details)
|
// Bottom half (details)
|
||||||
|
private val contractStatesTitledPane: TitledPane by fxid("ContractStatesTitledPane")
|
||||||
|
|
||||||
|
private val contractStatesInputStatesTable: TableView<StateNode> by fxid("ContractStatesInputStatesTable")
|
||||||
|
private val contractStatesInputStatesId: TableColumn<StateNode, String> by fxid("ContractStatesInputStatesId")
|
||||||
|
private val contractStatesInputStatesType: TableColumn<StateNode, Class<out ContractState>> by fxid("ContractStatesInputStatesType")
|
||||||
|
private val contractStatesInputStatesOwner: TableColumn<StateNode, String> by fxid("ContractStatesInputStatesOwner")
|
||||||
|
private val contractStatesInputStatesLocalCurrency: TableColumn<StateNode, Currency?> by fxid("ContractStatesInputStatesLocalCurrency")
|
||||||
|
private val contractStatesInputStatesAmount: TableColumn<StateNode, Long> by fxid("ContractStatesInputStatesAmount")
|
||||||
|
private val contractStatesInputStatesEquiv: TableColumn<StateNode, Amount<Currency>> by fxid("ContractStatesInputStatesEquiv")
|
||||||
|
|
||||||
|
private val contractStatesOutputStatesTable: TableView<StateNode> by fxid("ContractStatesOutputStatesTable")
|
||||||
|
private val contractStatesOutputStatesId: TableColumn<StateNode, String> by fxid("ContractStatesOutputStatesId")
|
||||||
|
private val contractStatesOutputStatesType: TableColumn<StateNode, Class<out ContractState>> by fxid("ContractStatesOutputStatesType")
|
||||||
|
private val contractStatesOutputStatesOwner: TableColumn<StateNode, String> by fxid("ContractStatesOutputStatesOwner")
|
||||||
|
private val contractStatesOutputStatesLocalCurrency: TableColumn<StateNode, Currency?> by fxid("ContractStatesOutputStatesLocalCurrency")
|
||||||
|
private val contractStatesOutputStatesAmount: TableColumn<StateNode, Long> by fxid("ContractStatesOutputStatesAmount")
|
||||||
|
private val contractStatesOutputStatesEquiv: TableColumn<StateNode, Amount<Currency>> by fxid("ContractStatesOutputStatesEquiv")
|
||||||
|
|
||||||
|
private val signaturesTitledPane: TitledPane by fxid("SignaturesTitledPane")
|
||||||
|
private val signaturesList: ListView<PublicKey> by fxid("SignaturesList")
|
||||||
|
|
||||||
|
private val lowLevelEventsTitledPane: TitledPane by fxid("LowLevelEventsTitledPane")
|
||||||
private val lowLevelEventsTable: TableView<ServiceToClientEvent> by fxid("LowLevelEventsTable")
|
private val lowLevelEventsTable: TableView<ServiceToClientEvent> by fxid("LowLevelEventsTable")
|
||||||
private val lowLevelEventsTimestamp: TableColumn<ServiceToClientEvent, Instant> by fxid("LowLevelEventsTimestamp")
|
private val lowLevelEventsTimestamp: TableColumn<ServiceToClientEvent, Instant> by fxid("LowLevelEventsTimestamp")
|
||||||
private val lowLevelEventsEvent: TableColumn<ServiceToClientEvent, ServiceToClientEvent> by fxid("LowLevelEventsEvent")
|
private val lowLevelEventsEvent: TableColumn<ServiceToClientEvent, ServiceToClientEvent> by fxid("LowLevelEventsEvent")
|
||||||
@ -56,17 +85,24 @@ class TransactionViewer: View() {
|
|||||||
private val reportingExchange: ObservableValue<Pair<Currency, (Amount<Currency>) -> Amount<Currency>>>
|
private val reportingExchange: ObservableValue<Pair<Currency, (Amount<Currency>) -> Amount<Currency>>>
|
||||||
by observableValue(ReportingCurrencyModel::reportingExchange)
|
by observableValue(ReportingCurrencyModel::reportingExchange)
|
||||||
|
|
||||||
|
private val myIdentity: ObservableValue<Party> by observableValue(IdentityModel::myIdentity)
|
||||||
|
|
||||||
data class ViewerNode(
|
data class ViewerNode(
|
||||||
val transactionId: ObservableValue<Pair<Long?, UUID?>>,
|
val transactionId: ObservableValue<Pair<Long?, UUID?>>,
|
||||||
val originator: ObservableValue<String>,
|
val originator: ObservableValue<String>,
|
||||||
val transactionStatus: ObservableValue<Pair<TransactionCreateStatus?, ProtocolStatus?>>,
|
val transactionStatus: ObservableValue<Pair<TransactionCreateStatus?, ProtocolStatus?>>,
|
||||||
val statusUpdated: ObservableValue<Instant>,
|
val statusUpdated: ObservableValue<Instant>,
|
||||||
val commandTypes: ObservableValue<Collection<Class<CommandData>>>,
|
val commandTypes: ObservableValue<Collection<Class<CommandData>>>,
|
||||||
val viewTotalValueEquiv: ObservableValue<Amount<Currency>?>,
|
val totalValueEquiv: ObservableValue<AmountDiff<Currency>?>,
|
||||||
val transaction: ObservableValue<SignedTransaction?>,
|
val transaction: ObservableValue<LedgerTransaction?>,
|
||||||
val allEvents: ObservableList<out ServiceToClientEvent>
|
val allEvents: ObservableList<out ServiceToClientEvent>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class StateNode(
|
||||||
|
val transactionState: TransactionState<*>,
|
||||||
|
val stateRef: StateRef
|
||||||
|
)
|
||||||
|
|
||||||
private val viewerNodes = EasyBind.map(gatheredTransactionDataList) {
|
private val viewerNodes = EasyBind.map(gatheredTransactionDataList) {
|
||||||
ViewerNode(
|
ViewerNode(
|
||||||
transactionId = EasyBind.combine(it.fiberId, it.uuid) { fiberId, uuid -> Pair(fiberId, uuid) },
|
transactionId = EasyBind.combine(it.fiberId, it.uuid) { fiberId, uuid -> Pair(fiberId, uuid) },
|
||||||
@ -83,13 +119,13 @@ class TransactionViewer: View() {
|
|||||||
statusUpdated = it.lastUpdate,
|
statusUpdated = it.lastUpdate,
|
||||||
commandTypes = EasyBind.map(it.transaction) {
|
commandTypes = EasyBind.map(it.transaction) {
|
||||||
val commands = mutableSetOf<Class<CommandData>>()
|
val commands = mutableSetOf<Class<CommandData>>()
|
||||||
it?.tx?.commands?.forEach {
|
it?.commands?.forEach {
|
||||||
commands.add(it.value.javaClass)
|
commands.add(it.value.javaClass)
|
||||||
}
|
}
|
||||||
commands
|
commands
|
||||||
},
|
},
|
||||||
viewTotalValueEquiv = EasyBind.combine(reportingExchange, it.transaction) { exchange, transaction ->
|
totalValueEquiv = EasyBind.combine(myIdentity, reportingExchange, it.transaction) { identity, exchange, transaction ->
|
||||||
transaction?.let { calculateTotalEquiv(exchange.first, exchange.second, transaction) }
|
transaction?.let { calculateTotalEquiv(setOf(identity.owningKey), exchange.first, exchange.second, transaction) }
|
||||||
},
|
},
|
||||||
transaction = it.transaction,
|
transaction = it.transaction,
|
||||||
allEvents = it.allEvents
|
allEvents = it.allEvents
|
||||||
@ -97,16 +133,60 @@ class TransactionViewer: View() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateTotalEquiv(
|
private fun calculateTotalEquiv(
|
||||||
|
relevantPublicKeys: Set<PublicKey>,
|
||||||
reportingCurrency: Currency,
|
reportingCurrency: Currency,
|
||||||
exchange: (Amount<Currency>) -> Amount<Currency>,
|
exchange: (Amount<Currency>) -> Amount<Currency>,
|
||||||
transaction: SignedTransaction): Amount<Currency> {
|
transaction: LedgerTransaction): AmountDiff<Currency> {
|
||||||
return transaction.tx.outputs.map { it.data }.filterIsInstance<Cash.State>().fold(
|
var sum = 0L
|
||||||
initial = Amount(0, reportingCurrency),
|
transaction.inputs.forEach {
|
||||||
operation = { sum, cashState -> sum + exchange(cashState.amount.withoutIssuer()) }
|
val contractState = it.state.data
|
||||||
)
|
if (contractState is Cash.State && relevantPublicKeys.contains(contractState.owner)) {
|
||||||
|
sum -= exchange(contractState.amount.withoutIssuer()).quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transaction.outputs.forEach {
|
||||||
|
val contractState = it.data
|
||||||
|
if (contractState is Cash.State && relevantPublicKeys.contains(contractState.owner)) {
|
||||||
|
sum += exchange(contractState.amount.withoutIssuer()).quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AmountDiff.fromLong(sum, reportingCurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val selectedViewerNode = transactionViewTable.singleRowSelection()
|
private val selectedViewerNode = transactionViewTable.singleRowSelection()
|
||||||
|
private val selectedTransaction = EasyBind.monadic(selectedViewerNode).flatMap<LedgerTransaction?, SingleRowSelection<ViewerNode>> {
|
||||||
|
when (it) {
|
||||||
|
is SingleRowSelection.None -> ReadOnlyObjectWrapper(null)
|
||||||
|
is SingleRowSelection.Selected -> it.node.transaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val inputStateNodes = ChosenList<StateNode>(EasyBind.map(selectedTransaction) {
|
||||||
|
if (it == null) {
|
||||||
|
FXCollections.emptyObservableList<StateNode>()
|
||||||
|
} else {
|
||||||
|
FXCollections.observableArrayList(it.inputs.map { StateNode(it.state, it.ref) })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
private val outputStateNodes = ChosenList<StateNode>(EasyBind.map(selectedTransaction) {
|
||||||
|
if (it == null) {
|
||||||
|
FXCollections.emptyObservableList<StateNode>()
|
||||||
|
} else {
|
||||||
|
FXCollections.observableArrayList(it.outputs.mapIndexed { index, transactionState ->
|
||||||
|
StateNode(transactionState, StateRef(it.id, index))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
private val signatures = ChosenList<PublicKey>(EasyBind.map(selectedTransaction) {
|
||||||
|
if (it == null) {
|
||||||
|
FXCollections.emptyObservableList<PublicKey>()
|
||||||
|
} else {
|
||||||
|
FXCollections.observableArrayList(it.mustSign)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
private val noLowLevelEvents = FXCollections.emptyObservableList<ServiceToClientEvent>()
|
private val noLowLevelEvents = FXCollections.emptyObservableList<ServiceToClientEvent>()
|
||||||
private val lowLevelEvents = ChosenList(EasyBind.map(selectedViewerNode) {
|
private val lowLevelEvents = ChosenList(EasyBind.map(selectedViewerNode) {
|
||||||
@ -116,7 +196,78 @@ class TransactionViewer: View() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
private val allNodesShown = FXCollections.observableArrayList<Node>(
|
||||||
|
transactionViewTable,
|
||||||
|
contractStatesTitledPane,
|
||||||
|
signaturesTitledPane,
|
||||||
|
lowLevelEventsTitledPane
|
||||||
|
)
|
||||||
|
private val onlyTransactionsTableShown = FXCollections.observableArrayList<Node>(
|
||||||
|
transactionViewTable
|
||||||
|
)
|
||||||
|
private val topSplitPaneNodesShown = ChosenList<Node>(
|
||||||
|
EasyBind.map(selectedViewerNode) { selection ->
|
||||||
|
if (selection is SingleRowSelection.None<*>) {
|
||||||
|
onlyTransactionsTableShown
|
||||||
|
} else {
|
||||||
|
allNodesShown
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
private fun wireUpStatesTable(
|
||||||
|
states: ObservableList<StateNode>,
|
||||||
|
statesTable: TableView<StateNode>,
|
||||||
|
statesId: TableColumn<StateNode, String>,
|
||||||
|
statesType: TableColumn<StateNode, Class<out ContractState>>,
|
||||||
|
statesOwner: TableColumn<StateNode, String>,
|
||||||
|
statesLocalCurrency: TableColumn<StateNode, Currency?>,
|
||||||
|
statesAmount: TableColumn<StateNode, Long>,
|
||||||
|
statesEquiv: TableColumn<StateNode, Amount<Currency>>
|
||||||
|
) {
|
||||||
|
Bindings.bindContent(statesTable.items, states)
|
||||||
|
|
||||||
|
statesId.setCellValueFactory { ReadOnlyObjectWrapper(it.value.stateRef.toString()) }
|
||||||
|
statesType.setCellValueFactory { ReadOnlyObjectWrapper(it.value.transactionState.data.javaClass) }
|
||||||
|
statesOwner.setCellValueFactory {
|
||||||
|
val state = it.value.transactionState.data
|
||||||
|
if (state is OwnableState) {
|
||||||
|
ReadOnlyObjectWrapper(state.owner.toStringShort())
|
||||||
|
} else {
|
||||||
|
ReadOnlyObjectWrapper("???")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statesLocalCurrency.setCellValueFactory {
|
||||||
|
val state = it.value.transactionState.data
|
||||||
|
if (state is Cash.State) {
|
||||||
|
ReadOnlyObjectWrapper(state.amount.token.product)
|
||||||
|
} else {
|
||||||
|
ReadOnlyObjectWrapper(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statesAmount.setCellValueFactory {
|
||||||
|
val state = it.value.transactionState.data
|
||||||
|
if (state is Cash.State) {
|
||||||
|
ReadOnlyObjectWrapper(state.amount.quantity)
|
||||||
|
} else {
|
||||||
|
ReadOnlyObjectWrapper(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statesAmount.setCellFactory(NumberFormatter.longComma.toTableCellFactory())
|
||||||
|
statesEquiv.setCellValueFactory {
|
||||||
|
val state = it.value.transactionState.data
|
||||||
|
if (state is Cash.State) {
|
||||||
|
EasyBind.map(reportingExchange) { exchange ->
|
||||||
|
exchange.second(state.amount.withoutIssuer())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ReadOnlyObjectWrapper(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
Bindings.bindContent(topSplitPane.items, topSplitPaneNodesShown)
|
||||||
|
|
||||||
// Transaction table
|
// Transaction table
|
||||||
Bindings.bindContent(transactionViewTable.items, viewerNodes)
|
Bindings.bindContent(transactionViewTable.items, viewerNodes)
|
||||||
|
|
||||||
@ -155,7 +306,7 @@ class TransactionViewer: View() {
|
|||||||
null -> BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)
|
null -> BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)
|
||||||
}
|
}
|
||||||
label.background = Background(backgroundFill)
|
label.background = Background(backgroundFill)
|
||||||
label.text = if (value.first == null && value.second == null){
|
label.text = if (value.first == null && value.second == null) {
|
||||||
"???"
|
"???"
|
||||||
} else {
|
} else {
|
||||||
(value.first?.toString() ?: "") + (value.second?.let { "[${it.toString()}]" } ?: "")
|
(value.first?.toString() ?: "") + (value.second?.let { "[${it.toString()}]" } ?: "")
|
||||||
@ -169,8 +320,39 @@ class TransactionViewer: View() {
|
|||||||
transactionViewCommandTypes.setCellValueFactory {
|
transactionViewCommandTypes.setCellValueFactory {
|
||||||
EasyBind.map(it.value.commandTypes) { it.map { it.simpleName }.joinToString(",") }
|
EasyBind.map(it.value.commandTypes) { it.map { it.simpleName }.joinToString(",") }
|
||||||
}
|
}
|
||||||
transactionViewTotalValueEquiv.setCellValueFactory<ViewerNode, Amount<Currency>> { it.value.viewTotalValueEquiv }
|
transactionViewTotalValueEquiv.setCellValueFactory<ViewerNode, AmountDiff<Currency>> { it.value.totalValueEquiv }
|
||||||
transactionViewTotalValueEquiv.cellFactory = AmountFormatter.comma.toTableCellFactory()
|
transactionViewTotalValueEquiv.cellFactory = object : Formatter<AmountDiff<Currency>> {
|
||||||
|
override fun format(value: AmountDiff<Currency>) =
|
||||||
|
"${value.positivity.sign}${AmountFormatter.comma.format(value.amount)}"
|
||||||
|
}.toTableCellFactory()
|
||||||
|
|
||||||
|
// Contract states
|
||||||
|
wireUpStatesTable(
|
||||||
|
inputStateNodes,
|
||||||
|
contractStatesInputStatesTable,
|
||||||
|
contractStatesInputStatesId,
|
||||||
|
contractStatesInputStatesType,
|
||||||
|
contractStatesInputStatesOwner,
|
||||||
|
contractStatesInputStatesLocalCurrency,
|
||||||
|
contractStatesInputStatesAmount,
|
||||||
|
contractStatesInputStatesEquiv
|
||||||
|
)
|
||||||
|
wireUpStatesTable(
|
||||||
|
outputStateNodes,
|
||||||
|
contractStatesOutputStatesTable,
|
||||||
|
contractStatesOutputStatesId,
|
||||||
|
contractStatesOutputStatesType,
|
||||||
|
contractStatesOutputStatesOwner,
|
||||||
|
contractStatesOutputStatesLocalCurrency,
|
||||||
|
contractStatesOutputStatesAmount,
|
||||||
|
contractStatesOutputStatesEquiv
|
||||||
|
)
|
||||||
|
|
||||||
|
// Signatures
|
||||||
|
Bindings.bindContent(signaturesList.items, signatures)
|
||||||
|
signaturesList.cellFactory = object : Formatter<PublicKey> {
|
||||||
|
override fun format(value: PublicKey) = value.toStringShort()
|
||||||
|
}.toListCellFactory()
|
||||||
|
|
||||||
// Low level events
|
// Low level events
|
||||||
Bindings.bindContent(lowLevelEventsTable.items, lowLevelEvents)
|
Bindings.bindContent(lowLevelEventsTable.items, lowLevelEvents)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
<?import java.lang.String?>
|
<?import java.lang.String?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Accordion?>
|
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.ListView?>
|
||||||
<?import javafx.scene.control.SplitPane?>
|
<?import javafx.scene.control.SplitPane?>
|
||||||
<?import javafx.scene.control.TableColumn?>
|
<?import javafx.scene.control.TableColumn?>
|
||||||
<?import javafx.scene.control.TableView?>
|
<?import javafx.scene.control.TableView?>
|
||||||
@ -11,7 +11,6 @@
|
|||||||
<?import javafx.scene.control.TitledPane?>
|
<?import javafx.scene.control.TitledPane?>
|
||||||
<?import javafx.scene.image.Image?>
|
<?import javafx.scene.image.Image?>
|
||||||
<?import javafx.scene.image.ImageView?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
|
||||||
@ -40,7 +39,7 @@
|
|||||||
</ImageView>
|
</ImageView>
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<SplitPane dividerPositions="0.5" orientation="VERTICAL" prefHeight="562.0" prefWidth="1087.0" VBox.vgrow="ALWAYS">
|
<SplitPane fx:id="TopSplitPane" dividerPositions="0.5, 0.5, 0.5" orientation="VERTICAL" prefHeight="562.0" prefWidth="1087.0" VBox.vgrow="ALWAYS">
|
||||||
<items>
|
<items>
|
||||||
<TableView fx:id="TransactionViewTable" prefHeight="200.0" prefWidth="200.0">
|
<TableView fx:id="TransactionViewTable" prefHeight="200.0" prefWidth="200.0">
|
||||||
<columns>
|
<columns>
|
||||||
@ -55,24 +54,7 @@
|
|||||||
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
||||||
</columnResizePolicy>
|
</columnResizePolicy>
|
||||||
</TableView>
|
</TableView>
|
||||||
<Accordion>
|
<TitledPane fx:id="ContractStatesTitledPane" animated="false" text="Contract states">
|
||||||
<panes>
|
|
||||||
<TitledPane text="Transaction details">
|
|
||||||
<content>
|
|
||||||
<AnchorPane>
|
|
||||||
<children>
|
|
||||||
<Label layoutX="5.0" layoutY="5.0" text="Transaction ID" />
|
|
||||||
<Label layoutX="97.0" layoutY="5.0" text="IC-3902-29090-32091" AnchorPane.leftAnchor="95.0" AnchorPane.rightAnchor="15.0" />
|
|
||||||
<Label layoutX="5.0" layoutY="33.0" text="Originator" />
|
|
||||||
<Label layoutX="97.0" layoutY="33.0" prefHeight="16.0" text="C03102 HSBC GROUP PLC" AnchorPane.leftAnchor="95.0" AnchorPane.rightAnchor="15.0" />
|
|
||||||
<Label layoutX="5.0" layoutY="49.0" prefHeight="26.0" prefWidth="78.0" text="Date/time originated" wrapText="true" />
|
|
||||||
<Label layoutX="97.0" layoutY="49.0" text="2019-05-24 11:47 UTC" AnchorPane.leftAnchor="95.0" AnchorPane.rightAnchor="15.0" />
|
|
||||||
<Label layoutX="5.0" layoutY="90.0" text="Current status" />
|
|
||||||
<Label layoutX="104.0" layoutY="90.0" prefHeight="16.0" text="01800 - EXCEPTION - UNSPECIFIED NETWORK ERROR" AnchorPane.leftAnchor="95.0" AnchorPane.rightAnchor="15.0" />
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
||||||
</content></TitledPane>
|
|
||||||
<TitledPane text="Contract states">
|
|
||||||
<content>
|
<content>
|
||||||
<SplitPane dividerPositions="0.5" prefHeight="160.0" prefWidth="200.0">
|
<SplitPane dividerPositions="0.5" prefHeight="160.0" prefWidth="200.0">
|
||||||
<items>
|
<items>
|
||||||
@ -81,20 +63,21 @@
|
|||||||
<Label text="Inputs: 23">
|
<Label text="Inputs: 23">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" top="5.0" />
|
<Insets bottom="5.0" top="5.0" />
|
||||||
</padding></Label>
|
</padding>
|
||||||
<TableView prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
</Label>
|
||||||
|
<TableView fx:id="ContractStatesInputStatesTable" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn prefWidth="75.0" text="ID" />
|
<TableColumn fx:id="ContractStatesInputStatesId" prefWidth="75.0" text="ID" />
|
||||||
<TableColumn prefWidth="75.0" text="Type" />
|
<TableColumn fx:id="ContractStatesInputStatesType" prefWidth="75.0" text="Type" />
|
||||||
<TableColumn prefWidth="75.0" text="Owner" />
|
<TableColumn fx:id="ContractStatesInputStatesOwner" prefWidth="75.0" text="Owner" />
|
||||||
<TableColumn prefWidth="75.0" styleClass="first-column" text="Local Ccy" />
|
<TableColumn fx:id="ContractStatesInputStatesLocalCurrency" prefWidth="75.0" styleClass="first-column" text="Local Ccy" />
|
||||||
<TableColumn prefWidth="75.0" text="Amount">
|
<TableColumn fx:id="ContractStatesInputStatesAmount" prefWidth="75.0" text="Amount">
|
||||||
<styleClass>
|
<styleClass>
|
||||||
<String fx:value="second-column" />
|
<String fx:value="second-column" />
|
||||||
<String fx:value="monetary-value" />
|
<String fx:value="monetary-value" />
|
||||||
</styleClass>
|
</styleClass>
|
||||||
</TableColumn>
|
</TableColumn>
|
||||||
<TableColumn prefWidth="75.0" text="USD Equiv" />
|
<TableColumn fx:id="ContractStatesInputStatesEquiv" prefWidth="75.0" text="USD Equiv" />
|
||||||
</columns>
|
</columns>
|
||||||
<columnResizePolicy>
|
<columnResizePolicy>
|
||||||
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
||||||
@ -110,20 +93,21 @@
|
|||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding></Label>
|
</padding>
|
||||||
<TableView prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
</Label>
|
||||||
|
<TableView fx:id="ContractStatesOutputStatesTable" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn prefWidth="75.0" text="ID" />
|
<TableColumn fx:id="ContractStatesOutputStatesId" prefWidth="75.0" text="ID" />
|
||||||
<TableColumn prefWidth="75.0" text="Type" />
|
<TableColumn fx:id="ContractStatesOutputStatesType" prefWidth="75.0" text="Type" />
|
||||||
<TableColumn prefWidth="75.0" text="Owner" />
|
<TableColumn fx:id="ContractStatesOutputStatesOwner" prefWidth="75.0" text="Owner" />
|
||||||
<TableColumn prefWidth="75.0" styleClass="first-column" text="Local Ccy" />
|
<TableColumn fx:id="ContractStatesOutputStatesLocalCurrency" prefWidth="75.0" styleClass="first-column" text="Local Ccy" />
|
||||||
<TableColumn prefWidth="75.0" text="Amount">
|
<TableColumn fx:id="ContractStatesOutputStatesAmount" prefWidth="75.0" text="Amount">
|
||||||
<styleClass>
|
<styleClass>
|
||||||
<String fx:value="second-column" />
|
<String fx:value="second-column" />
|
||||||
<String fx:value="monetary-value" />
|
<String fx:value="monetary-value" />
|
||||||
</styleClass>
|
</styleClass>
|
||||||
</TableColumn>
|
</TableColumn>
|
||||||
<TableColumn prefWidth="75.0" text="USD Equiv" />
|
<TableColumn fx:id="ContractStatesOutputStatesEquiv" prefWidth="75.0" text="USD Equiv" />
|
||||||
</columns>
|
</columns>
|
||||||
<columnResizePolicy>
|
<columnResizePolicy>
|
||||||
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
|
||||||
@ -135,28 +119,12 @@
|
|||||||
</SplitPane>
|
</SplitPane>
|
||||||
</content>
|
</content>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<TitledPane prefHeight="200.0" prefWidth="200.0" text="Signatures (3/4)">
|
<TitledPane fx:id="SignaturesTitledPane" animated="false" text="Required signatures">
|
||||||
<content>
|
<content>
|
||||||
<TableView prefHeight="200.0" prefWidth="200.0">
|
<ListView fx:id="SignaturesList" />
|
||||||
<columns>
|
|
||||||
<TableColumn prefWidth="305.0" text="Signatory" />
|
|
||||||
<TableColumn prefWidth="221.0" text="Status" />
|
|
||||||
<TableColumn prefWidth="271.0" text="Status updated" />
|
|
||||||
</columns>
|
|
||||||
</TableView>
|
|
||||||
</content>
|
</content>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<TitledPane prefHeight="54.0" prefWidth="722.0" text="Attachments (3)">
|
<TitledPane fx:id="LowLevelEventsTitledPane" animated="false" text="Low level events">
|
||||||
<content>
|
|
||||||
<TableView prefHeight="200.0" prefWidth="200.0">
|
|
||||||
<columns>
|
|
||||||
<TableColumn prefWidth="136.0" text="File name" />
|
|
||||||
<TableColumn minWidth="8.0" prefWidth="172.0" text="Size" />
|
|
||||||
<TableColumn prefWidth="218.0" text="Date modified" />
|
|
||||||
</columns>
|
|
||||||
</TableView>
|
|
||||||
</content></TitledPane>
|
|
||||||
<TitledPane animated="false" text="Low level events">
|
|
||||||
<content>
|
<content>
|
||||||
<TableView fx:id="LowLevelEventsTable">
|
<TableView fx:id="LowLevelEventsTable">
|
||||||
<columns>
|
<columns>
|
||||||
@ -166,8 +134,6 @@
|
|||||||
</TableView>
|
</TableView>
|
||||||
</content>
|
</content>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
</panes>
|
|
||||||
</Accordion>
|
|
||||||
</items>
|
</items>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
<Label text="133 matching transaction(s)" />
|
<Label text="133 matching transaction(s)" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user