create db/lnd/email packages

This commit is contained in:
Peter Rounce 2023-02-18 14:14:57 +00:00
parent 6153edd0c3
commit 9545e5bd4e
12 changed files with 255 additions and 736 deletions

View file

@ -1,4 +1,4 @@
package main package db
import ( import (
"database/sql" "database/sql"
@ -8,45 +8,45 @@ import (
"os" "os"
) )
type card struct { type Card struct {
card_id int Card_id int
card_guid string Card_guid string
k0_auth_key string K0_auth_key string
k1_decrypt_key string K1_decrypt_key string
k2_cmac_key string K2_cmac_key string
k3 string K3 string
k4 string K4 string
db_uid string Db_uid string
last_counter_value uint32 Last_counter_value uint32
lnurlw_request_timeout_sec int Lnurlw_request_timeout_sec int
lnurlw_enable string Lnurlw_enable string
tx_limit_sats int Tx_limit_sats int
day_limit_sats int Day_limit_sats int
lnurlp_enable string Lnurlp_enable string
email_address string Email_address string
email_enable string Email_enable string
uid_privacy string Uid_privacy string
one_time_code string One_time_code string
card_name string Card_name string
allow_negative_balance string Allow_negative_balance string
} }
type payment struct { type Payment struct {
card_payment_id int Card_payment_id int
card_id int Card_id int
lnurlw_k1 string Lnurlw_k1 string
paid_flag string Paid_flag string
} }
type transaction struct { type Transaction struct {
card_id int Card_id int
tx_id int Tx_id int
tx_type string Tx_type string
tx_amount_msats int Tx_amount_msats int
tx_time string Tx_time string
} }
func db_open() (*sql.DB, error) { func open() (*sql.DB, error) {
// get connection string from environment variables // get connection string from environment variables
@ -65,11 +65,11 @@ func db_open() (*sql.DB, error) {
return db, nil return db, nil
} }
func db_get_setting(setting_name string) string { func Get_setting(setting_name string) string {
setting_value := "" setting_value := ""
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return "" return ""
} }
@ -86,11 +86,11 @@ func db_get_setting(setting_name string) string {
return setting_value return setting_value
} }
func db_get_new_card(one_time_code string) (*card, error) { func Get_new_card(one_time_code string) (*Card, error) {
c := card{} c := Card{}
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -101,12 +101,12 @@ func db_get_new_card(one_time_code string) (*card, error) {
` one_time_code_expiry > NOW() AND one_time_code_used = 'N' AND wiped = 'N';` ` one_time_code_expiry > NOW() AND one_time_code_used = 'N' AND wiped = 'N';`
row := db.QueryRow(sqlStatement, one_time_code) row := db.QueryRow(sqlStatement, one_time_code)
err = row.Scan( err = row.Scan(
&c.k0_auth_key, &c.K0_auth_key,
&c.k2_cmac_key, &c.K2_cmac_key,
&c.k3, &c.K3,
&c.k4, &c.K4,
&c.card_name, &c.Card_name,
&c.uid_privacy) &c.Uid_privacy)
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -120,11 +120,11 @@ func db_get_new_card(one_time_code string) (*card, error) {
return &c, nil return &c, nil
} }
func db_get_card_count_for_uid(uid string) (int, error) { func Get_card_count_for_uid(uid string) (int, error) {
card_count := 0 card_count := 0
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -141,11 +141,11 @@ func db_get_card_count_for_uid(uid string) (int, error) {
return card_count, nil return card_count, nil
} }
func db_get_card_count_for_name_lnurlp(name string) (int, error) { func Get_card_count_for_name_lnurlp(name string) (int, error) {
card_count := 0 card_count := 0
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -162,11 +162,11 @@ func db_get_card_count_for_name_lnurlp(name string) (int, error) {
return card_count, nil return card_count, nil
} }
func db_get_card_id_for_name(name string) (int, error) { func Get_card_id_for_name(name string) (int, error) {
card_id := 0 card_id := 0
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -183,10 +183,10 @@ func db_get_card_id_for_name(name string) (int, error) {
return card_id, nil return card_id, nil
} }
func db_get_card_id_for_card_payment_id(card_payment_id int) (int, error) { func Get_card_id_for_card_payment_id(card_payment_id int) (int, error) {
card_id := 0 card_id := 0
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -203,10 +203,10 @@ func db_get_card_id_for_card_payment_id(card_payment_id int) (int, error) {
return card_id, nil return card_id, nil
} }
func db_get_card_id_for_r_hash(r_hash string) (int, error) { func Get_card_id_for_r_hash(r_hash string) (int, error) {
card_id := 0 card_id := 0
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -223,11 +223,11 @@ func db_get_card_id_for_r_hash(r_hash string) (int, error) {
return card_id, nil return card_id, nil
} }
func db_get_cards_blank_uid() ([]card, error) { func Get_cards_blank_uid() ([]Card, error) {
// open the database // open the database
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return nil, err return nil, err
@ -249,12 +249,12 @@ func db_get_cards_blank_uid() ([]card, error) {
// prepare the results // prepare the results
var cards []card var cards []Card
// Loop through rows, using Scan to assign column data to struct fields. // Loop through rows, using Scan to assign column data to struct fields.
for rows.Next() { for rows.Next() {
var c card var c Card
err := rows.Scan(&c.card_id, &c.k2_cmac_key) err := rows.Scan(&c.Card_id, &c.K2_cmac_key)
if err != nil { if err != nil {
return cards, err return cards, err
@ -271,8 +271,8 @@ func db_get_cards_blank_uid() ([]card, error) {
return cards, nil return cards, nil
} }
func db_update_card_uid_ctr(card_id int, uid string, ctr uint32) error { func Update_card_uid_ctr(card_id int, uid string, ctr uint32) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -294,11 +294,11 @@ func db_update_card_uid_ctr(card_id int, uid string, ctr uint32) error {
return nil return nil
} }
func db_get_card_from_uid(card_uid string) (*card, error) { func Get_card_from_uid(card_uid string) (*Card, error) {
c := card{} c := Card{}
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -310,14 +310,14 @@ func db_get_card_from_uid(card_uid string) (*card, error) {
` FROM cards WHERE uid=$1 AND wiped='N';` ` FROM cards WHERE uid=$1 AND wiped='N';`
row := db.QueryRow(sqlStatement, card_uid) row := db.QueryRow(sqlStatement, card_uid)
err = row.Scan( err = row.Scan(
&c.card_id, &c.Card_id,
&c.k2_cmac_key, &c.K2_cmac_key,
&c.db_uid, &c.Db_uid,
&c.last_counter_value, &c.Last_counter_value,
&c.lnurlw_request_timeout_sec, &c.Lnurlw_request_timeout_sec,
&c.lnurlw_enable, &c.Lnurlw_enable,
&c.tx_limit_sats, &c.Tx_limit_sats,
&c.day_limit_sats) &c.Day_limit_sats)
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -325,11 +325,11 @@ func db_get_card_from_uid(card_uid string) (*card, error) {
return &c, nil return &c, nil
} }
func db_get_card_from_card_id(card_id int) (*card, error) { func Get_card_from_card_id(card_id int) (*Card, error) {
c := card{} c := Card{}
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -342,18 +342,18 @@ func db_get_card_from_card_id(card_id int) (*card, error) {
`allow_negative_balance FROM cards WHERE card_id=$1;` `allow_negative_balance FROM cards WHERE card_id=$1;`
row := db.QueryRow(sqlStatement, card_id) row := db.QueryRow(sqlStatement, card_id)
err = row.Scan( err = row.Scan(
&c.card_id, &c.Card_id,
&c.k2_cmac_key, &c.K2_cmac_key,
&c.db_uid, &c.Db_uid,
&c.last_counter_value, &c.Last_counter_value,
&c.lnurlw_request_timeout_sec, &c.Lnurlw_request_timeout_sec,
&c.lnurlw_enable, &c.Lnurlw_enable,
&c.tx_limit_sats, &c.Tx_limit_sats,
&c.day_limit_sats, &c.Day_limit_sats,
&c.email_enable, &c.Email_enable,
&c.email_address, &c.Email_address,
&c.card_name, &c.Card_name,
&c.allow_negative_balance) &c.Allow_negative_balance)
if err != nil { if err != nil {
return &c, err return &c, err
} }
@ -361,9 +361,9 @@ func db_get_card_from_card_id(card_id int) (*card, error) {
return &c, nil return &c, nil
} }
func db_check_lnurlw_timeout(card_payment_id int) (bool, error) { func Check_lnurlw_timeout(card_payment_id int) (bool, error) {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return true, err return true, err
} }
@ -383,9 +383,9 @@ func db_check_lnurlw_timeout(card_payment_id int) (bool, error) {
return lnurlw_timeout, nil return lnurlw_timeout, nil
} }
func db_check_and_update_counter(card_id int, new_counter_value uint32) (bool, error) { func Check_and_update_counter(card_id int, new_counter_value uint32) (bool, error) {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return false, err return false, err
} }
@ -408,9 +408,9 @@ func db_check_and_update_counter(card_id int, new_counter_value uint32) (bool, e
return true, nil return true, nil
} }
func db_insert_payment(card_id int, lnurlw_k1 string) error { func Insert_payment(card_id int, lnurlw_k1 string) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -436,13 +436,13 @@ func db_insert_payment(card_id int, lnurlw_k1 string) error {
return nil return nil
} }
func db_insert_receipt( func Insert_receipt(
card_id int, card_id int,
ln_invoice string, ln_invoice string,
r_hash_hex string, r_hash_hex string,
amount_msat int64) error { amount_msat int64) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -468,8 +468,8 @@ func db_insert_receipt(
return nil return nil
} }
func db_update_receipt_state(r_hash_hex string, invoice_state string) error { func Update_receipt_state(r_hash_hex string, invoice_state string) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -493,10 +493,10 @@ func db_update_receipt_state(r_hash_hex string, invoice_state string) error {
return nil return nil
} }
func db_get_payment_k1(lnurlw_k1 string) (*payment, error) { func Get_payment_k1(lnurlw_k1 string) (*Payment, error) {
p := payment{} p := Payment{}
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return &p, err return &p, err
} }
@ -506,9 +506,9 @@ func db_get_payment_k1(lnurlw_k1 string) (*payment, error) {
` FROM card_payments WHERE lnurlw_k1=$1;` ` FROM card_payments WHERE lnurlw_k1=$1;`
row := db.QueryRow(sqlStatement, lnurlw_k1) row := db.QueryRow(sqlStatement, lnurlw_k1)
err = row.Scan( err = row.Scan(
&p.card_payment_id, &p.Card_payment_id,
&p.card_id, &p.Card_id,
&p.paid_flag) &p.Paid_flag)
if err != nil { if err != nil {
return &p, err return &p, err
} }
@ -516,9 +516,9 @@ func db_get_payment_k1(lnurlw_k1 string) (*payment, error) {
return &p, nil return &p, nil
} }
func db_update_payment_invoice(card_payment_id int, ln_invoice string, amount_msats int64) error { func Update_payment_invoice(card_payment_id int, ln_invoice string, amount_msats int64) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -540,9 +540,9 @@ func db_update_payment_invoice(card_payment_id int, ln_invoice string, amount_ms
return nil return nil
} }
func db_update_payment_paid(card_payment_id int) error { func Update_payment_paid(card_payment_id int) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
} }
@ -564,9 +564,9 @@ func db_update_payment_paid(card_payment_id int) error {
return nil return nil
} }
func db_update_payment_status(card_payment_id int, payment_status string, failure_reason string) error { func Update_payment_status(card_payment_id int, payment_status string, failure_reason string) error {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return err return err
@ -596,9 +596,9 @@ func db_update_payment_status(card_payment_id int, payment_status string, failur
return nil return nil
} }
func db_get_card_totals(card_id int) (int, error) { func Get_card_totals(card_id int) (int, error) {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -620,10 +620,10 @@ func db_get_card_totals(card_id int) (int, error) {
return day_total_sats, nil return day_total_sats, nil
} }
func db_get_card_txs(card_id int, max_txs int) ([]transaction, error) { func Get_card_txs(card_id int, max_txs int) ([]Transaction, error) {
// open the database // open the database
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return nil, err return nil, err
@ -655,12 +655,12 @@ func db_get_card_txs(card_id int, max_txs int) ([]transaction, error) {
// prepare the results // prepare the results
var transactions []transaction var transactions []Transaction
// Loop through rows, using Scan to assign column data to struct fields. // Loop through rows, using Scan to assign column data to struct fields.
for rows.Next() { for rows.Next() {
var t transaction var t Transaction
err := rows.Scan(&t.card_id, &t.tx_id, &t.tx_type, &t.tx_amount_msats, &t.tx_time) err := rows.Scan(&t.Card_id, &t.Tx_id, &t.Tx_type, &t.Tx_amount_msats, &t.Tx_time)
if err != nil { if err != nil {
return transactions, err return transactions, err
@ -677,9 +677,9 @@ func db_get_card_txs(card_id int, max_txs int) ([]transaction, error) {
return transactions, nil return transactions, nil
} }
func db_get_card_total_sats(card_id int) (int, error) { func Get_card_total_sats(card_id int) (int, error) {
db, err := db_open() db, err := open()
if err != nil { if err != nil {
return 0, err return 0, err
} }

View file

@ -1,4 +1,4 @@
package main package email
import ( import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -9,35 +9,36 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"strconv" "strconv"
"strings" "strings"
"github.com/boltcard/boltcard/db"
) )
func send_balance_email(recipient_email string, card_id int) { func Send_balance_email(recipient_email string, card_id int) {
c, err := db_get_card_from_card_id(card_id) c, err := db.Get_card_from_card_id(card_id)
if err != nil { if err != nil {
log.Warn(err.Error()) log.Warn(err.Error())
return return
} }
card_total_sats, err := db_get_card_total_sats(card_id) card_total_sats, err := db.Get_card_total_sats(card_id)
if err != nil { if err != nil {
log.Warn(err.Error()) log.Warn(err.Error())
return return
} }
email_max_txs, err := strconv.Atoi(db_get_setting("EMAIL_MAX_TXS")) email_max_txs, err := strconv.Atoi(db.Get_setting("EMAIL_MAX_TXS"))
if err != nil { if err != nil {
log.Warn(err.Error()) log.Warn(err.Error())
return return
} }
txs, err := db_get_card_txs(card_id, email_max_txs+1) txs, err := db.Get_card_txs(card_id, email_max_txs+1)
if err != nil { if err != nil {
log.Warn(err.Error()) log.Warn(err.Error())
return return
} }
subject := c.card_name + " balance = " + strconv.Itoa(card_total_sats) + " sats" subject := c.Card_name + " balance = " + strconv.Itoa(card_total_sats) + " sats"
// add transactions to the email body // add transactions to the email body
@ -56,9 +57,9 @@ func send_balance_email(recipient_email string, card_id int) {
if i < email_max_txs { if i < email_max_txs {
html_body_sb.WriteString( html_body_sb.WriteString(
"<tr>" + "<tr>" +
"<td>" + tx.tx_time + "</td>" + "<td>" + tx.Tx_time + "</td>" +
"<td>" + tx.tx_type + "</td>" + "<td>" + tx.Tx_type + "</td>" +
"<td style='text-align:right'>" + strconv.Itoa(tx.tx_amount_msats/1000) + "</td>" + "<td style='text-align:right'>" + strconv.Itoa(tx.Tx_amount_msats/1000) + "</td>" +
"</tr>") "</tr>")
} else { } else {
html_body_sb.WriteString( html_body_sb.WriteString(
@ -69,8 +70,8 @@ func send_balance_email(recipient_email string, card_id int) {
"</tr>") "</tr>")
} }
text_body_sb.WriteString(tx.tx_type + text_body_sb.WriteString(tx.Tx_type +
" " + strconv.Itoa(tx.tx_amount_msats/1000)) " " + strconv.Itoa(tx.Tx_amount_msats/1000))
} }
html_body_sb.WriteString("</table></body></html>") html_body_sb.WriteString("</table></body></html>")
@ -78,7 +79,7 @@ func send_balance_email(recipient_email string, card_id int) {
html_body := html_body_sb.String() html_body := html_body_sb.String()
text_body := text_body_sb.String() text_body := text_body_sb.String()
send_email(recipient_email, Send_email(recipient_email,
subject, subject,
html_body, html_body,
text_body) text_body)
@ -86,11 +87,11 @@ func send_balance_email(recipient_email string, card_id int) {
// https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/ses-example-send-email.html // https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/ses-example-send-email.html
func send_email(recipient string, subject string, htmlBody string, textBody string) { func Send_email(recipient string, subject string, htmlBody string, textBody string) {
aws_ses_id := db_get_setting("AWS_SES_ID") aws_ses_id := db.Get_setting("AWS_SES_ID")
aws_ses_secret := db_get_setting("AWS_SES_SECRET") aws_ses_secret := db.Get_setting("AWS_SES_SECRET")
sender := db_get_setting("AWS_SES_EMAIL_FROM") sender := db.Get_setting("AWS_SES_EMAIL_FROM")
sess, err := session.NewSession(&aws.Config{ sess, err := session.NewSession(&aws.Config{
Region: aws.String("us-east-1"), Region: aws.String("us-east-1"),

20
go.mod
View file

@ -16,9 +16,10 @@ require (
) )
require ( require (
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/siphash v1.0.1 // indirect github.com/aead/siphash v1.0.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd v0.23.4 // indirect github.com/btcsuite/btcd v0.23.4 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
@ -26,7 +27,6 @@ require (
github.com/btcsuite/btcd/btcutil/psbt v1.1.6 // indirect github.com/btcsuite/btcd/btcutil/psbt v1.1.6 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/btcsuite/btcutil v1.0.2 // indirect
github.com/btcsuite/btcwallet v0.16.4 // indirect github.com/btcsuite/btcwallet v0.16.4 // indirect
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect
github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect
@ -44,7 +44,6 @@ require (
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/decred/dcrd/lru v1.1.1 // indirect github.com/decred/dcrd/lru v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect
github.com/dvyukov/go-fuzz v0.0.0-20220726122315-1d375ef9f9f6 // indirect github.com/dvyukov/go-fuzz v0.0.0-20220726122315-1d375ef9f9f6 // indirect
github.com/fergusstrange/embedded-postgres v1.19.0 // indirect github.com/fergusstrange/embedded-postgres v1.19.0 // indirect
@ -75,10 +74,7 @@ require (
github.com/jonboulle/clockwork v0.3.0 // indirect github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/jrick/logrotate v1.0.0 // indirect github.com/jrick/logrotate v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/loggo v1.0.0 // indirect
github.com/kkdai/bstream v1.0.0 // indirect github.com/kkdai/bstream v1.0.0 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect
github.com/lightninglabs/neutrino v0.14.2 // indirect github.com/lightninglabs/neutrino v0.14.2 // indirect
github.com/lightningnetwork/lightning-onion v1.2.0 // indirect github.com/lightningnetwork/lightning-onion v1.2.0 // indirect
@ -89,15 +85,11 @@ require (
github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect
github.com/lightningnetwork/lnd/tlv v1.0.3 // indirect github.com/lightningnetwork/lnd/tlv v1.0.3 // indirect
github.com/lightningnetwork/lnd/tor v1.1.0 // indirect github.com/lightningnetwork/lnd/tor v1.1.0 // indirect
github.com/lncm/lnd-rpc v1.0.2 // indirect
github.com/ltcsuite/ltcd v0.22.1-beta // indirect github.com/ltcsuite/ltcd v0.22.1-beta // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mholt/archiver/v3 v3.5.1 // indirect
github.com/miekg/dns v1.1.50 // indirect github.com/miekg/dns v1.1.50 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
@ -110,7 +102,6 @@ require (
github.com/stretchr/testify v1.8.1 // indirect github.com/stretchr/testify v1.8.1 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/bbolt v1.3.6 // indirect
@ -121,18 +112,12 @@ require (
go.etcd.io/etcd/pkg/v3 v3.5.5 // indirect go.etcd.io/etcd/pkg/v3 v3.5.5 // indirect
go.etcd.io/etcd/raft/v3 v3.5.5 // indirect go.etcd.io/etcd/raft/v3 v3.5.5 // indirect
go.etcd.io/etcd/server/v3 v3.5.5 // indirect go.etcd.io/etcd/server/v3 v3.5.5 // indirect
go.opentelemetry.io/contrib v1.9.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.4 // indirect
go.opentelemetry.io/otel v1.11.1 // indirect go.opentelemetry.io/otel v1.11.1 // indirect
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 // indirect
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
go.opentelemetry.io/otel/metric v0.33.0 // indirect
go.opentelemetry.io/otel/sdk v1.11.1 // indirect go.opentelemetry.io/otel/sdk v1.11.1 // indirect
go.opentelemetry.io/otel/sdk/export/metric v0.28.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.33.0 // indirect
go.opentelemetry.io/otel/trace v1.11.1 // indirect go.opentelemetry.io/otel/trace v1.11.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
@ -146,7 +131,6 @@ require (
golang.org/x/text v0.4.0 // indirect golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.2.0 // indirect golang.org/x/time v0.2.0 // indirect
golang.org/x/tools v0.3.0 // indirect golang.org/x/tools v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/errgo.v1 v1.0.1 // indirect gopkg.in/errgo.v1 v1.0.1 // indirect

487
go.sum

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
package main package lnd
import ( import (
"context" "context"
@ -20,6 +20,9 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"gopkg.in/macaroon.v2" "gopkg.in/macaroon.v2"
"github.com/boltcard/boltcard/db"
"github.com/boltcard/boltcard/email"
) )
type rpcCreds map[string]string type rpcCreds map[string]string
@ -72,9 +75,9 @@ func getGrpcConn(hostname string, port int, tlsFile, macaroonFile string) *grpc.
// https://api.lightning.community/?shell#addinvoice // https://api.lightning.community/?shell#addinvoice
func add_invoice(amount_sat int64, metadata string) (payment_request string, r_hash []byte, return_err error) { func Add_invoice(amount_sat int64, metadata string) (payment_request string, r_hash []byte, return_err error) {
ln_port, err := strconv.Atoi(db_get_setting("LN_PORT")) ln_port, err := strconv.Atoi(db.Get_setting("LN_PORT"))
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
@ -82,10 +85,10 @@ func add_invoice(amount_sat int64, metadata string) (payment_request string, r_h
dh := sha256.Sum256([]byte(metadata)) dh := sha256.Sum256([]byte(metadata))
connection := getGrpcConn( connection := getGrpcConn(
db_get_setting("LN_HOST"), db.Get_setting("LN_HOST"),
ln_port, ln_port,
db_get_setting("LN_TLS_FILE"), db.Get_setting("LN_TLS_FILE"),
db_get_setting("LN_MACAROON_FILE")) db.Get_setting("LN_MACAROON_FILE"))
l_client := lnrpc.NewLightningClient(connection) l_client := lnrpc.NewLightningClient(connection)
@ -106,23 +109,23 @@ func add_invoice(amount_sat int64, metadata string) (payment_request string, r_h
// https://api.lightning.community/?shell#subscribesingleinvoice // https://api.lightning.community/?shell#subscribesingleinvoice
func monitor_invoice_state(r_hash []byte) { func Monitor_invoice_state(r_hash []byte) {
// SubscribeSingleInvoice // SubscribeSingleInvoice
// get node parameters from environment variables // get node parameters from environment variables
ln_port, err := strconv.Atoi(db_get_setting("LN_PORT")) ln_port, err := strconv.Atoi(db.Get_setting("LN_PORT"))
if err != nil { if err != nil {
log.Warn(err) log.Warn(err)
return return
} }
connection := getGrpcConn( connection := getGrpcConn(
db_get_setting("LN_HOST"), db.Get_setting("LN_HOST"),
ln_port, ln_port,
db_get_setting("LN_TLS_FILE"), db.Get_setting("LN_TLS_FILE"),
db_get_setting("LN_MACAROON_FILE")) db.Get_setting("LN_MACAROON_FILE"))
i_client := invoicesrpc.NewInvoicesClient(connection) i_client := invoicesrpc.NewInvoicesClient(connection)
@ -156,14 +159,14 @@ func monitor_invoice_state(r_hash []byte) {
"invoice_state": invoice_state, "invoice_state": invoice_state,
}).Info("invoice state updated") }).Info("invoice state updated")
db_update_receipt_state(hex.EncodeToString(r_hash), invoice_state) db.Update_receipt_state(hex.EncodeToString(r_hash), invoice_state)
} }
connection.Close() connection.Close()
// send email // send email
card_id, err := db_get_card_id_for_r_hash(hex.EncodeToString(r_hash)) card_id, err := db.Get_card_id_for_r_hash(hex.EncodeToString(r_hash))
if err != nil { if err != nil {
log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash)}).Warn(err) log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash)}).Warn(err)
return return
@ -171,52 +174,52 @@ func monitor_invoice_state(r_hash []byte) {
log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash), "card_id": card_id}).Debug("card found") log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash), "card_id": card_id}).Debug("card found")
c, err := db_get_card_from_card_id(card_id) c, err := db.Get_card_from_card_id(card_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash)}).Warn(err) log.WithFields(log.Fields{"r_hash": hex.EncodeToString(r_hash)}).Warn(err)
return return
} }
if c.email_enable != "Y" { if c.Email_enable != "Y" {
log.Debug("email is not enabled for the card") log.Debug("email is not enabled for the card")
return return
} }
go send_balance_email(c.email_address, card_id) go email.Send_balance_email(c.Email_address, card_id)
return return
} }
// https://api.lightning.community/?shell#sendpaymentv2 // https://api.lightning.community/?shell#sendpaymentv2
func pay_invoice(card_payment_id int, invoice string) { func Pay_invoice(card_payment_id int, invoice string) {
// SendPaymentV2 // SendPaymentV2
// get node parameters from environment variables // get node parameters from environment variables
ln_port, err := strconv.Atoi(db_get_setting("LN_PORT")) ln_port, err := strconv.Atoi(db.Get_setting("LN_PORT"))
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
return return
} }
connection := getGrpcConn( connection := getGrpcConn(
db_get_setting("LN_HOST"), db.Get_setting("LN_HOST"),
ln_port, ln_port,
db_get_setting("LN_TLS_FILE"), db.Get_setting("LN_TLS_FILE"),
db_get_setting("LN_MACAROON_FILE")) db.Get_setting("LN_MACAROON_FILE"))
r_client := routerrpc.NewRouterClient(connection) r_client := routerrpc.NewRouterClient(connection)
fee_limit_sat_str := db_get_setting("FEE_LIMIT_SAT") fee_limit_sat_str := db.Get_setting("FEE_LIMIT_SAT")
fee_limit_sat, err := strconv.ParseInt(fee_limit_sat_str, 10, 64) fee_limit_sat, err := strconv.ParseInt(fee_limit_sat_str, 10, 64)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
return return
} }
fee_limit_percent_str := db_get_setting("FEE_LIMIT_PERCENT") fee_limit_percent_str := db.Get_setting("FEE_LIMIT_PERCENT")
fee_limit_percent, err := strconv.ParseFloat(fee_limit_percent_str, 64) fee_limit_percent, err := strconv.ParseFloat(fee_limit_percent_str, 64)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
@ -260,7 +263,7 @@ func pay_invoice(card_payment_id int, invoice string) {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Info("payment failure reason : ", failure_reason) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Info("payment failure reason : ", failure_reason)
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Info("payment status : ", payment_status) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Info("payment status : ", payment_status)
err = db_update_payment_status(card_payment_id, payment_status, failure_reason) err = db.Update_payment_status(card_payment_id, payment_status, failure_reason)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
return return
@ -271,7 +274,7 @@ func pay_invoice(card_payment_id int, invoice string) {
// send email // send email
card_id, err := db_get_card_id_for_card_payment_id(card_payment_id) card_id, err := db.Get_card_id_for_card_payment_id(card_payment_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
return return
@ -279,18 +282,18 @@ func pay_invoice(card_payment_id int, invoice string) {
log.WithFields(log.Fields{"card_payment_id": card_payment_id, "card_id": card_id}).Debug("card found") log.WithFields(log.Fields{"card_payment_id": card_payment_id, "card_id": card_id}).Debug("card found")
c, err := db_get_card_from_card_id(card_id) c, err := db.Get_card_from_card_id(card_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": card_payment_id}).Warn(err)
return return
} }
if c.email_enable != "Y" { if c.Email_enable != "Y" {
log.Debug("email is not enabled for the card") log.Debug("email is not enabled for the card")
return return
} }
go send_balance_email(c.email_address, card_id) go email.Send_balance_email(c.Email_address, card_id)
return return
} }

View file

@ -6,10 +6,12 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"strconv" "strconv"
"github.com/boltcard/boltcard/lnd"
"github.com/boltcard/boltcard/db"
) )
func lnurlp_callback(w http.ResponseWriter, r *http.Request) { func lnurlp_callback(w http.ResponseWriter, r *http.Request) {
if db_get_setting("FUNCTION_LNURLP") != "ENABLE" { if db.Get_setting("FUNCTION_LNURLP") != "ENABLE" {
log.Debug("LNURLp function is not enabled") log.Debug("LNURLp function is not enabled")
return return
} }
@ -17,7 +19,7 @@ func lnurlp_callback(w http.ResponseWriter, r *http.Request) {
name := mux.Vars(r)["name"] name := mux.Vars(r)["name"]
amount := r.URL.Query().Get("amount") amount := r.URL.Query().Get("amount")
card_id, err := db_get_card_id_for_name(name) card_id, err := db.Get_card_id_for_name(name)
if err != nil { if err != nil {
log.Info("card name not found") log.Info("card name not found")
write_error(w) write_error(w)
@ -33,7 +35,7 @@ func lnurlp_callback(w http.ResponseWriter, r *http.Request) {
"req.Host": r.Host, "req.Host": r.Host,
}).Info("lnurlp_callback") }).Info("lnurlp_callback")
domain := db_get_setting("HOST_DOMAIN") domain := db.Get_setting("HOST_DOMAIN")
if r.Host != domain { if r.Host != domain {
log.Warn("wrong host domain") log.Warn("wrong host domain")
write_error(w) write_error(w)
@ -50,21 +52,21 @@ func lnurlp_callback(w http.ResponseWriter, r *http.Request) {
amount_sat := amount_msat / 1000 amount_sat := amount_msat / 1000
metadata := "[[\"text/identifier\",\"" + name + "@" + domain + "\"],[\"text/plain\",\"bolt card deposit\"]]" metadata := "[[\"text/identifier\",\"" + name + "@" + domain + "\"],[\"text/plain\",\"bolt card deposit\"]]"
pr, r_hash, err := add_invoice(amount_sat, metadata) pr, r_hash, err := lnd.Add_invoice(amount_sat, metadata)
if err != nil { if err != nil {
log.Warn("could not add_invoice") log.Warn("could not add_invoice")
write_error(w) write_error(w)
return return
} }
err = db_insert_receipt(card_id, pr, hex.EncodeToString(r_hash), amount_msat) err = db.Insert_receipt(card_id, pr, hex.EncodeToString(r_hash), amount_msat)
if err != nil { if err != nil {
log.Warn(err) log.Warn(err)
write_error(w) write_error(w)
return return
} }
go monitor_invoice_state(r_hash) go lnd.Monitor_invoice_state(r_hash)
log.Debug("sending 'status OK' response") log.Debug("sending 'status OK' response")

View file

@ -4,10 +4,11 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"github.com/boltcard/boltcard/db"
) )
func lnurlp_response(w http.ResponseWriter, r *http.Request) { func lnurlp_response(w http.ResponseWriter, r *http.Request) {
if db_get_setting("FUNCTION_LNURLP") != "ENABLE" { if db.Get_setting("FUNCTION_LNURLP") != "ENABLE" {
log.Debug("LNURLp function is not enabled") log.Debug("LNURLp function is not enabled")
return return
} }
@ -23,7 +24,7 @@ func lnurlp_response(w http.ResponseWriter, r *http.Request) {
// look up domain setting (HOST_DOMAIN) // look up domain setting (HOST_DOMAIN)
domain := db_get_setting("HOST_DOMAIN") domain := db.Get_setting("HOST_DOMAIN")
if r.Host != domain { if r.Host != domain {
log.Warn("wrong host domain") log.Warn("wrong host domain")
write_error(w) write_error(w)
@ -32,7 +33,7 @@ func lnurlp_response(w http.ResponseWriter, r *http.Request) {
// look up name in database (table cards, field card_name) // look up name in database (table cards, field card_name)
card_count, err := db_get_card_count_for_name_lnurlp(name) card_count, err := db.Get_card_count_for_name_lnurlp(name)
if err != nil { if err != nil {
log.Warn("could not get card count for name") log.Warn("could not get card count for name")
write_error(w) write_error(w)

View file

@ -4,11 +4,13 @@ import (
decodepay "github.com/fiatjaf/ln-decodepay" decodepay "github.com/fiatjaf/ln-decodepay"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"github.com/boltcard/boltcard/db"
"github.com/boltcard/boltcard/lnd"
) )
func lnurlw_callback(w http.ResponseWriter, req *http.Request) { func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
env_host_domain := db_get_setting("HOST_DOMAIN") env_host_domain := db.Get_setting("HOST_DOMAIN")
if req.Host != env_host_domain { if req.Host != env_host_domain {
log.Warn("wrong host domain") log.Warn("wrong host domain")
write_error(w) write_error(w)
@ -29,7 +31,7 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
param_k1 := params_k1[0] param_k1 := params_k1[0]
p, err := db_get_payment_k1(param_k1) p, err := db.Get_payment_k1(param_k1)
if err != nil { if err != nil {
log.WithFields(log.Fields{"url": url, "k1": param_k1}).Warn(err) log.WithFields(log.Fields{"url": url, "k1": param_k1}).Warn(err)
write_error(w) write_error(w)
@ -37,28 +39,28 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
} }
// check that payment has not been made // check that payment has not been made
if p.paid_flag != "N" { if p.Paid_flag != "N" {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("payment already made") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("payment already made")
write_error(w) write_error(w)
return return
} }
// check if lnurlw_request has timed out // check if lnurlw_request has timed out
lnurlw_timeout, err := db_check_lnurlw_timeout(p.card_payment_id) lnurlw_timeout, err := db.Check_lnurlw_timeout(p.Card_payment_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
if lnurlw_timeout == true { if lnurlw_timeout == true {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("lnurlw request has timed out") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("lnurlw request has timed out")
write_error(w) write_error(w)
return return
} }
params_pr, ok := req.URL.Query()["pr"] params_pr, ok := req.URL.Query()["pr"]
if !ok || len(params_pr[0]) < 1 { if !ok || len(params_pr[0]) < 1 {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn("pr field not found") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn("pr field not found")
write_error(w) write_error(w)
return return
} }
@ -67,19 +69,19 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
bolt11, _ := decodepay.Decodepay(param_pr) bolt11, _ := decodepay.Decodepay(param_pr)
// record the lightning invoice // record the lightning invoice
err = db_update_payment_invoice(p.card_payment_id, param_pr, bolt11.MSatoshi) err = db.Update_payment_invoice(p.Card_payment_id, param_pr, bolt11.MSatoshi)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Debug("checking payment rules") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Debug("checking payment rules")
// check if we are only sending funds to a defined test node // check if we are only sending funds to a defined test node
testnode := db_get_setting("LN_TESTNODE") testnode := db.Get_setting("LN_TESTNODE")
if testnode != "" && bolt11.Payee != testnode { if testnode != "" && bolt11.Payee != testnode {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("rejected as not the defined test node") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("rejected as not the defined test node")
write_error(w) write_error(w)
return return
} }
@ -88,33 +90,33 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
invoice_sats := int(bolt11.MSatoshi / 1000) invoice_sats := int(bolt11.MSatoshi / 1000)
day_total_sats, err := db_get_card_totals(p.card_id) day_total_sats, err := db.Get_card_totals(p.Card_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
c, err := db_get_card_from_card_id(p.card_id) c, err := db.Get_card_from_card_id(p.Card_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
if invoice_sats > c.tx_limit_sats { if invoice_sats > c.Tx_limit_sats {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("invoice_sats: ", invoice_sats) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("invoice_sats: ", invoice_sats)
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("tx_limit_sats: ", c.tx_limit_sats) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("tx_limit_sats: ", c.Tx_limit_sats)
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("over tx_limit_sats!") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("over tx_limit_sats!")
write_error(w) write_error(w)
return return
} }
if day_total_sats+invoice_sats > c.day_limit_sats { if day_total_sats+invoice_sats > c.Day_limit_sats {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("invoice_sats: ", invoice_sats) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("invoice_sats: ", invoice_sats)
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("day_total_sats: ", day_total_sats) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("day_total_sats: ", day_total_sats)
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("day_limit_sats: ", c.day_limit_sats) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("day_limit_sats: ", c.Day_limit_sats)
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("over day_limit_sats!") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("over day_limit_sats!")
write_error(w) write_error(w)
return return
} }
@ -122,27 +124,27 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
// check the card balance if marked as 'must stay above zero' (default) // check the card balance if marked as 'must stay above zero' (default)
// i.e. cards.allow_negative_balance == 'N' // i.e. cards.allow_negative_balance == 'N'
if c.allow_negative_balance != "Y" { if c.Allow_negative_balance != "Y" {
card_total, err := db_get_card_total_sats(p.card_id) card_total, err := db.Get_card_total_sats(p.Card_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
if card_total-invoice_sats < 0 { if card_total-invoice_sats < 0 {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn("not enough balance") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn("not enough balance")
write_error(w) write_error(w)
return return
} }
} }
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Info("paying invoice") log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Info("paying invoice")
// update paid_flag so we only attempt payment once // update paid_flag so we only attempt payment once
err = db_update_payment_paid(p.card_payment_id) err = db.Update_payment_paid(p.Card_payment_id)
if err != nil { if err != nil {
log.WithFields(log.Fields{"card_payment_id": p.card_payment_id}).Warn(err) log.WithFields(log.Fields{"card_payment_id": p.Card_payment_id}).Warn(err)
write_error(w) write_error(w)
return return
} }
@ -153,7 +155,7 @@ func lnurlw_callback(w http.ResponseWriter, req *http.Request) {
// {"status": "ERROR", "reason": "error details..."} // {"status": "ERROR", "reason": "error details..."}
// JSON response and then attempts to pay the invoices asynchronously. // JSON response and then attempts to pay the invoices asynchronously.
go pay_invoice(p.card_payment_id, param_pr) go lnd.Pay_invoice(p.Card_payment_id, param_pr)
log.Debug("sending 'status OK' response") log.Debug("sending 'status OK' response")

View file

@ -9,6 +9,7 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"github.com/boltcard/boltcard/db"
) )
type Response struct { type Response struct {
@ -74,10 +75,10 @@ func setup_card_record(uid string, ctr uint32, uid_bin []byte, ctr_bin []byte, c
// find the card record by matching the cmac // find the card record by matching the cmac
// get possible card records from the database // get possible card records from the database
cards, err := db_get_cards_blank_uid() cards, err := db.Get_cards_blank_uid()
if err != nil { if err != nil {
return errors.New("db_get_cards_blank_uid errored") return errors.New("db.Get_cards_blank_uid errored")
} }
// check card records for a matching cmac // check card records for a matching cmac
@ -85,7 +86,7 @@ func setup_card_record(uid string, ctr uint32, uid_bin []byte, ctr_bin []byte, c
for i, card := range cards { for i, card := range cards {
// check the cmac // check the cmac
k2_cmac_key, err := hex.DecodeString(card.k2_cmac_key) k2_cmac_key, err := hex.DecodeString(card.K2_cmac_key)
if err != nil { if err != nil {
return errors.New("card.k2_cmac_key decode failed") return errors.New("card.k2_cmac_key decode failed")
@ -100,12 +101,12 @@ func setup_card_record(uid string, ctr uint32, uid_bin []byte, ctr_bin []byte, c
if cmac_valid == true { if cmac_valid == true {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"i": i, "i": i,
"card.card_id": card.card_id, "card.card_id": card.Card_id,
"card.k2_cmac_key": card.k2_cmac_key, "card.k2_cmac_key": card.K2_cmac_key,
}).Info("cmac match found") }).Info("cmac match found")
// store the uid and ctr in the card record // store the uid and ctr in the card record
err := db_update_card_uid_ctr(card.card_id, uid, ctr) err := db.Update_card_uid_ctr(card.Card_id, uid, ctr)
if err != nil { if err != nil {
return err return err
@ -150,7 +151,7 @@ func parse_request(req *http.Request) (int, error) {
// decrypt p with aes_decrypt_key // decrypt p with aes_decrypt_key
aes_decrypt_key := db_get_setting("AES_DECRYPT_KEY") aes_decrypt_key := db.Get_setting("AES_DECRYPT_KEY")
key_sdm_file_read, err := hex.DecodeString(aes_decrypt_key) key_sdm_file_read, err := hex.DecodeString(aes_decrypt_key)
@ -179,7 +180,7 @@ func parse_request(req *http.Request) (int, error) {
log.WithFields(log.Fields{"uid": uid_str, "ctr": ctr_int}).Info("decrypted card data") log.WithFields(log.Fields{"uid": uid_str, "ctr": ctr_int}).Info("decrypted card data")
card_count, err := db_get_card_count_for_uid(uid_str) card_count, err := db.Get_card_count_for_uid(uid_str)
if err != nil { if err != nil {
return 0, errors.New("could not get card count for uid") return 0, errors.New("could not get card count for uid")
@ -197,7 +198,7 @@ func parse_request(req *http.Request) (int, error) {
// get card record from database for UID // get card record from database for UID
c, err := db_get_card_from_uid(uid_str) c, err := db.Get_card_from_uid(uid_str)
if err != nil { if err != nil {
return 0, errors.New("card not found for uid") return 0, errors.New("card not found for uid")
@ -205,13 +206,13 @@ func parse_request(req *http.Request) (int, error) {
// check if card is enabled // check if card is enabled
if c.lnurlw_enable != "Y" { if c.Lnurlw_enable != "Y" {
return 0, errors.New("card lnurlw enable is not set to Y") return 0, errors.New("card lnurlw enable is not set to Y")
} }
// check cmac // check cmac
k2_cmac_key, err := hex.DecodeString(c.k2_cmac_key) k2_cmac_key, err := hex.DecodeString(c.K2_cmac_key)
if err != nil { if err != nil {
return 0, err return 0, err
@ -229,7 +230,7 @@ func parse_request(req *http.Request) (int, error) {
// check and update last_counter_value // check and update last_counter_value
counter_ok, err := db_check_and_update_counter(c.card_id, ctr_int) counter_ok, err := db.Check_and_update_counter(c.Card_id, ctr_int)
if err != nil { if err != nil {
return 0, err return 0, err
@ -239,14 +240,14 @@ func parse_request(req *http.Request) (int, error) {
return 0, errors.New("counter not increasing") return 0, errors.New("counter not increasing")
} }
log.WithFields(log.Fields{"card_id": c.card_id, "counter": ctr_int}).Info("validated") log.WithFields(log.Fields{"card_id": c.Card_id, "counter": ctr_int}).Info("validated")
return c.card_id, nil return c.Card_id, nil
} }
func lnurlw_response(w http.ResponseWriter, req *http.Request) { func lnurlw_response(w http.ResponseWriter, req *http.Request) {
env_host_domain := db_get_setting("HOST_DOMAIN") env_host_domain := db.Get_setting("HOST_DOMAIN")
if req.Host != env_host_domain { if req.Host != env_host_domain {
log.Warn("wrong host domain") log.Warn("wrong host domain")
write_error(w) write_error(w)
@ -271,7 +272,7 @@ func lnurlw_response(w http.ResponseWriter, req *http.Request) {
// store k1 in database and include in response // store k1 in database and include in response
err = db_insert_payment(card_id, lnurlw_k1) err = db.Insert_payment(card_id, lnurlw_k1)
if err != nil { if err != nil {
log.Warn(err.Error()) log.Warn(err.Error())
@ -286,7 +287,7 @@ func lnurlw_response(w http.ResponseWriter, req *http.Request) {
lnurlw_cb_url = "https://" + req.Host + "/cb" lnurlw_cb_url = "https://" + req.Host + "/cb"
} }
min_withdraw_sats_str := db_get_setting("MIN_WITHDRAW_SATS") min_withdraw_sats_str := db.Get_setting("MIN_WITHDRAW_SATS")
min_withdraw_sats, err := strconv.Atoi(min_withdraw_sats_str) min_withdraw_sats, err := strconv.Atoi(min_withdraw_sats_str)
if err != nil { if err != nil {
@ -295,7 +296,7 @@ func lnurlw_response(w http.ResponseWriter, req *http.Request) {
return return
} }
max_withdraw_sats_str := db_get_setting("MAX_WITHDRAW_SATS") max_withdraw_sats_str := db.Get_setting("MAX_WITHDRAW_SATS")
max_withdraw_sats, err := strconv.Atoi(max_withdraw_sats_str) max_withdraw_sats, err := strconv.Atoi(max_withdraw_sats_str)
if err != nil { if err != nil {

View file

@ -5,6 +5,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"time" "time"
"github.com/boltcard/boltcard/db"
) )
var router = mux.NewRouter() var router = mux.NewRouter()
@ -24,7 +25,7 @@ func write_error_message(w http.ResponseWriter, message string) {
} }
func main() { func main() {
log_level := db_get_setting("LOG_LEVEL") log_level := db.Get_setting("LOG_LEVEL")
switch log_level { switch log_level {
case "DEBUG": case "DEBUG":
@ -50,7 +51,7 @@ func main() {
router.Path("/.well-known/lnurlp/{name}").Methods("GET").HandlerFunc(lnurlp_response) router.Path("/.well-known/lnurlp/{name}").Methods("GET").HandlerFunc(lnurlp_response)
router.Path("/lnurlp/{name}").Methods("GET").HandlerFunc(lnurlp_callback) router.Path("/lnurlp/{name}").Methods("GET").HandlerFunc(lnurlp_callback)
port := db_get_setting("HOST_PORT") port := db.Get_setting("HOST_PORT")
if port == "" { if port == "" {
port = "9000" port = "9000"
} }

View file

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"github.com/boltcard/boltcard/db"
) )
/** /**
@ -55,7 +56,7 @@ func new_card_request(w http.ResponseWriter, req *http.Request) {
lnurlw_base := "lnurlw://" + req.Host + "/ln" lnurlw_base := "lnurlw://" + req.Host + "/ln"
c, err := db_get_new_card(a) c, err := db.Get_new_card(a)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
log.Debug(err) log.Debug(err)
@ -69,19 +70,19 @@ func new_card_request(w http.ResponseWriter, req *http.Request) {
return return
} }
k1_decrypt_key := db_get_setting("AES_DECRYPT_KEY") k1_decrypt_key := db.Get_setting("AES_DECRYPT_KEY")
response := NewCardResponse{} response := NewCardResponse{}
response.PROTOCOL_NAME = "create_bolt_card_response" response.PROTOCOL_NAME = "create_bolt_card_response"
response.PROTOCOL_VERSION = 2 response.PROTOCOL_VERSION = 2
response.CARD_NAME = c.card_name response.CARD_NAME = c.Card_name
response.LNURLW_BASE = lnurlw_base response.LNURLW_BASE = lnurlw_base
response.K0 = c.k0_auth_key response.K0 = c.K0_auth_key
response.K1 = k1_decrypt_key response.K1 = k1_decrypt_key
response.K2 = c.k2_cmac_key response.K2 = c.K2_cmac_key
response.K3 = c.k3 response.K3 = c.K3
response.K4 = c.k4 response.K4 = c.K4
response.UID_PRIVACY = c.uid_privacy response.UID_PRIVACY = c.Uid_privacy
log.SetFormatter(&log.JSONFormatter{ log.SetFormatter(&log.JSONFormatter{
DisableHTMLEscape: true, DisableHTMLEscape: true,

View file

@ -21,3 +21,5 @@ INSERT INTO settings (name, value) VALUES ('AWS_SES_ID', '');
INSERT INTO settings (name, value) VALUES ('AWS_SES_SECRET', ''); INSERT INTO settings (name, value) VALUES ('AWS_SES_SECRET', '');
INSERT INTO settings (name, value) VALUES ('AWS_SES_EMAIL_FROM', ''); INSERT INTO settings (name, value) VALUES ('AWS_SES_EMAIL_FROM', '');
INSERT INTO settings (name, value) VALUES ('EMAIL_MAX_TXS', ''); INSERT INTO settings (name, value) VALUES ('EMAIL_MAX_TXS', '');
INSERT INTO settings (name, value) VALUES ('FUNCTION_LNDHUB', '');
INSERT INTO settings (name, value) VALUES ('LNDHUB_URL', '');