Skip to main content

Kotlin

The Polywrap Client

To use Wraps in your app, all you need is the Polywrap Client.

Kotlin application boilerplate

We'll be using a simple console application written in Kotlin for this guide.

You can either set up a new application through an IDE of your choice, or use gradle to initialize a project.

If using gradle, all you need to do is run gradle init within your project folder.

Make sure to:

  • Select kotlin as your implementation language
  • Use Kotlin as your build script DSL
  • Use a minimum target Java version of 17

Inside build.gradle.kts, you need to update your plugins and dependencies sections:

build.gradle.kts
plugins {
id("org.jetbrains.kotlin.jvm") version "1.9.0"

// The versions of the JVM and serialization plugins must be the same
id("org.jetbrains.kotlin.plugin.serialization") version "1.9.0"

application
}

//...

dependencies {
// Add the polywrap-client and serialization dependency required by the Polywrap Client
implementation("io.polywrap:polywrap-client:0.10.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1")
}

Now you can use the Polywrap Client inside your Kotlin app!

Invoking your first Wrap

In order to invoke a Wrap, we first need to instantiate the Polywrap Client:

At the top of your app's main file (usually App.kt), import the Polywrap Client:

App.kt
import io.polywrap.configBuilder.polywrapClient // Import of the Polywrap Client itself
import io.polywrap.core.resolution.Uri // The Polywrap Client uses the Uri class for invocations

You can now instantiate the Polywrap Client with a default configuration within your main function:

App.kt
  val client = polywrapClient { addDefaults() }

At this point, you can already invoke Wraps! In the simple example below, we will invoke the SHA3 Wrap within our main function:

App.kt
  val result =
client.invoke<String>(
uri = Uri("wrapscan.io/polywrap/sha3@1.0"),
method = "sha3_256",
args = mapOf("message" to "Hello Polywrap!")
)

if (result.isFailure) {
throw result.exceptionOrNull()!!
}

println(result)

Running the application using ./gradlew run or through your IDE, you should now see the following appear in your console:

Success(ba5a5d5fb7674f5975f0ecd0cd9a2f4bcadc9c04f5ac2ab3a887d8f10355fc38)

This is the InvokeResult object. It's isSuccess and isFailure properties denote whether the Wrap's invocation was successful, and we will see how to get the return value of the invocation in the next section.

What's going on here?

Using the Polywrap Client, we are invoking the sha3_256 method of a Wrap found under the WRAP URI wrapscan.io/polywrap/sha3@1.0 called the SHA3 Wrap.

Under the hood, through a process we call URI Resolution, the Polywrap Client knows how to fetch and execute the Wrap from decentralized storage.

The PolywrapClient comes pre-configured with everything you need for most Web2 and Web3 use-cases by default.

The InvokeResult object

The InvokeResult is an alias of the stdlib Result object.

On successful invocations, you can extract the return value of the invocation, while on errors you can extract the underlying wrap execution exception.

Universal SDKs

Now that we know how a Wrap is invoked, let's see Polywrap's true power: universal SDKs!

One of the greatest benefits of Polywrap for the end-user (you!) lies in the fact that you can use the Polywrap Client to invoke the same Wrap from a variety of platforms and languages. If there's a Polywrap Client for your language, you can invoke any Wrap. This means that you can use the same SDK across multiple languages!

Another important benefit of using Polywrap is that, since Wraps are downloaded from various sources, you can automatically receive patches and updates to your SDKs without having to update your codebase.

Now we'll invoke the Uniswap V3 Wrap which is a port of the Uniswap SDK, but written as a Wrap.

We can use the Uniswap Wrap to fetch Uniswap's basic data related to the WETH and USDC tokes, find the address of the pool for those two tokens. We are also checking each result for errors.

App.kt
  val wethResult =
client.invoke<Map<String, Any>>(
uri = Uri("wrapscan.io/polywrap/uniswap-v3@1.0"),
method = "fetchToken",
args =
mapOf(
"address" to "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"chainId" to "MAINNET"
)
)

// Log the invocation error and stop execution if the invocation fails
println(wethResult.getOrThrow())

val usdcResult =
client.invoke<Map<String, Any>>(
uri = Uri("wrapscan.io/polywrap/uniswap-v3@1.0"),
method = "fetchToken",
args =
mapOf(
"address" to "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"chainId" to "MAINNET"
)
)

// Log the invocation error and stop execution if the invocation fails
println(usdcResult.getOrThrow())

val poolAddressResult =
client.invoke<String>(
uri = Uri("wrapscan.io/polywrap/uniswap-v3@1.0"),
method = "getPoolAddress",
args =
mapOf(
"tokenA" to wethResult.getOrDefault(null),
"tokenB" to usdcResult.getOrDefault(null),
"fee" to "MEDIUM"
)
)

// Log the invocation error and stop execution if the invocation fails
println(poolAddressResult.getOrThrow())

You can see more examples on how to use the Uniswap V3 Wrap in its docs page.

Compose everything

So far, we've only invoked a single Wrap, essentially using Polywrap to access a single SDK.

Using the Polywrap Client, we can invoke any number of SDKs, allowing us to build infinitely composable applications. If there's a Wrap for it, we can invoke it and use its functionality.

Visit Wrapscan and the awesome-polywrap repository to find a curated list of Wraps we and our community have developed.