Given that a list of states is shown on a web interface, and there's an "update" option on that interface (and consequently, I need to implement an amendment flow), what would be the best approach to get the StateAndRef of the current state?
Store the transaction ID from the create command and use it to get the current StateAndRef
By the linearID of the current state
It doesn't matter.
Thanks
Maka
For a LinearState, I'd recommend retrieving the latest version of the state you want to spend using its linearId:
val queryCriteria = QueryCriteria.LinearStateQueryCriteria(linearId = listOf(linearId))
val iouStateAndRef = serviceHub.vaultQueryService.queryBy<IOUState>(queryCriteria).states.single()
The first line creates a query object to retrieve the state by linearId. By default, queries only retrieve the latest version (the "head") of the state chain. The second line uses the query to retrieve the object from the vault.
See https://docs.corda.net/api-vault-query.html for details.
Related
I learned how to create output state by corda.
However, I can't find documentation about how to consume those created outputs.
How can I specify outputs I want to consume as inputs in Flow code?
Usually it's like this:
Your state is a LinearState that has some UUID attribute as its linearId.
The flow that wants to consume that state has a constructor that takes as an input parameter that linearId.
Inside the flow you query the vault of the node to get that state by its linearId; the query returns a StateAndRef of your state.
You add that StateAndRef as an input to your transaction.
Let's say you're trying to update that state, so you add to the transaction an output; that output has the same value for linearId; but you can modify any other attribute. So this way you mimic an update, because states in Corda are final; so to update one, you consume it, then you create an output that has the same linearId but different values for the remaining attributes. This allows you to track the history of that state by its linearId.
This example shows the above steps, you'll see that the flow constructor takes the Id of the proposal, queries the vault for that proposal; then updates its amount by creating a new proposal with the same Id but different amount.
I'm developing a CorDapp but haven't implemented the schema as it is not a good practice.
But the code I have to get a particular record without using schema is first getting me all the states and then fetching a particular record, it is very time consuming as it is iterating through over each state object.
DataFeed, Vault.Update> dataFeed = proxy.vaultTrack(IOUState.class);
//this gives a snapshot of IOUState as of now. so if there are 11 IOUState as of now, this will return 11 IOUState objects
Vault.Page<IOUState> snapshot = dataFeed.getSnapshot();
for (StateAndRef<IOUState> state : snapshot.getStates()) {
if (state.getState().getData().getAssetId().equals(value)) {
cs = state.getState().getData();
}
}
Could you please suggest better approach to fetch a particular record from corda vault without using schema and iterating through over each state object.
Not sure how you come to the conclusion that using a schema is not a good practice. Do you have any data points to prove this? Or the source of this information would be helpful for us to understand the problem with implementing a schema.
Is's not possible to fetch a state based on one of its attributes without a schema. However, if you are specifically interested in fetching a state based on an ID (also considering your state is Linear/ Non-Fungible in nature), you could use a linear state. A linear state can be directly fetched from the vault using a LinearStateQueryCriteria.
val criteria = LinearStateQueryCriteria(linearId = listOf(linearId));
val results = vaultService.queryBy<LinearState>(criteria);
Who said implementing a schema is not a good practice?! Please post a link to where you read that.
You can't get a particular record from the vault (i.e. using a query on a certain attribute) without a custom schema.
I want to create a custom fungible asset on corda.. It is unclear to me how states that implement FungibleAsset are handled internally. Say I receive ten 1 dollar CoinStates from a transaction, are those merged to one 10 dollar Coinstate which I then use as the one and only input state if I wanted to make a payment myself?
basically I want something like the Cash.generateSpend which unfortunately is not very well documented
My approach so far for a transferFlow:
I have a function that does a vault query and should return some parties balance.. (this is assuming that the balance amount is internally merged to one state)
then using this balance as Input state I have a check if the input is equal the amount to pay in which case I will simply create one output state of the same amount but a new owner, otherwise I create another output state with the amount of change and myself as the owner
This is the function so far...
I have a function that does a vault query and should return some parties balance..
StateAndRef<CurrencyState> getBalaceOfIdentiy(AbstractParty id) throws FlowException {
QueryCriteria queryCriteria = new QueryCriteria.FungibleAssetQueryCriteria(null,ImmutableList.of(id),null, null,
null, null, null
);
// this assumes states are merged internally
List<StateAndRef<CurrencyState>> balanceOfID = getServiceHub().getVaultService().queryBy(CurrencyState.class, queryCriteria).getStates();
return balanceOfID.get(0);
}
Corda follows UTXO model. I'm not sure which version of Corda you are on but if you'll look closely enough you'll find that it would call OnLedgerAsset.generateSpend at some point of time and that does the job for you. and can be statically used as it is annotated with #JvmStatic.
I am trying to do simple fund transfer from one account to another account using simple state. 2 Flows have been created one for issue of transfer request with cash transfer and flow created to just consumed that transaction. My question is, is it possible to transfer and consume state in one flow ?
As per my opinion transaction must be consumed after transfer but also want to show it on UI.
Corda RPCQuery allowed to bring information of unconsumed states only, if I consume above transaction, is there way to show consumed transactions last state?
CordaRPCOps allows you to query for unconsumed states, consumed states, or both. Here's a simple way of querying for all states:
val criteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.ALL)
val results = proxy.vaultQueryBy<ContractState>(criteria)
To show the last consumed state, you could retrieve all the consumed states in descending order of consumption and grab the first one, as follows:
val criteria = QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED)
val sortColumn = Sort.SortColumn(SortAttribute.Standard(Sort.VaultStateAttribute.CONSUMED_TIME), Sort.Direction.DESC)
val sorting = Sort(listOf(sortColumn))
val results = proxy.vaultQueryBy<Obligation>(criteria, sorting = sorting)
val lastConsumedState = results.states[0]
From any flow, you need to call FinalityFlow, in order to notarize
and record the transaction in individual parties' vault. So I think
after the issuance (or transfer), you need to call FinalityFlow
first. Only then you can use the issued state as input for the new
transaction.
The notary is responsible for avoiding the double spend
of the input state in any transaction. So you can not use any newly
issued state (as input to new transaction), until the notary is aware
of it.
Thus I think in your case, you will need to call FinalityFlow twice, once after each transaction (i.e. issuance & consumption).
In a supply chain management current owner needs to track the life cycle of an asset. How do I achieve this in corda? Say the asset is a linearstate asset, which changes ownership over the time. If a current owner wants to view all the owner the asset had over the time, how to solve this issue?
Within a flow, you can query your vault for past versions of a state using its unique identifier. For example:
QueryCriteria.LinearStateQueryCriteria criteria = new QueryCriteria.LinearStateQueryCriteria(
null,
ImmutableList.of(stateLinearId),
// Change to `UNCONSUMED` for only unconsumed states, or `CONSUMED` for only consumed states.
Vault.StateStatus.ALL,
null);
Vault.Page<LinearState> results = getServiceHub().getVaultService().queryBy(LinearState.class, criteria);
List<StateAndRef<LinearState>> statesAndRefs = results.getStates();
You can then inspect these states to see past owners (unless the owners have used anonymous public keys to hide their identity).