mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Visualiser: reorganise, make it easier to invoke, document it.
This commit is contained in:
parent
2193dced0a
commit
58c526c68b
1
docs/build/html/_sources/index.txt
vendored
1
docs/build/html/_sources/index.txt
vendored
@ -26,5 +26,6 @@ Read on to learn:
|
||||
overview
|
||||
getting-set-up
|
||||
tutorial
|
||||
visualiser
|
||||
roadmap
|
||||
|
||||
|
9
docs/build/html/_sources/tutorial.txt
vendored
9
docs/build/html/_sources/tutorial.txt
vendored
@ -524,8 +524,13 @@ As this is JUnit, we must remember to annotate each test method with @Test. Let'
|
||||
We are trying to check that it's not possible for just anyone to issue commercial paper in MegaCorp's name. That would
|
||||
be bad!
|
||||
|
||||
The ``transactionGroup`` function works the same way as the ``requireThat`` construct above. It is an example of what
|
||||
Kotlin calls a type safe builder, which you can read about in `the documentation for builders <https://kotlinlang.org/docs/reference/type-safe-builders.html>`_.
|
||||
The ``transactionGroup`` function works the same way as the ``requireThat`` construct above.
|
||||
|
||||
.. note:: This DSL is an example of what Kotlin calls a type safe builder, which you can read about in `the
|
||||
documentation for builders <https://kotlinlang.org/docs/reference/type-safe-builders.html>`_. You can mix and match
|
||||
ordinary code inside such DSLs so please read the linked page to make sure you fully understand what they are capable
|
||||
of.
|
||||
|
||||
The code block that follows it is run in the scope of a freshly created ``TransactionGroupForTest`` object, which assists
|
||||
you with building little transaction graphs and verifying them as a whole. Here, our "group" only actually has a
|
||||
single transaction in it, with a single output, no inputs, and an Issue command signed by ``DUMMY_PUBKEY_1`` which is just
|
||||
|
1
docs/build/html/genindex.html
vendored
1
docs/build/html/genindex.html
vendored
@ -85,6 +85,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="overview.html">Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
|
||||
|
2
docs/build/html/index.html
vendored
2
docs/build/html/index.html
vendored
@ -85,6 +85,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="overview.html">Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
|
||||
@ -170,6 +171,7 @@ prove or disprove the following hypothesis:</p>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#non-asset-oriented-based-smart-contracts">Non-asset-oriented based smart contracts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
1
docs/build/html/search.html
vendored
1
docs/build/html/search.html
vendored
@ -84,6 +84,7 @@
|
||||
<li class="toctree-l1"><a class="reference internal" href="overview.html">Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
|
||||
|
2
docs/build/html/searchindex.js
vendored
2
docs/build/html/searchindex.js
vendored
File diff suppressed because one or more lines are too long
17
docs/build/html/tutorial.html
vendored
17
docs/build/html/tutorial.html
vendored
@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
<link rel="top" title="R3 Prototyping 0.1 documentation" href="index.html"/>
|
||||
<link rel="next" title="Roadmap" href="roadmap.html"/>
|
||||
<link rel="next" title="Using the visualiser" href="visualiser.html"/>
|
||||
<link rel="prev" title="Getting set up" href="getting-set-up.html"/>
|
||||
|
||||
|
||||
@ -97,6 +97,7 @@
|
||||
<li class="toctree-l2"><a class="reference internal" href="#non-asset-oriented-based-smart-contracts">Non-asset-oriented based smart contracts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
|
||||
@ -608,9 +609,15 @@ and returns a <code class="docutils literal"><span class="pre">java.time.Duratio
|
||||
<p>As this is JUnit, we must remember to annotate each test method with @Test. Let’s examine the contents of the first test.
|
||||
We are trying to check that it’s not possible for just anyone to issue commercial paper in MegaCorp’s name. That would
|
||||
be bad!</p>
|
||||
<p>The <code class="docutils literal"><span class="pre">transactionGroup</span></code> function works the same way as the <code class="docutils literal"><span class="pre">requireThat</span></code> construct above. It is an example of what
|
||||
Kotlin calls a type safe builder, which you can read about in <a class="reference external" href="https://kotlinlang.org/docs/reference/type-safe-builders.html">the documentation for builders</a>.
|
||||
The code block that follows it is run in the scope of a freshly created <code class="docutils literal"><span class="pre">TransactionGroupForTest</span></code> object, which assists
|
||||
<p>The <code class="docutils literal"><span class="pre">transactionGroup</span></code> function works the same way as the <code class="docutils literal"><span class="pre">requireThat</span></code> construct above.</p>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">This DSL is an example of what Kotlin calls a type safe builder, which you can read about in <a class="reference external" href="https://kotlinlang.org/docs/reference/type-safe-builders.html">the
|
||||
documentation for builders</a>. You can mix and match
|
||||
ordinary code inside such DSLs so please read the linked page to make sure you fully understand what they are capable
|
||||
of.</p>
|
||||
</div>
|
||||
<p>The code block that follows it is run in the scope of a freshly created <code class="docutils literal"><span class="pre">TransactionGroupForTest</span></code> object, which assists
|
||||
you with building little transaction graphs and verifying them as a whole. Here, our “group” only actually has a
|
||||
single transaction in it, with a single output, no inputs, and an Issue command signed by <code class="docutils literal"><span class="pre">DUMMY_PUBKEY_1</span></code> which is just
|
||||
an arbitrary public key. As the paper claims to be issued by <code class="docutils literal"><span class="pre">MEGA_CORP</span></code>, this doesn’t match and should cause a
|
||||
@ -850,7 +857,7 @@ be implemented once in a separate contract, with the controlling data being held
|
||||
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
|
||||
<a href="roadmap.html" class="btn btn-neutral float-right" title="Roadmap" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
<a href="visualiser.html" class="btn btn-neutral float-right" title="Using the visualiser" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
|
||||
|
||||
<a href="getting-set-up.html" class="btn btn-neutral" title="Getting set up" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
|
@ -26,5 +26,6 @@ Read on to learn:
|
||||
overview
|
||||
getting-set-up
|
||||
tutorial
|
||||
visualiser
|
||||
roadmap
|
||||
|
||||
|
@ -524,8 +524,13 @@ As this is JUnit, we must remember to annotate each test method with @Test. Let'
|
||||
We are trying to check that it's not possible for just anyone to issue commercial paper in MegaCorp's name. That would
|
||||
be bad!
|
||||
|
||||
The ``transactionGroup`` function works the same way as the ``requireThat`` construct above. It is an example of what
|
||||
Kotlin calls a type safe builder, which you can read about in `the documentation for builders <https://kotlinlang.org/docs/reference/type-safe-builders.html>`_.
|
||||
The ``transactionGroup`` function works the same way as the ``requireThat`` construct above.
|
||||
|
||||
.. note:: This DSL is an example of what Kotlin calls a type safe builder, which you can read about in `the
|
||||
documentation for builders <https://kotlinlang.org/docs/reference/type-safe-builders.html>`_. You can mix and match
|
||||
ordinary code inside such DSLs so please read the linked page to make sure you fully understand what they are capable
|
||||
of.
|
||||
|
||||
The code block that follows it is run in the scope of a freshly created ``TransactionGroupForTest`` object, which assists
|
||||
you with building little transaction graphs and verifying them as a whole. Here, our "group" only actually has a
|
||||
single transaction in it, with a single output, no inputs, and an Issue command signed by ``DUMMY_PUBKEY_1`` which is just
|
||||
|
BIN
docs/source/visualiser.png
Normal file
BIN
docs/source/visualiser.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
78
docs/source/visualiser.rst
Normal file
78
docs/source/visualiser.rst
Normal file
@ -0,0 +1,78 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
Using the visualiser
|
||||
====================
|
||||
|
||||
In order to assist with understanding of the state model, the repository includes a simple graph visualiser. The
|
||||
visualiser is integrated with the unit test framework and the same domain specific language. It is currently very
|
||||
early and the diagrams it produces are not especially beautiful. The intention is to improve it in future releases.
|
||||
|
||||
.. image:: visualiser.png
|
||||
|
||||
An example of how to use it can be seen in ``src/test/kotlin/contracts/CommercialPaperTests.kt``.
|
||||
|
||||
Briefly, define a set of transactions in a group using the same DSL that is used in the unit tests. Here's an example
|
||||
of a trade lifecycle using the commercial paper contract
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val group: TransactionGroupDSL<ContractState> = transactionGroupFor() {
|
||||
roots {
|
||||
transaction(900.DOLLARS.CASH `owned by` ALICE label "alice's $900")
|
||||
transaction(someProfits.CASH `owned by` MEGA_CORP_PUBKEY label "some profits")
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
transaction("Issuance") {
|
||||
output("paper") { PAPER_1 }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction("Trade") {
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output("borrowed $900") { 900.DOLLARS.CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
output("alice's paper") { "paper".output `owned by` ALICE }
|
||||
arg(ALICE) { Cash.Commands.Move() }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.
|
||||
transaction("Redemption", redemptionTime) {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
output("Alice's profit") { aliceGetsBack.CASH `owned by` ALICE }
|
||||
output("Change") { (someProfits - aliceGetsBack).CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
if (!destroyPaperAtRedemption)
|
||||
output { "paper".output }
|
||||
|
||||
arg(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
arg(ALICE) { CommercialPaper.Commands.Redeem() }
|
||||
}
|
||||
}
|
||||
|
||||
Now you can define a main method in your unit test class that takes the ``TransactionGroupDSL`` object and uses it:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
CommercialPaperTests().trade().visualise()
|
||||
|
||||
This will open up a window with the following features:
|
||||
|
||||
* The nodes can be dragged around to try and obtain a better layout (an improved layout algorithm will be a future
|
||||
feature).
|
||||
* States are rendered as circles. Transactions are small blue squares. Commands are small diamonds.
|
||||
* Clicking a state will open up a window that shows its fields.
|
||||
|
@ -95,51 +95,6 @@ class CommercialPaperTests {
|
||||
trade(destroyPaperAtRedemption = false).expectFailureOfTx(3, "must be destroyed")
|
||||
}
|
||||
|
||||
// Generate a trade lifecycle with various parameters.
|
||||
private fun trade(redemptionTime: Instant = TEST_TX_TIME + 8.days,
|
||||
aliceGetsBack: Amount = 1000.DOLLARS,
|
||||
destroyPaperAtRedemption: Boolean = true): TransactionGroupDSL<CommercialPaper.State> {
|
||||
val someProfits = 1200.DOLLARS
|
||||
return transactionGroupFor() {
|
||||
roots {
|
||||
transaction(900.DOLLARS.CASH `owned by` ALICE label "alice's $900")
|
||||
transaction(someProfits.CASH `owned by` MEGA_CORP_PUBKEY label "some profits")
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
transaction {
|
||||
output("paper") { PAPER_1 }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction {
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output { 900.DOLLARS.CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
output("alice's paper") { "paper".output `owned by` ALICE }
|
||||
arg(ALICE) { Cash.Commands.Move() }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.
|
||||
transaction(time = redemptionTime) {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
output { aliceGetsBack.CASH `owned by` ALICE }
|
||||
output { (someProfits - aliceGetsBack).CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
if (!destroyPaperAtRedemption)
|
||||
output { "paper".output }
|
||||
|
||||
arg(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
arg(ALICE) { CommercialPaper.Commands.Redeem() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun cashOutputsToWallet(vararg states: Cash.State): Pair<LedgerTransaction, List<StateAndRef<Cash.State>>> {
|
||||
val ltx = LedgerTransaction(emptyList(), listOf(*states), emptyList(), TEST_TX_TIME, SecureHash.randomSHA256())
|
||||
return Pair(ltx, states.mapIndexed { index, state -> StateAndRef(state, ContractStateRef(ltx.hash, index)) })
|
||||
@ -196,4 +151,53 @@ class CommercialPaperTests {
|
||||
|
||||
TransactionGroup(setOf(issueTX, moveTX, validRedemption), setOf(corpWalletTX, alicesWalletTX)).verify(TEST_PROGRAM_MAP)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a trade lifecycle with various parameters.
|
||||
fun trade(redemptionTime: Instant = TEST_TX_TIME + 8.days,
|
||||
aliceGetsBack: Amount = 1000.DOLLARS,
|
||||
destroyPaperAtRedemption: Boolean = true): TransactionGroupDSL<CommercialPaper.State> {
|
||||
val someProfits = 1200.DOLLARS
|
||||
return transactionGroupFor() {
|
||||
roots {
|
||||
transaction(900.DOLLARS.CASH `owned by` ALICE label "alice's $900")
|
||||
transaction(someProfits.CASH `owned by` MEGA_CORP_PUBKEY label "some profits")
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
transaction("Issuance") {
|
||||
output("paper") { PAPER_1 }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction("Trade") {
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output("borrowed $900") { 900.DOLLARS.CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
output("alice's paper") { "paper".output `owned by` ALICE }
|
||||
arg(ALICE) { Cash.Commands.Move() }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.
|
||||
transaction("Redemption", redemptionTime) {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
output("Alice's profit") { aliceGetsBack.CASH `owned by` ALICE }
|
||||
output("Change") { (someProfits - aliceGetsBack).CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
if (!destroyPaperAtRedemption)
|
||||
output { "paper".output }
|
||||
|
||||
arg(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
arg(ALICE) { CommercialPaper.Commands.Redeem() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
CommercialPaperTests().trade().visualise()
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ package core.testutils
|
||||
import com.google.common.io.BaseEncoding
|
||||
import contracts.*
|
||||
import core.*
|
||||
import core.visualiser.GraphVisualiser
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.DataInputStream
|
||||
@ -320,7 +321,12 @@ class TransactionGroupDSL<T : ContractState>(private val stateType: Class<T>) {
|
||||
throw AssertionError("Exception should have said '$message' but was actually: ${e.cause.message}", e.cause)
|
||||
return e
|
||||
}
|
||||
|
||||
fun visualise() {
|
||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||
GraphVisualiser(this as TransactionGroupDSL<ContractState>).display()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : ContractState> transactionGroupFor(body: TransactionGroupDSL<T>.() -> Unit) = TransactionGroupDSL<T>(T::class.java).apply { this.body() }
|
||||
fun transactionGroup(body: TransactionGroupDSL<ContractState>.() -> Unit) = TransactionGroupDSL(ContractState::class.java).apply { this.body() }
|
||||
fun transactionGroup(body: TransactionGroupDSL<ContractState>.() -> Unit) = TransactionGroupDSL(ContractState::class.java).apply { this.body() }
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
|
||||
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
|
||||
* set forth therein.
|
||||
*
|
||||
* All other rights reserved.
|
||||
*/
|
||||
@file:Suppress("CAST_NEVER_SUCCEEDS")
|
||||
|
||||
package core.visualiser
|
||||
|
||||
import contracts.Cash
|
||||
import contracts.CommercialPaper
|
||||
import core.Amount
|
||||
import core.ContractState
|
||||
import core.DOLLARS
|
||||
import core.days
|
||||
import core.testutils.*
|
||||
import java.time.Instant
|
||||
import kotlin.reflect.memberProperties
|
||||
|
||||
|
||||
val PAPER_1 = CommercialPaper.State(
|
||||
issuance = MEGA_CORP.ref(123),
|
||||
owner = MEGA_CORP_PUBKEY,
|
||||
faceValue = 1000.DOLLARS,
|
||||
maturityDate = TEST_TX_TIME + 7.days
|
||||
)
|
||||
|
||||
private fun trade(redemptionTime: Instant = TEST_TX_TIME + 8.days,
|
||||
aliceGetsBack: Amount = 1000.DOLLARS,
|
||||
destroyPaperAtRedemption: Boolean = true): TransactionGroupDSL<ContractState> {
|
||||
val someProfits = 1200.DOLLARS
|
||||
return transactionGroupFor<CommercialPaper.State>() {
|
||||
roots {
|
||||
transaction(900.DOLLARS.CASH `owned by` ALICE label "alice's $900")
|
||||
transaction(someProfits.CASH `owned by` MEGA_CORP_PUBKEY label "some profits")
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
transaction("Issuance") {
|
||||
output("paper") { PAPER_1 }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction("Trade") {
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output("borrowed $900") { 900.DOLLARS.CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
output("alice's paper") { "paper".output `owned by` ALICE }
|
||||
arg(ALICE) { Cash.Commands.Move() }
|
||||
arg(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.
|
||||
transaction("Redemption", redemptionTime) {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
output("Alice's profit") { aliceGetsBack.CASH `owned by` ALICE }
|
||||
output("Change") { (someProfits - aliceGetsBack).CASH `owned by` MEGA_CORP_PUBKEY }
|
||||
if (!destroyPaperAtRedemption)
|
||||
output { "paper".output }
|
||||
|
||||
arg(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
arg(ALICE) { CommercialPaper.Commands.Redeem() }
|
||||
}
|
||||
} as TransactionGroupDSL<ContractState>
|
||||
}
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val tg = trade()
|
||||
val graph = GraphConverter(tg).convert()
|
||||
runGraph(graph, nodeOnClick = { node ->
|
||||
val state: ContractState? = node.getAttribute("state")
|
||||
if (state != null) {
|
||||
val props: List<Pair<String, Any?>> = state.javaClass.kotlin.memberProperties.map { it.name to it.getter.call(state) }
|
||||
StateViewer.show(props)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -15,10 +15,11 @@ import core.testutils.TransactionGroupDSL
|
||||
import org.graphstream.graph.Edge
|
||||
import org.graphstream.graph.Node
|
||||
import org.graphstream.graph.implementations.SingleGraph
|
||||
import kotlin.reflect.memberProperties
|
||||
|
||||
class GraphConverter(val dsl: TransactionGroupDSL<in ContractState>) {
|
||||
class GraphVisualiser(val dsl: TransactionGroupDSL<in ContractState>) {
|
||||
companion object {
|
||||
val css = GraphConverter::class.java.getResourceAsStream("graph.css").bufferedReader().readText()
|
||||
val css = GraphVisualiser::class.java.getResourceAsStream("graph.css").bufferedReader().readText()
|
||||
}
|
||||
|
||||
fun convert(): SingleGraph {
|
||||
@ -69,4 +70,14 @@ class GraphConverter(val dsl: TransactionGroupDSL<in ContractState>) {
|
||||
private fun commandToTypeName(state: Command) = state.javaClass.canonicalName.removePrefix("contracts.").replace('$', '.')
|
||||
private fun stateToTypeName(state: ContractState) = state.javaClass.canonicalName.removePrefix("contracts.").removeSuffix(".State")
|
||||
private fun stateToCSSClass(state: ContractState) = stateToTypeName(state).replace('.', '_').toLowerCase()
|
||||
|
||||
fun display() {
|
||||
runGraph(convert(), nodeOnClick = { node ->
|
||||
val state: ContractState? = node.getAttribute("state")
|
||||
if (state != null) {
|
||||
val props: List<Pair<String, Any?>> = state.javaClass.kotlin.memberProperties.map { it.name to it.getter.call(state) }
|
||||
StateViewer.show(props)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,11 +1,3 @@
|
||||
/*
|
||||
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
|
||||
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
|
||||
* set forth therein.
|
||||
*
|
||||
* All other rights reserved.
|
||||
*/
|
||||
|
||||
node.tx {
|
||||
size: 10px;
|
||||
fill-color: blue;
|
||||
|
Loading…
Reference in New Issue
Block a user