Giter Club home page Giter Club logo

lightningcpp's Introduction

lightning-cpp

A C++11 wrapper to build plugins for C-lightning and access its JSON-RPC interface

Installation

This library makes an extensive use of libjson-rpc-cpp. Recommended way is to build it from source (here are Debian instructions but you can find more here) :

apt install libcurl4 libmicrohttpd-dev libjsoncpp-dev libargtable2-dev cmake libhiredis-dev catch libcurl4-openssl-dev
git clone git://github.com/cinemast/libjson-rpc-cpp.git
mkdir -p libjson-rpc-cpp/build
cd libjson-rpc-cpp/build
cmake -DUNIX_DOMAIN_SOCKET_CLIENT=YES .. && make -j8
make install # as root
ldconfig # as root

Then you can install lightningcpp :

git clone [email protected]:darosior/lightningcpp.git
cd lightningcpp
make
su -c "make install"

Usage

RPC wrapper

#include <clightningrpc.h>
#include <iostream>
#include <string>

int main (int argc, char *argv[])
{
    CLightningWrapper lightning = CLightningWrapper("/home/darosior/.lightning/lightning-rpc");
    std::cout << lightning.getInfo() << std::endl;
    
    return 0;
}

Plugin

You can write a plugin by whether inheriting the RpcMethod class :

#include <clightningplugin.h>

class Helloworld: public RpcMethod {
public:
    Helloworld(): RpcMethod() {
        name = "hello";
        description = "launch me so that I can greet the world";
    }

    Json::Value main(Json::Value &params) {
        return Json::Value("Hello world !");
    }
};

int main(int argc, char *argv[]) {
    Plugin testPlugin;
    Helloworld helloworld;
    testPlugin.addMethod(helloworld);
    testPlugin.start();

    return 0;
}

Or you can instanciate an RpcMethod object and set the main function :

#include <clightningplugin.h>
#include <string>

int main(int argc, char *argv[]) {
    Plugin testPlugin;
    RpcMethod byeworld("bye", "[name]", "Launch me so I can say bye to someone", "I am a long description");
    byeworld.setMain([&](Json::Value &params) {
        std::string bye = "Bye bye ";
        if (!params.empty())
            return Json::Value(bye + params.asString());
        return Json::Value(bye + "world !");
    });
    testPlugin.addMethod(byeworld);
    testPlugin.start();

    return 0;
}

Options

You can add startup options, for example with the byebye plugin from above :

#include <clightningplugin.h>
#include <string>

int main(int argc, char *argv[]) {
    Plugin testPlugin;
    testPlugin.addOption("byename", "world", "who to say bye to");
    RpcMethod byeworld("bye", "[name]", "Launch me so I can say bye to someone", "A LONG DESC");
    byeworld.setMain([&](Json::Value &params) {
        std::string bye = "Bye bye ";
        if (params.size() == 1)
            return Json::Value(bye + params[0].asString() + " !");
        return Json::Value(bye + testPlugin.getOptionValue("byename").asString() + " !");
    });
    testPlugin.addMethod(byeworld);
    testPlugin.start();

    return 0;
}

You can use addOption() by whether passing it a Json::Value, or the option name, default value, description, and type (which defaults to string and is not passed in the above example).

Notifications

You can subscribe to lightningd's notifications :

#include <clightningplugin.h>
#include <fstream>

class Helloworld: public RpcMethod {
public:
    Helloworld(): RpcMethod() {
        name = "hello";
        description = "launch me so that I can greet the world";
    }

    Json::Value main(Json::Value &params) {
        return Json::Value("Hello world !");
    }
};

void uselessLogger(Json::Value &params) {
    std::ofstream logFile;
    logFile.open("log_file.log", std::ios::app);
    std::string what = params["warning"]["log"].asString();
    logFile << what << std::endl;
    logFile.close();
}

int main(int argc, char *argv[]) {
    Plugin testPlugin;
    Helloworld helloworld;
    testPlugin.addMethod(helloworld);
    testPlugin.subscribe("warning", &uselessLogger);
    testPlugin.start();

    return 0;
}

Hooks

You can subscribe to lightningd's hooks (but be sure of what you are doing) :

#include <clightningplugin.h>
#include <fstream>

class Helloworld: public RpcMethod {
public:
    Helloworld(): RpcMethod() {
        name = "hello";
        description = "launch me so that I can greet the world";
    }

    Json::Value main(Json::Value &params) {
        return Json::Value("Hello world !");
    }
};

Json::Value dbDump(Json::Value &params) {
    std::ofstream logFile;
    logFile.open("db.log", std::ios::app);
    std::string operation = params["writes"][0].asString();
    logFile << operation << std::endl;
    logFile.close();
    return Json::Value(true);
}

int main(int argc, char *argv[]) {
    Plugin testPlugin;
    Helloworld helloworld;
    testPlugin.addMethod(helloworld);
    testPlugin.hookSubscribe("db_write", &dbDump);
    testPlugin.start();

    return 0;
}

Design

Brief

Highly inspired by Christian Decker's pylightning.

Rpc wrapper

The RPC wrapper is just a class (CLightningRpc) with methods wrapping lightningd's API.

Plugin interface

There are 2 classes for the Plugin management : Plugin and RpcMethod. Every RPC method added to lightningd must be an instance of RpcMethod, which is composed of a method's attributes (namely the name, usage, description and long description) and a pointer to the function to be executed when the method is called through lightningd.

This pointer defaults to the main(Json::Value&) function of the same class.
Any method's main function must take a Json::Value object as parameter and return a Json::Value.
You can assign it after instanciation with the setMain() method (as per examples above).

More about C-lightning plugins

You can find more about C-lightning plugins :

Plugins in other languages :

LICENCE

BSD 3-clause clear

lightningcpp's People

Contributors

darosior avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

lightningcpp's Issues

[Question] How set-up personal plugin

Hi @darosior,

I'm playing with the lightningcpp and I have some difficulty to understand how to run your plugin inside the readme.

First all, I noted maybe a refuse inside the readme file. In your first example you used the class called CLightningWrapper but inside the file clightningrpc.h there is only CLightningRpc. With this change, I compiled your example and worked.

In addition, I developed a plugin with your example, my code look like the following code

#include <clightningrpc.h>
#include <clightningplugin.h>
#include <iostream>
#include <string>

class Helloworld: public RpcMethod {
public:
    Helloworld(): RpcMethod() {
        name = "hello";
        description = "launch me so that I can greet the world";
    }

    Json::Value main(Json::Value &params) {
        return Json::Value("Hello world !");
    }
};

void GetInfoFromRpc();
void PersonalPlugin();

int main (int argc, char *argv[])
{
    //GetInfoFromRpc();

    std::cout << "\n---------------- PERSONAL PLUGIN ----------------\n";

    PersonalPlugin();

    return 0;
}

void GetInfoFromRpc(){
    CLightningRpc lightning = CLightningRpc("/lightningcpp/sandbox/sanboxTestWrapperRPC/lightning_dir_one/regtest/lightning-rpc");
    std::cout << lightning.getInfo() << std::endl;
}

void PersonalPlugin(){
    Plugin testPlugin;
    Helloworld helloworld;
    testPlugin.addMethod(helloworld);
    testPlugin.start();
}

I compiled this code and I inserted the executable inside directory ~/.lightningd/plugins, when I ran clightning the execution frozen and it didn't startup (possible loop inside method start?)

I tried also to startup clightining and only after I copied the executable inside the directory, then I called lightning-cli plugin rescan, In conclusion I have the following error

{
   "code": -32602,
   "message": "/lightningcpp/sandbox/sanboxTestWrapperRPC/lightning_dir_one/plugins/CRPCLightning-Demo: Plugin exited before completing handshake."
}

I don't thing is a bug inside the library but it is a my fault, What am I loasing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.