This is a utility that will generate fake BOLT11 invoices in the manner of the c-lightning command line interface. It is stateful in that it will list issued invoices.
The objective is to enable regression/unit testing of application code that is driven by issued, paid and expired invoices.
Once an invoice is issued, the time can be 'advanced' with the advancetimestamp
command such that invoices are appropriately treated as 'expired' without having to wait.
Also, an invoice can be marked paid with the markpaid
command and they will be subsequently listed as paid.
This is a very simple implementation, more fleshed-out feature are easy to imagine, but this is the minimal necessary for my app's needs at present.
$ ./mock_c_lightning.py -h
usage: mock_c_lightning.py [-h]
{invoice,listinvoices,autocleaninvoice,delinvoice,markpaid,advancetime,reset}
...
mock c-lightning
positional arguments:
{invoice,listinvoices,autocleaninvoice,delinvoice,markpaid,advancetime,reset}
sub-command help
invoice Create an invoice for {msatoshi} with {label} and
{description} with optional {expiry} seconds (default
1 hour) and optional {preimage} (default
autogenerated)
listinvoices list all invoices
autocleaninvoice autocleaninvoice help
delinvoice Delete invoice {label} with {status}
markpaid mark invoice as paid
advancetime advance the system clock to make invoices expire
sooner
reset reset the invoice state
optional arguments:
-h, --help show this help message and exit
Note - this is far from an exact replica of lightning-cli
$ ./mock_c_lightning.py listinvoices
[]
$ ./mock_c_lightning.py invoice 1000 myLabel1 "my description of the first invoice" 3600 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03
{
"bolt11": "lnbc10n1pduy53dpp5ajm9hwv0nkg9kuz93xrv887t44m3te0jlnpmrurhvltus03y8rxqdpcd4ujqer9wd3hy6tsw35k7m3qdanzqargv5sxv6tjwd6zq6twwehkjcm9xqrrssdnllrzc0mr0h3qay2knvxes2h23vjhq3vl4yld5zynmcsdlk2ms8lh78wvu656k7x63626ttpqjwuzzp3lsy7n5acakqa5t4ln4293qqud8wus",
"expires_at": 1539465277,
"expiry_time": 1539465277,
"payment_hash": "ecb65bb98f9d905b70458986c39fcbad7715e5f2fcc3b1f07767d7c83e2438cc"
}
$ ./mock_c_lightning.py invoice 1000 myLabel2 "my description of the second invoice" 3600 e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317
{
"bolt11": "lnbc10n1pduy5jlpp5ms986sz8auale8e2smwzwrnwvl9h5wnuqudvah6cnyuz7czq6yrqdp6d4ujqer9wd3hy6tsw35k7m3qdanzqargv5s8xetrdahxggrfdemx76trv5xqrrss6yh8s99j8ze9s6p9aqv2gwmv9pm26mdeq8waf7a3xjx2728zyjt9jjk8znxksuwglvzf9pyn3vjp820m7ncguztfjleeum6gcd8satgqqnpaxt",
"expires_at": 1539465327,
"expiry_time": 1539465327,
"payment_hash": "dc0a7d4047ef3bfc9f2a86dc270e6e67cb7a3a7c071acedf5899382f6040d106"
}
$ ./mock_c_lightning.py listinvoices
[
{
"bolt11": "lnbc10n1pduy53dpp5ajm9hwv0nkg9kuz93xrv887t44m3te0jlnpmrurhvltus03y8rxqdpcd4ujqer9wd3hy6tsw35k7m3qdanzqargv5sxv6tjwd6zq6twwehkjcm9xqrrssdnllrzc0mr0h3qay2knvxes2h23vjhq3vl4yld5zynmcsdlk2ms8lh78wvu656k7x63626ttpqjwuzzp3lsy7n5acakqa5t4ln4293qqud8wus",
"expires_at": 1539465277,
"expiry_time": 1539465277,
"label": "myLabel1",
"msatoshi": 1000,
"payment_hash": "ecb65bb98f9d905b70458986c39fcbad7715e5f2fcc3b1f07767d7c83e2438cc",
"status": "unpaid"
},
{
"bolt11": "lnbc10n1pduy5jlpp5ms986sz8auale8e2smwzwrnwvl9h5wnuqudvah6cnyuz7czq6yrqdp6d4ujqer9wd3hy6tsw35k7m3qdanzqargv5s8xetrdahxggrfdemx76trv5xqrrss6yh8s99j8ze9s6p9aqv2gwmv9pm26mdeq8waf7a3xjx2728zyjt9jjk8znxksuwglvzf9pyn3vjp820m7ncguztfjleeum6gcd8satgqqnpaxt",
"expires_at": 1539465327,
"expiry_time": 1539465327,
"label": "myLabel2",
"msatoshi": 1000,
"payment_hash": "dc0a7d4047ef3bfc9f2a86dc270e6e67cb7a3a7c071acedf5899382f6040d106",
"status": "unpaid"
}
]
$ ./mock_c_lightning.py markpaid myLabel2
$ ./mock_c_lightning.py advancetime 10000
$ ./mock_c_lightning.py listinvoices
[
{
"bolt11": "lnbc10n1pduy53dpp5ajm9hwv0nkg9kuz93xrv887t44m3te0jlnpmrurhvltus03y8rxqdpcd4ujqer9wd3hy6tsw35k7m3qdanzqargv5sxv6tjwd6zq6twwehkjcm9xqrrssdnllrzc0mr0h3qay2knvxes2h23vjhq3vl4yld5zynmcsdlk2ms8lh78wvu656k7x63626ttpqjwuzzp3lsy7n5acakqa5t4ln4293qqud8wus",
"expires_at": 1539465277,
"expiry_time": 1539465277,
"label": "myLabel1",
"msatoshi": 1000,
"payment_hash": "ecb65bb98f9d905b70458986c39fcbad7715e5f2fcc3b1f07767d7c83e2438cc",
"status": "expired"
},
{
"bolt11": "lnbc10n1pduy5jlpp5ms986sz8auale8e2smwzwrnwvl9h5wnuqudvah6cnyuz7czq6yrqdp6d4ujqer9wd3hy6tsw35k7m3qdanzqargv5s8xetrdahxggrfdemx76trv5xqrrss6yh8s99j8ze9s6p9aqv2gwmv9pm26mdeq8waf7a3xjx2728zyjt9jjk8znxksuwglvzf9pyn3vjp820m7ncguztfjleeum6gcd8satgqqnpaxt",
"expires_at": 1539465327,
"expiry_time": 1539465327,
"label": "myLabel2",
"msatoshi": 1000,
"msatoshi_recieved": 1033,
"paid_at": 1539461783,
"paid_timestamp": 1539461783,
"pay_index": 1,
"payment_hash": "dc0a7d4047ef3bfc9f2a86dc270e6e67cb7a3a7c071acedf5899382f6040d106",
"status": "paid"
}
]
$ ./mock_c_lightning.py delinvoice myLabel1 expired
$ ./mock_c_lightning.py delinvoice myLabel2 paid
$ ./mock_c_lightning.py listinvoices
[]
The module daemon.py provides example classes CliMockDaemon
, MemMockDaemon
and RealDaemon
that illustrate how this can be integrated into a program. Each implement the interface of the Daemon
superclass.
This interfaces with this utility via a subprocess shell-out. This is good for observing the state of the daemon on your own, but has the overhead of shelling out to the console and reading/writing from an on-disk JSON database, so it can be slower than MemMockDaemon
This instantiates the mock daemon and database as an in-memory object. This is faster for doing many invoices quickly (such as in a rapid-fire unit test), but doesn't provide a CLI interface for checking up on it.
This interfaces with the real c-lightning
daemon via the pylightning module that uses the RPC port.
This app uses code from https://github.com/rustyrussell/lightning-payencode to encode BOLT11 invoices, and hence has the same dependencies to be installed via pip3
.
None yet, but mainly because lightining-payencode
is not yet licensed. The intention is to follow along with what is chosen for that project. FWIW, The author of this project prefers MIT licences for this type of thing.