Open TAC911 opened 5 years ago
Thanks for the heads up. It's because I changed the constructor signature (added a type parameter) and the node shell can't deserialise a string to the type. I'll add a helper flow so this will work. Cheers
Actually I've had a look into this and there's no way to fix it in the short term, it requires some Corda changes or changes to the tokens SDK to provide jackson annotations for sub-classes. In the meantime, I'm going to include a node driver integration test which demonstrates the whole end to end workflow. Cheers
I got a similar error for NovateObligation.
Command:
start NovateObligation linearId: b4436194-5977-4c0b-9581-dc93ee625627, novationCommand: { oldToken: { currencyCode: EUR, type: fiat }, newToken: { currencyCode: XRP, type: digital }, oracle: Oracle, type: token }
Error:
No matching constructor found:
- [net.corda.core.contracts.UniqueIdentifier, com.r3.corda.finance.obligation.commands.ObligationCommands$Novate]: Could not parse as a command: Cannot construct instance of
com.r3.corda.sdk.token.contracts.types.TokenType
(no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.r3.corda.finance.obligation.commands.ObligationCommands$Novate$UpdateFaceAmountToken["oldToken"])
Is it the same cause?
Yes its the same problem. The shell cannot deserialise the types. There is one way around it which is to create a wrapper flow which just takes strings as input and then constructs the objects you need and then invokes the create obligation flow. It's not difficult to do but will get messy, e.g. you'll need to deal with whether the currency code is a fiat or digital currency, for example.
@roger3cev, I was just wondering if there is a node driver integration test for an end to end flow for ripple settlement since we are not able to test it using the shell?
There's not a node driver test at the moment - it's on our TODO To add one though. Cheers
Hi guys,
UPDATE: Here's the repo with all the below fixes: https://github.com/adelrustum/corda-settler-fixes
I was able to use Roger's workaround (i.e. instead of passing an Amount
, I passed the amount and currency code); below is how I achieved it:
cordaCompile "$tokens_release_group:tokens-money:$tokens_release_version"
into the gradle file of cordapp
module so I can use FiatCurrency
class.ext.tokens_release_version = '1.0-RC03'
, because I noticed when I opened FiatCurrency.kt
file and compared it to the latest version of tokens-sdk that they're different. This got me stuck for 2-3 hours lol not an expert on gradle/maven/intellij, but I'm getting there.CreateObligation.kt
and split Amount
into longAmount
and currencyCode
; this will trigger a couple of errors because some functions expect Amount<T>
instead of Amount<FiatCurrency>
so I'll leave locating those easy fixes to you.
Below is the part of the code that I changed:
class Initiator<T : TokenType>(
private val longAmount: Long,
private val currencyCode: String,
private val role: InitiatorRole,
private val counterparty: Party,
private val dueBy: Instant? = null,
private val anonymous: Boolean = true
) : FlowLogic<WireTransaction>() {
private val token = FiatCurrency(Currency.getInstance(currencyCode))
private val amount = Amount(longAmount, token)
start CreateObligation longAmount: 1000, currencyCode: USD, role: OBLIGOR, counterparty: PartyB, dueBy: 1650000000, anonymous: false
NovateObligation.kt
code: Again, it will trigger some errors in the class code (replace TokenType
with FiatCurrencty
or DigitalCurrency
where applicable).
class Initiator(
val linearId: UniqueIdentifier,
private val fiatIdentifier: String,
private val digitalIdentifier: String,
private val oracle: Party
) : FlowLogic<WireTransaction>() {
private val fiatToken = FiatCurrency(Currency.getInstance(fiatIdentifier))
private val digitalToken = DigitalCurrency(digitalIdentifier)
private val novationCommand = ObligationCommands.Novate.
UpdateFaceAmountToken(fiatToken, digitalToken, oracle)
start NovateObligation linearId: REPLACE_W_OBLIGATION_ID, fiatIdentifier: USD, digitalIdentifier: XRP, oracle: Oracle
UpdateSettlementMethod
flow I had to copy the entire ripple
library from modules\ripple to cordapp folder, I tried to use it first as a dependency in build.gradle but that created a circular reference error on build because ripple library relies on cordapp.build.gradle
under cordapp with compile 'com.ripple:ripple-core:0.0.1-SNAPSHOT'
UpdateSettlementMethod
:
class Initiator(
val linearId: UniqueIdentifier,
val accountToPay: String,
val settlementOracle: Party
) : FlowLogic<WireTransaction>() {
private val settlementMethod = XrpSettlement(accountToPay, settlementOracle)
start UpdateSettlementMethod linearId: REPLACE_W_OBLIGATION_UID, accountToPay: REPLACE_W_XRP_ADDRESS, settlementOracle: Oracle
OffLedgerSettleObligation
flow:
class Initiator<T : TokenType>(
private val longAmount: Long,
private val digitalIdentifier: String,
private val linearId: UniqueIdentifier
) : FlowLogic<WireTransaction>() {
private val token = DigitalCurrency(digitalIdentifier)
private val amount = Amount(longAmount, token)
start OffLedgerSettleObligation longAmount: 20000000, digitalIdentifier: XRP, linearId: REPLACE_W_OBLIGATION_UID
Hi guys,
UPDATE: Here's the repo with all the below fixes: https://github.com/adelRestom/corda-settler-fixes
I was able to use Roger's workaround (i.e. instead of passing an
Amount
, I passed the amount and currency code); below is how I achieved it:
- Add
cordaCompile "$tokens_release_group:tokens-money:$tokens_release_version"
into the gradle file ofcordapp
module so I can useFiatCurrency
class.- Optional: I updated the tokens-sdk version to
ext.tokens_release_version = '1.0-RC03'
, because I noticed when I openedFiatCurrency.kt
file and compared it to the latest version of tokens-sdk that they're different. This got me stuck for 2-3 hours lol not an expert on gradle/maven/intellij, but I'm getting there.- Modify
CreateObligation.kt
and splitAmount
intolongAmount
andcurrencyCode
; this will trigger a couple of errors because some functions expectAmount<T>
instead ofAmount<FiatCurrency>
so I'll leave locating those easy fixes to you. Below is the part of the code that I changed:class Initiator<T : TokenType>( private val longAmount: Long, private val currencyCode: String, private val role: InitiatorRole, private val counterparty: Party, private val dueBy: Instant? = null, private val anonymous: Boolean = true ) : FlowLogic<WireTransaction>() { private val token = FiatCurrency(Currency.getInstance(currencyCode)) private val amount = Amount(longAmount, token)
- Use this call in your terminal to create an obligation:
start CreateObligation longAmount: 1000, currencyCode: USD, role: OBLIGOR, counterparty: PartyB, dueBy: 1650000000, anonymous: false
- Below is the updated
NovateObligation.kt
code: Again, it will trigger some errors in the class code (replaceTokenType
withFiatCurrencty
orDigitalCurrency
where applicable).class Initiator( val linearId: UniqueIdentifier, private val fiatIdentifier: String, private val digitalIdentifier: String, private val oracle: Party ) : FlowLogic<WireTransaction>() { private val fiatToken = FiatCurrency(Currency.getInstance(fiatIdentifier)) private val digitalToken = DigitalCurrency(digitalIdentifier) private val novationCommand = ObligationCommands.Novate. UpdateFaceAmountToken(fiatToken, digitalToken, oracle)
- Use this call:
start NovateObligation linearId: REPLACE_W_OBLIGATION_ID, fiatIdentifier: USD, digitalIdentifier: XRP, oracle: Oracle
- To fix
UpdateSettlementMethod
flow I had to copy the entireripple
library from modules\ripple to cordapp folder, I tried to use it first as a dependency in build.gradle but that created a circular reference error on build because ripple library relies on cordapp.- Update
build.gradle
under cordapp withcompile 'com.ripple:ripple-core:0.0.1-SNAPSHOT'
- Update
UpdateSettlementMethod
:class Initiator( val linearId: UniqueIdentifier, val accountToPay: String, val settlementOracle: Party ) : FlowLogic<WireTransaction>() { private val settlementMethod = XrpSettlement(accountToPay, settlementOracle)
- Run this from PartyB terminal (not PartyA):
start NovateObligation linearId: REPLACE_W_OBLIGATION_UID, fiatIdentifier: USD, digitalIdentifier: XRP, oracle: Oracle
- Update
OffLedgerSettleObligation
flow:class Initiator<T : TokenType>( private val longAmount: Long, private val digitalIdentifier: String, private val linearId: UniqueIdentifier ) : FlowLogic<WireTransaction>() { private val token = DigitalCurrency(digitalIdentifier) private val amount = Amount(longAmount, token)
- Run this from PartyA terminal:
start OffLedgerSettleObligation longAmount: 20000000, digitalIdentifier: XRP, linearId: REPLACE_W_OBLIGATION_UID
Thanks for the fix. I was able to test the end to end flow on the Corda shell.
@koshikraj Thanx for your merge request, I also updated the comment here to remove the repeated instruction.
Calling the CreateObligation flow as described in the example leads to an error.
Command:
start CreateObligation amount: { quantity: 1000, token: { currencyCode: USD, type: fiat } }, role: OBLIGOR, counterparty: PartyB, dueBy: 1543922400, anonymous: false
Error:
Cheers, TAC