mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-17 21:32:56 +01:00
nip60: a helper to get amount from a bolt11 invoice.
This commit is contained in:
parent
1e76aec884
commit
5e2d455b72
@ -7,6 +7,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
@ -201,3 +203,57 @@ func parseKeysetKeys(keys nut01.KeysMap) (map[uint64]*btcec.PublicKey, error) {
|
||||
}
|
||||
return parsedKeys, nil
|
||||
}
|
||||
|
||||
func getSatoshisAmountFromBolt11(bolt11 string) (uint64, error) {
|
||||
if len(bolt11) < 50 {
|
||||
return 0, fmt.Errorf("invalid invoice, too short")
|
||||
}
|
||||
bolt11 = bolt11[0:50]
|
||||
idx := strings.LastIndex(bolt11, "1")
|
||||
if idx == -1 {
|
||||
return 0, fmt.Errorf("invalid invoice")
|
||||
}
|
||||
hrp := bolt11[0:idx]
|
||||
amount, ok := strings.CutPrefix(hrp, "lnbc")
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("invalid invoice")
|
||||
}
|
||||
if len(amount) < 1 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// if last character is a digit, then the amount can just be interpreted as BTC
|
||||
char := amount[len(amount)-1]
|
||||
digit := char - '0'
|
||||
isDigit := digit >= 0 && digit <= 9
|
||||
|
||||
cutPoint := len(amount) - 1
|
||||
if isDigit {
|
||||
cutPoint++
|
||||
}
|
||||
|
||||
// if not a digit, it must be part of the known units
|
||||
num := amount[:cutPoint]
|
||||
if len(num) < 1 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
am, err := strconv.ParseUint(num, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
switch char {
|
||||
case 'm':
|
||||
return am * 100000, nil
|
||||
case 'u':
|
||||
return am * 100, nil
|
||||
case 'n':
|
||||
return am / 10, nil
|
||||
case 'p':
|
||||
return am / 10000, nil
|
||||
default:
|
||||
// is BTC
|
||||
return am * 100000000, nil
|
||||
}
|
||||
}
|
||||
|
37
nip60/helpers_test.go
Normal file
37
nip60/helpers_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
package nip60
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBolt11Parsing(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
bolt11 string
|
||||
sats uint64
|
||||
hasError bool
|
||||
}{
|
||||
{"", 0, true},
|
||||
{"lnbc50n1pne523ypp57rn4l2ne673c093g72nm4pum2mkxjm0v2c0pjc9je909axyutdlqdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5rgp9fa9d8unmg949ztty48dgptke8f8zflt7af8d4yknamp2ymdq9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgqmatchtjjsyvk45mwwg2mvf8xshxhk2gveslvc27dda6dkp0kfc3hhs06e3c966h3z9j9aran0q8ncm6n458xdca3j5nsrke4saxrfmsqu7suv5", 5, false},
|
||||
{"lnbc10500n1pne5tn3pp53wha2waf6g8zac853ay43uscfm9xy3k6ntz0lft72vajyna8695qdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5vapxxnr2wd3780qwmexe24hfcd2m87hsnn8z9xt9u0kmlwq084aq9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgq7vljmxfwsxsmf773ad5fhghe4s840t4set4ypyan2tnzwsldxktquw9lzhtlzj3zldma79hgr6ftp7hst8jh0km3p63vtsfugadtmkgp8wtkzp", 1050, false},
|
||||
{"lnbc778970n1pne5t5jpp5yazceq5p3sr2dfvp283zqy4xd5jea9vwvc4ptw3m47qlkyzpzdtsdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5ssfackh9ys9ggc4h7ag3panc8wu3gqh84ghnkfd24khyy5pmjx6q9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgqdupshqq328498wk3evxh0ext6y5svfsnyauqvcse3l7u3lmk9s5yftmn7ec4l3d5aqd702je4g7aeng2nyjy0qcv23ue9ddn3ga3llsqzlnjv3", 77897, false},
|
||||
{"lnbc700u1pne5t4upp5qkxcf9xsmn3p2r55dm386vlp52cvtgjyrv450z6ft2kj6lsmm6asdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5r2ynl9fycj5eega7tzuae5nu8umwawv30glw2c6gh45ymaryxdjs9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgqx8d2dr05fmaelmfmxyd6snlyenx25pl6jaxlcm9vqvq89t2smwv8au8j24fwxjswz4j2vcvnmhkaja4dhxf9y49jvwgd7xasgp3tppcp27zlr0", 70000, false},
|
||||
{"lnbc2600u1pne5tkepp5q2g379zdf7k35ylf4r4f7hc47e9eazxlv3z55ydjnmtj8gt0vy8qdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5p45aam8azmegj747j8lwmdcjd6uj2f8mjpwh34qjye2h67g3azwq9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgq649a6ztfcqtalz3lfukesxep9tkaew90d80l6sds8cnppsqd0yx4jkttyuzw5k8erygzh36k6n3j5x4q3caqxsg3vy52j6va8879x4qqxlk7p5", 260000, false},
|
||||
{"lnbc400m1pne5thjpp57slr93076zkczq08nvufgp6td6yafr9su3hqr2w2jl64p8e7k4jsdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp55grhezefgcgjsddk4lp4jc564pwu5cp0zddg5f6tygt7xe57g47s9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgqf0xtyv62a4v9sjze3ftgdhwpgskhe3hlvwyjnhvt74grzsmpftvzdrlnh02cfg00st26pv7vgkxpknny52s3cuccwpm29l5yarq5fcqpfn7eh9", 40000000, false},
|
||||
{"lnbc81pne5tcdpp59qnlzkzyjz0wy0z7fvjxe67u75cpknzfzahwqzm640ly0yrs982sdq2f38xy6t5wvcqzpgxqrrssrzjq0nfr7qlprzkl2rke380tj0gkunm66pv7dtqt0396jrq02qz2fs98apyqqqqqqqqqgqqqqqqqqqqqzsqxgsp5lrljv8ce4c64l77gj4gffg5gc8nlrnngk85twzvp35l92jwwravq9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgq5a8yyyreke9x5u4up22tzknum43hqyza9y808hmvftcvj7t7m5lzdrz53mhdh6snxxwd4r0x2cgw9crlzm4pdln80hphwfzpuj869nqq73w8r3", 800000000, false},
|
||||
{"lnbc5n1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 0, false},
|
||||
{"lnbc1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 0, false},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%d = %s", tc.sats, tc.bolt11), func(t *testing.T) {
|
||||
sats, err := getSatoshisAmountFromBolt11(tc.bolt11)
|
||||
if tc.hasError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, int(tc.sats), int(sats))
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user