mirror of
https://github.com/corda/corda.git
synced 2024-12-22 14:22:28 +00:00
Remove deposit and issuanceDef fields
Remove deposit field from the FungibleAsset interface, and moved it into a fixed reference to amount.token.issuer. Remove issuanceDef field and replace it with amount.token.
This commit is contained in:
parent
276683e053
commit
613a86c5d9
@ -66,7 +66,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<State, Issued<Currency>>>
|
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<State, Issued<Currency>>>
|
||||||
= tx.groupStates<State, Issued<Currency>> { it.issuanceDef }
|
= tx.groupStates<State, Issued<Currency>> { it.amount.token }
|
||||||
}
|
}
|
||||||
|
|
||||||
class Issue : AbstractIssue<State, Commands, Currency>(
|
class Issue : AbstractIssue<State, Commands, Currency>(
|
||||||
@ -90,16 +90,14 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
|||||||
constructor(deposit: PartyAndReference, amount: Amount<Currency>, owner: PublicKey)
|
constructor(deposit: PartyAndReference, amount: Amount<Currency>, owner: PublicKey)
|
||||||
: this(Amount(amount.quantity, Issued(deposit, amount.token)), owner)
|
: this(Amount(amount.quantity, Issued(deposit, amount.token)), owner)
|
||||||
|
|
||||||
override val deposit = amount.token.issuer
|
override val exitKeys = setOf(owner, amount.token.issuer.party.owningKey)
|
||||||
override val exitKeys = setOf(owner, deposit.party.owningKey)
|
|
||||||
override val contract = CASH_PROGRAM_ID
|
override val contract = CASH_PROGRAM_ID
|
||||||
override val issuanceDef = amount.token
|
|
||||||
override val participants = listOf(owner)
|
override val participants = listOf(owner)
|
||||||
|
|
||||||
override fun move(newAmount: Amount<Issued<Currency>>, newOwner: PublicKey): FungibleAsset<Currency>
|
override fun move(newAmount: Amount<Issued<Currency>>, newOwner: PublicKey): FungibleAsset<Currency>
|
||||||
= copy(amount = amount.copy(newAmount.quantity, amount.token), owner = newOwner)
|
= copy(amount = amount.copy(newAmount.quantity, amount.token), owner = newOwner)
|
||||||
|
|
||||||
override fun toString() = "${Emoji.bagOfCash}Cash($amount at $deposit owned by ${owner.toStringShort()})"
|
override fun toString() = "${Emoji.bagOfCash}Cash($amount at ${amount.token.issuer} owned by ${owner.toStringShort()})"
|
||||||
|
|
||||||
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
||||||
|
|
||||||
@ -197,8 +195,8 @@ fun Iterable<ContractState>.sumCashOrZero(currency: Issued<Currency>): Amount<Is
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Cash.State.ownedBy(owner: PublicKey) = copy(owner = owner)
|
fun Cash.State.ownedBy(owner: PublicKey) = copy(owner = owner)
|
||||||
fun Cash.State.issuedBy(party: Party) = copy(amount = Amount(amount.quantity, issuanceDef.copy(issuer = deposit.copy(party = party))))
|
fun Cash.State.issuedBy(party: Party) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = amount.token.issuer.copy(party = party))))
|
||||||
fun Cash.State.issuedBy(deposit: PartyAndReference) = copy(amount = Amount(amount.quantity, issuanceDef.copy(issuer = deposit)))
|
fun Cash.State.issuedBy(deposit: PartyAndReference) = copy(amount = Amount(amount.quantity, amount.token.copy(issuer = deposit)))
|
||||||
fun Cash.State.withDeposit(deposit: PartyAndReference): Cash.State = copy(amount = amount.copy(token = amount.token.copy(issuer = deposit)))
|
fun Cash.State.withDeposit(deposit: PartyAndReference): Cash.State = copy(amount = amount.copy(token = amount.token.copy(issuer = deposit)))
|
||||||
|
|
||||||
infix fun Cash.State.`owned by`(owner: PublicKey) = ownedBy(owner)
|
infix fun Cash.State.`owned by`(owner: PublicKey) = ownedBy(owner)
|
||||||
|
@ -72,7 +72,7 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
|
|||||||
* Group commodity states by issuance definition (issuer and underlying commodity).
|
* Group commodity states by issuance definition (issuer and underlying commodity).
|
||||||
*/
|
*/
|
||||||
override fun groupStates(tx: TransactionForContract)
|
override fun groupStates(tx: TransactionForContract)
|
||||||
= tx.groupStates<State, Issued<Commodity>> { it.issuanceDef }
|
= tx.groupStates<State, Issued<Commodity>> { it.amount.token }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,16 +101,14 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
|
|||||||
constructor(deposit: PartyAndReference, amount: Amount<Commodity>, owner: PublicKey)
|
constructor(deposit: PartyAndReference, amount: Amount<Commodity>, owner: PublicKey)
|
||||||
: this(Amount(amount.quantity, Issued(deposit, amount.token)), owner)
|
: this(Amount(amount.quantity, Issued(deposit, amount.token)), owner)
|
||||||
|
|
||||||
override val deposit = amount.token.issuer
|
|
||||||
override val contract = COMMODITY_PROGRAM_ID
|
override val contract = COMMODITY_PROGRAM_ID
|
||||||
override val exitKeys = Collections.singleton(owner)
|
override val exitKeys = Collections.singleton(owner)
|
||||||
override val issuanceDef = amount.token
|
|
||||||
override val participants = listOf(owner)
|
override val participants = listOf(owner)
|
||||||
|
|
||||||
override fun move(newAmount: Amount<Issued<Commodity>>, newOwner: PublicKey): FungibleAsset<Commodity>
|
override fun move(newAmount: Amount<Issued<Commodity>>, newOwner: PublicKey): FungibleAsset<Commodity>
|
||||||
= copy(amount = amount.copy(newAmount.quantity, amount.token), owner = newOwner)
|
= copy(amount = amount.copy(newAmount.quantity, amount.token), owner = newOwner)
|
||||||
|
|
||||||
override fun toString() = "Commodity($amount at $deposit owned by ${owner.toStringShort()})"
|
override fun toString() = "Commodity($amount at ${amount.token.issuer} owned by ${owner.toStringShort()})"
|
||||||
|
|
||||||
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ class Obligation<P> : Contract {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<Obligation.State<P>, Issued<Terms<P>>>>
|
override fun groupStates(tx: TransactionForContract): List<TransactionForContract.InOutGroup<Obligation.State<P>, Issued<Terms<P>>>>
|
||||||
= tx.groupStates<Obligation.State<P>, Issued<Terms<P>>> { it.issuanceDef }
|
= tx.groupStates<Obligation.State<P>, Issued<Terms<P>>> { it.amount.token }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,7 +152,7 @@ class Obligation<P> : Contract {
|
|||||||
.filter { it.contract.legalContractReference in template.acceptableContracts }
|
.filter { it.contract.legalContractReference in template.acceptableContracts }
|
||||||
// Restrict the states to those of the correct issuance definition (this normally
|
// Restrict the states to those of the correct issuance definition (this normally
|
||||||
// covers issued product and obligor, but is opaque to us)
|
// covers issued product and obligor, but is opaque to us)
|
||||||
.filter { it.issuanceDef in template.acceptableIssuedProducts }
|
.filter { it.amount.token in template.acceptableIssuedProducts }
|
||||||
// Catch that there's nothing useful here, so we can dump out a useful error
|
// Catch that there's nothing useful here, so we can dump out a useful error
|
||||||
requireThat {
|
requireThat {
|
||||||
"there are fungible asset state outputs" by (assetStates.size > 0)
|
"there are fungible asset state outputs" by (assetStates.size > 0)
|
||||||
@ -164,7 +164,7 @@ class Obligation<P> : Contract {
|
|||||||
// this one.
|
// this one.
|
||||||
val moveCommands = tx.commands.select<MoveCommand>()
|
val moveCommands = tx.commands.select<MoveCommand>()
|
||||||
var totalPenniesSettled = 0L
|
var totalPenniesSettled = 0L
|
||||||
val requiredSigners = inputs.map { it.deposit.party.owningKey }.toSet()
|
val requiredSigners = inputs.map { it.amount.token.issuer.party.owningKey }.toSet()
|
||||||
|
|
||||||
for ((beneficiary, obligations) in inputs.groupBy { it.owner }) {
|
for ((beneficiary, obligations) in inputs.groupBy { it.owner }) {
|
||||||
val settled = amountReceivedByOwner[beneficiary]?.sumFungibleOrNull<P>()
|
val settled = amountReceivedByOwner[beneficiary]?.sumFungibleOrNull<P>()
|
||||||
@ -268,21 +268,12 @@ class Obligation<P> : Contract {
|
|||||||
/** The public key of the entity the contract pays to */
|
/** The public key of the entity the contract pays to */
|
||||||
val beneficiary: PublicKey
|
val beneficiary: PublicKey
|
||||||
) : FungibleAsset<Obligation.Terms<P>>, NettableState<State<P>, MultilateralNetState<P>> {
|
) : FungibleAsset<Obligation.Terms<P>>, NettableState<State<P>, MultilateralNetState<P>> {
|
||||||
override val amount: Amount<Issued<Terms<P>>>
|
override val amount: Amount<Issued<Terms<P>>> = Amount(quantity, Issued(obligor.ref(0), template))
|
||||||
get() = Amount(quantity, issuanceDef)
|
|
||||||
override val contract = OBLIGATION_PROGRAM_ID
|
override val contract = OBLIGATION_PROGRAM_ID
|
||||||
override val deposit: PartyAndReference
|
override val exitKeys: Collection<PublicKey> = setOf(beneficiary)
|
||||||
get() = amount.token.issuer
|
val dueBefore: Instant = template.dueBefore
|
||||||
override val exitKeys: Collection<PublicKey>
|
override val participants: List<PublicKey> = listOf(obligor.owningKey, beneficiary)
|
||||||
get() = setOf(owner)
|
override val owner: PublicKey = beneficiary
|
||||||
val dueBefore: Instant
|
|
||||||
get() = template.dueBefore
|
|
||||||
override val issuanceDef: Issued<Terms<P>>
|
|
||||||
get() = Issued(obligor.ref(0), template)
|
|
||||||
override val participants: List<PublicKey>
|
|
||||||
get() = listOf(obligor.owningKey, beneficiary)
|
|
||||||
override val owner: PublicKey
|
|
||||||
get() = beneficiary
|
|
||||||
|
|
||||||
override fun move(newAmount: Amount<Issued<Terms<P>>>, newOwner: PublicKey): State<P>
|
override fun move(newAmount: Amount<Issued<Terms<P>>>, newOwner: PublicKey): State<P>
|
||||||
= copy(quantity = newAmount.quantity, beneficiary = newOwner)
|
= copy(quantity = newAmount.quantity, beneficiary = newOwner)
|
||||||
@ -522,7 +513,7 @@ class Obligation<P> : Contract {
|
|||||||
require(states.all { it.lifecycle == existingLifecycle }) { "initial lifecycle must be $existingLifecycle for all input states" }
|
require(states.all { it.lifecycle == existingLifecycle }) { "initial lifecycle must be $existingLifecycle for all input states" }
|
||||||
|
|
||||||
// Produce a new set of states
|
// Produce a new set of states
|
||||||
val groups = statesAndRefs.groupBy { it.state.data.issuanceDef }
|
val groups = statesAndRefs.groupBy { it.state.data.amount.token }
|
||||||
for ((aggregateState, stateAndRefs) in groups) {
|
for ((aggregateState, stateAndRefs) in groups) {
|
||||||
val partiesUsed = ArrayList<PublicKey>()
|
val partiesUsed = ArrayList<PublicKey>()
|
||||||
stateAndRefs.forEach { stateAndRef ->
|
stateAndRefs.forEach { stateAndRef ->
|
||||||
@ -608,7 +599,7 @@ class Obligation<P> : Contract {
|
|||||||
|
|
||||||
/** Get the common issuance definition for one or more states, or throw an IllegalArgumentException. */
|
/** Get the common issuance definition for one or more states, or throw an IllegalArgumentException. */
|
||||||
private fun getIssuanceDefinitionOrThrow(states: Iterable<State<P>>): Issued<Terms<P>> =
|
private fun getIssuanceDefinitionOrThrow(states: Iterable<State<P>>): Issued<Terms<P>> =
|
||||||
states.map { it.issuanceDef }.distinct().single()
|
states.map { it.amount.token }.distinct().single()
|
||||||
|
|
||||||
/** Get the common issuance definition for one or more states, or throw an IllegalArgumentException. */
|
/** Get the common issuance definition for one or more states, or throw an IllegalArgumentException. */
|
||||||
private fun getTermsOrThrow(states: Iterable<State<P>>) =
|
private fun getTermsOrThrow(states: Iterable<State<P>>) =
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
package com.r3corda.contracts.clause
|
package com.r3corda.contracts.clause
|
||||||
|
|
||||||
import com.r3corda.core.contracts.FungibleAsset
|
|
||||||
import com.r3corda.core.contracts.InsufficientBalanceException
|
|
||||||
import com.r3corda.core.contracts.sumFungibleOrNull
|
|
||||||
import com.r3corda.core.contracts.sumFungibleOrZero
|
|
||||||
import com.r3corda.core.contracts.*
|
import com.r3corda.core.contracts.*
|
||||||
import com.r3corda.core.contracts.clauses.Clause
|
import com.r3corda.core.contracts.clauses.Clause
|
||||||
import com.r3corda.core.crypto.Party
|
|
||||||
import com.r3corda.core.transactions.TransactionBuilder
|
import com.r3corda.core.transactions.TransactionBuilder
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -68,7 +63,7 @@ abstract class AbstractConserveAmount<S : FungibleAsset<T>, C : CommandData, T :
|
|||||||
val (gathered, gatheredAmount) = gatherCoins(acceptableCoins, Amount(amount.quantity, currency))
|
val (gathered, gatheredAmount) = gatherCoins(acceptableCoins, Amount(amount.quantity, currency))
|
||||||
val takeChangeFrom = gathered.lastOrNull()
|
val takeChangeFrom = gathered.lastOrNull()
|
||||||
val change = if (takeChangeFrom != null && gatheredAmount > amount) {
|
val change = if (takeChangeFrom != null && gatheredAmount > amount) {
|
||||||
Amount(gatheredAmount.quantity - amount.quantity, takeChangeFrom.state.data.issuanceDef)
|
Amount(gatheredAmount.quantity - amount.quantity, takeChangeFrom.state.data.amount.token)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ class CashTests {
|
|||||||
val outState = issuerInState.copy(owner = DUMMY_PUBKEY_2)
|
val outState = issuerInState.copy(owner = DUMMY_PUBKEY_2)
|
||||||
|
|
||||||
fun Cash.State.editDepositRef(ref: Byte) = copy(
|
fun Cash.State.editDepositRef(ref: Byte) = copy(
|
||||||
amount = Amount(amount.quantity, token = amount.token.copy(deposit.copy(reference = OpaqueBytes.of(ref))))
|
amount = Amount(amount.quantity, token = amount.token.copy(amount.token.issuer.copy(reference = OpaqueBytes.of(ref))))
|
||||||
)
|
)
|
||||||
|
|
||||||
lateinit var services: MockServices
|
lateinit var services: MockServices
|
||||||
@ -173,7 +173,7 @@ class CashTests {
|
|||||||
assertTrue(tx.inputs.isEmpty())
|
assertTrue(tx.inputs.isEmpty())
|
||||||
val s = tx.outputs[0].data as Cash.State
|
val s = tx.outputs[0].data as Cash.State
|
||||||
assertEquals(100.DOLLARS `issued by` MINI_CORP.ref(12, 34), s.amount)
|
assertEquals(100.DOLLARS `issued by` MINI_CORP.ref(12, 34), s.amount)
|
||||||
assertEquals(MINI_CORP, s.deposit.party)
|
assertEquals(MINI_CORP, s.amount.token.issuer.party)
|
||||||
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
||||||
assertTrue(tx.commands[0].value is Cash.Commands.Issue)
|
assertTrue(tx.commands[0].value is Cash.Commands.Issue)
|
||||||
assertEquals(MINI_CORP_PUBKEY, tx.commands[0].signers[0])
|
assertEquals(MINI_CORP_PUBKEY, tx.commands[0].signers[0])
|
||||||
@ -650,22 +650,22 @@ class CashTests {
|
|||||||
val oneThousandDollarsFromMini = Cash.State(1000.DOLLARS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY)
|
val oneThousandDollarsFromMini = Cash.State(1000.DOLLARS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY)
|
||||||
|
|
||||||
// Obviously it must be possible to aggregate states with themselves
|
// Obviously it must be possible to aggregate states with themselves
|
||||||
assertEquals(fiveThousandDollarsFromMega.issuanceDef, fiveThousandDollarsFromMega.issuanceDef)
|
assertEquals(fiveThousandDollarsFromMega.amount.token, fiveThousandDollarsFromMega.amount.token)
|
||||||
|
|
||||||
// Owner is not considered when calculating whether it is possible to aggregate states
|
// Owner is not considered when calculating whether it is possible to aggregate states
|
||||||
assertEquals(fiveThousandDollarsFromMega.issuanceDef, twoThousandDollarsFromMega.issuanceDef)
|
assertEquals(fiveThousandDollarsFromMega.amount.token, twoThousandDollarsFromMega.amount.token)
|
||||||
|
|
||||||
// States cannot be aggregated if the deposit differs
|
// States cannot be aggregated if the deposit differs
|
||||||
assertNotEquals(fiveThousandDollarsFromMega.issuanceDef, oneThousandDollarsFromMini.issuanceDef)
|
assertNotEquals(fiveThousandDollarsFromMega.amount.token, oneThousandDollarsFromMini.amount.token)
|
||||||
assertNotEquals(twoThousandDollarsFromMega.issuanceDef, oneThousandDollarsFromMini.issuanceDef)
|
assertNotEquals(twoThousandDollarsFromMega.amount.token, oneThousandDollarsFromMini.amount.token)
|
||||||
|
|
||||||
// States cannot be aggregated if the currency differs
|
// States cannot be aggregated if the currency differs
|
||||||
assertNotEquals(oneThousandDollarsFromMini.issuanceDef,
|
assertNotEquals(oneThousandDollarsFromMini.amount.token,
|
||||||
Cash.State(1000.POUNDS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY).issuanceDef)
|
Cash.State(1000.POUNDS `issued by` MINI_CORP.ref(3), MEGA_CORP_PUBKEY).amount.token)
|
||||||
|
|
||||||
// States cannot be aggregated if the reference differs
|
// States cannot be aggregated if the reference differs
|
||||||
assertNotEquals(fiveThousandDollarsFromMega.issuanceDef, (fiveThousandDollarsFromMega `with deposit` defaultIssuer).issuanceDef)
|
assertNotEquals(fiveThousandDollarsFromMega.amount.token, (fiveThousandDollarsFromMega `with deposit` defaultIssuer).amount.token)
|
||||||
assertNotEquals((fiveThousandDollarsFromMega `with deposit` defaultIssuer).issuanceDef, fiveThousandDollarsFromMega.issuanceDef)
|
assertNotEquals((fiveThousandDollarsFromMega `with deposit` defaultIssuer).amount.token, fiveThousandDollarsFromMega.amount.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -245,7 +245,7 @@ class ObligationTests {
|
|||||||
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)
|
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)
|
||||||
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY)
|
val obligationBobToAlice = oneMillionDollars.OBLIGATION between Pair(BOB, ALICE_PUBKEY)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
val tx = TransactionType.General.Builder(DUMMY_NOTARY).apply {
|
||||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.issuanceDef, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||||
signWith(ALICE_KEY)
|
signWith(ALICE_KEY)
|
||||||
signWith(BOB_KEY)
|
signWith(BOB_KEY)
|
||||||
signWith(DUMMY_NOTARY_KEY)
|
signWith(DUMMY_NOTARY_KEY)
|
||||||
@ -259,7 +259,7 @@ class ObligationTests {
|
|||||||
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)
|
val obligationAliceToBob = oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)
|
||||||
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE_PUBKEY)
|
val obligationBobToAlice = (2000000.DOLLARS `issued by` defaultIssuer).OBLIGATION between Pair(BOB, ALICE_PUBKEY)
|
||||||
val tx = TransactionType.General.Builder(null).apply {
|
val tx = TransactionType.General.Builder(null).apply {
|
||||||
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.issuanceDef, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
Obligation<Currency>().generatePaymentNetting(this, obligationAliceToBob.amount.token, DUMMY_NOTARY, obligationAliceToBob, obligationBobToAlice)
|
||||||
signWith(ALICE_KEY)
|
signWith(ALICE_KEY)
|
||||||
signWith(BOB_KEY)
|
signWith(BOB_KEY)
|
||||||
}.toSignedTransaction().tx
|
}.toSignedTransaction().tx
|
||||||
@ -453,7 +453,7 @@ class ObligationTests {
|
|||||||
input("Alice's $1,000,000 obligation to Bob")
|
input("Alice's $1,000,000 obligation to Bob")
|
||||||
input("Alice's $1,000,000")
|
input("Alice's $1,000,000")
|
||||||
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.issuanceDef)) }
|
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) }
|
||||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
@ -467,7 +467,7 @@ class ObligationTests {
|
|||||||
input(500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY)
|
input(500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY)
|
||||||
output("Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) }
|
output("Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) }
|
||||||
output("Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
output("Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.issuanceDef)) }
|
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) }
|
||||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ class ObligationTests {
|
|||||||
input(defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob
|
input(defaultedObligation) // Alice's defaulted $1,000,000 obligation to Bob
|
||||||
input(1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY)
|
input(1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY)
|
||||||
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.issuanceDef)) }
|
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity, inState.amount.token)) }
|
||||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||||
this `fails with` "all inputs are in the normal state"
|
this `fails with` "all inputs are in the normal state"
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ class ObligationTests {
|
|||||||
input("Alice's $1,000,000 obligation to Bob")
|
input("Alice's $1,000,000 obligation to Bob")
|
||||||
input("Alice's $1,000,000")
|
input("Alice's $1,000,000")
|
||||||
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.issuanceDef)) }
|
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneMillionDollars.quantity / 2, inState.amount.token)) }
|
||||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||||
this `fails with` "amount in settle command"
|
this `fails with` "amount in settle command"
|
||||||
}
|
}
|
||||||
@ -517,7 +517,7 @@ class ObligationTests {
|
|||||||
input("Alice's 1 FCOJ obligation to Bob")
|
input("Alice's 1 FCOJ obligation to Bob")
|
||||||
input("Alice's 1 FCOJ")
|
input("Alice's 1 FCOJ")
|
||||||
output("Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB_PUBKEY) }
|
output("Bob's 1 FCOJ") { CommodityContract.State(oneUnitFcoj, BOB_PUBKEY) }
|
||||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneUnitFcoj.quantity, oneUnitFcojObligation.issuanceDef)) }
|
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Amount(oneUnitFcoj.quantity, oneUnitFcojObligation.amount.token)) }
|
||||||
command(ALICE_PUBKEY) { CommodityContract.Commands.Move(Obligation<Commodity>().legalContractReference) }
|
command(ALICE_PUBKEY) { CommodityContract.Commands.Move(Obligation<Commodity>().legalContractReference) }
|
||||||
verifies()
|
verifies()
|
||||||
}
|
}
|
||||||
@ -648,13 +648,13 @@ class ObligationTests {
|
|||||||
output { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) }
|
output { outState.copy(quantity = inState.quantity - 200.DOLLARS.quantity) }
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.issuanceDef)) }
|
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(100.DOLLARS.quantity, inState.amount.token)) }
|
||||||
command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() }
|
command(DUMMY_PUBKEY_1) { Obligation.Commands.Move() }
|
||||||
this `fails with` "the amounts balance"
|
this `fails with` "the amounts balance"
|
||||||
}
|
}
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.issuanceDef)) }
|
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token)) }
|
||||||
this `fails with` "required com.r3corda.core.contracts.FungibleAsset.Commands.Move command"
|
this `fails with` "required com.r3corda.core.contracts.FungibleAsset.Commands.Move command"
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
@ -679,10 +679,10 @@ class ObligationTests {
|
|||||||
|
|
||||||
this `fails with` "for reference [00] at issuer MegaCorp the amounts balance"
|
this `fails with` "for reference [00] at issuer MegaCorp the amounts balance"
|
||||||
|
|
||||||
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.issuanceDef.copy(product = megaCorpDollarSettlement))) }
|
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.DOLLARS.quantity, inState.amount.token.copy(product = megaCorpDollarSettlement))) }
|
||||||
this `fails with` "for reference [00] at issuer MegaCorp the amounts balance"
|
this `fails with` "for reference [00] at issuer MegaCorp the amounts balance"
|
||||||
|
|
||||||
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.issuanceDef.copy(product = megaCorpPoundSettlement))) }
|
command(DUMMY_PUBKEY_1) { Obligation.Commands.Exit(Amount(200.POUNDS.quantity, inState.amount.token.copy(product = megaCorpPoundSettlement))) }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,6 @@ class InsufficientBalanceException(val amountMissing: Amount<*>) : Exception() {
|
|||||||
* (GBP, USD, oil, shares in company <X>, etc.) and any additional metadata (issuer, grade, class, etc.).
|
* (GBP, USD, oil, shares in company <X>, etc.) and any additional metadata (issuer, grade, class, etc.).
|
||||||
*/
|
*/
|
||||||
interface FungibleAsset<T> : OwnableState {
|
interface FungibleAsset<T> : OwnableState {
|
||||||
/**
|
|
||||||
* Where the underlying asset backing this ledger entry can be found. The reference
|
|
||||||
* is only intended for use by the issuer, and is not intended to be meaningful to others.
|
|
||||||
*/
|
|
||||||
val deposit: PartyAndReference
|
|
||||||
val issuanceDef: Issued<T>
|
|
||||||
val amount: Amount<Issued<T>>
|
val amount: Amount<Issued<T>>
|
||||||
/**
|
/**
|
||||||
* There must be an ExitCommand signed by these keys to destroy the amount. While all states require their
|
* There must be an ExitCommand signed by these keys to destroy the amount. While all states require their
|
||||||
@ -55,7 +49,6 @@ interface FungibleAsset<T> : OwnableState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Small DSL extensions.
|
// Small DSL extensions.
|
||||||
|
|
||||||
/** Sums the asset states in the list, returning null if there are none. */
|
/** Sums the asset states in the list, returning null if there are none. */
|
||||||
|
@ -147,7 +147,7 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
|||||||
var acceptableCoins = run {
|
var acceptableCoins = run {
|
||||||
val ofCurrency = assetsStates.filter { it.state.data.amount.token.product == currency }
|
val ofCurrency = assetsStates.filter { it.state.data.amount.token.product == currency }
|
||||||
if (onlyFromParties != null)
|
if (onlyFromParties != null)
|
||||||
ofCurrency.filter { it.state.data.deposit.party in onlyFromParties }
|
ofCurrency.filter { it.state.data.amount.token.issuer.party in onlyFromParties }
|
||||||
else
|
else
|
||||||
ofCurrency
|
ofCurrency
|
||||||
}
|
}
|
||||||
@ -160,13 +160,13 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
|||||||
val (gathered, gatheredAmount) = gatherCoins(acceptableCoins, amount)
|
val (gathered, gatheredAmount) = gatherCoins(acceptableCoins, amount)
|
||||||
val takeChangeFrom = gathered.firstOrNull()
|
val takeChangeFrom = gathered.firstOrNull()
|
||||||
val change = if (takeChangeFrom != null && gatheredAmount > amount) {
|
val change = if (takeChangeFrom != null && gatheredAmount > amount) {
|
||||||
Amount(gatheredAmount.quantity - amount.quantity, takeChangeFrom.state.data.issuanceDef)
|
Amount(gatheredAmount.quantity - amount.quantity, takeChangeFrom.state.data.amount.token)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
val keysUsed = gathered.map { it.state.data.owner }.toSet()
|
val keysUsed = gathered.map { it.state.data.owner }.toSet()
|
||||||
|
|
||||||
val states = gathered.groupBy { it.state.data.deposit }.map {
|
val states = gathered.groupBy { it.state.data.amount.token.issuer }.map {
|
||||||
val coins = it.value
|
val coins = it.value
|
||||||
val totalAmount = coins.map { it.state.data.amount }.sumOrThrow()
|
val totalAmount = coins.map { it.state.data.amount }.sumOrThrow()
|
||||||
deriveState(coins.first().state, totalAmount, to)
|
deriveState(coins.first().state, totalAmount, to)
|
||||||
|
Loading…
Reference in New Issue
Block a user