Add recurring donations module

This commit is contained in:
Jonas Nick 2019-04-14 16:55:40 +00:00
parent c934285ef9
commit 492eab0e26
No known key found for this signature in database
GPG Key ID: 4861DBF262123605
5 changed files with 122 additions and 0 deletions

View File

@ -39,6 +39,7 @@ In `configuration.nix` the user can enable:
* an index page using nginx to display node information and link to nanopos * an index page using nginx to display node information and link to nanopos
* [spark-wallet](https://github.com/shesek/spark-wallet) * [spark-wallet](https://github.com/shesek/spark-wallet)
* [electrs](https://github.com/romanz/electrs) * [electrs](https://github.com/romanz/electrs)
* recurring-donations, a module to repeatedly send lightning payments to recipients specified in the configuration.
The data directories of the services can be found in `/var/lib` on the deployed machines. The data directories of the services can be found in `/var/lib` on the deployed machines.

View File

@ -58,6 +58,17 @@
# this if clightning, lightning-charge, and nanopos are enabled. # this if clightning, lightning-charge, and nanopos are enabled.
# services.nix-bitcoin-webindex.enable = true; # services.nix-bitcoin-webindex.enable = true;
### RECURRING-DONATIONS
# Enable this module to send recurring donations. Only enable this if
# clightning is enabled.
# services.recurring-donations.enable = true;
# Specify the receivers of the donations. By default donations are every
# Monday at a randomized time.
# services.recurring-donations.tallycoin = {
# "djbooth007" = 1000;
# "hillebrandmax" = 1000;
# };
# FIXME: Define your hostname. # FIXME: Define your hostname.
networking.hostName = "nix-bitcoin"; networking.hostName = "nix-bitcoin";
time.timeZone = "UTC"; time.timeZone = "UTC";

View File

@ -10,4 +10,5 @@
nix-bitcoin-pkgs = ./nix-bitcoin-pkgs.nix; nix-bitcoin-pkgs = ./nix-bitcoin-pkgs.nix;
nix-bitcoin-webindex = ./nix-bitcoin-webindex.nix; nix-bitcoin-webindex = ./nix-bitcoin-webindex.nix;
spark-wallet = ./spark-wallet.nix; spark-wallet = ./spark-wallet.nix;
recurring-donations = ./recurring-donations.nix
} }

View File

@ -26,6 +26,7 @@ in {
./spark-wallet.nix ./spark-wallet.nix
./electrs.nix ./electrs.nix
./onion-chef.nix ./onion-chef.nix
./recurring-donations.nix
]; ];
options.services.nix-bitcoin = { options.services.nix-bitcoin = {

View File

@ -0,0 +1,108 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.recurring-donations;
recurring-donations-script = pkgs.writeScript "recurring-donations.sh" ''
LNCLI="lightning-cli --lightning-dir=${config.services.clightning.dataDir}"
pay_tallycoin() {
NAME=$1
AMOUNT=$2
echo Attempting to pay $AMOUNT sat to $NAME
INVOICE=$(torsocks curl -d "satoshi_amount=$AMOUNT&payment_method=ln&id=$NAME&type=profile" -X POST https://api.tallyco.in/v1/payment/request/ | jq -r '.lightning_pay_request') 2> /dev/null
if [ -z "$INVOICE" ] || [ "$INVOICE" = "null" ]; then
echo "ERROR: did not get invoice from tallycoin"
return
fi
# Decode invoice and compare amount with requested amount
DECODED_AMOUNT=$($LNCLI decodepay "$INVOICE" | jq -r '.amount_msat' | head -c 4)
if [ -z "$DECODED_AMOUNT" ] || [ "$DECODED_AMOUNT" = "null" ]; then
echo "ERROR: did not get response from clightning"
return
fi
if [ $DECODED_AMOUNT -eq $AMOUNT ]; then
echo Paying with invoice "$INVOICE"
$LNCLI pay "$INVOICE"
else
echo ERROR: requested amount and invoice amount do not match. $AMOUNT vs $DECODED_AMOUNT
return
fi
}
${ builtins.foldl'
(x: receiver: x +
''
pay_tallycoin ${receiver} ${toString (builtins.getAttr receiver cfg.tallycoin)}
'')
""
(builtins.attrNames cfg.tallycoin)
}
'';
in {
options.services.recurring-donations = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, the recurring-donations service will be installed.
'';
};
tallycoin = mkOption {
type = types.attrs;
default = {};
description = ''
This option is used to specify tallycoin donation receivers using an
attribute set. For example the following setting instructs the module
to repeatedly send 1000 satoshis to djbooth007.
{
"djbooth007" = 1000;
}
'';
};
interval = mkOption {
type = types.string;
default = "Mon *-*-* 00:00:00";
description = ''
Schedules the donations. Default is weekly on Mon 00:00:00. See `man
systemd.time` for further options.
'';
};
randomizedDelaySec = mkOption {
type = types.int;
default = 86400;
description = ''
Random delay to add to scheduled time for donation. Default is one day.
'';
};
};
config = mkIf cfg.enable {
systemd.services.recurring-donations = {
description = "Run recurring-donations";
requires = [ "clightning.service" ];
after = [ "clightning.service" ];
path = [ pkgs.clightning pkgs.curl pkgs.torsocks pkgs.sudo pkgs.jq ];
serviceConfig = {
ExecStart = "${pkgs.bash}/bin/bash ${recurring-donations-script}";
# TODO: would be better if this was operator, but I don't get sudo
# working inside the shell script
User = "clightning";
Type = "oneshot";
PrivateTmp = "true";
ProtectSystem = "full";
NoNewPrivileges = "true";
PrivateDevices = "true";
};
};
systemd.timers.recurring-donations = {
requires = [ "clightning.service" ];
after = [ "clightning.service" ];
timerConfig = {
Unit = "recurring-donations.service";
OnCalendar = cfg.interval;
RandomizedDelaySec = toString cfg.randomizedDelaySec;
};
wantedBy = [ "multi-user.target" ];
};
};
}