Merge branch 'recurring-donations'
This commit is contained in:
commit
d0df130c11
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,18 @@
|
||||||
# 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. This is EXPERIMENTAL; it's
|
||||||
|
# not guaranteed that payments are succeeding or that you will notice payment
|
||||||
|
# failure. 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";
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
108
modules/recurring-donations.nix
Normal file
108
modules/recurring-donations.nix
Normal 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 -8)
|
||||||
|
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" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user