A day in a c-lightning plugin with Kotlin

Vincenzo Palazzo
5 min readSep 13, 2021

Welcome to a c-lightning plugin with Kotlin 101.

This article will introduce some basic concepts to start writing a plugin for c-lightning with Kotlin over the JVM.

Start from the basics!

C-lightning is a lightning network implementation written in C, and for someone can be scary. It can be true, however, this implementation provides an awesome plugin interface, and you can write a plugin to modify o implement some cool stuff for the c-lightning ecosystem.

You can start to write a plugin, more or less with all the language that you want (see languages supported). In this article, we will use Kotlin based on JVM.

Why use kotlin on JVM? because in this article we will use the Java library called JRPCLightning.

c-lightning plugins building blocks.

A plugin in c-lightning has only a couple of building blocks, that are

  • RPC methods: A plugin can define indefinitely RPC method, that can use other RPC methods;
  • Plugin options: A plugin is run by c-lightning, and the option is the method to pass parameters (like custom configuration) to plugins;
  • Plugin Notification: A plugin can receive (and also send, but it is an advanced topic) notification when an error happens. These notifications are asynchronous, and this means that c-lightning doesn’t wait for the end of the execution.
  • Plugin Hooks: A plugin can receive some custom event when a method is called on the c-lightning node. In particular, the plugin can subscribe itself to some event to listen to it, and c-lightning will send all the information when these events will happen.

Here we go, we are ready to fall inside the developing process.

Start to develop your Kotlin plugin.

Before to start we need some developing tools, that are:

Get started

Open the project cloned from git, with the IDE and If you are using the tools that I suggested in the previous section, you are seeing the following view

IDE view of the project.

At this point, you need to search two classes in the project directory, one file is called App.kt, and the other one is called Plugin.kt.

Basically the App.kt it is the starting point of the plugin, and it contains only a couple of line of code.

That it is reported here

package io.github.clightning4j.template

import io.github.clightning4j.template.plugin.Plugin

fun main() {
// Starting point of your plugin!
val
plugin = Plugin()
// start to listen c-lightning calls
plugin.start()
}

In addition, the core of the plugin it is contained in the file Plugin.kt, and the code here it is reported below

// Extend the abstract class CLightningPlugin to use all the stuff
// to implement the plugin.
// Se also the java doc at the following link https://clightning4j.github.io/JRPClightning/
class
Plugin : CLightningPlugin() {

// all the propriety with the PluginOption annotation
// are bind from the library jrpclightning.
// so, you don't need to made any other check on it
@PluginOption(
name = "hello-kotlin",
description = "This propriety is a fake propriety, there is any problem if it is not exist in the command line",
defValue = "true",
typeValue = "flag"
)
private var sayHello = false

// This method is called by the library, when the plugin finish to set up all the stuff with
// c-lightning, at this point this method is called
override fun
onInit(plugin: ICLightningPlugin, request: CLightningJsonObject, response: CLightningJsonObject) {
super.onInit(plugin, request, response)
// if you need to call some RPC method, you need to wrap the call inside a therea
Executors.newSingleThreadScheduledExecutor().schedule(
{
var getInfo = CLightningRPC.getInstance().info
plugin.log(PluginLog.INFO, "Message from the template plugin %s".format(getInfo.id))
plugin.log(PluginLog.INFO, "Form more information visit the doc: https://clightning4j.github.io/JRPClightning/")
},
10, TimeUnit.SECONDS
)
}

@RPCMethod(
name = "say-hello",
description = "Say hello from the Kotlin plugin",
parameter = "[name]"
)
fun sayHello(plugin: CLightningPlugin, request: CLightningJsonObject, response: CLightningJsonObject) {
val params = request["params"].asJsonArray
plugin.log(PluginLog.DEBUG, "The request was: %s".format(request))
if (params.size() == 0) {
response.apply {
add("answer", "Hello by Kotlin")
add("warning", "The rpc method accept also a name parameter")
}
} else {
val name = params[0]
response.apply {
add("answer", "Hello %s".format(name.asString))
}
}
}

@Subscription(notification = "invoice_creation")
fun logInvoice(data: CLightningJsonObject) {
log(PluginLog.DEBUG, "Subscription to 'invoice_creation' called")
}

@Hook(hook = "rpc_command")
fun checkStopCommand(plugin: CLightningPlugin, request: CLightningJsonObject, response: CLightningJsonObject) {
plugin.log(PluginLog.DEBUG, "Hook received %s".format(request))
val params = request["params"].asJsonObject
val
rpcMethod = params["rpc_command"].asJsonObject["method"].asString
if
(rpcMethod == "stop") {
plugin.log(PluginLog.INFO, "Hello by the kotlin plugin")
}
response.apply {
add("result", "continue")
}
}
}

How to run the plugin in c-lightning

When you have read all the stuff on your plugin, and you are ready to build it. You can use the following Gradle command from the command line

./gradlew createRunnableScript

From the command line, you should see the following status

Here we go, Gradle will generate a new bash script in the app directory called app-gen.sh with all the info to run the plugin. Now what you need to do is to link your kotlin plugin with the c-lightning node, and you have a different option. But the option that I suggest it is to stop your c-lightning node and run it again with the following command

lightningd — plugin=/your/path/of/template/kotlin-template/app/app-gen.sh

As the last step is to use your RPC method to say hello, in my case it is

➜  ~ lightning-cli say-hello                                                                    
{
"answer": "Hello by Kotlin",
"warning": "The rpc method accept also a name parameter"
}
➜ ~ lightning-cli say-hello vincent
{
"answer": "Hello vincent"
}

Conclusion

The c-lightning plugin is somethings very powerful, and with some plugin, you are able to run c-lightning with on a raspberry pi with only a 30 Gb of space.

One of these plugins is clightning4j/btcli4j, and there are many more where to take some tips here https://github.com/clightning4j

If you want to contribute, pull requests are welcome, and some of these plugins are waiting to find a mantainer. Please, check out these awesome things.

If you like my Job, please considered supporting me with the following methods

- 3BQ8qbn8hLdmBKEjt1Hj1Z6SiDsnjJurfU
- liberapay.com/vincenzopalazzo
- Github support
- buymeacoffee

P.S: Lightning donation is coming ;-)

If you want open channels with my c-lightning node build on top of Java and Kotlin, here we go https://bruce.bublina.eu.org

--

--

Vincenzo Palazzo

I'm an Open Source software developer, and in my free time, I'm a master's student. My main focus is to build some tools useful for other developers.