/
Launch Online IDE

Tokens Wrap-Up

Recap and reflection


Reading Time: 6 min

It feels like you have gone through the Tokens SDK extensively. Before moving on, let's recap a bit and cover disparate connected topics.

Classes you learned about

Currency

To create TokenType instances of the most common Fiat and Digital currencies:

Types

Those classes form the nucleus of your tokens:

States

Token classes:

Schemas

So far, you accessed the vault and queried it without further explanation, although all those actions should have made sense in a high-level sense. Explanations come later. On the other hand, if you want, you can explore those custom schemas so as to give you an idea of what attributes are available for VaultCustomQueryCriteria:

Flows

Probably the most important part of the SDK. Those flows also come in a combination of other flavors, confidential, non-fungible:

And don't forget to dig into their inheritance and the functions they call, so that you can create your own atomic transactions.

Utilities

It is recommended that you spend some time exploring these utility classes. They will make your life much easier, and you'll see them used very frequently in all official examples:

  • AmountUtilities, to create amounts of your token type with fraction digits conversions taken care of.
  • TokenUtilities
  • TransactionUtilities provides various functions to filter and aggregate your tokens.
  • NotaryUtilities, to choose a notary for your tokens.
  • QueryUtilities, to create a QueryCriteria by issuer and / or holder for your queries.
  • FlowUtilities, some useful functions to get FlowSession and signing keys for your flows.
  • IssueTokensUtilities, an important utility if you have a requirement to create an atomic Issue transaction manually instead of using the ready flows of the SDK.
  • MoveTokensUtilities, an important utility if you have a requirement to create an atomic Move transaction manually instead of using the ready flows of the SDK.
  • RedeemFlowUtilities, an important utility if you have a requirement to create an atomic Redeem transaction manually instead of using the ready flows of the SDK.
  • SelectionUtilities, gives you some QueryCriteria for token selectors.
  • EvolvableTokenUtilities is an important utility if you have a requirement to create an atomic transaction manually instead of using the ready flows of the SDK.

Builders

If you are using a version of the Tokens SDK more recent than that used in this course, you can have access to some builders that allow a Java developer to use the same DSL syntax that a Kotlin developer has through receiver and infix functions (see below):

Token Selectors

Those selectors are used by the SDK's ready flows, but you can use them as well if there is a necessity to avoid using the ready flows or the utility functions, e.g. addMoveTokens():

Using Kotlin code in Java

As you know, Corda is written in Kotlin, a JVM language. More than a JVM language, it is interoperable with Java code. This means you can use the Kotlin code (classes, files, functions, etc..) inside a Java class. But Kotlin has a couple of features that Java doesn't:

  1. In Kotlin, you can have a file that has a collection of functions without an encapsulating class. In order to import that file inside your Java class, you have to suffix its name with Kt (short for Kotlin). For instance, AmountUtilities is a file in the Tokens SDK that has a collection of useful functions. To use any of them inside a Java class, you must use this import statement:

    import com.r3.corda.lib.tokens.contracts.utilities.AmountUtilitiesKt; // <-- Kt!
  2. Kotlin has something called a function receiver, which lets the developer add functions to pre-existing classes without the need to create a custom class that extends the base class to add that function. Explore the below sample code from the AmountUtilities Kotlin file:

    /** For creating [BigDecimal] quantities of [TokenType]s. */
    infix fun BigDecimal.of(token: TokenType): Amount<TokenType> = amount(this, token)
    //        ^^^ BigDecimal is the receiver.
    // -->               ^^ "of" is the function that is "added" to the BigDecimal type.
    // -->                                                                ^^ "this" refers to the BigDecimal instance to which the .of function has been "added".

    Here, BigDecimal is the receiver, instructing the Kotlin compiler to add as public the of function to the preexisting BigDecimal type. Inside the body of the function, this gives the BigDecimal instance as if of was truly a class method. The only restriction is that you still cannot access private and protected methods.

    Moreover, the above function declaration adds the infix keyword, which means that the function name can be placed between the receiver and the argument. Using it in Kotlin would look like this:

    import com.r3.corda.lib.tokens.contracts.types.TokenType
    import com.r3.corda.lib.tokens.contracts.utilities.of
    import com.r3.corda.lib.tokens.money.USD
    import java.math.BigDecimal
    
    fun testReceiverAndInfixFunction() {
        // Create USD token type using "money" helper file.
        val usdType: TokenType = USD
    
        // Create a BigDecimal amount of USD using the receiver aspect of the "of" function.
        val one: BigDecimal = BigDecimal.valueOf(1)
        val oneUsd = one.of(usdType)
    
        // Create a BigDecimal amount of USD using the receiver and infix aspects.
        val ten: BigDecimal = BigDecimal.valueOf(10)
        val tenUsd = ten of usdType
    }

    As you can see, the intent and readability of the code improves. Now, since Java doesn't support the receiver feature, nor infix functions, out of the box, Kotlin exposes the following to Java:

    UtilityClassName/UtilityFileKt.infixFunctionName(receiverObjectInstance, functionInputParameterValue)

    So the above example would look like this in Java:

    import com.r3.corda.lib.tokens.contracts.types.TokenType;
    import com.r3.corda.lib.tokens.contracts.utilities.AmountUtilitiesKt;
    // -->                                                            ^^ Kt
    import com.r3.corda.lib.tokens.money.FiatCurrency;
    import net.corda.core.contracts.Amount;
    
    import java.math.BigDecimal;
    
    public class TestInfixFunction {
        public void properSyntax {
            // Create USD token type using "FiatCurrency" class.
            final TokenType usdType = FiatCurrency.Companion.getInstance("USD");
    
            // Create a BigDecimal amount of USD using the utility function.
            final BigDecimal ten = BigDecimal.valueOf(10);
            final Amount<TokenType> tenUSD = AmountUtilitiesKt.of(ten, usdType);
            // -->                                          ^^ Kt
    }

Conclusion

Consider this chapter a handy list that you can skim when you can't quite remember the name of the class that you know will help you out.

Discuss on Slack
Rate this Page
Would you like to add a message?
Submit
Thank you for your Feedback!