Using the UTXO Ledger Token Selection API heading-link-icon

This section contains the following:

The following example outlines the basic building blocks to consider when using the token selection API with the UTXO Unspent Transaction Output. The unspent output of a cryptocurrency transaction, representing the amount of digital currency that has not been spent and is available for use in future transactions. ledger. The example only covers the token selection aspects of a flow Communication between participants in an application network is peer-to-peer using flows. and omits any details about how to create UTXO ledger transactions.

  1. Define a custom state with enough detail to create a token A type of programmable digital asset that can represent value and be traded. Tokens can be fungible or non-fungible. from:

    class CoinState(
        override val participants: List<PublicKey>,
        val issuer: SecureHash,
        val currency: String,
        val value: BigDecimal,
        val tag: String? = null,
        val ownerHash: SecureHash? = null
    ) : ContractState {
       companion object {
          val tokenType = CoinState::class.java.name.toString()
       }
    
  2. Create an observer to convert the state to a token:

    class CoinStateObserver : UtxoTokenTransactionStateObserver<CoinState> {
       override val stateType = CoinState::class.java
    
       override fun onCommit(context: TokenStateObserverContext<CoinState>): UtxoToken {
          return UtxoToken(
             poolKey = UtxoTokenPoolKey(
                tokenType = CoinState.tokenType,
                issuerHash = context.stateAndRef.state.contractState.issuer,
                symbol = context.stateAndRef.state.contractState.currency
             ),
             context.stateAndRef.state.contractState.value,
             filterFields = UtxoTokenFilterFields((context.stateAndRef.state.contractState.tag, context.stateAndRef.state.contractState.ownerHash)
          )
       }
    }
    

    Corda can now create pools of tokens for the unconsumed CoinStates.

  3. You can now begin selecting states to spend in a flow. This example does not show code for creating transactions but in a real example you would need to create a flow to mint the coins (states) by creating and finalizing UTXO transactions that have CoinStates as output states. Add the token selection API to a flow as an injected property:

    @CordaInject
    lateinit var tokenSelection: TokenSelection
    

    a. Create the criteria for the type of tokens you need and set a target amount:

    // Assume we have an issuer who has created some coin states
    val bankX500 = MemberX500Name.parse(ISSUING_BANK_X500)
    // Assume we are using a single notrary
    val notary = notaryLookup.notaryServices.single()
    
    // Create our selection criteria to select a minimum of 100 GBP worth of coins
    val selectionCriteria = TokenClaimCriteria(
      tokenType = CoinState.tokenType,
      issuerHash = bankX500.toSecureHash(),
      notaryX500Name = notary.name,
      symbol = "GBP",
      targetAmount = BigDecimal(100)
    )
    

    b. Issue the query, handle the response, and clean-up any claim you make:

     // Query for required tokens
    val tokenClaim = tokenSelection.tryClaim(selectionCriteria)
    
    // A null result indicates the query could not be satisfied
    if (tokenClaim == null) {
     return "FAILED TO FIND ENOUGH TOKENS"
    }
    
    // You've claimed some tokens you can now try and spend them
    aSpendFunction(tokenClaim.claimedTokens)
    

The Balance Query API enables users to retrieve the balance of a pool of tokens, taking into account only the tokens that satisfy a certain criteria. Two values are calculated when the query is executed:

  • The available balance which only includes tokens that have not been spent nor claimed.
  • The total balance which includes all tokens that have not been spent. That is, the total balance is the available balance plus the balance of all claimed tokens.

The following example has similarities to the Token Claim API example and assumes that CoinState and CoinStateObserver have been implemented as described in that example.

To query the balance of a pool of tokens:

  1. Add the token selection API to your flow as an injected property:
    @CordaInject
    lateinit var tokenSelection: TokenSelection
    
  2. Create the criteria that specifies which tokens should be taken into account to calculate the balance:
    // Assume there is an issuer who has created some coin states
    val bankX500 = MemberX500Name.parse(ISSUING_BANK_X500)
    
    // Assume you are using a single notary
    val notary = notaryLookup.notaryServices.single()
    
    // Create the balance criteria
    val balanceQueryCriteria = TokenBalanceCriteria(
      tokenType = CoinState.tokenType,
      issuerHash = bankX500.toSecureHash(),
      notaryX500Name = notary.name,
      symbol = "GBP"
    )
    
  3. Issue the query and print the response:
    // Query the balance tokens
    val tokenBalance = tokenSelection.queryBalance(balanceQueryCriteria)!!
    
    // Output the result
    println("Available balance: ${tokenBalance.availableBalance}")
    println("Total balance: ${tokenBalance.totalBalance}")
    

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.