Skip to content

DevRel-1953 - worldcupticketbooking, QueryCriteria for holder for Tokens #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions Accounts/worldcupticketbooking/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ buildscript {
confidential_id_release_version = "1.0"

//tokens
tokens_release_version = '1.1'
tokens_release_version = '1.2'
tokens_release_group = 'com.r3.corda.lib.tokens'

//springboot
Expand Down Expand Up @@ -116,8 +116,6 @@ dependencies {
//tokens
cordapp "$tokens_release_group:tokens-contracts:$tokens_release_version"
cordapp "$tokens_release_group:tokens-workflows:$tokens_release_version"
cordapp "$tokens_release_group:tokens-money:$tokens_release_version"
cordapp "$tokens_release_group:tokens-selection:$tokens_release_version"


}
Expand Down Expand Up @@ -161,8 +159,6 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
//tokens
cordapp("$tokens_release_group:tokens-contracts:$tokens_release_version")
cordapp("$tokens_release_group:tokens-workflows:$tokens_release_version")
cordapp("$tokens_release_group:tokens-money:$tokens_release_version")
cordapp("$tokens_release_group:tokens-selection:$tokens_release_version")
}
node {
name "O=Notary,L=London,C=GB"
Expand Down
2 changes: 0 additions & 2 deletions Accounts/worldcupticketbooking/workflows/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ dependencies {
// Token SDK dependencies.
cordaCompile "$tokens_release_group:tokens-workflows:$tokens_release_version"
cordaCompile "$tokens_release_group:tokens-contracts:$tokens_release_version"
cordaCompile "$tokens_release_group:tokens-money:$tokens_release_version"
cordapp "$tokens_release_group:tokens-selection:$tokens_release_version"

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilitiesKt;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilities;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilities;
import com.t20worldcup.states.T20CricketTicket;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
import com.r3.corda.lib.accounts.workflows.UtilitiesKt;
Expand All @@ -17,7 +18,6 @@
import com.r3.corda.lib.tokens.selection.TokenQueryBy;
import com.r3.corda.lib.tokens.selection.database.config.DatabaseSelectionConfigKt;
import com.r3.corda.lib.tokens.selection.database.selector.DatabaseTokenSelection;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilitiesKt;
import kotlin.Pair;
import net.corda.core.contracts.*;
import net.corda.core.flows.*;
Expand Down Expand Up @@ -94,10 +94,18 @@ public String call() throws FlowException {
Amount<FiatCurrency> amount = new Amount(costOfTicket, FiatCurrency.Companion.getInstance(currency));

//Buyer Query for token balance.
QueryCriteria queryCriteria = QueryUtilitiesKt.heldTokenAmountCriteria(this.getInstance(currency), buyerAccount).and(QueryUtilitiesKt.sumTokenCriteria());
List<Object> sum = getServiceHub().getVaultService().queryBy(FungibleToken.class, queryCriteria).component5();

//construct the query criteria and get all USD available unconsumed fungible tokens which belong to buyers account
QueryCriteria queryCriteriaForTokenBalance = QueryUtilities.tokenAmountCriteria(this.getInstance(currency))
.and(new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
withExternalIds(Arrays.asList(buyerAccountInfo.getIdentifier().getId())));

// Note: component5 is a shortcut to 'other-results' of the Vault.Page, this is where the sumTokenCriteria return value is.
List<Object> sum = getServiceHub().getVaultService().
queryBy(FungibleToken.class, queryCriteriaForTokenBalance.and(QueryUtilities.sumTokenCriteria())).component5();

if(sum.size() == 0)
throw new FlowException(buyerAccountName + " has 0 token balance. Please ask the Bank to issue some cash.");
throw new FlowException(buyerAccountName + "has 0 token balance. Please ask the Bank to issue some cash.");
else {
Long tokenBalance = (Long) sum.get(0);
if(tokenBalance < costOfTicket)
Expand All @@ -106,7 +114,7 @@ public String call() throws FlowException {

//the tokens to move to new account which is the seller account
Pair<AbstractParty, Amount<TokenType>> partyAndAmount = new Pair(sellerAccount, amount);

//let's use the DatabaseTokenSelection to get the tokens from the db
DatabaseTokenSelection tokenSelection = new DatabaseTokenSelection(
getServiceHub(),
Expand All @@ -115,7 +123,7 @@ public String call() throws FlowException {
DatabaseSelectionConfigKt.RETRY_CAP_DEFAULT,
DatabaseSelectionConfigKt.PAGE_SIZE_DEFAULT
);

//call generateMove which gives us 2 stateandrefs with tokens having new owner as seller.
Pair<List<StateAndRef<FungibleToken>>, List<FungibleToken>> inputsAndOutputs =
tokenSelection.generateMove(Arrays.asList(partyAndAmount), buyerAccount, new TokenQueryBy(), getRunId().getUuid());
Expand All @@ -141,7 +149,7 @@ public String call() throws FlowException {
//this is the handler for synckeymapping called by seller. seller must also have created some keys not known to us - buyer
subFlow(new SyncKeyMappingFlowHandler(sellerSession));

//recieve the data from counter session in tx formatt.
//recieve the data from counter session in tx formatt.
subFlow(new SignTransactionFlow(sellerSession) {
@Override
protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException {
Expand Down Expand Up @@ -194,7 +202,7 @@ public Void call() throws FlowException {
AnonymousParty buyerAccount = subFlow(new RequestKeyForAccount(buyerAccountInfo));
AnonymousParty sellerAccount = subFlow(new RequestKeyForAccount(sellerAccountInfo));

//query for all tickets
//query for all tickets
QueryCriteria queryCriteriaForSellerTicketType = new QueryCriteria.VaultQueryCriteria()
.withExternalIds(Arrays.asList(sellerAccountInfo.getIdentifier().getId()))
.withStatus(Vault.StateStatus.UNCONSUMED);
Expand Down Expand Up @@ -240,10 +248,10 @@ public Void call() throws FlowException {
TransactionBuilder transactionBuilder = new TransactionBuilder(notary);

//part1 of DVP is to transfer the non fungible token from seller to buyer
MoveTokensUtilitiesKt.addMoveNonFungibleTokens(transactionBuilder, getServiceHub(), tokenPointer, buyerAccount);
MoveTokensUtilities.addMoveNonFungibleTokens(transactionBuilder, getServiceHub(), tokenPointer, buyerAccount);

//part2 of DVP is to transfer cash - fungible token from buyer to seller and return the change to buyer
MoveTokensUtilitiesKt.addMoveTokens(transactionBuilder, inputs, moneyReceived);
MoveTokensUtilities.addMoveTokens(transactionBuilder, inputs, moneyReceived);

//sync keys with buyer, again sync for similar members

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@


import co.paralleluniverse.fibers.Suspendable;
import com.r3.corda.lib.tokens.contracts.states.FungibleToken;
import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
import com.r3.corda.lib.tokens.contracts.types.TokenType;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilitiesKt;
import com.t20worldcup.states.T20CricketTicket;
import com.r3.corda.lib.accounts.contracts.states.AccountInfo;
import com.r3.corda.lib.accounts.workflows.UtilitiesKt;
import com.r3.corda.lib.accounts.workflows.flows.RequestKeyForAccount;
import com.r3.corda.lib.tokens.contracts.states.FungibleToken;
import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
import com.r3.corda.lib.tokens.contracts.types.TokenPointer;
import com.r3.corda.lib.tokens.contracts.types.TokenType;
import com.r3.corda.lib.tokens.money.FiatCurrency;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilitiesKt;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilities;
import com.r3.corda.lib.tokens.workflows.internal.flows.finality.ObserverAwareFinalityFlow;
import com.r3.corda.lib.tokens.workflows.types.PartyAndAmount;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilities;
import com.t20worldcup.states.T20CricketTicket;
import net.corda.core.contracts.Amount;
import net.corda.core.contracts.StateAndRef;
import net.corda.core.flows.*;
Expand Down Expand Up @@ -118,14 +118,18 @@ public String call() throws FlowException {

//first part of DVP is to transfer the non fungible token from seller to buyer
//this add inputs and outputs to transactionBuilder
MoveTokensUtilitiesKt.addMoveNonFungibleTokens(transactionBuilder, getServiceHub(), tokenPointer, buyerAccount);
MoveTokensUtilities.addMoveNonFungibleTokens(transactionBuilder, getServiceHub(), tokenPointer, buyerAccount);

//Part2 : Move fungible token - cash from buyer to seller

QueryCriteria queryCriteriaForTokenBalance = QueryUtilitiesKt.heldTokenAmountCriteria(this.getInstance(currency), buyerAccount).and(QueryUtilitiesKt.sumTokenCriteria());
//construct the query criteria and get all USD available unconsumed fungible tokens which belong to buyers account
QueryCriteria queryCriteriaForTokenBalance = QueryUtilities.tokenAmountCriteria(this.getInstance(currency))
.and(new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
withExternalIds(Arrays.asList(buyerAccountInfo.getIdentifier().getId())));

// Note: component5 is a shortcut to 'other-results' of the Vault.Page, this is where the sumTokenCriteria return value is.
List<Object> sum = getServiceHub().getVaultService().
queryBy(FungibleToken.class, queryCriteriaForTokenBalance).component5();
queryBy(FungibleToken.class, queryCriteriaForTokenBalance.and(QueryUtilities.sumTokenCriteria())).component5();

if(sum.size() == 0)
throw new FlowException(buyerAccountName + "has 0 token balance. Please ask the Bank to issue some cash.");
Expand All @@ -140,14 +144,10 @@ public String call() throws FlowException {
//move money to sellerAccountInfo account.
PartyAndAmount partyAndAmount = new PartyAndAmount(sellerAccount, amount);

//construct the query criteria and get all available unconsumed fungible tokens which belong to buyers account
QueryCriteria criteria = new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
withExternalIds(Arrays.asList(buyerAccountInfo.getIdentifier().getId()));

//call utility function to move the fungible token from buyer to seller account
//this also adds inputs and outputs to the transactionBuilder
//till now we have only 1 transaction with 2 inputs and 2 outputs - one moving fungible tokens other moving non fungible tokens between accounts
MoveTokensUtilitiesKt.addMoveFungibleTokens(transactionBuilder, getServiceHub(), Arrays.asList(partyAndAmount), buyerAccount, criteria);
MoveTokensUtilities.addMoveFungibleTokens(transactionBuilder, getServiceHub(), Arrays.asList(partyAndAmount), buyerAccount, queryCriteriaForTokenBalance);

//self sign the transaction. note : the host party will first self sign the transaction.
SignedTransaction selfSignedTransaction = getServiceHub().signInitialTransaction(transactionBuilder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import com.r3.corda.lib.tokens.selection.TokenQueryBy;
import com.r3.corda.lib.tokens.selection.database.config.DatabaseSelectionConfigKt;
import com.r3.corda.lib.tokens.selection.database.selector.DatabaseTokenSelection;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilitiesKt;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilitiesKt;
import com.r3.corda.lib.tokens.workflows.flows.move.MoveTokensUtilities;
import com.r3.corda.lib.tokens.workflows.utilities.QueryUtilities;
import kotlin.Pair;
import net.corda.core.contracts.Amount;
import net.corda.core.contracts.CommandData;
Expand All @@ -20,6 +20,7 @@
import net.corda.core.identity.AbstractParty;
import net.corda.core.identity.AnonymousParty;
import net.corda.core.identity.Party;
import net.corda.core.node.services.Vault;
import net.corda.core.node.services.vault.QueryCriteria;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
Expand Down Expand Up @@ -62,10 +63,18 @@ public String call() throws FlowException {
Amount<TokenType> amount = new Amount(costOfTicket, getInstance(currency));

//Buyer Query for token balance.
QueryCriteria queryCriteria = QueryUtilitiesKt.heldTokenAmountCriteria(this.getInstance(currency), buyerAccount).and(QueryUtilitiesKt.sumTokenCriteria());
List<Object> sum = getServiceHub().getVaultService().queryBy(FungibleToken.class, queryCriteria).component5();

//construct the query criteria and get all USD available unconsumed fungible tokens which belong to buyers account
QueryCriteria queryCriteriaForTokenBalance = QueryUtilities.tokenAmountCriteria(this.getInstance(currency))
.and(new QueryCriteria.VaultQueryCriteria().withStatus(Vault.StateStatus.UNCONSUMED).
withExternalIds(Arrays.asList(buyerAccountInfo.getIdentifier().getId())));

// Note: component5 is a shortcut to 'other-results' of the Vault.Page, this is where the sumTokenCriteria return value is.
List<Object> sum = getServiceHub().getVaultService().
queryBy(FungibleToken.class, queryCriteriaForTokenBalance.and(QueryUtilities.sumTokenCriteria())).component5();

if(sum.size() == 0)
throw new FlowException(buyerAccountName + " has 0 token balance. Please ask the Bank to issue some cash.");
throw new FlowException(buyerAccountName + "has 0 token balance. Please ask the Bank to issue some cash.");
else {
Long tokenBalance = (Long) sum.get(0);
if(tokenBalance < costOfTicket)
Expand All @@ -92,7 +101,7 @@ public String call() throws FlowException {

TransactionBuilder transactionBuilder = new TransactionBuilder(notary);

MoveTokensUtilitiesKt.addMoveTokens(transactionBuilder, inputsAndOutputs.getFirst(), inputsAndOutputs.getSecond());
MoveTokensUtilities.addMoveTokens(transactionBuilder, inputsAndOutputs.getFirst(), inputsAndOutputs.getSecond());

Set<PublicKey> mySigners = new HashSet<>();

Expand All @@ -106,7 +115,7 @@ public String call() throws FlowException {

FlowSession sellerSession = initiateFlow(sellerAccountInfo.getHost());

//sign the transaction with the signers we got by calling filterMyKeys
//sign the transaction with the signers we got by calling filterMyKeys
SignedTransaction selfSignedTransaction = getServiceHub().signInitialTransaction(transactionBuilder, mySigners);

//call FinalityFlow for finality
Expand Down