Skip to content

Commit da623ea

Browse files
Merge pull request #2 from onix-labs/1.1.0
1.1.0
2 parents 1d8e293 + b7597e6 commit da623ea

File tree

11 files changed

+512
-125
lines changed

11 files changed

+512
-125
lines changed

CHANGELOG.md

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
![ONIX Labs](https://raw.githubusercontent.com/onix-labs/onix-labs.github.io/master/content/logo/master_full_md.png)
2+
3+
# Change Log
4+
5+
This document serves as the change log for the ONIXLabs Corda Core API.
6+
7+
## Version 1.1.0
8+
9+
### Contract
10+
11+
#### Extensions
12+
13+
- Moved to new extension file naming convention for maintainability.
14+
- Added extensions to obtain single inputs, reference inputs and outputs from a `LedgerTransaction`.
15+
- Added extension to cast `Iterable<StateAndRef<*>>` to `List<StateAndRef<T>>`.
16+
17+
### Workflow
18+
19+
#### Extensions
20+
21+
- Moved to new extension naming convention for maintainability.
22+
- Added extensions to filter a set of sessions to include or exclude certain counter-parties, or state participants.
23+
24+
## Version 1.0.0
25+
26+
### Contract
27+
28+
#### ChainState (interface)
29+
30+
Defines a Corda chain state.
31+
32+
> A chain state is similar to a `LinearState`, in that it represents a set of state transitions. Chain states adopt a concept similar to blockchain, where each new state transition references the previous one by it's `StateRef`, or null if it's the first state in the chain.
33+
34+
#### Hashable (interface)
35+
36+
Defines an object that can produce a unique hash.
37+
38+
> This is useful if you require some level of state uniqueness.
39+
40+
#### Resolvable (interface)
41+
42+
Defines an object which resolves a `ContractState`.
43+
44+
> This is the fundamental principle on which state pointers are implemented in Corda; their ability to maintain and resolve a reference back to another known state in the vault. The implementation here is flexible and open, allowing developers to model resolvable as a design pattern, rather than as a strict implementation detail.
45+
46+
#### TransactionResolution (enum)
47+
48+
Defines how to resolve states from a transaction, and is used by the `Resolvable` interface.
49+
50+
#### Extensions
51+
52+
- Added extension to obtain a set of owning keys from a collection of `AbstractParty`.
53+
- Added extension to obtain a participant hash to determine state uniqueness by participation.
54+
- Added extensions to determine whether a chain state instance is pointing to a specified `StateRef`.
55+
- Added extension to cast an unknown `StateAndRef<*>` to a typed `StateAndRef<T>`.
56+
57+
### Workflow
58+
59+
#### FindStateFlow (abstract class)
60+
61+
Represents the base class for implementing a query that finds a single state.
62+
63+
#### FindStatesFlow (abstract class)
64+
65+
Represents the base class for implementing a query that finds multiple states.
66+
67+
> This design pattern enables developers to be more consistent in their approach to performing vault queries, regardless of whether they're being performed from within the node (using `ServiceHub`) or from an RPC client (using `CordaRPCOps`).
68+
69+
#### Message (open class)
70+
71+
Represents an open, transient message.
72+
73+
#### MessageAcknowledgement (open class)
74+
75+
Represents an open acknowledgement to a message.
76+
77+
#### SendMessageFlow (class)
78+
79+
Sends a message to other nodes on the Corda network.
80+
81+
#### ReceiveMessageFlow (class)
82+
83+
Receives a message from another node on the Corda network.
84+
85+
#### SendMessageAcknowledgementFlow (class)
86+
87+
Sends a message acknowledgement to other nodes on the Corda network.
88+
89+
#### ReceiveMessageAcknowledgementFlow (class)
90+
91+
Receives a message acknowledgement from another node on the Corda network.
92+
93+
#### TransactionNote (class)
94+
95+
Represents a wrapper around a transaction note and the transaction that the note belongs to.
96+
97+
#### SendTransactionNoteFlow (class)
98+
99+
Sends a transaction note to other nodes on the Corda network for persistence.
100+
101+
#### ReceiveTransactionNoteFlow (class)
102+
103+
Receives a transaction note from another node on the Corda network, and optionally persists it.
104+
105+
> All messaging APIs are part of the ONIXLabs Corda Code messaging protocol, which allows Corda nodes to send and receive transient messages and messages acknowledgements, which are not bound to the ledger.
106+
107+
#### Extensions
108+
109+
- Added extensions to obtain the first notary from the network map cache.
110+
- Added extensions to obtain a random notary from the network map cache.
111+
- Added extensions to obtain the preferred notary from the CorDapp config file.
112+
- Added extensions to set, and optionally log progress tracker steps.
113+
- Added extensions to initiate flow sessions for a collection of parties and/or state participants.
114+
- Added extensions to check that sufficient flow sessions have been passed for the specified states.
115+
- Added extensions to find transactions by transaction ID or `StateRef`.
116+
- Added constants for default sorting and default, or maximum size page specification.
117+
- Added extensions to build complex query expressions.
118+
119+
### Integration
120+
121+
#### RPCService (abstract class)
122+
123+
Represents the base class for implementing services that utilize `CordaRPCOps`.
124+
125+
#### MessageService (class)
126+
127+
Represents an RPC service for sending and subscribing to transient messages.
128+
129+
#### MessageAcknowledgementService (class)
130+
131+
Represents an RPC service for sending and subscribing to transience message acknowledgements.
132+
133+
#### TransactionNoteService (class)
134+
135+
Represents an RPC service for adding, sending and persisting transaction notes.
136+
137+
138+

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ buildscript {
4242
}
4343

4444
group 'io.onixlabs'
45-
version '1.0.0'
45+
version '1.1.0'
4646

4747
subprojects {
4848
repositories {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package io.onixlabs.corda.core.contract
2+
3+
import net.corda.core.contracts.Command
4+
import net.corda.core.contracts.CommandData
5+
import net.corda.core.contracts.ContractState
6+
import net.corda.core.contracts.StateAndRef
7+
import net.corda.core.transactions.LedgerTransaction
8+
9+
/**
10+
* Obtains a single input ref from a ledger transaction.
11+
*
12+
* @param T The underlying contract state type to obtain.
13+
* @param contractStateClass The class of the contract state type to obtain.
14+
* @return Returns a single input ref from a ledger transaction of the specified type.
15+
*/
16+
fun <T : ContractState> LedgerTransaction.singleInputRefOfType(contractStateClass: Class<T>): StateAndRef<T> {
17+
return inRefsOfType(contractStateClass).single()
18+
}
19+
20+
/**
21+
* Obtains a single input ref from a ledger transaction.
22+
*
23+
* @param T The underlying contract state type to obtain.
24+
* @return Returns a single input ref from a ledger transaction of the specified type.
25+
*/
26+
inline fun <reified T : ContractState> LedgerTransaction.singleInputRefOfType(): StateAndRef<T> {
27+
return singleInputRefOfType(T::class.java)
28+
}
29+
30+
/**
31+
* Obtains a single input from a ledger transaction.
32+
*
33+
* @param T The underlying contract state type to obtain.
34+
* @param contractStateClass The class of the contract state type to obtain.
35+
* @return Returns a single input from a ledger transaction of the specified type.
36+
*/
37+
fun <T : ContractState> LedgerTransaction.singleInputOfType(contractStateClass: Class<T>): T {
38+
return inputsOfType(contractStateClass).single()
39+
}
40+
41+
/**
42+
* Obtains a single input from a ledger transaction.
43+
*
44+
* @param T The underlying contract state type to obtain.
45+
* @return Returns a single input from a ledger transaction of the specified type.
46+
*/
47+
inline fun <reified T : ContractState> LedgerTransaction.singleInputOfType(): T {
48+
return singleInputOfType(T::class.java)
49+
}
50+
51+
/**
52+
* Obtains a single reference input ref from a ledger transaction.
53+
*
54+
* @param T The underlying contract state type to obtain.
55+
* @param contractStateClass The class of the contract state type to obtain.
56+
* @return Returns a single reference input ref from a ledger transaction of the specified type.
57+
*/
58+
fun <T : ContractState> LedgerTransaction.singleReferenceInputRefOfType(contractStateClass: Class<T>): StateAndRef<T> {
59+
return referenceInputRefsOfType(contractStateClass).single()
60+
}
61+
62+
/**
63+
* Obtains a single reference input ref from a ledger transaction.
64+
*
65+
* @param T The underlying contract state type to obtain.
66+
* @return Returns a single reference input ref from a ledger transaction of the specified type.
67+
*/
68+
inline fun <reified T : ContractState> LedgerTransaction.singleReferenceInputRefOfType(): StateAndRef<T> {
69+
return singleReferenceInputRefOfType(T::class.java)
70+
}
71+
72+
/**
73+
* Obtains a single reference input from a ledger transaction.
74+
*
75+
* @param T The underlying contract state type to obtain.
76+
* @param contractStateClass The class of the contract state type to obtain.
77+
* @return Returns a single reference input from a ledger transaction of the specified type.
78+
*/
79+
fun <T : ContractState> LedgerTransaction.singleReferenceInputOfType(contractStateClass: Class<T>): T {
80+
return referenceInputsOfType(contractStateClass).single()
81+
}
82+
83+
/**
84+
* Obtains a single reference input from a ledger transaction.
85+
*
86+
* @param T The underlying contract state type to obtain.
87+
* @return Returns a single reference input from a ledger transaction of the specified type.
88+
*/
89+
inline fun <reified T : ContractState> LedgerTransaction.singleReferenceInputOfType(): T {
90+
return singleReferenceInputOfType(T::class.java)
91+
}
92+
93+
/**
94+
* Obtains a single output ref from a ledger transaction.
95+
*
96+
* @param T The underlying contract state type to obtain.
97+
* @param contractStateClass The class of the contract state type to obtain.
98+
* @return Returns a single output ref from a ledger transaction of the specified type.
99+
*/
100+
fun <T : ContractState> LedgerTransaction.singleOutputRefOfType(contractStateClass: Class<T>): StateAndRef<T> {
101+
return outRefsOfType(contractStateClass).single()
102+
}
103+
104+
/**
105+
* Obtains a single output ref from a ledger transaction.
106+
*
107+
* @param T The underlying contract state type to obtain.
108+
* @return Returns a single output ref from a ledger transaction of the specified type.
109+
*/
110+
inline fun <reified T : ContractState> LedgerTransaction.singleOutputRefOfType(): StateAndRef<T> {
111+
return singleOutputRefOfType(T::class.java)
112+
}
113+
114+
/**
115+
* Obtains a single output from a ledger transaction.
116+
*
117+
* @param T The underlying contract state type to obtain.
118+
* @param contractStateClass The class of the contract state type to obtain.
119+
* @return Returns a single output from a ledger transaction of the specified type.
120+
*/
121+
fun <T : ContractState> LedgerTransaction.singleOutputOfType(contractStateClass: Class<T>): T {
122+
return outputsOfType(contractStateClass).single()
123+
}
124+
125+
/**
126+
* Obtains a single output from a ledger transaction.
127+
*
128+
* @param T The underlying contract state type to obtain.
129+
* @return Returns a single output from a ledger transaction of the specified type.
130+
*/
131+
inline fun <reified T : ContractState> LedgerTransaction.singleOutputOfType(): T {
132+
return singleOutputOfType(T::class.java)
133+
}
134+
135+
/**
136+
* Obtains a single command from a ledger transaction.
137+
*
138+
* @param T The underlying contract state type to obtain.
139+
* @param commandClass The class of the command type to obtain.
140+
* @return Returns a single command from a ledger transaction of the specified type.
141+
*/
142+
fun <T : CommandData> LedgerTransaction.singleCommandOfType(commandClass: Class<T>): Command<T> {
143+
return commandsOfType(commandClass).single()
144+
}
145+
146+
/**
147+
* Obtains a single command from a ledger transaction.
148+
*
149+
* @param T The underlying contract state type to obtain.
150+
* @return Returns a single command from a ledger transaction of the specified type.
151+
*/
152+
inline fun <reified T : CommandData> LedgerTransaction.singleCommandOfType(): Command<T> {
153+
return singleCommandOfType(T::class.java)
154+
}
+11
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,14 @@ import net.corda.core.contracts.TransactionState
3030
inline fun <reified T> StateAndRef<*>.cast(): StateAndRef<T> where T : ContractState = with(state) {
3131
StateAndRef(TransactionState(T::class.java.cast(data), contract, notary, encumbrance, constraint), ref)
3232
}
33+
34+
/**
35+
* Casts an iterable of [StateAndRef] of an unknown [ContractState] to a list of [StateAndRef] of type [T].
36+
*
37+
* @param T The underlying [ContractState] type to cast to.
38+
* @return Returns a list of [StateAndRef] of type [T].
39+
* @throws ClassCastException if the unknown [ContractState] type cannot be cast to [T].
40+
*/
41+
inline fun <reified T> Iterable<StateAndRef<*>>.cast(): List<StateAndRef<T>> where T : ContractState {
42+
return map { it.cast<T>() }
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.onixlabs.corda.core.workflow
2+
3+
import co.paralleluniverse.fibers.Suspendable
4+
import net.corda.core.cordapp.CordappContext
5+
import net.corda.core.flows.FlowLogic
6+
import net.corda.core.identity.CordaX500Name
7+
import net.corda.core.identity.Party
8+
import net.corda.core.internal.randomOrNull
9+
import net.corda.core.node.ServiceHub
10+
11+
/**
12+
* Gets the first available notary.
13+
*/
14+
val FlowLogic<*>.firstNotary: Party
15+
get() = serviceHub.networkMapCache.notaryIdentities.firstOrNull()
16+
?: throw NoSuchElementException("No available notaries.")
17+
18+
/**
19+
* Gets a randomly available notary.
20+
*/
21+
val FlowLogic<*>.randomNotary: Party
22+
get() = serviceHub.networkMapCache.notaryIdentities.randomOrNull()
23+
?: throw NoSuchElementException("No available notaries.")
24+
25+
/**
26+
* Gets the preferred notary from the CorDapp config, or alternatively a default notary in the event that
27+
* a preferred notary has not been specified in the CorDapp config.
28+
*
29+
* @param serviceHub The service hub which will be used to obtain a notary from the config file.
30+
* @param defaultSelector The selector function to obtain a notary if none have been specified in the CorDapp config.
31+
* @return Returns the preferred or default notary.
32+
* @throws IllegalArgumentException If the preferred notary cannot be found in the network map cache.
33+
*/
34+
@Suspendable
35+
fun FlowLogic<*>.getPreferredNotary(
36+
serviceHub: ServiceHub = this.serviceHub,
37+
defaultSelector: (ServiceHub) -> Party = { firstNotary }
38+
): Party {
39+
val cordappContext: CordappContext = serviceHub.getAppContext()
40+
logger.info("Using the specified cordapp for notary selection: ${cordappContext.cordapp.name}")
41+
return if (serviceHub.getAppContext().config.exists("notary")) {
42+
val name = CordaX500Name.parse(serviceHub.getAppContext().config.getString("notary"))
43+
serviceHub.networkMapCache.getNotary(name) ?: throw IllegalArgumentException(
44+
"Notary with the specified name cannot be found in the network map cache: $name."
45+
)
46+
} else defaultSelector(serviceHub)
47+
}

0 commit comments

Comments
 (0)