plugin

package
v1.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2023 License: MIT Imports: 13 Imported by: 6

README

Easy c-lightning plugin builder

If you love gjson, hates Go interfaces and want less boilerplate you'll prefer this over https://github.com/niftynei/glightning.

How to make a plugin

A c-lightning plugin is expected to work as a daemon that listens to JSON-RPC commands on stdin and returns responses on stdout. It's kept alive by lightningd for as long as that is alive.

Here you don't have to think about that, just instantiate a p = Plugin{} object, then call p.Run(). Done.

To instantiate your Plugin struct you'll need some values:

  • Name: The plugin name, used on logging.
  • Dynamic: If you want lightningd's plugin start/stop commands to work on this.
  • Options: A list of options the plugin will accept from lightningd initialization. These could be passed either as command-line arguments to lightningdor written at the.lightning/config` file.
  • RPCMethods: A list of RPC methods with names and descriptions and a "usage" string that describes the accepted and required parameters.
  • Subscriptions: A list of subscription
  • Hooks: A list of hook names and handler functions.
  • OnInit: A function to run after the plugin has initialized. It will have access to the plugin struct (as a parameter) and you can do odd stuff here, like start a webserver or just do one-off things.

From inside the functions and handlers you'll have access to a plugin.Plugin struct with Args, the set of options passed to the plugins from lightningd initialization; Log and Logf, basic logging functions that will print a line to the lightningd logs prefixed with your plugin name; and Client, a lightningd-gjson-rpc client you can use to call methods on lightningd.

With the above, the godoc reference and the Plugins docs you'll be able to make any plugin you want.

Example plugin

package main

import "github.com/fiatjaf/lightningd-gjson-rpc/plugin"

func main() {
    p := plugin.Plugin{
        Name: "useless",
        Version: "v1.0"
        Options: []plugin.Option{
            {
                 "payment-adjective",
                 "string",
                 "How do you want your payments to be called.",
            },
        },
        RPCMethods: []plugin.RPCMethod{
            {
                "donothing",
                "arg1 [arg2]",
                "does nothing with {arg1} and optional {arg2}.",
                "",
                func (p *plugin.Plugin, params Params) (interface{}, int, error) {
                    arg1 := params.Get("arg1").String()
                    arg2 := params.Get("arg2").String()

                    if arg2 != "" && arg2 != arg1 {
                        return nil, -1, errors.New("arg2 is not equal to arg1!")
                    }

                    return map[string]interface{}{
                        "arg1": arg1,
                        "arg2": arg2,
                    }, 0, nil
                },
            },
        },
        Subscriptions: []plugin.Subscription{
            {
                "invoice_payment",
                func(p *plugin.Plugin, params plugin.Params) {
                    label := params.Get("invoice_payment.label").String()
                    adjective := p.Args.Get("payment-adjective").String()
                    p.Logf("%s payment received with label %s", adjective, label)
                },
            },
        },
        Hooks: []plugin.Hook{
            {
                "htlc_accepted",
                func(p *plugin.Plugin, params plugin.Params) (resp interface{}) {
                    // hold the invoice just because you want lightning to fail
                    time.Sleep(30 * time.Minute)
                    return map[string]interface{}{"result": "continue"}
                },
            },
        },
        OnInit: func(p *plugin.Plugin) {
            p.Log("already listening for hooks, subscriptions and RPC methods")
        },
    }

    p.Run()
}

Also

We have colored logs!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Features

type Features struct {
	Node    string `json:"features"`
	Channel string `json:"channel"`
	Init    string `json:"init"`
	Invoice string `json:"invoice"`
}

type Hook

type Hook struct {
	Type    string
	Handler HookHandler
}

func (Hook) MarshalJSON

func (h Hook) MarshalJSON() ([]byte, error)

type HookHandler

type HookHandler func(p *Plugin, params Params) (resp interface{})

type LogProxy added in v1.6.2

type LogProxy struct {
	// contains filtered or unexported fields
}

func (*LogProxy) Write added in v1.6.2

func (lp *LogProxy) Write(p []byte) (n int, err error)

type NotificationHandler

type NotificationHandler func(p *Plugin, params Params)

type NotificationTopic added in v1.3.0

type NotificationTopic struct {
	Method string `json:"method"`
}

type Option

type Option struct {
	Name        string      `json:"name"`
	Type        string      `json:"type"`
	Default     interface{} `json:"default"`
	Description string      `json:"description"`
}

type Params

type Params map[string]interface{}

func GetParams

func GetParams(givenParams interface{}, usage string) (params Params, err error)

func (Params) Bool

func (params Params) Bool(key string) (b bool, err error)

func (Params) Float64

func (params Params) Float64(key string) (i float64, err error)

func (Params) Get

func (params Params) Get(path string) gjson.Result

func (Params) Int

func (params Params) Int(key string) (i int, err error)

func (Params) String

func (params Params) String(key string) (s string, err error)

type Plugin

type Plugin struct {
	Client  *lightning.Client            `json:"-"`
	Log     func(...interface{})         `json:"-"`
	Logf    func(string, ...interface{}) `json:"-"`
	Name    string                       `json:"-"`
	Version string                       `json:"-"`
	Network string                       `json:"-"`

	Options       []Option            `json:"options"`
	RPCMethods    []RPCMethod         `json:"rpcmethods"`
	Subscriptions []Subscription      `json:"subscriptions"`
	Hooks         []Hook              `json:"hooks"`
	Features      Features            `json:"featurebits"`
	Dynamic       bool                `json:"dynamic"`
	Notifications []NotificationTopic `json:"notifications"`

	Configuration Params        `json:"-"`
	Args          Params        `json:"-"`
	OnInit        func(*Plugin) `json:"-"`
}

func (*Plugin) Listener

func (p *Plugin) Listener(initialized chan<- bool)

func (*Plugin) Run

func (p *Plugin) Run()

type RPCHandler

type RPCHandler func(p *Plugin, params Params) (resp interface{}, errCode int, err error)

type RPCMethod

type RPCMethod struct {
	Name            string     `json:"name"`
	Usage           string     `json:"usage"`
	Description     string     `json:"description"`
	LongDescription string     `json:"long_description"`
	Handler         RPCHandler `json:"-"`
}

type Subscription

type Subscription struct {
	Type    string
	Handler NotificationHandler
}

func (Subscription) MarshalJSON

func (s Subscription) MarshalJSON() ([]byte, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL