https://github.com/polywrap/kotlin-client
https://github.com/polywrap/kotlin-client
Last synced: 10 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/polywrap/kotlin-client
- Owner: polywrap
- Created: 2023-03-21T15:46:17.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-08-31T14:48:42.000Z (over 2 years ago)
- Last Synced: 2024-11-05T07:35:29.552Z (about 1 year ago)
- Language: Kotlin
- Size: 357 MB
- Stars: 2
- Watchers: 3
- Forks: 1
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
- awesome-polywrap - Kotlin
README

[**Polywrap**](https://polywrap.io/) is a developer tool that enables easy integration of Web3 protocols into any application. It makes it possible for applications on any platform, written in any language, to read and write data to Web3 protocols.
This repository hosts a Kotlin implementation of the Polywrap Client for Android/JVM.
The readiness of the Kotlin client is tracked at https://github.com/polywrap/client-readiness
# Installation
Kotlin
```kotlin
plugins {
kotlin("plugin.serialization") version "1.x.x" // Required for serialization
}
dependencies {
implementation("io.polywrap:polywrap-client:0.10.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.x.x") // Required for serialization
}
```
Groovy
```groovy
plugins {
id 'org.jetbrains.kotlin.plugin.serialization' version '1.x.x' // Required for serialization
}
dependencies {
implementation "io.polywrap:polywrap-client:0.10.4"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.x.x" // Required for serialization
}
```
# Quick Start
The following examples can be found in [SanityClientTest](https://github.com/polywrap/kotlin-client/blob/main/src/commonTest/kotlin/client/SanityClientTest.kt). Many more examples are available in the client section of the [tests](https://github.com/polywrap/kotlin-client/tree/main/src/commonTest/kotlin/client) and the Kotlin client's section of the [client readiness](https://github.com/polywrap/client-readiness/tree/main/clients/kotlin/src/main/kotlin/features) test harness.
```kotlin
import io.polywrap.configBuilder.ConfigBuilder
import io.polywrap.configBuilder.polywrapClient
import io.polywrap.core.InvokeResult
import io.polywrap.core.resolution.Uri
import kotlinx.serialization.Serializable
private val sha3Uri = Uri("ipfs/QmThRxFfr7Hj9Mq6WmcGXjkRrgqMG3oD93SLX27tinQWy5")
@Test
fun invokeWithMapStringAnyArgs() {
// instantiate the client with default configuration using the polywrapClient builder DSL
val client = polywrapClient {
addDefaults()
}
// invoke the sha3 wrap with a Map of arguments
val result = client.invoke(
uri = sha3Uri,
method = "keccak_256",
args = mapOf("message" to "Hello World!")
)
assertNull(result.exceptionOrNull())
val hash = result.getOrThrow()
// to prevent a memory leak, close the client when you're done with it
// this typically happens at the end of your application's lifecycle
client.close()
}
@Test
fun invokeWithReifiedTypes() {
@Serializable
data class Keccak256Args(val message: String)
// instantiate the client with default configuration using the builder pattern
val client = ConfigBuilder().addDefaults().build()
// invoke the sha3 wrap with a serializable type
val result: InvokeResult = client.invoke(
uri = sha3Uri,
method = "keccak_256",
args = Keccak256Args("Hello World!")
)
assertNull(result.exceptionOrNull())
val hash = result.getOrThrow()
}
```
# Examples & Documentation
Reference documentation is hosted at https://kotlin.client.polywrap.io/
| Example | Platform | Description | Location |
|-------------|----------|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| IPFS | Android | Add a file to IPFS and then retrieve it | [Link](https://github.com/polywrap/ipfs/tree/main/demos/kotlin) |
| Ethereum | JVM | Sign typed data with the Ethers wrap | [Link](https://github.com/polywrap/ethereum-wallet/tree/main/implementations/kt/src/commonTest/kotlin/io/polywrap/plugins/ethereum/EthersExample.kt) |
| ENS | JVM | Get the content hash of an ENS address | [examples/ens](./examples/ens) |
| File System | JVM | Write a file to the file system, read its contents, then remove it | [examples/fileSystem](./examples/fileSystem) |
| HTTP | JVM | Make an HTTP request | [examples/http](./examples/http) |
| Hello World | JVM | Print a message to the console | [Link](https://github.com/polywrap/logging/blob/main/logger/implementations/kt/src/test/kotlin/io/polywrap/plugins/logger/HelloWorld.kt) |
# Plugins
The Kotlin client supports plugins that can be used to extend its functionality.
Some plugins are written in Rust and packaged with the Polywrap Client.
- System Bundle: File-system and HTTP plugins
- Web3 Bundle: Ethereum wallet plugin
*The Rust Ethereum Wallet plugin is not configurable from Kotlin. For custom configuration, use the Kotlin Ethereum Wallet plugin instead.*
These plugins can be loaded with the `addDefaults` method of the `ConfigBuilder`, or added using the `addBundle` method.
```kotlin
val client = polywrapClient { addDefaults() }
val client = polywrapClient {
addBundle(NativeBundle.System)
addBundle(NativeBundle.Web3)
}
```
The Rust plugins are located in the [Rust client repo](https://github.com/polywrap/rust-client/tree/main/packages/plugins).
Other plugins are written in Kotlin. The available Kotlin plugins include:
| Plugin | Description | Maven publication | Location |
|-----------------|--------------------------------------------------------------------------------|--------------------------------------------|----------------------------------------------------------------------------------|
| Ethereum Wallet | Support the Ethers wrap with an configurable Ethereum signer or RPC connection | io.polywrap.plugins:ethereum-wallet:0.10.4 | [Link](https://github.com/polywrap/ethereum-wallet/tree/main/implementations/kt) |
| Logger | Enable logging in Wasm wraps with SL4J | io.polywrap.plugins:logger:0.10.4 | [Link](https://github.com/polywrap/logging/tree/main/logger/implementations/kt) |
| File System | Interact with the host file system | io.polywrap.plugins:file-system:0.10.4 | [Link](https://github.com/polywrap/file-system/tree/main/implementations/kt) |
| HTTP | Send HTTP requests | io.polywrap.plugins:http:0.10.4 | [Link](https://github.com/polywrap/http/tree/main/implementations/kt) |
# Using GenericMap
The `GenericMap` type is implemented as an extension type for MessagePack serialization.
```kotlin
@Serializable(with = GenericMapExtensionSerializer::class)
data class GenericMap(val map: Map)
```
In practice, this means you must wrap a `Map` in a `GenericMap` before passing it to the client.
```kotlin
val myMap: Map = mapOf("Hello" to 1, "Heyo" to 50)
val genericMap: GenericMap = GenericMap(myMap)
val alsoGenericMap: GenericMap = myMap.toGenericMap()
val myMapReference: Map = genercMap.map
```
It also means the client will return a `GenericMap`, not a `Map`.
```kotlin
@Serializable
data class ArgsReturnMap(val map: GenericMap)
@Test
fun testReturnMap() = runTest {
val genericMap = mapOf("Hello" to 1, "Heyo" to 50).toGenericMap()
val result: InvokeResult> = client.invoke(
uri = uri,
method = "returnMap",
args = ArgsReturnMap(genericMap)
)
if (result.isFailure) throw result.exceptionOrNull()!!
assertEquals(genericMap, result.getOrThrow())
}
```
A contextual serializer is provided for `GenericMap` to help the `kotlinx.serialization` framework find the `GenericMapExtensionSerializer` serializer when the `@Contextual` annotation is used.
```kotlin
@Serializable
data class ArgsReturnMap(
@Contextual
val map: GenericMap
)
```
It is often preferable to annotate a typealias to help the `kotlinx.serialization` framework find the serializer.
```kotlin
typealias GenericMap = @Serializable(with = GenericMapExtensionSerializer::class) io.polywrap.core.msgpack.GenericMap
```
# Memory Management
The Kotlin client relies on a native library containing the [Rust version of the Polywrap Client](https://github.com/polywrap/rust-client). Some Kotlin objects contain pointers to natively allocated memory. These objects implement the `Autoclosable` interface and should be closed when the memory resources are no longer needed. Once closed, these objects cannot be used again.
The client `ConfigBuilder` takes ownership of its configuration and closes those resources for you. In most cases, the client is the only object that needs to be manually closed.
```kotlin
val client = polywrapClient {
addDefaults()
}
// do stuff with the client
// ...
// close the client to avoid a memory leak
client.close()
```
```kotlin
val client = ConfigBuilder().addDefaults().build()
// the autocloseable interface provides the `use` extension function,
// which closes the resource when the block completes (even if an exception is thrown)
client.use {
// do stuff with the client
}
```
# Development
### Build
Run the following to compile the project:
```
./gradlew assemble
```
### Test
Run the following to run all checks:
```
./gradlew jvmTest
```
### Lint
To lint the project, run the following:
```
./gradlew ktlintCheck
```
To auto-fix lint errors:
```
./gradlew ktlintFormat
```
# Resources
- [Website](https://polywrap.io/)
- [Documentation](https://docs.polywrap.io/)
- [Forum](https://forum.polywrap.io/)