mirror of
https://github.com/corda/corda.git
synced 2025-01-22 04:18:31 +00:00
Add Party type parameter to IRS state
Makes IRS states generic so that the can store anonmyous or full parties depending on use-case (ledger vs UI).
This commit is contained in:
parent
ad71a48505
commit
81b0393766
@ -61,7 +61,7 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
val vaultUpdates = proxy.vaultAndUpdates().second
|
||||
|
||||
val fixingDates = vaultUpdates.map { update ->
|
||||
val irsStates = update.produced.map { it.state.data }.filterIsInstance<InterestRateSwap.State>()
|
||||
val irsStates = update.produced.map { it.state.data }.filterIsInstance<InterestRateSwap.State<*>>()
|
||||
irsStates.mapNotNull { it.calculation.nextFixingDate() }.max()
|
||||
}.cache().toBlocking()
|
||||
|
||||
@ -76,8 +76,6 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
private fun runTrade(nodeAddr: HostAndPort, fixedRatePayer: Party, floatingRatePayer: Party) {
|
||||
val fileContents = IOUtils.toString(Thread.currentThread().contextClassLoader.getResourceAsStream("example-irs-trade.json"))
|
||||
val tradeFile = fileContents.replace("tradeXXX", "trade1")
|
||||
.replace("fixedRatePayerKey", fixedRatePayer.owningKey.toBase58String())
|
||||
.replace("floatingRatePayerKey", floatingRatePayer.owningKey.toBase58String())
|
||||
val url = URL("http://$nodeAddr/api/irs/deals")
|
||||
assert(postJson(url, tradeFile))
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.corda.irs.api
|
||||
|
||||
import net.corda.core.contracts.filterStatesOfType
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
@ -42,18 +44,18 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) {
|
||||
|
||||
private val logger = loggerFor<InterestRateSwapAPI>()
|
||||
|
||||
private fun generateDealLink(deal: InterestRateSwap.State) = "/api/irs/deals/" + deal.common.tradeID
|
||||
private fun generateDealLink(deal: InterestRateSwap.State<*>) = "/api/irs/deals/" + deal.common.tradeID
|
||||
|
||||
private fun getDealByRef(ref: String): InterestRateSwap.State? {
|
||||
val states = rpc.vaultAndUpdates().first.filterStatesOfType<InterestRateSwap.State>().filter { it.state.data.ref == ref }
|
||||
private fun getDealByRef(ref: String): InterestRateSwap.State<*>? {
|
||||
val states = rpc.vaultAndUpdates().first.filterStatesOfType<InterestRateSwap.State<*>>().filter { it.state.data.ref == ref }
|
||||
return if (states.isEmpty()) null else {
|
||||
val deals = states.map { it.state.data }
|
||||
return if (deals.isEmpty()) null else deals[0]
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllDeals(): Array<InterestRateSwap.State> {
|
||||
val states = rpc.vaultAndUpdates().first.filterStatesOfType<InterestRateSwap.State>()
|
||||
private fun getAllDeals(): Array<InterestRateSwap.State<*>> {
|
||||
val states = rpc.vaultAndUpdates().first.filterStatesOfType<InterestRateSwap.State<*>>()
|
||||
val swaps = states.map { it.state.data }.toTypedArray()
|
||||
return swaps
|
||||
}
|
||||
@ -61,24 +63,14 @@ class InterestRateSwapAPI(val rpc: CordaRPCOps) {
|
||||
@GET
|
||||
@Path("deals")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun fetchDeals(): Array<InterestRateSwap.State> = getAllDeals()
|
||||
|
||||
// Function needed to substitute party keys in JSON file example-irs-trade.json
|
||||
@GET
|
||||
@Path("partykeys")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun partyFromName(): Response {
|
||||
val keyA = rpc.partyFromName("Bank A")?.owningKey
|
||||
val keyB = rpc.partyFromName("Bank B")?.owningKey
|
||||
return Response.ok().entity(Pair(keyA, keyB)).build()
|
||||
}
|
||||
fun fetchDeals(): Array<InterestRateSwap.State<*>> = getAllDeals()
|
||||
|
||||
@POST
|
||||
@Path("deals")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
fun storeDeal(newDeal: InterestRateSwap.State): Response {
|
||||
fun storeDeal(newDeal: InterestRateSwap.State<Party>): Response {
|
||||
return try {
|
||||
rpc.startFlow(AutoOfferFlow::Requester, newDeal).returnValue.getOrThrow()
|
||||
rpc.startFlow(AutoOfferFlow::Requester, newDeal.toAnonymous()).returnValue.getOrThrow()
|
||||
Response.created(URI.create(generateDealLink(newDeal))).build()
|
||||
} catch (ex: Throwable) {
|
||||
logger.info("Exception when creating deal: $ex")
|
||||
|
@ -14,8 +14,7 @@ class IRSDemoClientApi(private val hostAndPort: HostAndPort) {
|
||||
|
||||
fun runTrade(tradeId: String): Boolean {
|
||||
val fileContents = IOUtils.toString(javaClass.classLoader.getResourceAsStream("example-irs-trade.json"))
|
||||
val (keyA, keyB) = api.getJson<Pair<String, String>>("partykeys")
|
||||
val tradeFile = fileContents.replace("tradeXXX", tradeId).replace("fixedRatePayerKey", keyA).replace("floatingRatePayerKey", keyB)
|
||||
val tradeFile = fileContents.replace("tradeXXX", tradeId)
|
||||
return api.postJson("deals", tradeFile)
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,8 @@ object NodeInterestRates {
|
||||
override val dataTypePrefix = "interest-rates"
|
||||
override val acceptableFileExtensions = listOf(".rates", ".txt")
|
||||
|
||||
override fun upload(data: InputStream): String {
|
||||
val fixes = parseFile(data.bufferedReader().readText())
|
||||
override fun upload(file: InputStream): String {
|
||||
val fixes = parseFile(file.bufferedReader().readText())
|
||||
oracle.knownFixes = fixes
|
||||
val msg = "Interest rates oracle accepted ${fixes.size} new interest rate fixes"
|
||||
println(msg)
|
||||
|
@ -2,10 +2,7 @@ package net.corda.irs.contract
|
||||
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.clauses.*
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.flows.FlowLogicRefFactory
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -311,8 +308,8 @@ class InterestRateSwap() : Contract {
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
open class FixedLeg(
|
||||
var fixedRatePayer: AnonymousParty,
|
||||
open class FixedLeg<P: AbstractParty>(
|
||||
var fixedRatePayer: P,
|
||||
notional: Amount<Currency>,
|
||||
paymentFrequency: Frequency,
|
||||
effectiveDate: LocalDate,
|
||||
@ -339,7 +336,7 @@ class InterestRateSwap() : Contract {
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as FixedLeg
|
||||
other as FixedLeg<*>
|
||||
|
||||
if (fixedRatePayer != other.fixedRatePayer) return false
|
||||
if (fixedRate != other.fixedRate) return false
|
||||
@ -351,7 +348,7 @@ class InterestRateSwap() : Contract {
|
||||
override fun hashCode() = super.hashCode() + 31 * Objects.hash(fixedRatePayer, fixedRate, rollConvention)
|
||||
|
||||
// Can't autogenerate as not a data class :-(
|
||||
fun copy(fixedRatePayer: AnonymousParty = this.fixedRatePayer,
|
||||
fun copy(fixedRatePayer: P = this.fixedRatePayer,
|
||||
notional: Amount<Currency> = this.notional,
|
||||
paymentFrequency: Frequency = this.paymentFrequency,
|
||||
effectiveDate: LocalDate = this.effectiveDate,
|
||||
@ -369,12 +366,16 @@ class InterestRateSwap() : Contract {
|
||||
fixedRatePayer, notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate,
|
||||
terminationDateAdjustment, dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay,
|
||||
paymentCalendar, interestPeriodAdjustment, fixedRate, rollConvention)
|
||||
|
||||
fun toAnonymous(): FixedLeg<AnonymousParty> {
|
||||
return FixedLeg(fixedRatePayer.toAnonymous(), notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment,
|
||||
dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment,
|
||||
fixedRate, rollConvention)
|
||||
}
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
open class FloatingLeg(
|
||||
var floatingRatePayer: AnonymousParty,
|
||||
open class FloatingLeg<P: AbstractParty>(
|
||||
var floatingRatePayer: P,
|
||||
notional: Amount<Currency>,
|
||||
paymentFrequency: Frequency,
|
||||
effectiveDate: LocalDate,
|
||||
@ -410,7 +411,7 @@ class InterestRateSwap() : Contract {
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as FloatingLeg
|
||||
other as FloatingLeg<*>
|
||||
|
||||
if (floatingRatePayer != other.floatingRatePayer) return false
|
||||
if (rollConvention != other.rollConvention) return false
|
||||
@ -432,7 +433,7 @@ class InterestRateSwap() : Contract {
|
||||
index, indexSource, indexTenor)
|
||||
|
||||
|
||||
fun copy(floatingRatePayer: AnonymousParty = this.floatingRatePayer,
|
||||
fun copy(floatingRatePayer: P = this.floatingRatePayer,
|
||||
notional: Amount<Currency> = this.notional,
|
||||
paymentFrequency: Frequency = this.paymentFrequency,
|
||||
effectiveDate: LocalDate = this.effectiveDate,
|
||||
@ -461,6 +462,12 @@ class InterestRateSwap() : Contract {
|
||||
paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, rollConvention,
|
||||
fixingRollConvention, resetDayInMonth, fixingPeriod, resetRule, fixingsPerPayment,
|
||||
fixingCalendar, index, indexSource, indexTenor)
|
||||
fun toAnonymous(): FloatingLeg<AnonymousParty> {
|
||||
return FloatingLeg(floatingRatePayer.toAnonymous(), notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment,
|
||||
dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment,
|
||||
rollConvention, fixingRollConvention, resetDayInMonth, fixingPeriodOffset, resetRule, fixingsPerPayment,
|
||||
fixingCalendar, index, indexSource, indexTenor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract) = verifyClause(tx, AllComposition(Clauses.Timestamped(), Clauses.Group()), tx.commands.select<Commands>())
|
||||
@ -470,7 +477,7 @@ class InterestRateSwap() : Contract {
|
||||
* Common superclass for IRS contract clauses, which defines behaviour on match/no-match, and provides
|
||||
* helper functions for the clauses.
|
||||
*/
|
||||
abstract class AbstractIRSClause : Clause<State, Commands, UniqueIdentifier>() {
|
||||
abstract class AbstractIRSClause : Clause<State<*>, Commands, UniqueIdentifier>() {
|
||||
// These functions may make more sense to use for basket types, but for now let's leave them here
|
||||
fun checkLegDates(legs: List<CommonLeg>) {
|
||||
requireThat {
|
||||
@ -486,7 +493,7 @@ class InterestRateSwap() : Contract {
|
||||
"The notional for all legs must be the same" by legs.all { it.notional == legs[0].notional }
|
||||
}
|
||||
for (leg: CommonLeg in legs) {
|
||||
if (leg is FixedLeg) {
|
||||
if (leg is FixedLeg<*>) {
|
||||
requireThat {
|
||||
// TODO: Confirm: would someone really enter a swap with a negative fixed rate?
|
||||
"Fixed leg rate must be positive" by leg.fixedRate.isPositive()
|
||||
@ -512,9 +519,9 @@ class InterestRateSwap() : Contract {
|
||||
}
|
||||
}
|
||||
|
||||
class Group : GroupClauseVerifier<State, Commands, UniqueIdentifier>(AnyComposition(Agree(), Fix(), Pay(), Mature())) {
|
||||
class Group : GroupClauseVerifier<State<*>, Commands, UniqueIdentifier>(AnyComposition(Agree(), Fix(), Pay(), Mature())) {
|
||||
// Group by Trade ID for in / out states
|
||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<State, UniqueIdentifier>> {
|
||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<State<*>, UniqueIdentifier>> {
|
||||
return tx.groupStates() { state -> state.linearId }
|
||||
}
|
||||
}
|
||||
@ -535,12 +542,12 @@ class InterestRateSwap() : Contract {
|
||||
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Agree::class.java)
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<State>,
|
||||
outputs: List<State>,
|
||||
inputs: List<State<*>>,
|
||||
outputs: List<State<*>>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: UniqueIdentifier?): Set<Commands> {
|
||||
val command = tx.commands.requireSingleCommand<Commands.Agree>()
|
||||
val irs = outputs.filterIsInstance<State>().single()
|
||||
val irs = outputs.filterIsInstance<State<*>>().single()
|
||||
requireThat {
|
||||
"There are no in states for an agreement" by inputs.isEmpty()
|
||||
"There are events in the fix schedule" by (irs.calculation.fixedLegPaymentSchedule.size > 0)
|
||||
@ -571,13 +578,13 @@ class InterestRateSwap() : Contract {
|
||||
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Refix::class.java)
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<State>,
|
||||
outputs: List<State>,
|
||||
inputs: List<State<*>>,
|
||||
outputs: List<State<*>>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: UniqueIdentifier?): Set<Commands> {
|
||||
val command = tx.commands.requireSingleCommand<Commands.Refix>()
|
||||
val irs = outputs.filterIsInstance<State>().single()
|
||||
val prevIrs = inputs.filterIsInstance<State>().single()
|
||||
val irs = outputs.filterIsInstance<State<*>>().single()
|
||||
val prevIrs = inputs.filterIsInstance<State<*>>().single()
|
||||
val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule)
|
||||
|
||||
// Having both of these tests are "redundant" as far as verify() goes, however, by performing both
|
||||
@ -616,8 +623,8 @@ class InterestRateSwap() : Contract {
|
||||
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Pay::class.java)
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<State>,
|
||||
outputs: List<State>,
|
||||
inputs: List<State<*>>,
|
||||
outputs: List<State<*>>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: UniqueIdentifier?): Set<Commands> {
|
||||
val command = tx.commands.requireSingleCommand<Commands.Pay>()
|
||||
@ -632,12 +639,12 @@ class InterestRateSwap() : Contract {
|
||||
override val requiredCommands: Set<Class<out CommandData>> = setOf(Commands.Mature::class.java)
|
||||
|
||||
override fun verify(tx: TransactionForContract,
|
||||
inputs: List<State>,
|
||||
outputs: List<State>,
|
||||
inputs: List<State<*>>,
|
||||
outputs: List<State<*>>,
|
||||
commands: List<AuthenticatedObject<Commands>>,
|
||||
groupingKey: UniqueIdentifier?): Set<Commands> {
|
||||
val command = tx.commands.requireSingleCommand<Commands.Mature>()
|
||||
val irs = inputs.filterIsInstance<State>().single()
|
||||
val irs = inputs.filterIsInstance<State<*>>().single()
|
||||
requireThat {
|
||||
"No more fixings to be applied" by (irs.calculation.nextFixingDate() == null)
|
||||
"The irs is fully consumed and there is no id matched output state" by outputs.isEmpty()
|
||||
@ -659,9 +666,9 @@ class InterestRateSwap() : Contract {
|
||||
/**
|
||||
* The state class contains the 4 major data classes.
|
||||
*/
|
||||
data class State(
|
||||
val fixedLeg: FixedLeg,
|
||||
val floatingLeg: FloatingLeg,
|
||||
data class State<P: AbstractParty>(
|
||||
val fixedLeg: FixedLeg<P>,
|
||||
val floatingLeg: FloatingLeg<P>,
|
||||
val calculation: Calculation,
|
||||
val common: Common,
|
||||
override val linearId: UniqueIdentifier = UniqueIdentifier(common.tradeID)
|
||||
@ -682,7 +689,7 @@ class InterestRateSwap() : Contract {
|
||||
}
|
||||
|
||||
override val parties: List<AnonymousParty>
|
||||
get() = listOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer)
|
||||
get() = listOf(fixedLeg.fixedRatePayer.toAnonymous(), floatingLeg.floatingRatePayer.toAnonymous())
|
||||
|
||||
override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? {
|
||||
val nextFixingOf = nextFixingOf() ?: return null
|
||||
@ -692,10 +699,10 @@ class InterestRateSwap() : Contract {
|
||||
return ScheduledActivity(flowLogicRefFactory.create(FixingFlow.FixingRoleDecider::class.java, thisStateRef), instant)
|
||||
}
|
||||
|
||||
override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary)
|
||||
override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg.toAnonymous(), fixedLeg.toAnonymous(), calculation, common, notary)
|
||||
|
||||
override fun generateFix(ptx: TransactionBuilder, oldState: StateAndRef<*>, fix: Fix) {
|
||||
InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this, oldState.state.notary), oldState.ref), fix)
|
||||
InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this.toAnonymous(), oldState.state.notary), oldState.ref), fix)
|
||||
}
|
||||
|
||||
override fun nextFixingOf(): FixOf? {
|
||||
@ -730,13 +737,20 @@ class InterestRateSwap() : Contract {
|
||||
*/
|
||||
fun prettyPrint() = toString().replace(",", "\n")
|
||||
|
||||
fun toAnonymous(): State<AnonymousParty> {
|
||||
return if (this.fixedLeg.fixedRatePayer is AnonymousParty) {
|
||||
this as State<AnonymousParty>
|
||||
} else {
|
||||
State(fixedLeg.toAnonymous(), floatingLeg.toAnonymous(), calculation, common, linearId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This generates the agreement state and also the schedules from the initial data.
|
||||
* Note: The day count, interest rate calculation etc are not finished yet, but they are demonstrable.
|
||||
*/
|
||||
fun generateAgreement(floatingLeg: FloatingLeg, fixedLeg: FixedLeg, calculation: Calculation,
|
||||
fun generateAgreement(floatingLeg: FloatingLeg<AnonymousParty>, fixedLeg: FixedLeg<AnonymousParty>, calculation: Calculation,
|
||||
common: Common, notary: Party): TransactionBuilder {
|
||||
|
||||
val fixedLegPaymentSchedule = LinkedHashMap<LocalDate, FixedRatePaymentEvent>()
|
||||
@ -800,7 +814,7 @@ class InterestRateSwap() : Contract {
|
||||
}
|
||||
}
|
||||
|
||||
fun generateFix(tx: TransactionBuilder, irs: StateAndRef<State>, fixing: Fix) {
|
||||
fun generateFix(tx: TransactionBuilder, irs: StateAndRef<State<AnonymousParty>>, fixing: Fix) {
|
||||
tx.addInputState(irs)
|
||||
val fixedRate = FixedRate(RatioUnit(fixing.value))
|
||||
tx.addOutputState(
|
||||
|
@ -1,6 +1,6 @@
|
||||
package net.corda.irs.contract
|
||||
|
||||
fun InterestRateSwap.State.exportIRSToCSV(): String =
|
||||
fun InterestRateSwap.State<*>.exportIRSToCSV(): String =
|
||||
"Fixed Leg\n" + FixedRatePaymentEvent.CSVHeader + "\n" +
|
||||
this.calculation.fixedLegPaymentSchedule.toSortedMap().values.map { it.asCSV() }.joinToString("\n") + "\n" +
|
||||
"Floating Leg\n" + FloatingRatePaymentEvent.CSVHeader + "\n" +
|
||||
|
@ -8,6 +8,7 @@ import com.google.common.util.concurrent.SettableFuture
|
||||
import net.corda.core.RunOnCallerThread
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.flatMap
|
||||
import net.corda.core.flows.FlowStateMachine
|
||||
import net.corda.core.map
|
||||
@ -73,9 +74,9 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
return future
|
||||
}
|
||||
|
||||
private fun loadLinearHeads(node: SimulatedNode): Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> {
|
||||
private fun loadLinearHeads(node: SimulatedNode): Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State<AnonymousParty>>> {
|
||||
return databaseTransaction(node.database) {
|
||||
node.services.vaultService.linearHeadsOfType<InterestRateSwap.State>()
|
||||
node.services.vaultService.linearHeadsOfType<InterestRateSwap.State<AnonymousParty>>()
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,8 +85,8 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
val node1: SimulatedNode = banks[i]
|
||||
val node2: SimulatedNode = banks[j]
|
||||
|
||||
val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> = loadLinearHeads(node1)
|
||||
val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.values.single()
|
||||
val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State<AnonymousParty>>> = loadLinearHeads(node1)
|
||||
val theDealRef: StateAndRef<InterestRateSwap.State<AnonymousParty>> = swaps.values.single()
|
||||
|
||||
// Do we have any more days left in this deal's lifetime? If not, return.
|
||||
val nextFixingDate = theDealRef.state.data.calculation.nextFixingDate() ?: return null
|
||||
@ -115,7 +116,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
||||
// We load the IRS afresh each time because the leg parts of the structure aren't data classes so they don't
|
||||
// have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable.
|
||||
// TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface.
|
||||
val irs = om.readValue<InterestRateSwap.State>(javaClass.classLoader.getResource("simulation/trade.json"))
|
||||
val irs = om.readValue<InterestRateSwap.State<AnonymousParty>>(javaClass.classLoader.getResource("simulation/trade.json"))
|
||||
irs.fixedLeg.fixedRatePayer = node1.info.legalIdentity.toAnonymous()
|
||||
irs.floatingLeg.floatingRatePayer = node2.info.legalIdentity.toAnonymous()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"fixedLeg": {
|
||||
"fixedRatePayer": "fixedRatePayerKey",
|
||||
"fixedRatePayer": "Bank A",
|
||||
"notional": "€25000000",
|
||||
"paymentFrequency": "SemiAnnual",
|
||||
"effectiveDate": "2016-03-11",
|
||||
@ -22,7 +22,7 @@
|
||||
"interestPeriodAdjustment": "Adjusted"
|
||||
},
|
||||
"floatingLeg": {
|
||||
"floatingRatePayer": "floatingRatePayerKey",
|
||||
"floatingRatePayer": "Bank B",
|
||||
"notional": "€25000000",
|
||||
"paymentFrequency": "Quarterly",
|
||||
"effectiveDate": "2016-03-11",
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.irs.testing
|
||||
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.AnonymousParty
|
||||
import net.corda.core.seconds
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.DUMMY_NOTARY
|
||||
@ -14,7 +15,7 @@ import java.math.BigDecimal
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
|
||||
fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
|
||||
fun createDummyIRS(irsSelect: Int): InterestRateSwap.State<AnonymousParty> {
|
||||
return when (irsSelect) {
|
||||
1 -> {
|
||||
|
||||
@ -244,8 +245,8 @@ class IRSTests {
|
||||
/**
|
||||
* Utility so I don't have to keep typing this.
|
||||
*/
|
||||
fun singleIRS(irsSelector: Int = 1): InterestRateSwap.State {
|
||||
return generateIRSTxn(irsSelector).tx.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State>().single()
|
||||
fun singleIRS(irsSelector: Int = 1): InterestRateSwap.State<AnonymousParty> {
|
||||
return generateIRSTxn(irsSelector).tx.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State<AnonymousParty>>().single()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,7 +300,7 @@ class IRSTests {
|
||||
var previousTXN = generateIRSTxn(1)
|
||||
previousTXN.toLedgerTransaction(services).verify()
|
||||
services.recordTransactions(previousTXN)
|
||||
fun currentIRS() = previousTXN.tx.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State>().single()
|
||||
fun currentIRS() = previousTXN.tx.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State<AnonymousParty>>().single()
|
||||
|
||||
while (true) {
|
||||
val nextFix: FixOf = currentIRS().nextFixingOf() ?: break
|
||||
@ -379,7 +380,7 @@ class IRSTests {
|
||||
|
||||
transaction("Fix") {
|
||||
input("irs post agreement")
|
||||
val postAgreement = "irs post agreement".output<InterestRateSwap.State>()
|
||||
val postAgreement = "irs post agreement".output<InterestRateSwap.State<AnonymousParty>>()
|
||||
output("irs post first fixing") {
|
||||
postAgreement.copy(
|
||||
postAgreement.fixedLeg,
|
||||
@ -686,7 +687,7 @@ class IRSTests {
|
||||
transaction("Fix") {
|
||||
input("irs post agreement1")
|
||||
input("irs post agreement2")
|
||||
val postAgreement1 = "irs post agreement1".output<InterestRateSwap.State>()
|
||||
val postAgreement1 = "irs post agreement1".output<InterestRateSwap.State<AnonymousParty>>()
|
||||
output("irs post first fixing1") {
|
||||
postAgreement1.copy(
|
||||
postAgreement1.fixedLeg,
|
||||
@ -695,7 +696,7 @@ class IRSTests {
|
||||
postAgreement1.common.copy(tradeID = "t1")
|
||||
)
|
||||
}
|
||||
val postAgreement2 = "irs post agreement2".output<InterestRateSwap.State>()
|
||||
val postAgreement2 = "irs post agreement2".output<InterestRateSwap.State<AnonymousParty>>()
|
||||
output("irs post first fixing2") {
|
||||
postAgreement2.copy(
|
||||
postAgreement2.fixedLeg,
|
||||
|
Loading…
Reference in New Issue
Block a user