🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@getalby/lightning-tools

Package Overview
Dependencies
Maintainers
4
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@getalby/lightning-tools - npm Package Compare versions

Comparing version
5.2.1
to
6.0.0
+1250
dist/cjs/bolt11.cjs
'use strict';
var lib = {};
var hasRequiredLib;
function requireLib () {
if (hasRequiredLib) return lib;
hasRequiredLib = 1;
(function (exports) {
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64url = exports.base64 = exports.base32crockford = exports.base32hex = exports.base32 = exports.base16 = exports.utils = exports.assertNumber = void 0;
function assertNumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`Wrong integer: ${n}`);
}
exports.assertNumber = assertNumber;
function chain(...args) {
const wrap = (a, b) => (c) => a(b(c));
const encode = Array.from(args)
.reverse()
.reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);
const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);
return { encode, decode };
}
function alphabet(alphabet) {
return {
encode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('alphabet.encode input should be an array of numbers');
return digits.map((i) => {
assertNumber(i);
if (i < 0 || i >= alphabet.length)
throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);
return alphabet[i];
});
},
decode: (input) => {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('alphabet.decode input should be array of strings');
return input.map((letter) => {
if (typeof letter !== 'string')
throw new Error(`alphabet.decode: not string element=${letter}`);
const index = alphabet.indexOf(letter);
if (index === -1)
throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);
return index;
});
},
};
}
function join(separator = '') {
if (typeof separator !== 'string')
throw new Error('join separator should be string');
return {
encode: (from) => {
if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))
throw new Error('join.encode input should be array of strings');
for (let i of from)
if (typeof i !== 'string')
throw new Error(`join.encode: non-string input=${i}`);
return from.join(separator);
},
decode: (to) => {
if (typeof to !== 'string')
throw new Error('join.decode input should be string');
return to.split(separator);
},
};
}
function padding(bits, chr = '=') {
assertNumber(bits);
if (typeof chr !== 'string')
throw new Error('padding chr should be string');
return {
encode(data) {
if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of data)
if (typeof i !== 'string')
throw new Error(`padding.encode: non-string input=${i}`);
while ((data.length * bits) % 8)
data.push(chr);
return data;
},
decode(input) {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of input)
if (typeof i !== 'string')
throw new Error(`padding.decode: non-string input=${i}`);
let end = input.length;
if ((end * bits) % 8)
throw new Error('Invalid padding: string should have whole number of bytes');
for (; end > 0 && input[end - 1] === chr; end--) {
if (!(((end - 1) * bits) % 8))
throw new Error('Invalid padding: string has too much padding');
}
return input.slice(0, end);
},
};
}
function normalize(fn) {
if (typeof fn !== 'function')
throw new Error('normalize fn should be function');
return { encode: (from) => from, decode: (to) => fn(to) };
}
function convertRadix(data, from, to) {
if (from < 2)
throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
if (to < 2)
throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
if (!Array.isArray(data))
throw new Error('convertRadix: data should be array');
if (!data.length)
return [];
let pos = 0;
const res = [];
const digits = Array.from(data);
digits.forEach((d) => {
assertNumber(d);
if (d < 0 || d >= from)
throw new Error(`Wrong integer: ${d}`);
});
while (true) {
let carry = 0;
let done = true;
for (let i = pos; i < digits.length; i++) {
const digit = digits[i];
const digitBase = from * carry + digit;
if (!Number.isSafeInteger(digitBase) ||
(from * carry) / from !== carry ||
digitBase - digit !== from * carry) {
throw new Error('convertRadix: carry overflow');
}
carry = digitBase % to;
digits[i] = Math.floor(digitBase / to);
if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)
throw new Error('convertRadix: carry overflow');
if (!done)
continue;
else if (!digits[i])
pos = i;
else
done = false;
}
res.push(carry);
if (done)
break;
}
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
res.push(0);
return res.reverse();
}
const gcd = (a, b) => (!b ? a : gcd(b, a % b));
const radix2carry = (from, to) => from + (to - gcd(from, to));
function convertRadix2(data, from, to, padding) {
if (!Array.isArray(data))
throw new Error('convertRadix2: data should be array');
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0;
const mask = 2 ** to - 1;
const res = [];
for (const n of data) {
assertNumber(n);
if (n >= 2 ** from)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = (carry << from) | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push(((carry >> (pos - to)) & mask) >>> 0);
carry &= 2 ** pos - 1;
}
carry = (carry << (to - pos)) & mask;
if (!padding && pos >= from)
throw new Error('Excess padding');
if (!padding && carry)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
function radix(num) {
assertNumber(num);
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix.encode input should be Uint8Array');
return convertRadix(Array.from(bytes), 2 ** 8, num);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix.decode input should be array of strings');
return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
},
};
}
function radix2(bits, revPadding = false) {
assertNumber(bits);
if (bits <= 0 || bits > 32)
throw new Error('radix2: bits should be in (0..32]');
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
throw new Error('radix2: carry overflow');
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix2.encode input should be Uint8Array');
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix2.decode input should be array of strings');
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
},
};
}
function unsafeWrapper(fn) {
if (typeof fn !== 'function')
throw new Error('unsafeWrapper fn should be function');
return function (...args) {
try {
return fn.apply(null, args);
}
catch (e) { }
};
}
function checksum(len, fn) {
assertNumber(len);
if (typeof fn !== 'function')
throw new Error('checksum fn should be function');
return {
encode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.encode: input should be Uint8Array');
const checksum = fn(data).slice(0, len);
const res = new Uint8Array(data.length + len);
res.set(data);
res.set(checksum, data.length);
return res;
},
decode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.decode: input should be Uint8Array');
const payload = data.slice(0, -len);
const newChecksum = fn(payload).slice(0, len);
const oldChecksum = data.slice(-len);
for (let i = 0; i < len; i++)
if (newChecksum[i] !== oldChecksum[i])
throw new Error('Invalid checksum');
return payload;
},
};
}
exports.utils = { alphabet, chain, checksum, radix, radix2, join, padding };
exports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
exports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
exports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
exports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
exports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
exports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
const genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));
exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
exports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
exports.base58xmr = {
encode(data) {
let res = '';
for (let i = 0; i < data.length; i += 8) {
const block = data.subarray(i, i + 8);
res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
}
return res;
},
decode(str) {
let res = [];
for (let i = 0; i < str.length; i += 11) {
const slice = str.slice(i, i + 11);
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
const block = exports.base58.decode(slice);
for (let j = 0; j < block.length - blockLen; j++) {
if (block[j] !== 0)
throw new Error('base58xmr: wrong padding');
}
res = res.concat(Array.from(block.slice(block.length - blockLen)));
}
return Uint8Array.from(res);
},
};
const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
exports.base58check = base58check;
const BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 0x1ffffff) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if (((b >> i) & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ (c >> 5);
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
}
function genBech32(encoding) {
const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
const _words = radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
if (typeof prefix !== 'string')
throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))
throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
const actualLength = prefix.length + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
prefix = prefix.toLowerCase();
return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
}
function decode(str, limit = 90) {
if (typeof str !== 'string')
throw new Error(`bech32.decode input should be string, not ${typeof str}`);
if (str.length < 8 || (limit !== false && str.length > limit))
throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
str = lowered;
const sepIndex = str.lastIndexOf('1');
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = str.slice(0, sepIndex);
const _words = str.slice(sepIndex + 1);
if (_words.length < 6)
throw new Error('Data must be at least 6 characters long');
const words = BECH_ALPHABET.decode(_words).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!_words.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
}
exports.bech32 = genBech32('bech32');
exports.bech32m = genBech32('bech32m');
exports.utf8 = {
encode: (data) => new TextDecoder().decode(data),
decode: (str) => new TextEncoder().encode(str),
};
exports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
if (typeof s !== 'string' || s.length % 2)
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
return s.toLowerCase();
}));
const CODERS = {
utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
};
const coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;
const bytesToString = (type, bytes) => {
if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (!(bytes instanceof Uint8Array))
throw new TypeError('bytesToString() expects Uint8Array');
return CODERS[type].encode(bytes);
};
exports.bytesToString = bytesToString;
exports.str = exports.bytesToString;
const stringToBytes = (type, str) => {
if (!CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (typeof str !== 'string')
throw new TypeError('stringToBytes() expects string');
return CODERS[type].decode(str);
};
exports.stringToBytes = stringToBytes;
exports.bytes = exports.stringToBytes;
} (lib));
return lib;
}
var bolt11;
var hasRequiredBolt11;
function requireBolt11 () {
if (hasRequiredBolt11) return bolt11;
hasRequiredBolt11 = 1;
const {bech32, hex, utf8} = requireLib();
// defaults for encode; default timestamp is current time at call
const DEFAULTNETWORK = {
// default network is bitcoin
bech32: 'bc',
pubKeyHash: 0x00,
scriptHash: 0x05,
validWitnessVersions: [0]
};
const TESTNETWORK = {
bech32: 'tb',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIGNETNETWORK = {
bech32: 'tbs',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const REGTESTNETWORK = {
bech32: 'bcrt',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIMNETWORK = {
bech32: 'sb',
pubKeyHash: 0x3f,
scriptHash: 0x7b,
validWitnessVersions: [0]
};
const FEATUREBIT_ORDER = [
'option_data_loss_protect',
'initial_routing_sync',
'option_upfront_shutdown_script',
'gossip_queries',
'var_onion_optin',
'gossip_queries_ex',
'option_static_remotekey',
'payment_secret',
'basic_mpp',
'option_support_large_channel'
];
const DIVISORS = {
m: BigInt(1e3),
u: BigInt(1e6),
n: BigInt(1e9),
p: BigInt(1e12)
};
const MAX_MILLISATS = BigInt('2100000000000000000');
const MILLISATS_PER_BTC = BigInt(1e11);
const TAGCODES = {
payment_hash: 1,
payment_secret: 16,
description: 13,
payee: 19,
description_hash: 23, // commit to longer descriptions (used by lnurl-pay)
expiry: 6, // default: 3600 (1 hour)
min_final_cltv_expiry: 24, // default: 9
fallback_address: 9,
route_hint: 3, // for extra routing info (private etc.)
feature_bits: 5,
metadata: 27
};
// reverse the keys and values of TAGCODES and insert into TAGNAMES
const TAGNAMES = {};
for (let i = 0, keys = Object.keys(TAGCODES); i < keys.length; i++) {
const currentName = keys[i];
const currentCode = TAGCODES[keys[i]].toString();
TAGNAMES[currentCode] = currentName;
}
const TAGPARSERS = {
1: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
16: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
13: words => utf8.encode(bech32.fromWordsUnsafe(words)), // string variable length
19: words => hex.encode(bech32.fromWordsUnsafe(words)), // 264 bits
23: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
27: words => hex.encode(bech32.fromWordsUnsafe(words)), // variable
6: wordsToIntBE, // default: 3600 (1 hour)
24: wordsToIntBE, // default: 9
3: routingInfoParser, // for extra routing info (private etc.)
5: featureBitsParser // keep feature bits as array of 5 bit words
};
function getUnknownParser(tagCode) {
return words => ({
tagCode: parseInt(tagCode),
words: bech32.encode('unknown', words, Number.MAX_SAFE_INTEGER)
})
}
function wordsToIntBE(words) {
return words.reverse().reduce((total, item, index) => {
return total + item * Math.pow(32, index)
}, 0)
}
// first convert from words to buffer, trimming padding where necessary
// parse in 51 byte chunks. See encoder for details.
function routingInfoParser(words) {
const routes = [];
let pubkey,
shortChannelId,
feeBaseMSats,
feeProportionalMillionths,
cltvExpiryDelta;
let routesBuffer = bech32.fromWordsUnsafe(words);
while (routesBuffer.length > 0) {
pubkey = hex.encode(routesBuffer.slice(0, 33)); // 33 bytes
shortChannelId = hex.encode(routesBuffer.slice(33, 41)); // 8 bytes
feeBaseMSats = parseInt(hex.encode(routesBuffer.slice(41, 45)), 16); // 4 bytes
feeProportionalMillionths = parseInt(
hex.encode(routesBuffer.slice(45, 49)),
16
); // 4 bytes
cltvExpiryDelta = parseInt(hex.encode(routesBuffer.slice(49, 51)), 16); // 2 bytes
routesBuffer = routesBuffer.slice(51);
routes.push({
pubkey,
short_channel_id: shortChannelId,
fee_base_msat: feeBaseMSats,
fee_proportional_millionths: feeProportionalMillionths,
cltv_expiry_delta: cltvExpiryDelta
});
}
return routes
}
function featureBitsParser(words) {
const bools = words
.slice()
.reverse()
.map(word => [
!!(word & 0b1),
!!(word & 0b10),
!!(word & 0b100),
!!(word & 0b1000),
!!(word & 0b10000)
])
.reduce((finalArr, itemArr) => finalArr.concat(itemArr), []);
while (bools.length < FEATUREBIT_ORDER.length * 2) {
bools.push(false);
}
const featureBits = {};
FEATUREBIT_ORDER.forEach((featureName, index) => {
let status;
if (bools[index * 2]) {
status = 'required';
} else if (bools[index * 2 + 1]) {
status = 'supported';
} else {
status = 'unsupported';
}
featureBits[featureName] = status;
});
const extraBits = bools.slice(FEATUREBIT_ORDER.length * 2);
featureBits.extra_bits = {
start_bit: FEATUREBIT_ORDER.length * 2,
bits: extraBits,
has_required: extraBits.reduce(
(result, bit, index) =>
index % 2 !== 0 ? result || false : result || bit,
false
)
};
return featureBits
}
function hrpToMillisat(hrpString, outputString) {
let divisor, value;
if (hrpString.slice(-1).match(/^[munp]$/)) {
divisor = hrpString.slice(-1);
value = hrpString.slice(0, -1);
} else if (hrpString.slice(-1).match(/^[^munp0-9]$/)) {
throw new Error('Not a valid multiplier for the amount')
} else {
value = hrpString;
}
if (!value.match(/^\d+$/))
throw new Error('Not a valid human readable amount')
const valueBN = BigInt(value);
const millisatoshisBN = divisor
? (valueBN * MILLISATS_PER_BTC) / DIVISORS[divisor]
: valueBN * MILLISATS_PER_BTC;
if (
(divisor === 'p' && !(valueBN % BigInt(10) === BigInt(0))) ||
millisatoshisBN > MAX_MILLISATS
) {
throw new Error('Amount is outside of valid range')
}
return outputString ? millisatoshisBN.toString() : millisatoshisBN
}
// decode will only have extra comments that aren't covered in encode comments.
// also if anything is hard to read I'll comment.
function decode(paymentRequest, network) {
if (typeof paymentRequest !== 'string')
throw new Error('Lightning Payment Request must be string')
if (paymentRequest.slice(0, 2).toLowerCase() !== 'ln')
throw new Error('Not a proper lightning payment request')
const sections = [];
const decoded = bech32.decode(paymentRequest, Number.MAX_SAFE_INTEGER);
paymentRequest = paymentRequest.toLowerCase();
const prefix = decoded.prefix;
let words = decoded.words;
let letters = paymentRequest.slice(prefix.length + 1);
let sigWords = words.slice(-104);
words = words.slice(0, -104);
// Without reverse lookups, can't say that the multipier at the end must
// have a number before it, so instead we parse, and if the second group
// doesn't have anything, there's a good chance the last letter of the
// coin type got captured by the third group, so just re-regex without
// the number.
let prefixMatches = prefix.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);
if (prefixMatches && !prefixMatches[2])
prefixMatches = prefix.match(/^ln(\S+)$/);
if (!prefixMatches) {
throw new Error('Not a proper lightning payment request')
}
// "ln" section
sections.push({
name: 'lightning_network',
letters: 'ln'
});
// "bc" section
const bech32Prefix = prefixMatches[1];
let coinNetwork;
if (!network) {
switch (bech32Prefix) {
case DEFAULTNETWORK.bech32:
coinNetwork = DEFAULTNETWORK;
break
case TESTNETWORK.bech32:
coinNetwork = TESTNETWORK;
break
case SIGNETNETWORK.bech32:
coinNetwork = SIGNETNETWORK;
break
case REGTESTNETWORK.bech32:
coinNetwork = REGTESTNETWORK;
break
case SIMNETWORK.bech32:
coinNetwork = SIMNETWORK;
break
}
} else {
if (
network.bech32 === undefined ||
network.pubKeyHash === undefined ||
network.scriptHash === undefined ||
!Array.isArray(network.validWitnessVersions)
)
throw new Error('Invalid network')
coinNetwork = network;
}
if (!coinNetwork || coinNetwork.bech32 !== bech32Prefix) {
throw new Error('Unknown coin bech32 prefix')
}
sections.push({
name: 'coin_network',
letters: bech32Prefix,
value: coinNetwork
});
// amount section
const value = prefixMatches[2];
let millisatoshis;
if (value) {
const divisor = prefixMatches[3];
millisatoshis = hrpToMillisat(value + divisor, true);
sections.push({
name: 'amount',
letters: prefixMatches[2] + prefixMatches[3],
value: millisatoshis
});
} else {
millisatoshis = null;
}
// "1" separator
sections.push({
name: 'separator',
letters: '1'
});
// timestamp
const timestamp = wordsToIntBE(words.slice(0, 7));
words = words.slice(7); // trim off the left 7 words
sections.push({
name: 'timestamp',
letters: letters.slice(0, 7),
value: timestamp
});
letters = letters.slice(7);
let tagName, parser, tagLength, tagWords;
// we have no tag count to go on, so just keep hacking off words
// until we have none.
while (words.length > 0) {
const tagCode = words[0].toString();
tagName = TAGNAMES[tagCode] || 'unknown_tag';
parser = TAGPARSERS[tagCode] || getUnknownParser(tagCode);
words = words.slice(1);
tagLength = wordsToIntBE(words.slice(0, 2));
words = words.slice(2);
tagWords = words.slice(0, tagLength);
words = words.slice(tagLength);
sections.push({
name: tagName,
tag: letters[0],
letters: letters.slice(0, 1 + 2 + tagLength),
value: parser(tagWords) // see: parsers for more comments
});
letters = letters.slice(1 + 2 + tagLength);
}
// signature
sections.push({
name: 'signature',
letters: letters.slice(0, 104),
value: hex.encode(bech32.fromWordsUnsafe(sigWords))
});
letters = letters.slice(104);
// checksum
sections.push({
name: 'checksum',
letters: letters
});
let result = {
paymentRequest,
sections,
get expiry() {
let exp = sections.find(s => s.name === 'expiry');
if (exp) return getValue('timestamp') + exp.value
},
get route_hints() {
return sections.filter(s => s.name === 'route_hint').map(s => s.value)
}
};
for (let name in TAGCODES) {
if (name === 'route_hint') {
// route hints can be multiple, so this won't work for them
continue
}
Object.defineProperty(result, name, {
get() {
return getValue(name)
}
});
}
return result
function getValue(name) {
let section = sections.find(s => s.name === name);
return section ? section.value : undefined
}
}
bolt11 = {
decode,
hrpToMillisat
};
return bolt11;
}
var bolt11Exports = requireBolt11();
// from https://stackoverflow.com/a/50868276
const fromHexString = (hexString) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const decodeInvoice = (paymentRequest) => {
if (!paymentRequest)
return null;
try {
const decoded = bolt11Exports.decode(paymentRequest);
if (!decoded || !decoded.sections)
return null;
const hashTag = decoded.sections.find((value) => value.name === "payment_hash");
if (hashTag?.name !== "payment_hash" || !hashTag.value)
return null;
const paymentHash = hashTag.value;
let satoshi = 0;
const amountTag = decoded.sections.find((value) => value.name === "amount");
if (amountTag?.name === "amount" && amountTag.value) {
satoshi = parseInt(amountTag.value) / 1000; // millisats
}
const timestampTag = decoded.sections.find((value) => value.name === "timestamp");
if (timestampTag?.name !== "timestamp" || !timestampTag.value)
return null;
const timestamp = timestampTag.value;
let expiry;
const expiryTag = decoded.sections.find((value) => value.name === "expiry");
if (expiryTag?.name === "expiry") {
expiry = expiryTag.value;
}
const descriptionTag = decoded.sections.find((value) => value.name === "description");
const description = descriptionTag?.name === "description"
? descriptionTag?.value
: undefined;
return {
paymentHash,
satoshi,
timestamp,
expiry,
description,
};
}
catch {
return null;
}
};
function bytes(b, ...lengths) {
if (!(b instanceof Uint8Array))
throw new Error('Expected Uint8Array');
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error('Hash instance has been destroyed');
if (checkFinished && instance.finished)
throw new Error('Hash#digest() has already been called');
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
// node.js versions earlier than v19 don't declare it in global scope.
// For node.js, package.json#exports field mapping rewrites import
// from `crypto` to `cryptoNode`, which imports native module.
// Makes the utils un-importable in browsers without a bundler.
// Once node.js 18 is deprecated, we can just drop the import.
const u8a = (a) => a instanceof Uint8Array;
// Cast array to view
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
// The rotate right (circular right shift) operation for uint32
const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
// big-endian hardware is rare. Just in case someone still decides to run hashes:
// early-throw an error because we don't support BE yet.
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
if (!isLE)
throw new Error('Non little-endian hardware is not supported');
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
/**
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
function bytesToHex(bytes) {
if (!u8a(bytes))
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x
let hex = '';
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]];
}
return hex;
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
function utf8ToBytes(str) {
if (typeof str !== 'string')
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
/**
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
* Warning: when Uint8Array is passed, it would NOT get copied.
* Keep in mind for future mutable operations.
*/
function toBytes(data) {
if (typeof data === 'string')
data = utf8ToBytes(data);
if (!u8a(data))
throw new Error(`expected Uint8Array, got ${typeof data}`);
return data;
}
// For runtime check if class implements interface
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
// Polyfill for Safari 14
function setBigUint64(view, byteOffset, value, isLE) {
if (typeof view.setBigUint64 === 'function')
return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(0xffffffff);
const wh = Number((value >> _32n) & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
// Base SHA2 class (RFC 6234)
class SHA2 extends Hash {
constructor(blockLen, outputLen, padOffset, isLE) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
exists(this);
const { view, buffer, blockLen } = this;
data = toBytes(data);
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
exists(this);
output(out, this);
this.finished = true;
// Padding
// We can avoid allocation of buffer for padding completely if it
// was previously not allocated here. But it won't change performance.
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
// append the bit '1' to the message
buffer[pos++] = 0b10000000;
this.buffer.subarray(pos).fill(0);
// we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
// Pad until full block byte with zeros
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
// So we just write lowest 64 bits of that value.
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
// NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
if (len % 4)
throw new Error('_sha2: outputLen should be aligned to 32bit');
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error('_sha2: outputLen bigger than state');
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
}
// SHA2-256 need to try 2^128 hashes to execute birthday attack.
// BTC network is doing 2^67 hashes/sec as per early 2023.
// Choice: a ? b : c
const Chi = (a, b, c) => (a & b) ^ (~a & c);
// Majority function, true if any two inpust is true
const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
// Round constants:
// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
// prettier-ignore
const SHA256_K = /* @__PURE__ */ new Uint32Array([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
// prettier-ignore
const IV = /* @__PURE__ */ new Uint32Array([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
]);
// Temporary buffer, not used to store anything between runs
// Named this way because it matches specification.
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends SHA2 {
constructor() {
super(64, 32, 8, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
this.A = IV[0] | 0;
this.B = IV[1] | 0;
this.C = IV[2] | 0;
this.D = IV[3] | 0;
this.E = IV[4] | 0;
this.F = IV[5] | 0;
this.G = IV[6] | 0;
this.H = IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
}
// Compression function main loop, 64 rounds
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = (sigma0 + Maj(A, B, C)) | 0;
H = G;
G = F;
F = E;
E = (D + T1) | 0;
D = C;
C = B;
B = A;
A = (T1 + T2) | 0;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
F = (F + this.F) | 0;
G = (G + this.G) | 0;
H = (H + this.H) | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
}
/**
* SHA2-256 hash function
* @param message - data that would be hashed
*/
const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
class Invoice {
constructor(args) {
this.paymentRequest = args.pr;
if (!this.paymentRequest) {
throw new Error("Invalid payment request");
}
const decodedInvoice = decodeInvoice(this.paymentRequest);
if (!decodedInvoice) {
throw new Error("Failed to decode payment request");
}
this.paymentHash = decodedInvoice.paymentHash;
this.satoshi = decodedInvoice.satoshi;
this.timestamp = decodedInvoice.timestamp;
this.expiry = decodedInvoice.expiry;
this.createdDate = new Date(this.timestamp * 1000);
this.expiryDate = this.expiry
? new Date((this.timestamp + this.expiry) * 1000)
: undefined;
this.description = decodedInvoice.description ?? null;
this.verify = args.verify ?? null;
this.preimage = args.preimage ?? null;
this.successAction = args.successAction ?? null;
}
async isPaid() {
if (this.preimage)
return this.validatePreimage(this.preimage);
else if (this.verify) {
return await this.verifyPayment();
}
else {
throw new Error("Could not verify payment");
}
}
validatePreimage(preimage) {
if (!preimage || !this.paymentHash)
return false;
try {
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
return this.paymentHash === preimageHash;
}
catch {
return false;
}
}
async verifyPayment() {
try {
if (!this.verify) {
throw new Error("LNURL verify not available");
}
const response = await fetch(this.verify);
if (!response.ok) {
throw new Error(`Verification request failed: ${response.status} ${response.statusText}`);
}
const json = await response.json();
if (json.preimage) {
this.preimage = json.preimage;
}
return json.settled;
}
catch (error) {
console.error("Failed to check LNURL-verify", error);
return false;
}
}
hasExpired() {
const { expiryDate } = this;
if (expiryDate) {
return expiryDate.getTime() < Date.now();
}
return false;
}
}
exports.Invoice = Invoice;
exports.decodeInvoice = decodeInvoice;
exports.fromHexString = fromHexString;
//# sourceMappingURL=bolt11.cjs.map

Sorry, the diff of this file is too big to display

'use strict';
const numSatsInBtc = 100000000;
const getFiatBtcRate = async (currency) => {
const url = "https://getalby.com/api/rates/" + currency.toLowerCase() + ".json";
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch rate: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data.rate_float / numSatsInBtc;
};
const getFiatValue = async ({ satoshi, currency, }) => {
const rate = await getFiatBtcRate(currency);
return Number(satoshi) * rate;
};
const getSatoshiValue = async ({ amount, currency, }) => {
const rate = await getFiatBtcRate(currency);
return Math.floor(Number(amount) / rate);
};
const getFormattedFiatValue = async ({ satoshi, currency, locale, }) => {
if (!locale) {
locale = "en";
}
const fiatValue = await getFiatValue({ satoshi, currency });
return fiatValue.toLocaleString(locale, {
style: "currency",
currency,
});
};
exports.getFiatBtcRate = getFiatBtcRate;
exports.getFiatValue = getFiatValue;
exports.getFormattedFiatValue = getFormattedFiatValue;
exports.getSatoshiValue = getSatoshiValue;
//# sourceMappingURL=fiat.cjs.map
{"version":3,"file":"fiat.cjs","sources":["../../src/fiat/fiat.ts"],"sourcesContent":["const numSatsInBtc = 100_000_000;\n\nexport const getFiatBtcRate = async (currency: string): Promise<number> => {\n const url =\n \"https://getalby.com/api/rates/\" + currency.toLowerCase() + \".json\";\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch rate: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n return data.rate_float / numSatsInBtc;\n};\n\nexport const getFiatValue = async ({\n satoshi,\n currency,\n}: {\n satoshi: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Number(satoshi) * rate;\n};\n\nexport const getSatoshiValue = async ({\n amount,\n currency,\n}: {\n amount: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Math.floor(Number(amount) / rate);\n};\n\nexport const getFormattedFiatValue = async ({\n satoshi,\n currency,\n locale,\n}: {\n satoshi: number | string;\n currency: string;\n locale: string;\n}) => {\n if (!locale) {\n locale = \"en\";\n }\n const fiatValue = await getFiatValue({ satoshi, currency });\n return fiatValue.toLocaleString(locale, {\n style: \"currency\",\n currency,\n });\n};\n"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,SAAW;MAEnB,cAAc,GAAG,OAAO,QAAgB,KAAqB;IACxE,MAAM,GAAG,GACP,gCAAgC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,OAAO;AACrE,IAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AAEjC,IAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CAClE;IACH;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AAElC,IAAA,OAAO,IAAI,CAAC,UAAU,GAAG,YAAY;AACvC;AAEO,MAAM,YAAY,GAAG,OAAO,EACjC,OAAO,EACP,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;AAE3C,IAAA,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI;AAC/B;AAEO,MAAM,eAAe,GAAG,OAAO,EACpC,MAAM,EACN,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;IAE3C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC1C;AAEO,MAAM,qBAAqB,GAAG,OAAO,EAC1C,OAAO,EACP,QAAQ,EACR,MAAM,GAKP,KAAI;IACH,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,IAAI;IACf;IACA,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC3D,IAAA,OAAO,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE;AACtC,QAAA,KAAK,EAAE,UAAU;QACjB,QAAQ;AACT,KAAA,CAAC;AACJ;;;;;;;"}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

'use strict';
class MemoryStorage {
constructor(initial) {
this.storage = initial || {};
}
getItem(key) {
return this.storage[key];
}
setItem(key, value) {
this.storage[key] = value;
}
}
class NoStorage {
constructor(initial) { }
getItem(key) {
return null;
}
setItem(key, value) { }
}
const parseL402 = (input) => {
// Remove the L402 and LSAT identifiers
const string = input.replace("L402", "").replace("LSAT", "").trim();
// Initialize an object to store the key-value pairs
const keyValuePairs = {};
// Regular expression to match key and (quoted or unquoted) value
const regex = /(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;
let match;
// Use regex to find all key-value pairs
while ((match = regex.exec(string)) !== null) {
// Key is always match[1]
// Value is either match[3] (double-quoted), match[4] (single-quoted), or match[5] (unquoted)
keyValuePairs[match[1]] = match[3] || match[4] || match[5];
}
return keyValuePairs;
};
const memoryStorage = new MemoryStorage();
const HEADER_KEY = "L402"; // we have to update this to L402 at some point
const fetchWithL402 = async (url, fetchArgs, options) => {
if (!options) {
options = {};
}
const headerKey = options.headerKey || HEADER_KEY;
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN is missing");
}
const store = options.store || memoryStorage;
if (!fetchArgs) {
fetchArgs = {};
}
fetchArgs.cache = "no-store";
fetchArgs.mode = "cors";
if (!fetchArgs.headers) {
fetchArgs.headers = {};
}
const cachedL402Data = store.getItem(url);
if (cachedL402Data) {
const data = JSON.parse(cachedL402Data);
fetchArgs.headers["Authorization"] =
`${headerKey} ${data.token}:${data.preimage}`;
return await fetch(url, fetchArgs);
}
fetchArgs.headers["Accept-Authenticate"] = headerKey;
const initResp = await fetch(url, fetchArgs);
const header = initResp.headers.get("www-authenticate");
if (!header) {
return initResp;
}
const details = parseL402(header);
const token = details.token || details.macaroon;
const inv = details.invoice;
await webln.enable();
const invResp = await webln.sendPayment(inv);
store.setItem(url, JSON.stringify({
token: token,
preimage: invResp.preimage,
}));
fetchArgs.headers["Authorization"] =
`${headerKey} ${token}:${invResp.preimage}`;
return await fetch(url, fetchArgs);
};
exports.MemoryStorage = MemoryStorage;
exports.NoStorage = NoStorage;
exports.fetchWithL402 = fetchWithL402;
exports.parseL402 = parseL402;
//# sourceMappingURL=l402.cjs.map
{"version":3,"file":"l402.cjs","sources":["../../src/l402/utils.ts","../../src/l402/l402.ts"],"sourcesContent":["export interface KVStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nexport class MemoryStorage implements KVStorage {\n storage;\n\n constructor(initial?: Record<string, unknown>) {\n this.storage = initial || {};\n }\n\n getItem(key: string) {\n return this.storage[key];\n }\n\n setItem(key: string, value: unknown) {\n this.storage[key] = value;\n }\n}\n\nexport class NoStorage implements KVStorage {\n constructor(initial?: unknown) {}\n\n getItem(key: string) {\n return null;\n }\n\n setItem(key: string, value: unknown) {}\n}\n\nexport const parseL402 = (input: string): Record<string, string> => {\n // Remove the L402 and LSAT identifiers\n const string = input.replace(\"L402\", \"\").replace(\"LSAT\", \"\").trim();\n\n // Initialize an object to store the key-value pairs\n const keyValuePairs = {};\n\n // Regular expression to match key and (quoted or unquoted) value\n const regex = /(\\w+)=(\"([^\"]*)\"|'([^']*)'|([^,]*))/g;\n let match;\n\n // Use regex to find all key-value pairs\n while ((match = regex.exec(string)) !== null) {\n // Key is always match[1]\n // Value is either match[3] (double-quoted), match[4] (single-quoted), or match[5] (unquoted)\n keyValuePairs[match[1]] = match[3] || match[4] || match[5];\n }\n\n return keyValuePairs;\n};\n","import { KVStorage, MemoryStorage, parseL402 } from \"./utils\";\nimport { WebLNProvider } from \"@webbtc/webln-types\";\n\nconst memoryStorage = new MemoryStorage();\n\nconst HEADER_KEY = \"L402\"; // we have to update this to L402 at some point\n\nexport const fetchWithL402 = async (\n url: string,\n fetchArgs: RequestInit,\n options: {\n headerKey?: string;\n webln?: WebLNProvider;\n store?: KVStorage;\n },\n) => {\n if (!options) {\n options = {};\n }\n const headerKey = options.headerKey || HEADER_KEY;\n const webln: WebLNProvider = options.webln || globalThis.webln;\n if (!webln) {\n throw new Error(\"WebLN is missing\");\n }\n const store = options.store || memoryStorage;\n if (!fetchArgs) {\n fetchArgs = {};\n }\n fetchArgs.cache = \"no-store\";\n fetchArgs.mode = \"cors\";\n if (!fetchArgs.headers) {\n fetchArgs.headers = {};\n }\n const cachedL402Data = store.getItem(url);\n if (cachedL402Data) {\n const data = JSON.parse(cachedL402Data);\n fetchArgs.headers[\"Authorization\"] =\n `${headerKey} ${data.token}:${data.preimage}`;\n return await fetch(url, fetchArgs);\n }\n\n fetchArgs.headers[\"Accept-Authenticate\"] = headerKey;\n const initResp = await fetch(url, fetchArgs);\n const header = initResp.headers.get(\"www-authenticate\");\n if (!header) {\n return initResp;\n }\n\n const details = parseL402(header);\n const token = details.token || details.macaroon;\n const inv = details.invoice;\n\n await webln.enable();\n const invResp = await webln.sendPayment(inv);\n\n store.setItem(\n url,\n JSON.stringify({\n token: token,\n preimage: invResp.preimage,\n }),\n );\n\n fetchArgs.headers[\"Authorization\"] =\n `${headerKey} ${token}:${invResp.preimage}`;\n return await fetch(url, fetchArgs);\n};\n"],"names":[],"mappings":";;MAKa,aAAa,CAAA;AAGxB,IAAA,WAAA,CAAY,OAAiC,EAAA;AAC3C,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE;IAC9B;AAEA,IAAA,OAAO,CAAC,GAAW,EAAA;AACjB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC1B;IAEA,OAAO,CAAC,GAAW,EAAE,KAAc,EAAA;AACjC,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK;IAC3B;AACD;MAEY,SAAS,CAAA;IACpB,WAAA,CAAY,OAAiB,IAAG;AAEhC,IAAA,OAAO,CAAC,GAAW,EAAA;AACjB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,OAAO,CAAC,GAAW,EAAE,KAAc,IAAG;AACvC;AAEM,MAAM,SAAS,GAAG,CAAC,KAAa,KAA4B;;IAEjE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;;IAGnE,MAAM,aAAa,GAAG,EAAE;;IAGxB,MAAM,KAAK,GAAG,sCAAsC;AACpD,IAAA,IAAI,KAAK;;AAGT,IAAA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE;;;QAG5C,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;IAC5D;AAEA,IAAA,OAAO,aAAa;AACtB;;AC/CA,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE;AAEzC,MAAM,UAAU,GAAG,MAAM,CAAC;AAEnB,MAAM,aAAa,GAAG,OAC3B,GAAW,EACX,SAAsB,EACtB,OAIC,KACC;IACF,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,GAAG,EAAE;IACd;AACA,IAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,UAAU;IACjD,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;IAC9D,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC;IACrC;AACA,IAAA,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa;IAC5C,IAAI,CAAC,SAAS,EAAE;QACd,SAAS,GAAG,EAAE;IAChB;AACA,IAAA,SAAS,CAAC,KAAK,GAAG,UAAU;AAC5B,IAAA,SAAS,CAAC,IAAI,GAAG,MAAM;AACvB,IAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;AACtB,QAAA,SAAS,CAAC,OAAO,GAAG,EAAE;IACxB;IACA,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IACzC,IAAI,cAAc,EAAE;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;AACvC,QAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;YAChC,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAA,CAAE;AAC/C,QAAA,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;IACpC;AAEA,IAAA,SAAS,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,SAAS;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;IAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,OAAO,QAAQ;IACjB;AAEA,IAAA,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,QAAQ;AAC/C,IAAA,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO;AAE3B,IAAA,MAAM,KAAK,CAAC,MAAM,EAAE;IACpB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;IAE5C,KAAK,CAAC,OAAO,CACX,GAAG,EACH,IAAI,CAAC,SAAS,CAAC;AACb,QAAA,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC3B,KAAA,CAAC,CACH;AAED,IAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;QAChC,CAAA,EAAG,SAAS,IAAI,KAAK,CAAA,CAAA,EAAI,OAAO,CAAC,QAAQ,EAAE;AAC7C,IAAA,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;AACpC;;;;;;;"}
'use strict';
function bytes(b, ...lengths) {
if (!(b instanceof Uint8Array))
throw new Error('Expected Uint8Array');
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error('Hash instance has been destroyed');
if (checkFinished && instance.finished)
throw new Error('Hash#digest() has already been called');
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
// node.js versions earlier than v19 don't declare it in global scope.
// For node.js, package.json#exports field mapping rewrites import
// from `crypto` to `cryptoNode`, which imports native module.
// Makes the utils un-importable in browsers without a bundler.
// Once node.js 18 is deprecated, we can just drop the import.
const u8a = (a) => a instanceof Uint8Array;
// Cast array to view
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
// The rotate right (circular right shift) operation for uint32
const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
// big-endian hardware is rare. Just in case someone still decides to run hashes:
// early-throw an error because we don't support BE yet.
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
if (!isLE)
throw new Error('Non little-endian hardware is not supported');
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
/**
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
function bytesToHex(bytes) {
if (!u8a(bytes))
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x
let hex = '';
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]];
}
return hex;
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
function utf8ToBytes(str) {
if (typeof str !== 'string')
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
/**
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
* Warning: when Uint8Array is passed, it would NOT get copied.
* Keep in mind for future mutable operations.
*/
function toBytes(data) {
if (typeof data === 'string')
data = utf8ToBytes(data);
if (!u8a(data))
throw new Error(`expected Uint8Array, got ${typeof data}`);
return data;
}
// For runtime check if class implements interface
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
// Polyfill for Safari 14
function setBigUint64(view, byteOffset, value, isLE) {
if (typeof view.setBigUint64 === 'function')
return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(0xffffffff);
const wh = Number((value >> _32n) & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
// Base SHA2 class (RFC 6234)
class SHA2 extends Hash {
constructor(blockLen, outputLen, padOffset, isLE) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
exists(this);
const { view, buffer, blockLen } = this;
data = toBytes(data);
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
exists(this);
output(out, this);
this.finished = true;
// Padding
// We can avoid allocation of buffer for padding completely if it
// was previously not allocated here. But it won't change performance.
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
// append the bit '1' to the message
buffer[pos++] = 0b10000000;
this.buffer.subarray(pos).fill(0);
// we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
// Pad until full block byte with zeros
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
// So we just write lowest 64 bits of that value.
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
// NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
if (len % 4)
throw new Error('_sha2: outputLen should be aligned to 32bit');
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error('_sha2: outputLen bigger than state');
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
}
// SHA2-256 need to try 2^128 hashes to execute birthday attack.
// BTC network is doing 2^67 hashes/sec as per early 2023.
// Choice: a ? b : c
const Chi = (a, b, c) => (a & b) ^ (~a & c);
// Majority function, true if any two inpust is true
const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
// Round constants:
// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
// prettier-ignore
const SHA256_K = /* @__PURE__ */ new Uint32Array([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
// prettier-ignore
const IV = /* @__PURE__ */ new Uint32Array([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
]);
// Temporary buffer, not used to store anything between runs
// Named this way because it matches specification.
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends SHA2 {
constructor() {
super(64, 32, 8, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
this.A = IV[0] | 0;
this.B = IV[1] | 0;
this.C = IV[2] | 0;
this.D = IV[3] | 0;
this.E = IV[4] | 0;
this.F = IV[5] | 0;
this.G = IV[6] | 0;
this.H = IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
}
// Compression function main loop, 64 rounds
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = (sigma0 + Maj(A, B, C)) | 0;
H = G;
G = F;
F = E;
E = (D + T1) | 0;
D = C;
C = B;
B = A;
A = (T1 + T2) | 0;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
F = (F + this.F) | 0;
G = (G + this.G) | 0;
H = (H + this.H) | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
}
/**
* SHA2-256 hash function
* @param message - data that would be hashed
*/
const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
const TAG_KEYSEND = "keysend";
const parseKeysendResponse = (data) => {
if (data.tag !== TAG_KEYSEND)
throw new Error("Invalid keysend params");
if (data.status !== "OK")
throw new Error("Keysend status not OK");
if (!data.pubkey)
throw new Error("Pubkey does not exist");
const destination = data.pubkey;
let customKey, customValue;
if (data.customData && data.customData[0]) {
customKey = data.customData[0].customKey;
customValue = data.customData[0].customValue;
}
return {
destination,
customKey,
customValue,
};
};
async function generateZapEvent({ satoshi, comment, p, e, relays }, options = {}) {
const nostr = options.nostr || globalThis.nostr;
if (!nostr) {
throw new Error("nostr option or window.nostr is not available");
}
const nostrTags = [
["relays", ...relays],
["amount", satoshi.toString()],
];
if (p) {
nostrTags.push(["p", p]);
}
if (e) {
nostrTags.push(["e", e]);
}
const pubkey = await nostr.getPublicKey();
const nostrEvent = {
pubkey,
created_at: Math.floor(Date.now() / 1000),
kind: 9734,
tags: nostrTags,
content: comment ?? "",
};
nostrEvent.id = getEventHash(nostrEvent);
return await nostr.signEvent(nostrEvent);
}
function validateEvent(event) {
if (typeof event.content !== "string")
return false;
if (typeof event.created_at !== "number")
return false;
// ignore these checks because if the pubkey is not set we add it to the event. same for the ID.
// if (typeof event.pubkey !== "string") return false;
// if (!event.pubkey.match(/^[a-f0-9]{64}$/)) return false;
if (!Array.isArray(event.tags))
return false;
for (let i = 0; i < event.tags.length; i++) {
const tag = event.tags[i];
if (!Array.isArray(tag))
return false;
for (let j = 0; j < tag.length; j++) {
if (typeof tag[j] === "object")
return false;
}
}
return true;
}
function serializeEvent(evt) {
if (!validateEvent(evt))
throw new Error("can't serialize event with wrong or missing properties");
return JSON.stringify([
0,
evt.pubkey,
evt.created_at,
evt.kind,
evt.tags,
evt.content,
]);
}
function getEventHash(event) {
return bytesToHex(sha256(serializeEvent(event)));
}
function parseNostrResponse(nostrData, username) {
let nostrPubkey;
let nostrRelays;
if (username && nostrData) {
nostrPubkey = nostrData.names?.[username];
nostrRelays = nostrPubkey ? nostrData.relays?.[nostrPubkey] : undefined;
}
return [nostrData, nostrPubkey, nostrRelays];
}
const URL_REGEX = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/;
const isUrl = (url) => {
if (!url)
return false;
return URL_REGEX.test(url);
};
const isValidAmount = ({ amount, min, max, }) => {
return amount > 0 && amount >= min && amount <= max;
};
const TAG_PAY_REQUEST = "payRequest";
// From: https://github.com/dolcalmi/lnurl-pay/blob/main/src/request-pay-service-params.ts
const parseLnUrlPayResponse = async (data) => {
if (data.tag !== TAG_PAY_REQUEST)
throw new Error("Invalid pay service params");
const callback = (data.callback + "").trim();
if (!isUrl(callback))
throw new Error("Callback must be a valid url");
const min = Math.ceil(Number(data.minSendable || 0));
const max = Math.floor(Number(data.maxSendable));
if (!(min && max) || min > max)
throw new Error("Invalid pay service params");
let metadata;
let metadataHash;
try {
metadata = JSON.parse(data.metadata + "");
metadataHash = bytesToHex(sha256(data.metadata + ""));
}
catch {
metadata = [];
metadataHash = bytesToHex(sha256("[]"));
}
let email = "";
let image = "";
let description = "";
let identifier = "";
for (let i = 0; i < metadata.length; i++) {
const [k, v] = metadata[i];
switch (k) {
case "text/plain":
description = v;
break;
case "text/identifier":
identifier = v;
break;
case "text/email":
email = v;
break;
case "image/png;base64":
case "image/jpeg;base64":
image = "data:" + k + "," + v;
break;
}
}
const payerData = data.payerData;
let domain;
try {
domain = new URL(callback).hostname;
}
catch {
// fail silently and let domain remain undefined if callback is not a valid URL
}
return {
callback,
fixed: min === max,
min,
max,
domain,
metadata,
metadataHash,
identifier,
email,
description,
image,
payerData,
commentAllowed: Number(data.commentAllowed) || 0,
rawData: data,
allowsNostr: data.allowsNostr || false,
};
};
var lib = {};
var hasRequiredLib;
function requireLib () {
if (hasRequiredLib) return lib;
hasRequiredLib = 1;
(function (exports) {
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64url = exports.base64 = exports.base32crockford = exports.base32hex = exports.base32 = exports.base16 = exports.utils = exports.assertNumber = void 0;
function assertNumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`Wrong integer: ${n}`);
}
exports.assertNumber = assertNumber;
function chain(...args) {
const wrap = (a, b) => (c) => a(b(c));
const encode = Array.from(args)
.reverse()
.reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);
const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);
return { encode, decode };
}
function alphabet(alphabet) {
return {
encode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('alphabet.encode input should be an array of numbers');
return digits.map((i) => {
assertNumber(i);
if (i < 0 || i >= alphabet.length)
throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);
return alphabet[i];
});
},
decode: (input) => {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('alphabet.decode input should be array of strings');
return input.map((letter) => {
if (typeof letter !== 'string')
throw new Error(`alphabet.decode: not string element=${letter}`);
const index = alphabet.indexOf(letter);
if (index === -1)
throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);
return index;
});
},
};
}
function join(separator = '') {
if (typeof separator !== 'string')
throw new Error('join separator should be string');
return {
encode: (from) => {
if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))
throw new Error('join.encode input should be array of strings');
for (let i of from)
if (typeof i !== 'string')
throw new Error(`join.encode: non-string input=${i}`);
return from.join(separator);
},
decode: (to) => {
if (typeof to !== 'string')
throw new Error('join.decode input should be string');
return to.split(separator);
},
};
}
function padding(bits, chr = '=') {
assertNumber(bits);
if (typeof chr !== 'string')
throw new Error('padding chr should be string');
return {
encode(data) {
if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of data)
if (typeof i !== 'string')
throw new Error(`padding.encode: non-string input=${i}`);
while ((data.length * bits) % 8)
data.push(chr);
return data;
},
decode(input) {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of input)
if (typeof i !== 'string')
throw new Error(`padding.decode: non-string input=${i}`);
let end = input.length;
if ((end * bits) % 8)
throw new Error('Invalid padding: string should have whole number of bytes');
for (; end > 0 && input[end - 1] === chr; end--) {
if (!(((end - 1) * bits) % 8))
throw new Error('Invalid padding: string has too much padding');
}
return input.slice(0, end);
},
};
}
function normalize(fn) {
if (typeof fn !== 'function')
throw new Error('normalize fn should be function');
return { encode: (from) => from, decode: (to) => fn(to) };
}
function convertRadix(data, from, to) {
if (from < 2)
throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
if (to < 2)
throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
if (!Array.isArray(data))
throw new Error('convertRadix: data should be array');
if (!data.length)
return [];
let pos = 0;
const res = [];
const digits = Array.from(data);
digits.forEach((d) => {
assertNumber(d);
if (d < 0 || d >= from)
throw new Error(`Wrong integer: ${d}`);
});
while (true) {
let carry = 0;
let done = true;
for (let i = pos; i < digits.length; i++) {
const digit = digits[i];
const digitBase = from * carry + digit;
if (!Number.isSafeInteger(digitBase) ||
(from * carry) / from !== carry ||
digitBase - digit !== from * carry) {
throw new Error('convertRadix: carry overflow');
}
carry = digitBase % to;
digits[i] = Math.floor(digitBase / to);
if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)
throw new Error('convertRadix: carry overflow');
if (!done)
continue;
else if (!digits[i])
pos = i;
else
done = false;
}
res.push(carry);
if (done)
break;
}
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
res.push(0);
return res.reverse();
}
const gcd = (a, b) => (!b ? a : gcd(b, a % b));
const radix2carry = (from, to) => from + (to - gcd(from, to));
function convertRadix2(data, from, to, padding) {
if (!Array.isArray(data))
throw new Error('convertRadix2: data should be array');
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0;
const mask = 2 ** to - 1;
const res = [];
for (const n of data) {
assertNumber(n);
if (n >= 2 ** from)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = (carry << from) | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push(((carry >> (pos - to)) & mask) >>> 0);
carry &= 2 ** pos - 1;
}
carry = (carry << (to - pos)) & mask;
if (!padding && pos >= from)
throw new Error('Excess padding');
if (!padding && carry)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
function radix(num) {
assertNumber(num);
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix.encode input should be Uint8Array');
return convertRadix(Array.from(bytes), 2 ** 8, num);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix.decode input should be array of strings');
return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
},
};
}
function radix2(bits, revPadding = false) {
assertNumber(bits);
if (bits <= 0 || bits > 32)
throw new Error('radix2: bits should be in (0..32]');
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
throw new Error('radix2: carry overflow');
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix2.encode input should be Uint8Array');
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix2.decode input should be array of strings');
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
},
};
}
function unsafeWrapper(fn) {
if (typeof fn !== 'function')
throw new Error('unsafeWrapper fn should be function');
return function (...args) {
try {
return fn.apply(null, args);
}
catch (e) { }
};
}
function checksum(len, fn) {
assertNumber(len);
if (typeof fn !== 'function')
throw new Error('checksum fn should be function');
return {
encode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.encode: input should be Uint8Array');
const checksum = fn(data).slice(0, len);
const res = new Uint8Array(data.length + len);
res.set(data);
res.set(checksum, data.length);
return res;
},
decode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.decode: input should be Uint8Array');
const payload = data.slice(0, -len);
const newChecksum = fn(payload).slice(0, len);
const oldChecksum = data.slice(-len);
for (let i = 0; i < len; i++)
if (newChecksum[i] !== oldChecksum[i])
throw new Error('Invalid checksum');
return payload;
},
};
}
exports.utils = { alphabet, chain, checksum, radix, radix2, join, padding };
exports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
exports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
exports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
exports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
exports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
exports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
const genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));
exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
exports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
exports.base58xmr = {
encode(data) {
let res = '';
for (let i = 0; i < data.length; i += 8) {
const block = data.subarray(i, i + 8);
res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
}
return res;
},
decode(str) {
let res = [];
for (let i = 0; i < str.length; i += 11) {
const slice = str.slice(i, i + 11);
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
const block = exports.base58.decode(slice);
for (let j = 0; j < block.length - blockLen; j++) {
if (block[j] !== 0)
throw new Error('base58xmr: wrong padding');
}
res = res.concat(Array.from(block.slice(block.length - blockLen)));
}
return Uint8Array.from(res);
},
};
const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
exports.base58check = base58check;
const BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 0x1ffffff) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if (((b >> i) & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ (c >> 5);
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
}
function genBech32(encoding) {
const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
const _words = radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
if (typeof prefix !== 'string')
throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))
throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
const actualLength = prefix.length + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
prefix = prefix.toLowerCase();
return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
}
function decode(str, limit = 90) {
if (typeof str !== 'string')
throw new Error(`bech32.decode input should be string, not ${typeof str}`);
if (str.length < 8 || (limit !== false && str.length > limit))
throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
str = lowered;
const sepIndex = str.lastIndexOf('1');
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = str.slice(0, sepIndex);
const _words = str.slice(sepIndex + 1);
if (_words.length < 6)
throw new Error('Data must be at least 6 characters long');
const words = BECH_ALPHABET.decode(_words).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!_words.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
}
exports.bech32 = genBech32('bech32');
exports.bech32m = genBech32('bech32m');
exports.utf8 = {
encode: (data) => new TextDecoder().decode(data),
decode: (str) => new TextEncoder().encode(str),
};
exports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
if (typeof s !== 'string' || s.length % 2)
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
return s.toLowerCase();
}));
const CODERS = {
utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
};
const coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;
const bytesToString = (type, bytes) => {
if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (!(bytes instanceof Uint8Array))
throw new TypeError('bytesToString() expects Uint8Array');
return CODERS[type].encode(bytes);
};
exports.bytesToString = bytesToString;
exports.str = exports.bytesToString;
const stringToBytes = (type, str) => {
if (!CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (typeof str !== 'string')
throw new TypeError('stringToBytes() expects string');
return CODERS[type].decode(str);
};
exports.stringToBytes = stringToBytes;
exports.bytes = exports.stringToBytes;
} (lib));
return lib;
}
var bolt11;
var hasRequiredBolt11;
function requireBolt11 () {
if (hasRequiredBolt11) return bolt11;
hasRequiredBolt11 = 1;
const {bech32, hex, utf8} = requireLib();
// defaults for encode; default timestamp is current time at call
const DEFAULTNETWORK = {
// default network is bitcoin
bech32: 'bc',
pubKeyHash: 0x00,
scriptHash: 0x05,
validWitnessVersions: [0]
};
const TESTNETWORK = {
bech32: 'tb',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIGNETNETWORK = {
bech32: 'tbs',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const REGTESTNETWORK = {
bech32: 'bcrt',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIMNETWORK = {
bech32: 'sb',
pubKeyHash: 0x3f,
scriptHash: 0x7b,
validWitnessVersions: [0]
};
const FEATUREBIT_ORDER = [
'option_data_loss_protect',
'initial_routing_sync',
'option_upfront_shutdown_script',
'gossip_queries',
'var_onion_optin',
'gossip_queries_ex',
'option_static_remotekey',
'payment_secret',
'basic_mpp',
'option_support_large_channel'
];
const DIVISORS = {
m: BigInt(1e3),
u: BigInt(1e6),
n: BigInt(1e9),
p: BigInt(1e12)
};
const MAX_MILLISATS = BigInt('2100000000000000000');
const MILLISATS_PER_BTC = BigInt(1e11);
const TAGCODES = {
payment_hash: 1,
payment_secret: 16,
description: 13,
payee: 19,
description_hash: 23, // commit to longer descriptions (used by lnurl-pay)
expiry: 6, // default: 3600 (1 hour)
min_final_cltv_expiry: 24, // default: 9
fallback_address: 9,
route_hint: 3, // for extra routing info (private etc.)
feature_bits: 5,
metadata: 27
};
// reverse the keys and values of TAGCODES and insert into TAGNAMES
const TAGNAMES = {};
for (let i = 0, keys = Object.keys(TAGCODES); i < keys.length; i++) {
const currentName = keys[i];
const currentCode = TAGCODES[keys[i]].toString();
TAGNAMES[currentCode] = currentName;
}
const TAGPARSERS = {
1: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
16: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
13: words => utf8.encode(bech32.fromWordsUnsafe(words)), // string variable length
19: words => hex.encode(bech32.fromWordsUnsafe(words)), // 264 bits
23: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
27: words => hex.encode(bech32.fromWordsUnsafe(words)), // variable
6: wordsToIntBE, // default: 3600 (1 hour)
24: wordsToIntBE, // default: 9
3: routingInfoParser, // for extra routing info (private etc.)
5: featureBitsParser // keep feature bits as array of 5 bit words
};
function getUnknownParser(tagCode) {
return words => ({
tagCode: parseInt(tagCode),
words: bech32.encode('unknown', words, Number.MAX_SAFE_INTEGER)
})
}
function wordsToIntBE(words) {
return words.reverse().reduce((total, item, index) => {
return total + item * Math.pow(32, index)
}, 0)
}
// first convert from words to buffer, trimming padding where necessary
// parse in 51 byte chunks. See encoder for details.
function routingInfoParser(words) {
const routes = [];
let pubkey,
shortChannelId,
feeBaseMSats,
feeProportionalMillionths,
cltvExpiryDelta;
let routesBuffer = bech32.fromWordsUnsafe(words);
while (routesBuffer.length > 0) {
pubkey = hex.encode(routesBuffer.slice(0, 33)); // 33 bytes
shortChannelId = hex.encode(routesBuffer.slice(33, 41)); // 8 bytes
feeBaseMSats = parseInt(hex.encode(routesBuffer.slice(41, 45)), 16); // 4 bytes
feeProportionalMillionths = parseInt(
hex.encode(routesBuffer.slice(45, 49)),
16
); // 4 bytes
cltvExpiryDelta = parseInt(hex.encode(routesBuffer.slice(49, 51)), 16); // 2 bytes
routesBuffer = routesBuffer.slice(51);
routes.push({
pubkey,
short_channel_id: shortChannelId,
fee_base_msat: feeBaseMSats,
fee_proportional_millionths: feeProportionalMillionths,
cltv_expiry_delta: cltvExpiryDelta
});
}
return routes
}
function featureBitsParser(words) {
const bools = words
.slice()
.reverse()
.map(word => [
!!(word & 0b1),
!!(word & 0b10),
!!(word & 0b100),
!!(word & 0b1000),
!!(word & 0b10000)
])
.reduce((finalArr, itemArr) => finalArr.concat(itemArr), []);
while (bools.length < FEATUREBIT_ORDER.length * 2) {
bools.push(false);
}
const featureBits = {};
FEATUREBIT_ORDER.forEach((featureName, index) => {
let status;
if (bools[index * 2]) {
status = 'required';
} else if (bools[index * 2 + 1]) {
status = 'supported';
} else {
status = 'unsupported';
}
featureBits[featureName] = status;
});
const extraBits = bools.slice(FEATUREBIT_ORDER.length * 2);
featureBits.extra_bits = {
start_bit: FEATUREBIT_ORDER.length * 2,
bits: extraBits,
has_required: extraBits.reduce(
(result, bit, index) =>
index % 2 !== 0 ? result || false : result || bit,
false
)
};
return featureBits
}
function hrpToMillisat(hrpString, outputString) {
let divisor, value;
if (hrpString.slice(-1).match(/^[munp]$/)) {
divisor = hrpString.slice(-1);
value = hrpString.slice(0, -1);
} else if (hrpString.slice(-1).match(/^[^munp0-9]$/)) {
throw new Error('Not a valid multiplier for the amount')
} else {
value = hrpString;
}
if (!value.match(/^\d+$/))
throw new Error('Not a valid human readable amount')
const valueBN = BigInt(value);
const millisatoshisBN = divisor
? (valueBN * MILLISATS_PER_BTC) / DIVISORS[divisor]
: valueBN * MILLISATS_PER_BTC;
if (
(divisor === 'p' && !(valueBN % BigInt(10) === BigInt(0))) ||
millisatoshisBN > MAX_MILLISATS
) {
throw new Error('Amount is outside of valid range')
}
return outputString ? millisatoshisBN.toString() : millisatoshisBN
}
// decode will only have extra comments that aren't covered in encode comments.
// also if anything is hard to read I'll comment.
function decode(paymentRequest, network) {
if (typeof paymentRequest !== 'string')
throw new Error('Lightning Payment Request must be string')
if (paymentRequest.slice(0, 2).toLowerCase() !== 'ln')
throw new Error('Not a proper lightning payment request')
const sections = [];
const decoded = bech32.decode(paymentRequest, Number.MAX_SAFE_INTEGER);
paymentRequest = paymentRequest.toLowerCase();
const prefix = decoded.prefix;
let words = decoded.words;
let letters = paymentRequest.slice(prefix.length + 1);
let sigWords = words.slice(-104);
words = words.slice(0, -104);
// Without reverse lookups, can't say that the multipier at the end must
// have a number before it, so instead we parse, and if the second group
// doesn't have anything, there's a good chance the last letter of the
// coin type got captured by the third group, so just re-regex without
// the number.
let prefixMatches = prefix.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);
if (prefixMatches && !prefixMatches[2])
prefixMatches = prefix.match(/^ln(\S+)$/);
if (!prefixMatches) {
throw new Error('Not a proper lightning payment request')
}
// "ln" section
sections.push({
name: 'lightning_network',
letters: 'ln'
});
// "bc" section
const bech32Prefix = prefixMatches[1];
let coinNetwork;
if (!network) {
switch (bech32Prefix) {
case DEFAULTNETWORK.bech32:
coinNetwork = DEFAULTNETWORK;
break
case TESTNETWORK.bech32:
coinNetwork = TESTNETWORK;
break
case SIGNETNETWORK.bech32:
coinNetwork = SIGNETNETWORK;
break
case REGTESTNETWORK.bech32:
coinNetwork = REGTESTNETWORK;
break
case SIMNETWORK.bech32:
coinNetwork = SIMNETWORK;
break
}
} else {
if (
network.bech32 === undefined ||
network.pubKeyHash === undefined ||
network.scriptHash === undefined ||
!Array.isArray(network.validWitnessVersions)
)
throw new Error('Invalid network')
coinNetwork = network;
}
if (!coinNetwork || coinNetwork.bech32 !== bech32Prefix) {
throw new Error('Unknown coin bech32 prefix')
}
sections.push({
name: 'coin_network',
letters: bech32Prefix,
value: coinNetwork
});
// amount section
const value = prefixMatches[2];
let millisatoshis;
if (value) {
const divisor = prefixMatches[3];
millisatoshis = hrpToMillisat(value + divisor, true);
sections.push({
name: 'amount',
letters: prefixMatches[2] + prefixMatches[3],
value: millisatoshis
});
} else {
millisatoshis = null;
}
// "1" separator
sections.push({
name: 'separator',
letters: '1'
});
// timestamp
const timestamp = wordsToIntBE(words.slice(0, 7));
words = words.slice(7); // trim off the left 7 words
sections.push({
name: 'timestamp',
letters: letters.slice(0, 7),
value: timestamp
});
letters = letters.slice(7);
let tagName, parser, tagLength, tagWords;
// we have no tag count to go on, so just keep hacking off words
// until we have none.
while (words.length > 0) {
const tagCode = words[0].toString();
tagName = TAGNAMES[tagCode] || 'unknown_tag';
parser = TAGPARSERS[tagCode] || getUnknownParser(tagCode);
words = words.slice(1);
tagLength = wordsToIntBE(words.slice(0, 2));
words = words.slice(2);
tagWords = words.slice(0, tagLength);
words = words.slice(tagLength);
sections.push({
name: tagName,
tag: letters[0],
letters: letters.slice(0, 1 + 2 + tagLength),
value: parser(tagWords) // see: parsers for more comments
});
letters = letters.slice(1 + 2 + tagLength);
}
// signature
sections.push({
name: 'signature',
letters: letters.slice(0, 104),
value: hex.encode(bech32.fromWordsUnsafe(sigWords))
});
letters = letters.slice(104);
// checksum
sections.push({
name: 'checksum',
letters: letters
});
let result = {
paymentRequest,
sections,
get expiry() {
let exp = sections.find(s => s.name === 'expiry');
if (exp) return getValue('timestamp') + exp.value
},
get route_hints() {
return sections.filter(s => s.name === 'route_hint').map(s => s.value)
}
};
for (let name in TAGCODES) {
if (name === 'route_hint') {
// route hints can be multiple, so this won't work for them
continue
}
Object.defineProperty(result, name, {
get() {
return getValue(name)
}
});
}
return result
function getValue(name) {
let section = sections.find(s => s.name === name);
return section ? section.value : undefined
}
}
bolt11 = {
decode,
hrpToMillisat
};
return bolt11;
}
var bolt11Exports = requireBolt11();
// from https://stackoverflow.com/a/50868276
const fromHexString = (hexString) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const decodeInvoice = (paymentRequest) => {
if (!paymentRequest)
return null;
try {
const decoded = bolt11Exports.decode(paymentRequest);
if (!decoded || !decoded.sections)
return null;
const hashTag = decoded.sections.find((value) => value.name === "payment_hash");
if (hashTag?.name !== "payment_hash" || !hashTag.value)
return null;
const paymentHash = hashTag.value;
let satoshi = 0;
const amountTag = decoded.sections.find((value) => value.name === "amount");
if (amountTag?.name === "amount" && amountTag.value) {
satoshi = parseInt(amountTag.value) / 1000; // millisats
}
const timestampTag = decoded.sections.find((value) => value.name === "timestamp");
if (timestampTag?.name !== "timestamp" || !timestampTag.value)
return null;
const timestamp = timestampTag.value;
let expiry;
const expiryTag = decoded.sections.find((value) => value.name === "expiry");
if (expiryTag?.name === "expiry") {
expiry = expiryTag.value;
}
const descriptionTag = decoded.sections.find((value) => value.name === "description");
const description = descriptionTag?.name === "description"
? descriptionTag?.value
: undefined;
return {
paymentHash,
satoshi,
timestamp,
expiry,
description,
};
}
catch {
return null;
}
};
class Invoice {
constructor(args) {
this.paymentRequest = args.pr;
if (!this.paymentRequest) {
throw new Error("Invalid payment request");
}
const decodedInvoice = decodeInvoice(this.paymentRequest);
if (!decodedInvoice) {
throw new Error("Failed to decode payment request");
}
this.paymentHash = decodedInvoice.paymentHash;
this.satoshi = decodedInvoice.satoshi;
this.timestamp = decodedInvoice.timestamp;
this.expiry = decodedInvoice.expiry;
this.createdDate = new Date(this.timestamp * 1000);
this.expiryDate = this.expiry
? new Date((this.timestamp + this.expiry) * 1000)
: undefined;
this.description = decodedInvoice.description ?? null;
this.verify = args.verify ?? null;
this.preimage = args.preimage ?? null;
this.successAction = args.successAction ?? null;
}
async isPaid() {
if (this.preimage)
return this.validatePreimage(this.preimage);
else if (this.verify) {
return await this.verifyPayment();
}
else {
throw new Error("Could not verify payment");
}
}
validatePreimage(preimage) {
if (!preimage || !this.paymentHash)
return false;
try {
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
return this.paymentHash === preimageHash;
}
catch {
return false;
}
}
async verifyPayment() {
try {
if (!this.verify) {
throw new Error("LNURL verify not available");
}
const response = await fetch(this.verify);
if (!response.ok) {
throw new Error(`Verification request failed: ${response.status} ${response.statusText}`);
}
const json = await response.json();
if (json.preimage) {
this.preimage = json.preimage;
}
return json.settled;
}
catch (error) {
console.error("Failed to check LNURL-verify", error);
return false;
}
}
hasExpired() {
const { expiryDate } = this;
if (expiryDate) {
return expiryDate.getTime() < Date.now();
}
return false;
}
}
const sendBoostagram = async (args, options) => {
const { boost } = args;
if (!options) {
options = {};
}
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN not available");
}
if (!webln.keysend) {
throw new Error("Keysend not available in current WebLN provider");
}
const amount = args.amount || Math.floor(boost.value_msat / 1000);
const weblnParams = {
destination: args.destination,
amount: amount,
customRecords: {
"7629169": JSON.stringify(boost),
},
};
if (args.customKey && args.customValue) {
weblnParams.customRecords[args.customKey] = args.customValue;
}
await webln.enable();
const response = await webln.keysend(weblnParams);
return response;
};
const LN_ADDRESS_REGEX = /^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const DEFAULT_PROXY = "https://api.getalby.com/lnurl";
class LightningAddress {
constructor(address, options) {
this.address = address;
this.options = { proxy: DEFAULT_PROXY };
this.options = Object.assign(this.options, options);
this.parse();
this.webln = this.options.webln;
}
parse() {
const result = LN_ADDRESS_REGEX.exec(this.address.toLowerCase());
if (result) {
this.username = result[1];
this.domain = result[2];
}
}
getWebLN() {
return this.webln || globalThis.webln;
}
async fetch() {
if (this.options.proxy) {
return this.fetchWithProxy();
}
else {
return this.fetchWithoutProxy();
}
}
async fetchWithProxy() {
const response = await fetch(`${this.options.proxy}/lightning-address-details?${new URLSearchParams({
ln: this.address,
}).toString()}`);
if (!response.ok) {
throw new Error(`Failed to fetch lnurl info: ${response.status} ${response.statusText}`);
}
const json = await response.json();
await this.parseLnUrlPayResponse(json.lnurlp);
this.parseKeysendResponse(json.keysend);
this.parseNostrResponse(json.nostr);
}
async fetchWithoutProxy() {
if (!this.domain || !this.username) {
return;
}
await Promise.all([
this.fetchLnurlData(),
this.fetchKeysendData(),
this.fetchNostrData(),
]);
}
async fetchLnurlData() {
const lnurlResult = await fetch(this.lnurlpUrl());
if (lnurlResult.ok) {
const lnurlData = await lnurlResult.json();
await this.parseLnUrlPayResponse(lnurlData);
}
}
async fetchKeysendData() {
const keysendResult = await fetch(this.keysendUrl());
if (keysendResult.ok) {
const keysendData = await keysendResult.json();
this.parseKeysendResponse(keysendData);
}
}
async fetchNostrData() {
const nostrResult = await fetch(this.nostrUrl());
if (nostrResult.ok) {
const nostrData = await nostrResult.json();
this.parseNostrResponse(nostrData);
}
}
lnurlpUrl() {
return `https://${this.domain}/.well-known/lnurlp/${this.username}`;
}
keysendUrl() {
return `https://${this.domain}/.well-known/keysend/${this.username}`;
}
nostrUrl() {
return `https://${this.domain}/.well-known/nostr.json?name=${this.username}`;
}
async generateInvoice(params) {
let data;
if (this.options.proxy) {
const invoiceResponse = await fetch(`${this.options.proxy}/generate-invoice?${new URLSearchParams({
ln: this.address,
...params,
}).toString()}`);
if (!invoiceResponse.ok) {
throw new Error(`Failed to generate invoice: ${invoiceResponse.status} ${invoiceResponse.statusText}`);
}
const json = await invoiceResponse.json();
data = json.invoice;
}
else {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
if (!this.lnurlpData.callback || !isUrl(this.lnurlpData.callback))
throw new Error("Valid callback does not exist in lnurlpData");
const callbackUrl = new URL(this.lnurlpData.callback);
callbackUrl.search = new URLSearchParams(params).toString();
const invoiceResponse = await fetch(callbackUrl.toString());
if (!invoiceResponse.ok) {
throw new Error(`Failed to generate invoice: ${invoiceResponse.status} ${invoiceResponse.statusText}`);
}
data = await invoiceResponse.json();
}
const paymentRequest = data && data.pr && data.pr.toString();
if (!paymentRequest)
throw new Error("Invalid pay service invoice");
const invoiceArgs = { pr: paymentRequest };
if (data && data.verify)
invoiceArgs.verify = data.verify.toString();
if (data && data.successAction && typeof data.successAction === "object") {
const { tag, message, description, url } = data.successAction;
if (tag === "message") {
invoiceArgs.successAction = { tag, message };
}
else if (tag === "url") {
invoiceArgs.successAction = { tag, description, url };
}
}
return new Invoice(invoiceArgs);
}
async requestInvoice(args) {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
const msat = args.satoshi * 1000;
const { commentAllowed, min, max } = this.lnurlpData;
if (!isValidAmount({ amount: msat, min, max }))
throw new Error("Invalid amount");
if (args.comment &&
commentAllowed &&
commentAllowed > 0 &&
args.comment.length > commentAllowed)
throw new Error(`The comment length must be ${commentAllowed} characters or fewer`);
const invoiceParams = { amount: msat.toString() };
if (args.comment)
invoiceParams.comment = args.comment;
if (args.payerdata)
invoiceParams.payerdata = JSON.stringify(args.payerdata);
return this.generateInvoice(invoiceParams);
}
async boost(boost, amount = 0) {
if (!this.keysendData) {
throw new Error("No keysendData available. Please call fetch() first.");
}
const { destination, customKey, customValue } = this.keysendData;
const webln = this.getWebLN();
if (!webln) {
throw new Error("WebLN not available");
}
return sendBoostagram({
destination,
customKey,
customValue,
amount,
boost,
}, { webln });
}
async zapInvoice({ satoshi, comment, relays, e }, options = {}) {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
if (!this.nostrPubkey) {
throw new Error("Nostr Pubkey is missing");
}
const p = this.nostrPubkey;
const msat = satoshi * 1000;
const { allowsNostr, min, max } = this.lnurlpData;
if (!isValidAmount({ amount: msat, min, max }))
throw new Error("Invalid amount");
if (!allowsNostr)
throw new Error("Your provider does not support zaps");
const event = await generateZapEvent({
satoshi: msat,
comment,
p,
e,
relays,
}, options);
const zapParams = {
amount: msat.toString(),
nostr: JSON.stringify(event),
};
const invoice = await this.generateInvoice(zapParams);
return invoice;
}
async zap(args, options = {}) {
const invoice = this.zapInvoice(args, options);
const webln = this.getWebLN();
if (!webln) {
throw new Error("WebLN not available");
}
await webln.enable();
const response = webln.sendPayment((await invoice).paymentRequest);
return response;
}
async parseLnUrlPayResponse(lnurlpData) {
if (lnurlpData) {
this.lnurlpData = await parseLnUrlPayResponse(lnurlpData);
}
}
parseKeysendResponse(keysendData) {
if (keysendData) {
this.keysendData = parseKeysendResponse(keysendData);
}
}
parseNostrResponse(nostrData) {
if (nostrData) {
[this.nostrData, this.nostrPubkey, this.nostrRelays] = parseNostrResponse(nostrData, this.username);
}
}
}
exports.DEFAULT_PROXY = DEFAULT_PROXY;
exports.LN_ADDRESS_REGEX = LN_ADDRESS_REGEX;
exports.LightningAddress = LightningAddress;
exports.generateZapEvent = generateZapEvent;
exports.getEventHash = getEventHash;
exports.isUrl = isUrl;
exports.isValidAmount = isValidAmount;
exports.parseKeysendResponse = parseKeysendResponse;
exports.parseLnUrlPayResponse = parseLnUrlPayResponse;
exports.parseNostrResponse = parseNostrResponse;
exports.serializeEvent = serializeEvent;
exports.validateEvent = validateEvent;
//# sourceMappingURL=lnurl.cjs.map

Sorry, the diff of this file is too big to display

'use strict';
const sendBoostagram = async (args, options) => {
const { boost } = args;
if (!options) {
options = {};
}
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN not available");
}
if (!webln.keysend) {
throw new Error("Keysend not available in current WebLN provider");
}
const amount = args.amount || Math.floor(boost.value_msat / 1000);
const weblnParams = {
destination: args.destination,
amount: amount,
customRecords: {
"7629169": JSON.stringify(boost),
},
};
if (args.customKey && args.customValue) {
weblnParams.customRecords[args.customKey] = args.customValue;
}
await webln.enable();
const response = await webln.keysend(weblnParams);
return response;
};
exports.sendBoostagram = sendBoostagram;
//# sourceMappingURL=podcasting2.cjs.map
{"version":3,"file":"podcasting2.cjs","sources":["../../src/podcasting2/boostagrams.ts"],"sourcesContent":["import { WebLNProvider } from \"@webbtc/webln-types\";\nimport { BoostArguments, BoostOptions, WeblnBoostParams } from \"./types\";\n\nexport const sendBoostagram = async (\n args: BoostArguments,\n options?: BoostOptions,\n) => {\n const { boost } = args;\n if (!options) {\n options = {};\n }\n const webln: WebLNProvider = options.webln || globalThis.webln;\n\n if (!webln) {\n throw new Error(\"WebLN not available\");\n }\n if (!webln.keysend) {\n throw new Error(\"Keysend not available in current WebLN provider\");\n }\n\n const amount = args.amount || Math.floor(boost.value_msat / 1000);\n\n const weblnParams: WeblnBoostParams = {\n destination: args.destination,\n amount: amount,\n customRecords: {\n \"7629169\": JSON.stringify(boost),\n },\n };\n if (args.customKey && args.customValue) {\n weblnParams.customRecords[args.customKey] = args.customValue;\n }\n await webln.enable();\n const response = await webln.keysend(weblnParams);\n return response;\n};\n"],"names":[],"mappings":";;AAGO,MAAM,cAAc,GAAG,OAC5B,IAAoB,EACpB,OAAsB,KACpB;AACF,IAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IACtB,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,GAAG,EAAE;IACd;IACA,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;IAE9D,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;IACxC;AACA,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AAClB,QAAA,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC;IACpE;AAEA,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;AAEjE,IAAA,MAAM,WAAW,GAAqB;QACpC,WAAW,EAAE,IAAI,CAAC,WAAW;AAC7B,QAAA,MAAM,EAAE,MAAM;AACd,QAAA,aAAa,EAAE;AACb,YAAA,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;AACjC,SAAA;KACF;IACD,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE;QACtC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW;IAC9D;AACA,IAAA,MAAM,KAAK,CAAC,MAAM,EAAE;IACpB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;AACjD,IAAA,OAAO,QAAQ;AACjB;;;;"}
var lib = {};
var hasRequiredLib;
function requireLib () {
if (hasRequiredLib) return lib;
hasRequiredLib = 1;
(function (exports) {
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64url = exports.base64 = exports.base32crockford = exports.base32hex = exports.base32 = exports.base16 = exports.utils = exports.assertNumber = void 0;
function assertNumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`Wrong integer: ${n}`);
}
exports.assertNumber = assertNumber;
function chain(...args) {
const wrap = (a, b) => (c) => a(b(c));
const encode = Array.from(args)
.reverse()
.reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);
const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);
return { encode, decode };
}
function alphabet(alphabet) {
return {
encode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('alphabet.encode input should be an array of numbers');
return digits.map((i) => {
assertNumber(i);
if (i < 0 || i >= alphabet.length)
throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);
return alphabet[i];
});
},
decode: (input) => {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('alphabet.decode input should be array of strings');
return input.map((letter) => {
if (typeof letter !== 'string')
throw new Error(`alphabet.decode: not string element=${letter}`);
const index = alphabet.indexOf(letter);
if (index === -1)
throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);
return index;
});
},
};
}
function join(separator = '') {
if (typeof separator !== 'string')
throw new Error('join separator should be string');
return {
encode: (from) => {
if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))
throw new Error('join.encode input should be array of strings');
for (let i of from)
if (typeof i !== 'string')
throw new Error(`join.encode: non-string input=${i}`);
return from.join(separator);
},
decode: (to) => {
if (typeof to !== 'string')
throw new Error('join.decode input should be string');
return to.split(separator);
},
};
}
function padding(bits, chr = '=') {
assertNumber(bits);
if (typeof chr !== 'string')
throw new Error('padding chr should be string');
return {
encode(data) {
if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of data)
if (typeof i !== 'string')
throw new Error(`padding.encode: non-string input=${i}`);
while ((data.length * bits) % 8)
data.push(chr);
return data;
},
decode(input) {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of input)
if (typeof i !== 'string')
throw new Error(`padding.decode: non-string input=${i}`);
let end = input.length;
if ((end * bits) % 8)
throw new Error('Invalid padding: string should have whole number of bytes');
for (; end > 0 && input[end - 1] === chr; end--) {
if (!(((end - 1) * bits) % 8))
throw new Error('Invalid padding: string has too much padding');
}
return input.slice(0, end);
},
};
}
function normalize(fn) {
if (typeof fn !== 'function')
throw new Error('normalize fn should be function');
return { encode: (from) => from, decode: (to) => fn(to) };
}
function convertRadix(data, from, to) {
if (from < 2)
throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
if (to < 2)
throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
if (!Array.isArray(data))
throw new Error('convertRadix: data should be array');
if (!data.length)
return [];
let pos = 0;
const res = [];
const digits = Array.from(data);
digits.forEach((d) => {
assertNumber(d);
if (d < 0 || d >= from)
throw new Error(`Wrong integer: ${d}`);
});
while (true) {
let carry = 0;
let done = true;
for (let i = pos; i < digits.length; i++) {
const digit = digits[i];
const digitBase = from * carry + digit;
if (!Number.isSafeInteger(digitBase) ||
(from * carry) / from !== carry ||
digitBase - digit !== from * carry) {
throw new Error('convertRadix: carry overflow');
}
carry = digitBase % to;
digits[i] = Math.floor(digitBase / to);
if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)
throw new Error('convertRadix: carry overflow');
if (!done)
continue;
else if (!digits[i])
pos = i;
else
done = false;
}
res.push(carry);
if (done)
break;
}
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
res.push(0);
return res.reverse();
}
const gcd = (a, b) => (!b ? a : gcd(b, a % b));
const radix2carry = (from, to) => from + (to - gcd(from, to));
function convertRadix2(data, from, to, padding) {
if (!Array.isArray(data))
throw new Error('convertRadix2: data should be array');
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0;
const mask = 2 ** to - 1;
const res = [];
for (const n of data) {
assertNumber(n);
if (n >= 2 ** from)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = (carry << from) | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push(((carry >> (pos - to)) & mask) >>> 0);
carry &= 2 ** pos - 1;
}
carry = (carry << (to - pos)) & mask;
if (!padding && pos >= from)
throw new Error('Excess padding');
if (!padding && carry)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
function radix(num) {
assertNumber(num);
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix.encode input should be Uint8Array');
return convertRadix(Array.from(bytes), 2 ** 8, num);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix.decode input should be array of strings');
return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
},
};
}
function radix2(bits, revPadding = false) {
assertNumber(bits);
if (bits <= 0 || bits > 32)
throw new Error('radix2: bits should be in (0..32]');
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
throw new Error('radix2: carry overflow');
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix2.encode input should be Uint8Array');
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix2.decode input should be array of strings');
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
},
};
}
function unsafeWrapper(fn) {
if (typeof fn !== 'function')
throw new Error('unsafeWrapper fn should be function');
return function (...args) {
try {
return fn.apply(null, args);
}
catch (e) { }
};
}
function checksum(len, fn) {
assertNumber(len);
if (typeof fn !== 'function')
throw new Error('checksum fn should be function');
return {
encode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.encode: input should be Uint8Array');
const checksum = fn(data).slice(0, len);
const res = new Uint8Array(data.length + len);
res.set(data);
res.set(checksum, data.length);
return res;
},
decode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.decode: input should be Uint8Array');
const payload = data.slice(0, -len);
const newChecksum = fn(payload).slice(0, len);
const oldChecksum = data.slice(-len);
for (let i = 0; i < len; i++)
if (newChecksum[i] !== oldChecksum[i])
throw new Error('Invalid checksum');
return payload;
},
};
}
exports.utils = { alphabet, chain, checksum, radix, radix2, join, padding };
exports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
exports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
exports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
exports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
exports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
exports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
const genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));
exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
exports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
exports.base58xmr = {
encode(data) {
let res = '';
for (let i = 0; i < data.length; i += 8) {
const block = data.subarray(i, i + 8);
res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
}
return res;
},
decode(str) {
let res = [];
for (let i = 0; i < str.length; i += 11) {
const slice = str.slice(i, i + 11);
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
const block = exports.base58.decode(slice);
for (let j = 0; j < block.length - blockLen; j++) {
if (block[j] !== 0)
throw new Error('base58xmr: wrong padding');
}
res = res.concat(Array.from(block.slice(block.length - blockLen)));
}
return Uint8Array.from(res);
},
};
const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
exports.base58check = base58check;
const BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 0x1ffffff) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if (((b >> i) & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ (c >> 5);
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
}
function genBech32(encoding) {
const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
const _words = radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
if (typeof prefix !== 'string')
throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))
throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
const actualLength = prefix.length + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
prefix = prefix.toLowerCase();
return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
}
function decode(str, limit = 90) {
if (typeof str !== 'string')
throw new Error(`bech32.decode input should be string, not ${typeof str}`);
if (str.length < 8 || (limit !== false && str.length > limit))
throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
str = lowered;
const sepIndex = str.lastIndexOf('1');
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = str.slice(0, sepIndex);
const _words = str.slice(sepIndex + 1);
if (_words.length < 6)
throw new Error('Data must be at least 6 characters long');
const words = BECH_ALPHABET.decode(_words).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!_words.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
}
exports.bech32 = genBech32('bech32');
exports.bech32m = genBech32('bech32m');
exports.utf8 = {
encode: (data) => new TextDecoder().decode(data),
decode: (str) => new TextEncoder().encode(str),
};
exports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
if (typeof s !== 'string' || s.length % 2)
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
return s.toLowerCase();
}));
const CODERS = {
utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
};
const coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;
const bytesToString = (type, bytes) => {
if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (!(bytes instanceof Uint8Array))
throw new TypeError('bytesToString() expects Uint8Array');
return CODERS[type].encode(bytes);
};
exports.bytesToString = bytesToString;
exports.str = exports.bytesToString;
const stringToBytes = (type, str) => {
if (!CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (typeof str !== 'string')
throw new TypeError('stringToBytes() expects string');
return CODERS[type].decode(str);
};
exports.stringToBytes = stringToBytes;
exports.bytes = exports.stringToBytes;
} (lib));
return lib;
}
var bolt11;
var hasRequiredBolt11;
function requireBolt11 () {
if (hasRequiredBolt11) return bolt11;
hasRequiredBolt11 = 1;
const {bech32, hex, utf8} = requireLib();
// defaults for encode; default timestamp is current time at call
const DEFAULTNETWORK = {
// default network is bitcoin
bech32: 'bc',
pubKeyHash: 0x00,
scriptHash: 0x05,
validWitnessVersions: [0]
};
const TESTNETWORK = {
bech32: 'tb',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIGNETNETWORK = {
bech32: 'tbs',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const REGTESTNETWORK = {
bech32: 'bcrt',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIMNETWORK = {
bech32: 'sb',
pubKeyHash: 0x3f,
scriptHash: 0x7b,
validWitnessVersions: [0]
};
const FEATUREBIT_ORDER = [
'option_data_loss_protect',
'initial_routing_sync',
'option_upfront_shutdown_script',
'gossip_queries',
'var_onion_optin',
'gossip_queries_ex',
'option_static_remotekey',
'payment_secret',
'basic_mpp',
'option_support_large_channel'
];
const DIVISORS = {
m: BigInt(1e3),
u: BigInt(1e6),
n: BigInt(1e9),
p: BigInt(1e12)
};
const MAX_MILLISATS = BigInt('2100000000000000000');
const MILLISATS_PER_BTC = BigInt(1e11);
const TAGCODES = {
payment_hash: 1,
payment_secret: 16,
description: 13,
payee: 19,
description_hash: 23, // commit to longer descriptions (used by lnurl-pay)
expiry: 6, // default: 3600 (1 hour)
min_final_cltv_expiry: 24, // default: 9
fallback_address: 9,
route_hint: 3, // for extra routing info (private etc.)
feature_bits: 5,
metadata: 27
};
// reverse the keys and values of TAGCODES and insert into TAGNAMES
const TAGNAMES = {};
for (let i = 0, keys = Object.keys(TAGCODES); i < keys.length; i++) {
const currentName = keys[i];
const currentCode = TAGCODES[keys[i]].toString();
TAGNAMES[currentCode] = currentName;
}
const TAGPARSERS = {
1: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
16: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
13: words => utf8.encode(bech32.fromWordsUnsafe(words)), // string variable length
19: words => hex.encode(bech32.fromWordsUnsafe(words)), // 264 bits
23: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
27: words => hex.encode(bech32.fromWordsUnsafe(words)), // variable
6: wordsToIntBE, // default: 3600 (1 hour)
24: wordsToIntBE, // default: 9
3: routingInfoParser, // for extra routing info (private etc.)
5: featureBitsParser // keep feature bits as array of 5 bit words
};
function getUnknownParser(tagCode) {
return words => ({
tagCode: parseInt(tagCode),
words: bech32.encode('unknown', words, Number.MAX_SAFE_INTEGER)
})
}
function wordsToIntBE(words) {
return words.reverse().reduce((total, item, index) => {
return total + item * Math.pow(32, index)
}, 0)
}
// first convert from words to buffer, trimming padding where necessary
// parse in 51 byte chunks. See encoder for details.
function routingInfoParser(words) {
const routes = [];
let pubkey,
shortChannelId,
feeBaseMSats,
feeProportionalMillionths,
cltvExpiryDelta;
let routesBuffer = bech32.fromWordsUnsafe(words);
while (routesBuffer.length > 0) {
pubkey = hex.encode(routesBuffer.slice(0, 33)); // 33 bytes
shortChannelId = hex.encode(routesBuffer.slice(33, 41)); // 8 bytes
feeBaseMSats = parseInt(hex.encode(routesBuffer.slice(41, 45)), 16); // 4 bytes
feeProportionalMillionths = parseInt(
hex.encode(routesBuffer.slice(45, 49)),
16
); // 4 bytes
cltvExpiryDelta = parseInt(hex.encode(routesBuffer.slice(49, 51)), 16); // 2 bytes
routesBuffer = routesBuffer.slice(51);
routes.push({
pubkey,
short_channel_id: shortChannelId,
fee_base_msat: feeBaseMSats,
fee_proportional_millionths: feeProportionalMillionths,
cltv_expiry_delta: cltvExpiryDelta
});
}
return routes
}
function featureBitsParser(words) {
const bools = words
.slice()
.reverse()
.map(word => [
!!(word & 0b1),
!!(word & 0b10),
!!(word & 0b100),
!!(word & 0b1000),
!!(word & 0b10000)
])
.reduce((finalArr, itemArr) => finalArr.concat(itemArr), []);
while (bools.length < FEATUREBIT_ORDER.length * 2) {
bools.push(false);
}
const featureBits = {};
FEATUREBIT_ORDER.forEach((featureName, index) => {
let status;
if (bools[index * 2]) {
status = 'required';
} else if (bools[index * 2 + 1]) {
status = 'supported';
} else {
status = 'unsupported';
}
featureBits[featureName] = status;
});
const extraBits = bools.slice(FEATUREBIT_ORDER.length * 2);
featureBits.extra_bits = {
start_bit: FEATUREBIT_ORDER.length * 2,
bits: extraBits,
has_required: extraBits.reduce(
(result, bit, index) =>
index % 2 !== 0 ? result || false : result || bit,
false
)
};
return featureBits
}
function hrpToMillisat(hrpString, outputString) {
let divisor, value;
if (hrpString.slice(-1).match(/^[munp]$/)) {
divisor = hrpString.slice(-1);
value = hrpString.slice(0, -1);
} else if (hrpString.slice(-1).match(/^[^munp0-9]$/)) {
throw new Error('Not a valid multiplier for the amount')
} else {
value = hrpString;
}
if (!value.match(/^\d+$/))
throw new Error('Not a valid human readable amount')
const valueBN = BigInt(value);
const millisatoshisBN = divisor
? (valueBN * MILLISATS_PER_BTC) / DIVISORS[divisor]
: valueBN * MILLISATS_PER_BTC;
if (
(divisor === 'p' && !(valueBN % BigInt(10) === BigInt(0))) ||
millisatoshisBN > MAX_MILLISATS
) {
throw new Error('Amount is outside of valid range')
}
return outputString ? millisatoshisBN.toString() : millisatoshisBN
}
// decode will only have extra comments that aren't covered in encode comments.
// also if anything is hard to read I'll comment.
function decode(paymentRequest, network) {
if (typeof paymentRequest !== 'string')
throw new Error('Lightning Payment Request must be string')
if (paymentRequest.slice(0, 2).toLowerCase() !== 'ln')
throw new Error('Not a proper lightning payment request')
const sections = [];
const decoded = bech32.decode(paymentRequest, Number.MAX_SAFE_INTEGER);
paymentRequest = paymentRequest.toLowerCase();
const prefix = decoded.prefix;
let words = decoded.words;
let letters = paymentRequest.slice(prefix.length + 1);
let sigWords = words.slice(-104);
words = words.slice(0, -104);
// Without reverse lookups, can't say that the multipier at the end must
// have a number before it, so instead we parse, and if the second group
// doesn't have anything, there's a good chance the last letter of the
// coin type got captured by the third group, so just re-regex without
// the number.
let prefixMatches = prefix.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);
if (prefixMatches && !prefixMatches[2])
prefixMatches = prefix.match(/^ln(\S+)$/);
if (!prefixMatches) {
throw new Error('Not a proper lightning payment request')
}
// "ln" section
sections.push({
name: 'lightning_network',
letters: 'ln'
});
// "bc" section
const bech32Prefix = prefixMatches[1];
let coinNetwork;
if (!network) {
switch (bech32Prefix) {
case DEFAULTNETWORK.bech32:
coinNetwork = DEFAULTNETWORK;
break
case TESTNETWORK.bech32:
coinNetwork = TESTNETWORK;
break
case SIGNETNETWORK.bech32:
coinNetwork = SIGNETNETWORK;
break
case REGTESTNETWORK.bech32:
coinNetwork = REGTESTNETWORK;
break
case SIMNETWORK.bech32:
coinNetwork = SIMNETWORK;
break
}
} else {
if (
network.bech32 === undefined ||
network.pubKeyHash === undefined ||
network.scriptHash === undefined ||
!Array.isArray(network.validWitnessVersions)
)
throw new Error('Invalid network')
coinNetwork = network;
}
if (!coinNetwork || coinNetwork.bech32 !== bech32Prefix) {
throw new Error('Unknown coin bech32 prefix')
}
sections.push({
name: 'coin_network',
letters: bech32Prefix,
value: coinNetwork
});
// amount section
const value = prefixMatches[2];
let millisatoshis;
if (value) {
const divisor = prefixMatches[3];
millisatoshis = hrpToMillisat(value + divisor, true);
sections.push({
name: 'amount',
letters: prefixMatches[2] + prefixMatches[3],
value: millisatoshis
});
} else {
millisatoshis = null;
}
// "1" separator
sections.push({
name: 'separator',
letters: '1'
});
// timestamp
const timestamp = wordsToIntBE(words.slice(0, 7));
words = words.slice(7); // trim off the left 7 words
sections.push({
name: 'timestamp',
letters: letters.slice(0, 7),
value: timestamp
});
letters = letters.slice(7);
let tagName, parser, tagLength, tagWords;
// we have no tag count to go on, so just keep hacking off words
// until we have none.
while (words.length > 0) {
const tagCode = words[0].toString();
tagName = TAGNAMES[tagCode] || 'unknown_tag';
parser = TAGPARSERS[tagCode] || getUnknownParser(tagCode);
words = words.slice(1);
tagLength = wordsToIntBE(words.slice(0, 2));
words = words.slice(2);
tagWords = words.slice(0, tagLength);
words = words.slice(tagLength);
sections.push({
name: tagName,
tag: letters[0],
letters: letters.slice(0, 1 + 2 + tagLength),
value: parser(tagWords) // see: parsers for more comments
});
letters = letters.slice(1 + 2 + tagLength);
}
// signature
sections.push({
name: 'signature',
letters: letters.slice(0, 104),
value: hex.encode(bech32.fromWordsUnsafe(sigWords))
});
letters = letters.slice(104);
// checksum
sections.push({
name: 'checksum',
letters: letters
});
let result = {
paymentRequest,
sections,
get expiry() {
let exp = sections.find(s => s.name === 'expiry');
if (exp) return getValue('timestamp') + exp.value
},
get route_hints() {
return sections.filter(s => s.name === 'route_hint').map(s => s.value)
}
};
for (let name in TAGCODES) {
if (name === 'route_hint') {
// route hints can be multiple, so this won't work for them
continue
}
Object.defineProperty(result, name, {
get() {
return getValue(name)
}
});
}
return result
function getValue(name) {
let section = sections.find(s => s.name === name);
return section ? section.value : undefined
}
}
bolt11 = {
decode,
hrpToMillisat
};
return bolt11;
}
var bolt11Exports = requireBolt11();
// from https://stackoverflow.com/a/50868276
const fromHexString = (hexString) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const decodeInvoice = (paymentRequest) => {
if (!paymentRequest)
return null;
try {
const decoded = bolt11Exports.decode(paymentRequest);
if (!decoded || !decoded.sections)
return null;
const hashTag = decoded.sections.find((value) => value.name === "payment_hash");
if (hashTag?.name !== "payment_hash" || !hashTag.value)
return null;
const paymentHash = hashTag.value;
let satoshi = 0;
const amountTag = decoded.sections.find((value) => value.name === "amount");
if (amountTag?.name === "amount" && amountTag.value) {
satoshi = parseInt(amountTag.value) / 1000; // millisats
}
const timestampTag = decoded.sections.find((value) => value.name === "timestamp");
if (timestampTag?.name !== "timestamp" || !timestampTag.value)
return null;
const timestamp = timestampTag.value;
let expiry;
const expiryTag = decoded.sections.find((value) => value.name === "expiry");
if (expiryTag?.name === "expiry") {
expiry = expiryTag.value;
}
const descriptionTag = decoded.sections.find((value) => value.name === "description");
const description = descriptionTag?.name === "description"
? descriptionTag?.value
: undefined;
return {
paymentHash,
satoshi,
timestamp,
expiry,
description,
};
}
catch {
return null;
}
};
function bytes(b, ...lengths) {
if (!(b instanceof Uint8Array))
throw new Error('Expected Uint8Array');
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error('Hash instance has been destroyed');
if (checkFinished && instance.finished)
throw new Error('Hash#digest() has already been called');
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
// node.js versions earlier than v19 don't declare it in global scope.
// For node.js, package.json#exports field mapping rewrites import
// from `crypto` to `cryptoNode`, which imports native module.
// Makes the utils un-importable in browsers without a bundler.
// Once node.js 18 is deprecated, we can just drop the import.
const u8a = (a) => a instanceof Uint8Array;
// Cast array to view
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
// The rotate right (circular right shift) operation for uint32
const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
// big-endian hardware is rare. Just in case someone still decides to run hashes:
// early-throw an error because we don't support BE yet.
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
if (!isLE)
throw new Error('Non little-endian hardware is not supported');
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
/**
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
function bytesToHex(bytes) {
if (!u8a(bytes))
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x
let hex = '';
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]];
}
return hex;
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
function utf8ToBytes(str) {
if (typeof str !== 'string')
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
/**
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
* Warning: when Uint8Array is passed, it would NOT get copied.
* Keep in mind for future mutable operations.
*/
function toBytes(data) {
if (typeof data === 'string')
data = utf8ToBytes(data);
if (!u8a(data))
throw new Error(`expected Uint8Array, got ${typeof data}`);
return data;
}
// For runtime check if class implements interface
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
// Polyfill for Safari 14
function setBigUint64(view, byteOffset, value, isLE) {
if (typeof view.setBigUint64 === 'function')
return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(0xffffffff);
const wh = Number((value >> _32n) & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
// Base SHA2 class (RFC 6234)
class SHA2 extends Hash {
constructor(blockLen, outputLen, padOffset, isLE) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
exists(this);
const { view, buffer, blockLen } = this;
data = toBytes(data);
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
exists(this);
output(out, this);
this.finished = true;
// Padding
// We can avoid allocation of buffer for padding completely if it
// was previously not allocated here. But it won't change performance.
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
// append the bit '1' to the message
buffer[pos++] = 0b10000000;
this.buffer.subarray(pos).fill(0);
// we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
// Pad until full block byte with zeros
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
// So we just write lowest 64 bits of that value.
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
// NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
if (len % 4)
throw new Error('_sha2: outputLen should be aligned to 32bit');
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error('_sha2: outputLen bigger than state');
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
}
// SHA2-256 need to try 2^128 hashes to execute birthday attack.
// BTC network is doing 2^67 hashes/sec as per early 2023.
// Choice: a ? b : c
const Chi = (a, b, c) => (a & b) ^ (~a & c);
// Majority function, true if any two inpust is true
const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
// Round constants:
// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
// prettier-ignore
const SHA256_K = /* @__PURE__ */ new Uint32Array([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
// prettier-ignore
const IV = /* @__PURE__ */ new Uint32Array([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
]);
// Temporary buffer, not used to store anything between runs
// Named this way because it matches specification.
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends SHA2 {
constructor() {
super(64, 32, 8, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
this.A = IV[0] | 0;
this.B = IV[1] | 0;
this.C = IV[2] | 0;
this.D = IV[3] | 0;
this.E = IV[4] | 0;
this.F = IV[5] | 0;
this.G = IV[6] | 0;
this.H = IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
}
// Compression function main loop, 64 rounds
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = (sigma0 + Maj(A, B, C)) | 0;
H = G;
G = F;
F = E;
E = (D + T1) | 0;
D = C;
C = B;
B = A;
A = (T1 + T2) | 0;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
F = (F + this.F) | 0;
G = (G + this.G) | 0;
H = (H + this.H) | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
}
/**
* SHA2-256 hash function
* @param message - data that would be hashed
*/
const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
class Invoice {
constructor(args) {
this.paymentRequest = args.pr;
if (!this.paymentRequest) {
throw new Error("Invalid payment request");
}
const decodedInvoice = decodeInvoice(this.paymentRequest);
if (!decodedInvoice) {
throw new Error("Failed to decode payment request");
}
this.paymentHash = decodedInvoice.paymentHash;
this.satoshi = decodedInvoice.satoshi;
this.timestamp = decodedInvoice.timestamp;
this.expiry = decodedInvoice.expiry;
this.createdDate = new Date(this.timestamp * 1000);
this.expiryDate = this.expiry
? new Date((this.timestamp + this.expiry) * 1000)
: undefined;
this.description = decodedInvoice.description ?? null;
this.verify = args.verify ?? null;
this.preimage = args.preimage ?? null;
this.successAction = args.successAction ?? null;
}
async isPaid() {
if (this.preimage)
return this.validatePreimage(this.preimage);
else if (this.verify) {
return await this.verifyPayment();
}
else {
throw new Error("Could not verify payment");
}
}
validatePreimage(preimage) {
if (!preimage || !this.paymentHash)
return false;
try {
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
return this.paymentHash === preimageHash;
}
catch {
return false;
}
}
async verifyPayment() {
try {
if (!this.verify) {
throw new Error("LNURL verify not available");
}
const response = await fetch(this.verify);
if (!response.ok) {
throw new Error(`Verification request failed: ${response.status} ${response.statusText}`);
}
const json = await response.json();
if (json.preimage) {
this.preimage = json.preimage;
}
return json.settled;
}
catch (error) {
console.error("Failed to check LNURL-verify", error);
return false;
}
}
hasExpired() {
const { expiryDate } = this;
if (expiryDate) {
return expiryDate.getTime() < Date.now();
}
return false;
}
}
export { Invoice, decodeInvoice, fromHexString };
//# sourceMappingURL=bolt11.js.map

Sorry, the diff of this file is too big to display

const numSatsInBtc = 100000000;
const getFiatBtcRate = async (currency) => {
const url = "https://getalby.com/api/rates/" + currency.toLowerCase() + ".json";
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch rate: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data.rate_float / numSatsInBtc;
};
const getFiatValue = async ({ satoshi, currency, }) => {
const rate = await getFiatBtcRate(currency);
return Number(satoshi) * rate;
};
const getSatoshiValue = async ({ amount, currency, }) => {
const rate = await getFiatBtcRate(currency);
return Math.floor(Number(amount) / rate);
};
const getFormattedFiatValue = async ({ satoshi, currency, locale, }) => {
if (!locale) {
locale = "en";
}
const fiatValue = await getFiatValue({ satoshi, currency });
return fiatValue.toLocaleString(locale, {
style: "currency",
currency,
});
};
export { getFiatBtcRate, getFiatValue, getFormattedFiatValue, getSatoshiValue };
//# sourceMappingURL=fiat.js.map
{"version":3,"file":"fiat.js","sources":["../../src/fiat/fiat.ts"],"sourcesContent":["const numSatsInBtc = 100_000_000;\n\nexport const getFiatBtcRate = async (currency: string): Promise<number> => {\n const url =\n \"https://getalby.com/api/rates/\" + currency.toLowerCase() + \".json\";\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch rate: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n return data.rate_float / numSatsInBtc;\n};\n\nexport const getFiatValue = async ({\n satoshi,\n currency,\n}: {\n satoshi: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Number(satoshi) * rate;\n};\n\nexport const getSatoshiValue = async ({\n amount,\n currency,\n}: {\n amount: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Math.floor(Number(amount) / rate);\n};\n\nexport const getFormattedFiatValue = async ({\n satoshi,\n currency,\n locale,\n}: {\n satoshi: number | string;\n currency: string;\n locale: string;\n}) => {\n if (!locale) {\n locale = \"en\";\n }\n const fiatValue = await getFiatValue({ satoshi, currency });\n return fiatValue.toLocaleString(locale, {\n style: \"currency\",\n currency,\n });\n};\n"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,SAAW;MAEnB,cAAc,GAAG,OAAO,QAAgB,KAAqB;IACxE,MAAM,GAAG,GACP,gCAAgC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,OAAO;AACrE,IAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AAEjC,IAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CAClE;IACH;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AAElC,IAAA,OAAO,IAAI,CAAC,UAAU,GAAG,YAAY;AACvC;AAEO,MAAM,YAAY,GAAG,OAAO,EACjC,OAAO,EACP,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;AAE3C,IAAA,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI;AAC/B;AAEO,MAAM,eAAe,GAAG,OAAO,EACpC,MAAM,EACN,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;IAE3C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC1C;AAEO,MAAM,qBAAqB,GAAG,OAAO,EAC1C,OAAO,EACP,QAAQ,EACR,MAAM,GAKP,KAAI;IACH,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,IAAI;IACf;IACA,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC3D,IAAA,OAAO,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE;AACtC,QAAA,KAAK,EAAE,UAAU;QACjB,QAAQ;AACT,KAAA,CAAC;AACJ;;;;"}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

class MemoryStorage {
constructor(initial) {
this.storage = initial || {};
}
getItem(key) {
return this.storage[key];
}
setItem(key, value) {
this.storage[key] = value;
}
}
class NoStorage {
constructor(initial) { }
getItem(key) {
return null;
}
setItem(key, value) { }
}
const parseL402 = (input) => {
// Remove the L402 and LSAT identifiers
const string = input.replace("L402", "").replace("LSAT", "").trim();
// Initialize an object to store the key-value pairs
const keyValuePairs = {};
// Regular expression to match key and (quoted or unquoted) value
const regex = /(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;
let match;
// Use regex to find all key-value pairs
while ((match = regex.exec(string)) !== null) {
// Key is always match[1]
// Value is either match[3] (double-quoted), match[4] (single-quoted), or match[5] (unquoted)
keyValuePairs[match[1]] = match[3] || match[4] || match[5];
}
return keyValuePairs;
};
const memoryStorage = new MemoryStorage();
const HEADER_KEY = "L402"; // we have to update this to L402 at some point
const fetchWithL402 = async (url, fetchArgs, options) => {
if (!options) {
options = {};
}
const headerKey = options.headerKey || HEADER_KEY;
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN is missing");
}
const store = options.store || memoryStorage;
if (!fetchArgs) {
fetchArgs = {};
}
fetchArgs.cache = "no-store";
fetchArgs.mode = "cors";
if (!fetchArgs.headers) {
fetchArgs.headers = {};
}
const cachedL402Data = store.getItem(url);
if (cachedL402Data) {
const data = JSON.parse(cachedL402Data);
fetchArgs.headers["Authorization"] =
`${headerKey} ${data.token}:${data.preimage}`;
return await fetch(url, fetchArgs);
}
fetchArgs.headers["Accept-Authenticate"] = headerKey;
const initResp = await fetch(url, fetchArgs);
const header = initResp.headers.get("www-authenticate");
if (!header) {
return initResp;
}
const details = parseL402(header);
const token = details.token || details.macaroon;
const inv = details.invoice;
await webln.enable();
const invResp = await webln.sendPayment(inv);
store.setItem(url, JSON.stringify({
token: token,
preimage: invResp.preimage,
}));
fetchArgs.headers["Authorization"] =
`${headerKey} ${token}:${invResp.preimage}`;
return await fetch(url, fetchArgs);
};
export { MemoryStorage, NoStorage, fetchWithL402, parseL402 };
//# sourceMappingURL=l402.js.map
{"version":3,"file":"l402.js","sources":["../../src/l402/utils.ts","../../src/l402/l402.ts"],"sourcesContent":["export interface KVStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nexport class MemoryStorage implements KVStorage {\n storage;\n\n constructor(initial?: Record<string, unknown>) {\n this.storage = initial || {};\n }\n\n getItem(key: string) {\n return this.storage[key];\n }\n\n setItem(key: string, value: unknown) {\n this.storage[key] = value;\n }\n}\n\nexport class NoStorage implements KVStorage {\n constructor(initial?: unknown) {}\n\n getItem(key: string) {\n return null;\n }\n\n setItem(key: string, value: unknown) {}\n}\n\nexport const parseL402 = (input: string): Record<string, string> => {\n // Remove the L402 and LSAT identifiers\n const string = input.replace(\"L402\", \"\").replace(\"LSAT\", \"\").trim();\n\n // Initialize an object to store the key-value pairs\n const keyValuePairs = {};\n\n // Regular expression to match key and (quoted or unquoted) value\n const regex = /(\\w+)=(\"([^\"]*)\"|'([^']*)'|([^,]*))/g;\n let match;\n\n // Use regex to find all key-value pairs\n while ((match = regex.exec(string)) !== null) {\n // Key is always match[1]\n // Value is either match[3] (double-quoted), match[4] (single-quoted), or match[5] (unquoted)\n keyValuePairs[match[1]] = match[3] || match[4] || match[5];\n }\n\n return keyValuePairs;\n};\n","import { KVStorage, MemoryStorage, parseL402 } from \"./utils\";\nimport { WebLNProvider } from \"@webbtc/webln-types\";\n\nconst memoryStorage = new MemoryStorage();\n\nconst HEADER_KEY = \"L402\"; // we have to update this to L402 at some point\n\nexport const fetchWithL402 = async (\n url: string,\n fetchArgs: RequestInit,\n options: {\n headerKey?: string;\n webln?: WebLNProvider;\n store?: KVStorage;\n },\n) => {\n if (!options) {\n options = {};\n }\n const headerKey = options.headerKey || HEADER_KEY;\n const webln: WebLNProvider = options.webln || globalThis.webln;\n if (!webln) {\n throw new Error(\"WebLN is missing\");\n }\n const store = options.store || memoryStorage;\n if (!fetchArgs) {\n fetchArgs = {};\n }\n fetchArgs.cache = \"no-store\";\n fetchArgs.mode = \"cors\";\n if (!fetchArgs.headers) {\n fetchArgs.headers = {};\n }\n const cachedL402Data = store.getItem(url);\n if (cachedL402Data) {\n const data = JSON.parse(cachedL402Data);\n fetchArgs.headers[\"Authorization\"] =\n `${headerKey} ${data.token}:${data.preimage}`;\n return await fetch(url, fetchArgs);\n }\n\n fetchArgs.headers[\"Accept-Authenticate\"] = headerKey;\n const initResp = await fetch(url, fetchArgs);\n const header = initResp.headers.get(\"www-authenticate\");\n if (!header) {\n return initResp;\n }\n\n const details = parseL402(header);\n const token = details.token || details.macaroon;\n const inv = details.invoice;\n\n await webln.enable();\n const invResp = await webln.sendPayment(inv);\n\n store.setItem(\n url,\n JSON.stringify({\n token: token,\n preimage: invResp.preimage,\n }),\n );\n\n fetchArgs.headers[\"Authorization\"] =\n `${headerKey} ${token}:${invResp.preimage}`;\n return await fetch(url, fetchArgs);\n};\n"],"names":[],"mappings":"MAKa,aAAa,CAAA;AAGxB,IAAA,WAAA,CAAY,OAAiC,EAAA;AAC3C,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE;IAC9B;AAEA,IAAA,OAAO,CAAC,GAAW,EAAA;AACjB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;IAC1B;IAEA,OAAO,CAAC,GAAW,EAAE,KAAc,EAAA;AACjC,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK;IAC3B;AACD;MAEY,SAAS,CAAA;IACpB,WAAA,CAAY,OAAiB,IAAG;AAEhC,IAAA,OAAO,CAAC,GAAW,EAAA;AACjB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,OAAO,CAAC,GAAW,EAAE,KAAc,IAAG;AACvC;AAEM,MAAM,SAAS,GAAG,CAAC,KAAa,KAA4B;;IAEjE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;;IAGnE,MAAM,aAAa,GAAG,EAAE;;IAGxB,MAAM,KAAK,GAAG,sCAAsC;AACpD,IAAA,IAAI,KAAK;;AAGT,IAAA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE;;;QAG5C,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC;IAC5D;AAEA,IAAA,OAAO,aAAa;AACtB;;AC/CA,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE;AAEzC,MAAM,UAAU,GAAG,MAAM,CAAC;AAEnB,MAAM,aAAa,GAAG,OAC3B,GAAW,EACX,SAAsB,EACtB,OAIC,KACC;IACF,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,GAAG,EAAE;IACd;AACA,IAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,UAAU;IACjD,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;IAC9D,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC;IACrC;AACA,IAAA,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa;IAC5C,IAAI,CAAC,SAAS,EAAE;QACd,SAAS,GAAG,EAAE;IAChB;AACA,IAAA,SAAS,CAAC,KAAK,GAAG,UAAU;AAC5B,IAAA,SAAS,CAAC,IAAI,GAAG,MAAM;AACvB,IAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;AACtB,QAAA,SAAS,CAAC,OAAO,GAAG,EAAE;IACxB;IACA,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IACzC,IAAI,cAAc,EAAE;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC;AACvC,QAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;YAChC,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAA,CAAE;AAC/C,QAAA,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;IACpC;AAEA,IAAA,SAAS,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,SAAS;IACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;IAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,OAAO,QAAQ;IACjB;AAEA,IAAA,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,QAAQ;AAC/C,IAAA,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO;AAE3B,IAAA,MAAM,KAAK,CAAC,MAAM,EAAE;IACpB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC;IAE5C,KAAK,CAAC,OAAO,CACX,GAAG,EACH,IAAI,CAAC,SAAS,CAAC;AACb,QAAA,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC3B,KAAA,CAAC,CACH;AAED,IAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;QAChC,CAAA,EAAG,SAAS,IAAI,KAAK,CAAA,CAAA,EAAI,OAAO,CAAC,QAAQ,EAAE;AAC7C,IAAA,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;AACpC;;;;"}
function bytes(b, ...lengths) {
if (!(b instanceof Uint8Array))
throw new Error('Expected Uint8Array');
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error('Hash instance has been destroyed');
if (checkFinished && instance.finished)
throw new Error('Hash#digest() has already been called');
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
// node.js versions earlier than v19 don't declare it in global scope.
// For node.js, package.json#exports field mapping rewrites import
// from `crypto` to `cryptoNode`, which imports native module.
// Makes the utils un-importable in browsers without a bundler.
// Once node.js 18 is deprecated, we can just drop the import.
const u8a = (a) => a instanceof Uint8Array;
// Cast array to view
const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
// The rotate right (circular right shift) operation for uint32
const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
// big-endian hardware is rare. Just in case someone still decides to run hashes:
// early-throw an error because we don't support BE yet.
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
if (!isLE)
throw new Error('Non little-endian hardware is not supported');
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
/**
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
*/
function bytesToHex(bytes) {
if (!u8a(bytes))
throw new Error('Uint8Array expected');
// pre-caching improves the speed 6x
let hex = '';
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]];
}
return hex;
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
function utf8ToBytes(str) {
if (typeof str !== 'string')
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
/**
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
* Warning: when Uint8Array is passed, it would NOT get copied.
* Keep in mind for future mutable operations.
*/
function toBytes(data) {
if (typeof data === 'string')
data = utf8ToBytes(data);
if (!u8a(data))
throw new Error(`expected Uint8Array, got ${typeof data}`);
return data;
}
// For runtime check if class implements interface
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
// Polyfill for Safari 14
function setBigUint64(view, byteOffset, value, isLE) {
if (typeof view.setBigUint64 === 'function')
return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(0xffffffff);
const wh = Number((value >> _32n) & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
// Base SHA2 class (RFC 6234)
class SHA2 extends Hash {
constructor(blockLen, outputLen, padOffset, isLE) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
exists(this);
const { view, buffer, blockLen } = this;
data = toBytes(data);
const len = data.length;
for (let pos = 0; pos < len;) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
exists(this);
output(out, this);
this.finished = true;
// Padding
// We can avoid allocation of buffer for padding completely if it
// was previously not allocated here. But it won't change performance.
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
// append the bit '1' to the message
buffer[pos++] = 0b10000000;
this.buffer.subarray(pos).fill(0);
// we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
// Pad until full block byte with zeros
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
// So we just write lowest 64 bits of that value.
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
// NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
if (len % 4)
throw new Error('_sha2: outputLen should be aligned to 32bit');
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error('_sha2: outputLen bigger than state');
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
}
// SHA2-256 need to try 2^128 hashes to execute birthday attack.
// BTC network is doing 2^67 hashes/sec as per early 2023.
// Choice: a ? b : c
const Chi = (a, b, c) => (a & b) ^ (~a & c);
// Majority function, true if any two inpust is true
const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
// Round constants:
// first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
// prettier-ignore
const SHA256_K = /* @__PURE__ */ new Uint32Array([
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]);
// Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
// prettier-ignore
const IV = /* @__PURE__ */ new Uint32Array([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
]);
// Temporary buffer, not used to store anything between runs
// Named this way because it matches specification.
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
class SHA256 extends SHA2 {
constructor() {
super(64, 32, 8, false);
// We cannot use array here since array allows indexing by variable
// which means optimizer/compiler cannot use registers.
this.A = IV[0] | 0;
this.B = IV[1] | 0;
this.C = IV[2] | 0;
this.D = IV[3] | 0;
this.E = IV[4] | 0;
this.F = IV[5] | 0;
this.G = IV[6] | 0;
this.H = IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
// Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
}
// Compression function main loop, 64 rounds
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = (sigma0 + Maj(A, B, C)) | 0;
H = G;
G = F;
F = E;
E = (D + T1) | 0;
D = C;
C = B;
B = A;
A = (T1 + T2) | 0;
}
// Add the compressed chunk to the current hash value
A = (A + this.A) | 0;
B = (B + this.B) | 0;
C = (C + this.C) | 0;
D = (D + this.D) | 0;
E = (E + this.E) | 0;
F = (F + this.F) | 0;
G = (G + this.G) | 0;
H = (H + this.H) | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
}
/**
* SHA2-256 hash function
* @param message - data that would be hashed
*/
const sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
const TAG_KEYSEND = "keysend";
const parseKeysendResponse = (data) => {
if (data.tag !== TAG_KEYSEND)
throw new Error("Invalid keysend params");
if (data.status !== "OK")
throw new Error("Keysend status not OK");
if (!data.pubkey)
throw new Error("Pubkey does not exist");
const destination = data.pubkey;
let customKey, customValue;
if (data.customData && data.customData[0]) {
customKey = data.customData[0].customKey;
customValue = data.customData[0].customValue;
}
return {
destination,
customKey,
customValue,
};
};
async function generateZapEvent({ satoshi, comment, p, e, relays }, options = {}) {
const nostr = options.nostr || globalThis.nostr;
if (!nostr) {
throw new Error("nostr option or window.nostr is not available");
}
const nostrTags = [
["relays", ...relays],
["amount", satoshi.toString()],
];
if (p) {
nostrTags.push(["p", p]);
}
if (e) {
nostrTags.push(["e", e]);
}
const pubkey = await nostr.getPublicKey();
const nostrEvent = {
pubkey,
created_at: Math.floor(Date.now() / 1000),
kind: 9734,
tags: nostrTags,
content: comment ?? "",
};
nostrEvent.id = getEventHash(nostrEvent);
return await nostr.signEvent(nostrEvent);
}
function validateEvent(event) {
if (typeof event.content !== "string")
return false;
if (typeof event.created_at !== "number")
return false;
// ignore these checks because if the pubkey is not set we add it to the event. same for the ID.
// if (typeof event.pubkey !== "string") return false;
// if (!event.pubkey.match(/^[a-f0-9]{64}$/)) return false;
if (!Array.isArray(event.tags))
return false;
for (let i = 0; i < event.tags.length; i++) {
const tag = event.tags[i];
if (!Array.isArray(tag))
return false;
for (let j = 0; j < tag.length; j++) {
if (typeof tag[j] === "object")
return false;
}
}
return true;
}
function serializeEvent(evt) {
if (!validateEvent(evt))
throw new Error("can't serialize event with wrong or missing properties");
return JSON.stringify([
0,
evt.pubkey,
evt.created_at,
evt.kind,
evt.tags,
evt.content,
]);
}
function getEventHash(event) {
return bytesToHex(sha256(serializeEvent(event)));
}
function parseNostrResponse(nostrData, username) {
let nostrPubkey;
let nostrRelays;
if (username && nostrData) {
nostrPubkey = nostrData.names?.[username];
nostrRelays = nostrPubkey ? nostrData.relays?.[nostrPubkey] : undefined;
}
return [nostrData, nostrPubkey, nostrRelays];
}
const URL_REGEX = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/;
const isUrl = (url) => {
if (!url)
return false;
return URL_REGEX.test(url);
};
const isValidAmount = ({ amount, min, max, }) => {
return amount > 0 && amount >= min && amount <= max;
};
const TAG_PAY_REQUEST = "payRequest";
// From: https://github.com/dolcalmi/lnurl-pay/blob/main/src/request-pay-service-params.ts
const parseLnUrlPayResponse = async (data) => {
if (data.tag !== TAG_PAY_REQUEST)
throw new Error("Invalid pay service params");
const callback = (data.callback + "").trim();
if (!isUrl(callback))
throw new Error("Callback must be a valid url");
const min = Math.ceil(Number(data.minSendable || 0));
const max = Math.floor(Number(data.maxSendable));
if (!(min && max) || min > max)
throw new Error("Invalid pay service params");
let metadata;
let metadataHash;
try {
metadata = JSON.parse(data.metadata + "");
metadataHash = bytesToHex(sha256(data.metadata + ""));
}
catch {
metadata = [];
metadataHash = bytesToHex(sha256("[]"));
}
let email = "";
let image = "";
let description = "";
let identifier = "";
for (let i = 0; i < metadata.length; i++) {
const [k, v] = metadata[i];
switch (k) {
case "text/plain":
description = v;
break;
case "text/identifier":
identifier = v;
break;
case "text/email":
email = v;
break;
case "image/png;base64":
case "image/jpeg;base64":
image = "data:" + k + "," + v;
break;
}
}
const payerData = data.payerData;
let domain;
try {
domain = new URL(callback).hostname;
}
catch {
// fail silently and let domain remain undefined if callback is not a valid URL
}
return {
callback,
fixed: min === max,
min,
max,
domain,
metadata,
metadataHash,
identifier,
email,
description,
image,
payerData,
commentAllowed: Number(data.commentAllowed) || 0,
rawData: data,
allowsNostr: data.allowsNostr || false,
};
};
var lib = {};
var hasRequiredLib;
function requireLib () {
if (hasRequiredLib) return lib;
hasRequiredLib = 1;
(function (exports) {
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64url = exports.base64 = exports.base32crockford = exports.base32hex = exports.base32 = exports.base16 = exports.utils = exports.assertNumber = void 0;
function assertNumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`Wrong integer: ${n}`);
}
exports.assertNumber = assertNumber;
function chain(...args) {
const wrap = (a, b) => (c) => a(b(c));
const encode = Array.from(args)
.reverse()
.reduce((acc, i) => (acc ? wrap(acc, i.encode) : i.encode), undefined);
const decode = args.reduce((acc, i) => (acc ? wrap(acc, i.decode) : i.decode), undefined);
return { encode, decode };
}
function alphabet(alphabet) {
return {
encode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('alphabet.encode input should be an array of numbers');
return digits.map((i) => {
assertNumber(i);
if (i < 0 || i >= alphabet.length)
throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);
return alphabet[i];
});
},
decode: (input) => {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('alphabet.decode input should be array of strings');
return input.map((letter) => {
if (typeof letter !== 'string')
throw new Error(`alphabet.decode: not string element=${letter}`);
const index = alphabet.indexOf(letter);
if (index === -1)
throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);
return index;
});
},
};
}
function join(separator = '') {
if (typeof separator !== 'string')
throw new Error('join separator should be string');
return {
encode: (from) => {
if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))
throw new Error('join.encode input should be array of strings');
for (let i of from)
if (typeof i !== 'string')
throw new Error(`join.encode: non-string input=${i}`);
return from.join(separator);
},
decode: (to) => {
if (typeof to !== 'string')
throw new Error('join.decode input should be string');
return to.split(separator);
},
};
}
function padding(bits, chr = '=') {
assertNumber(bits);
if (typeof chr !== 'string')
throw new Error('padding chr should be string');
return {
encode(data) {
if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of data)
if (typeof i !== 'string')
throw new Error(`padding.encode: non-string input=${i}`);
while ((data.length * bits) % 8)
data.push(chr);
return data;
},
decode(input) {
if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
throw new Error('padding.encode input should be array of strings');
for (let i of input)
if (typeof i !== 'string')
throw new Error(`padding.decode: non-string input=${i}`);
let end = input.length;
if ((end * bits) % 8)
throw new Error('Invalid padding: string should have whole number of bytes');
for (; end > 0 && input[end - 1] === chr; end--) {
if (!(((end - 1) * bits) % 8))
throw new Error('Invalid padding: string has too much padding');
}
return input.slice(0, end);
},
};
}
function normalize(fn) {
if (typeof fn !== 'function')
throw new Error('normalize fn should be function');
return { encode: (from) => from, decode: (to) => fn(to) };
}
function convertRadix(data, from, to) {
if (from < 2)
throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
if (to < 2)
throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
if (!Array.isArray(data))
throw new Error('convertRadix: data should be array');
if (!data.length)
return [];
let pos = 0;
const res = [];
const digits = Array.from(data);
digits.forEach((d) => {
assertNumber(d);
if (d < 0 || d >= from)
throw new Error(`Wrong integer: ${d}`);
});
while (true) {
let carry = 0;
let done = true;
for (let i = pos; i < digits.length; i++) {
const digit = digits[i];
const digitBase = from * carry + digit;
if (!Number.isSafeInteger(digitBase) ||
(from * carry) / from !== carry ||
digitBase - digit !== from * carry) {
throw new Error('convertRadix: carry overflow');
}
carry = digitBase % to;
digits[i] = Math.floor(digitBase / to);
if (!Number.isSafeInteger(digits[i]) || digits[i] * to + carry !== digitBase)
throw new Error('convertRadix: carry overflow');
if (!done)
continue;
else if (!digits[i])
pos = i;
else
done = false;
}
res.push(carry);
if (done)
break;
}
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
res.push(0);
return res.reverse();
}
const gcd = (a, b) => (!b ? a : gcd(b, a % b));
const radix2carry = (from, to) => from + (to - gcd(from, to));
function convertRadix2(data, from, to, padding) {
if (!Array.isArray(data))
throw new Error('convertRadix2: data should be array');
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0;
const mask = 2 ** to - 1;
const res = [];
for (const n of data) {
assertNumber(n);
if (n >= 2 ** from)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = (carry << from) | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push(((carry >> (pos - to)) & mask) >>> 0);
carry &= 2 ** pos - 1;
}
carry = (carry << (to - pos)) & mask;
if (!padding && pos >= from)
throw new Error('Excess padding');
if (!padding && carry)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
function radix(num) {
assertNumber(num);
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix.encode input should be Uint8Array');
return convertRadix(Array.from(bytes), 2 ** 8, num);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix.decode input should be array of strings');
return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
},
};
}
function radix2(bits, revPadding = false) {
assertNumber(bits);
if (bits <= 0 || bits > 32)
throw new Error('radix2: bits should be in (0..32]');
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
throw new Error('radix2: carry overflow');
return {
encode: (bytes) => {
if (!(bytes instanceof Uint8Array))
throw new Error('radix2.encode input should be Uint8Array');
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
throw new Error('radix2.decode input should be array of strings');
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
},
};
}
function unsafeWrapper(fn) {
if (typeof fn !== 'function')
throw new Error('unsafeWrapper fn should be function');
return function (...args) {
try {
return fn.apply(null, args);
}
catch (e) { }
};
}
function checksum(len, fn) {
assertNumber(len);
if (typeof fn !== 'function')
throw new Error('checksum fn should be function');
return {
encode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.encode: input should be Uint8Array');
const checksum = fn(data).slice(0, len);
const res = new Uint8Array(data.length + len);
res.set(data);
res.set(checksum, data.length);
return res;
},
decode(data) {
if (!(data instanceof Uint8Array))
throw new Error('checksum.decode: input should be Uint8Array');
const payload = data.slice(0, -len);
const newChecksum = fn(payload).slice(0, len);
const oldChecksum = data.slice(-len);
for (let i = 0; i < len; i++)
if (newChecksum[i] !== oldChecksum[i])
throw new Error('Invalid checksum');
return payload;
},
};
}
exports.utils = { alphabet, chain, checksum, radix, radix2, join, padding };
exports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
exports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
exports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
exports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
exports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
exports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
const genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));
exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
exports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
exports.base58xmr = {
encode(data) {
let res = '';
for (let i = 0; i < data.length; i += 8) {
const block = data.subarray(i, i + 8);
res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
}
return res;
},
decode(str) {
let res = [];
for (let i = 0; i < str.length; i += 11) {
const slice = str.slice(i, i + 11);
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
const block = exports.base58.decode(slice);
for (let j = 0; j < block.length - blockLen; j++) {
if (block[j] !== 0)
throw new Error('base58xmr: wrong padding');
}
res = res.concat(Array.from(block.slice(block.length - blockLen)));
}
return Uint8Array.from(res);
},
};
const base58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
exports.base58check = base58check;
const BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 0x1ffffff) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if (((b >> i) & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ (c >> 5);
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
}
function genBech32(encoding) {
const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
const _words = radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
if (typeof prefix !== 'string')
throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))
throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
const actualLength = prefix.length + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
prefix = prefix.toLowerCase();
return `${prefix}1${BECH_ALPHABET.encode(words)}${bechChecksum(prefix, words, ENCODING_CONST)}`;
}
function decode(str, limit = 90) {
if (typeof str !== 'string')
throw new Error(`bech32.decode input should be string, not ${typeof str}`);
if (str.length < 8 || (limit !== false && str.length > limit))
throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
str = lowered;
const sepIndex = str.lastIndexOf('1');
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = str.slice(0, sepIndex);
const _words = str.slice(sepIndex + 1);
if (_words.length < 6)
throw new Error('Data must be at least 6 characters long');
const words = BECH_ALPHABET.decode(_words).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!_words.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
return { encode, decode, decodeToBytes, decodeUnsafe, fromWords, fromWordsUnsafe, toWords };
}
exports.bech32 = genBech32('bech32');
exports.bech32m = genBech32('bech32m');
exports.utf8 = {
encode: (data) => new TextDecoder().decode(data),
decode: (str) => new TextEncoder().encode(str),
};
exports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
if (typeof s !== 'string' || s.length % 2)
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
return s.toLowerCase();
}));
const CODERS = {
utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
};
const coderTypeError = `Invalid encoding type. Available types: ${Object.keys(CODERS).join(', ')}`;
const bytesToString = (type, bytes) => {
if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (!(bytes instanceof Uint8Array))
throw new TypeError('bytesToString() expects Uint8Array');
return CODERS[type].encode(bytes);
};
exports.bytesToString = bytesToString;
exports.str = exports.bytesToString;
const stringToBytes = (type, str) => {
if (!CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (typeof str !== 'string')
throw new TypeError('stringToBytes() expects string');
return CODERS[type].decode(str);
};
exports.stringToBytes = stringToBytes;
exports.bytes = exports.stringToBytes;
} (lib));
return lib;
}
var bolt11;
var hasRequiredBolt11;
function requireBolt11 () {
if (hasRequiredBolt11) return bolt11;
hasRequiredBolt11 = 1;
const {bech32, hex, utf8} = requireLib();
// defaults for encode; default timestamp is current time at call
const DEFAULTNETWORK = {
// default network is bitcoin
bech32: 'bc',
pubKeyHash: 0x00,
scriptHash: 0x05,
validWitnessVersions: [0]
};
const TESTNETWORK = {
bech32: 'tb',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIGNETNETWORK = {
bech32: 'tbs',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const REGTESTNETWORK = {
bech32: 'bcrt',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
validWitnessVersions: [0]
};
const SIMNETWORK = {
bech32: 'sb',
pubKeyHash: 0x3f,
scriptHash: 0x7b,
validWitnessVersions: [0]
};
const FEATUREBIT_ORDER = [
'option_data_loss_protect',
'initial_routing_sync',
'option_upfront_shutdown_script',
'gossip_queries',
'var_onion_optin',
'gossip_queries_ex',
'option_static_remotekey',
'payment_secret',
'basic_mpp',
'option_support_large_channel'
];
const DIVISORS = {
m: BigInt(1e3),
u: BigInt(1e6),
n: BigInt(1e9),
p: BigInt(1e12)
};
const MAX_MILLISATS = BigInt('2100000000000000000');
const MILLISATS_PER_BTC = BigInt(1e11);
const TAGCODES = {
payment_hash: 1,
payment_secret: 16,
description: 13,
payee: 19,
description_hash: 23, // commit to longer descriptions (used by lnurl-pay)
expiry: 6, // default: 3600 (1 hour)
min_final_cltv_expiry: 24, // default: 9
fallback_address: 9,
route_hint: 3, // for extra routing info (private etc.)
feature_bits: 5,
metadata: 27
};
// reverse the keys and values of TAGCODES and insert into TAGNAMES
const TAGNAMES = {};
for (let i = 0, keys = Object.keys(TAGCODES); i < keys.length; i++) {
const currentName = keys[i];
const currentCode = TAGCODES[keys[i]].toString();
TAGNAMES[currentCode] = currentName;
}
const TAGPARSERS = {
1: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
16: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
13: words => utf8.encode(bech32.fromWordsUnsafe(words)), // string variable length
19: words => hex.encode(bech32.fromWordsUnsafe(words)), // 264 bits
23: words => hex.encode(bech32.fromWordsUnsafe(words)), // 256 bits
27: words => hex.encode(bech32.fromWordsUnsafe(words)), // variable
6: wordsToIntBE, // default: 3600 (1 hour)
24: wordsToIntBE, // default: 9
3: routingInfoParser, // for extra routing info (private etc.)
5: featureBitsParser // keep feature bits as array of 5 bit words
};
function getUnknownParser(tagCode) {
return words => ({
tagCode: parseInt(tagCode),
words: bech32.encode('unknown', words, Number.MAX_SAFE_INTEGER)
})
}
function wordsToIntBE(words) {
return words.reverse().reduce((total, item, index) => {
return total + item * Math.pow(32, index)
}, 0)
}
// first convert from words to buffer, trimming padding where necessary
// parse in 51 byte chunks. See encoder for details.
function routingInfoParser(words) {
const routes = [];
let pubkey,
shortChannelId,
feeBaseMSats,
feeProportionalMillionths,
cltvExpiryDelta;
let routesBuffer = bech32.fromWordsUnsafe(words);
while (routesBuffer.length > 0) {
pubkey = hex.encode(routesBuffer.slice(0, 33)); // 33 bytes
shortChannelId = hex.encode(routesBuffer.slice(33, 41)); // 8 bytes
feeBaseMSats = parseInt(hex.encode(routesBuffer.slice(41, 45)), 16); // 4 bytes
feeProportionalMillionths = parseInt(
hex.encode(routesBuffer.slice(45, 49)),
16
); // 4 bytes
cltvExpiryDelta = parseInt(hex.encode(routesBuffer.slice(49, 51)), 16); // 2 bytes
routesBuffer = routesBuffer.slice(51);
routes.push({
pubkey,
short_channel_id: shortChannelId,
fee_base_msat: feeBaseMSats,
fee_proportional_millionths: feeProportionalMillionths,
cltv_expiry_delta: cltvExpiryDelta
});
}
return routes
}
function featureBitsParser(words) {
const bools = words
.slice()
.reverse()
.map(word => [
!!(word & 0b1),
!!(word & 0b10),
!!(word & 0b100),
!!(word & 0b1000),
!!(word & 0b10000)
])
.reduce((finalArr, itemArr) => finalArr.concat(itemArr), []);
while (bools.length < FEATUREBIT_ORDER.length * 2) {
bools.push(false);
}
const featureBits = {};
FEATUREBIT_ORDER.forEach((featureName, index) => {
let status;
if (bools[index * 2]) {
status = 'required';
} else if (bools[index * 2 + 1]) {
status = 'supported';
} else {
status = 'unsupported';
}
featureBits[featureName] = status;
});
const extraBits = bools.slice(FEATUREBIT_ORDER.length * 2);
featureBits.extra_bits = {
start_bit: FEATUREBIT_ORDER.length * 2,
bits: extraBits,
has_required: extraBits.reduce(
(result, bit, index) =>
index % 2 !== 0 ? result || false : result || bit,
false
)
};
return featureBits
}
function hrpToMillisat(hrpString, outputString) {
let divisor, value;
if (hrpString.slice(-1).match(/^[munp]$/)) {
divisor = hrpString.slice(-1);
value = hrpString.slice(0, -1);
} else if (hrpString.slice(-1).match(/^[^munp0-9]$/)) {
throw new Error('Not a valid multiplier for the amount')
} else {
value = hrpString;
}
if (!value.match(/^\d+$/))
throw new Error('Not a valid human readable amount')
const valueBN = BigInt(value);
const millisatoshisBN = divisor
? (valueBN * MILLISATS_PER_BTC) / DIVISORS[divisor]
: valueBN * MILLISATS_PER_BTC;
if (
(divisor === 'p' && !(valueBN % BigInt(10) === BigInt(0))) ||
millisatoshisBN > MAX_MILLISATS
) {
throw new Error('Amount is outside of valid range')
}
return outputString ? millisatoshisBN.toString() : millisatoshisBN
}
// decode will only have extra comments that aren't covered in encode comments.
// also if anything is hard to read I'll comment.
function decode(paymentRequest, network) {
if (typeof paymentRequest !== 'string')
throw new Error('Lightning Payment Request must be string')
if (paymentRequest.slice(0, 2).toLowerCase() !== 'ln')
throw new Error('Not a proper lightning payment request')
const sections = [];
const decoded = bech32.decode(paymentRequest, Number.MAX_SAFE_INTEGER);
paymentRequest = paymentRequest.toLowerCase();
const prefix = decoded.prefix;
let words = decoded.words;
let letters = paymentRequest.slice(prefix.length + 1);
let sigWords = words.slice(-104);
words = words.slice(0, -104);
// Without reverse lookups, can't say that the multipier at the end must
// have a number before it, so instead we parse, and if the second group
// doesn't have anything, there's a good chance the last letter of the
// coin type got captured by the third group, so just re-regex without
// the number.
let prefixMatches = prefix.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);
if (prefixMatches && !prefixMatches[2])
prefixMatches = prefix.match(/^ln(\S+)$/);
if (!prefixMatches) {
throw new Error('Not a proper lightning payment request')
}
// "ln" section
sections.push({
name: 'lightning_network',
letters: 'ln'
});
// "bc" section
const bech32Prefix = prefixMatches[1];
let coinNetwork;
if (!network) {
switch (bech32Prefix) {
case DEFAULTNETWORK.bech32:
coinNetwork = DEFAULTNETWORK;
break
case TESTNETWORK.bech32:
coinNetwork = TESTNETWORK;
break
case SIGNETNETWORK.bech32:
coinNetwork = SIGNETNETWORK;
break
case REGTESTNETWORK.bech32:
coinNetwork = REGTESTNETWORK;
break
case SIMNETWORK.bech32:
coinNetwork = SIMNETWORK;
break
}
} else {
if (
network.bech32 === undefined ||
network.pubKeyHash === undefined ||
network.scriptHash === undefined ||
!Array.isArray(network.validWitnessVersions)
)
throw new Error('Invalid network')
coinNetwork = network;
}
if (!coinNetwork || coinNetwork.bech32 !== bech32Prefix) {
throw new Error('Unknown coin bech32 prefix')
}
sections.push({
name: 'coin_network',
letters: bech32Prefix,
value: coinNetwork
});
// amount section
const value = prefixMatches[2];
let millisatoshis;
if (value) {
const divisor = prefixMatches[3];
millisatoshis = hrpToMillisat(value + divisor, true);
sections.push({
name: 'amount',
letters: prefixMatches[2] + prefixMatches[3],
value: millisatoshis
});
} else {
millisatoshis = null;
}
// "1" separator
sections.push({
name: 'separator',
letters: '1'
});
// timestamp
const timestamp = wordsToIntBE(words.slice(0, 7));
words = words.slice(7); // trim off the left 7 words
sections.push({
name: 'timestamp',
letters: letters.slice(0, 7),
value: timestamp
});
letters = letters.slice(7);
let tagName, parser, tagLength, tagWords;
// we have no tag count to go on, so just keep hacking off words
// until we have none.
while (words.length > 0) {
const tagCode = words[0].toString();
tagName = TAGNAMES[tagCode] || 'unknown_tag';
parser = TAGPARSERS[tagCode] || getUnknownParser(tagCode);
words = words.slice(1);
tagLength = wordsToIntBE(words.slice(0, 2));
words = words.slice(2);
tagWords = words.slice(0, tagLength);
words = words.slice(tagLength);
sections.push({
name: tagName,
tag: letters[0],
letters: letters.slice(0, 1 + 2 + tagLength),
value: parser(tagWords) // see: parsers for more comments
});
letters = letters.slice(1 + 2 + tagLength);
}
// signature
sections.push({
name: 'signature',
letters: letters.slice(0, 104),
value: hex.encode(bech32.fromWordsUnsafe(sigWords))
});
letters = letters.slice(104);
// checksum
sections.push({
name: 'checksum',
letters: letters
});
let result = {
paymentRequest,
sections,
get expiry() {
let exp = sections.find(s => s.name === 'expiry');
if (exp) return getValue('timestamp') + exp.value
},
get route_hints() {
return sections.filter(s => s.name === 'route_hint').map(s => s.value)
}
};
for (let name in TAGCODES) {
if (name === 'route_hint') {
// route hints can be multiple, so this won't work for them
continue
}
Object.defineProperty(result, name, {
get() {
return getValue(name)
}
});
}
return result
function getValue(name) {
let section = sections.find(s => s.name === name);
return section ? section.value : undefined
}
}
bolt11 = {
decode,
hrpToMillisat
};
return bolt11;
}
var bolt11Exports = requireBolt11();
// from https://stackoverflow.com/a/50868276
const fromHexString = (hexString) => Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const decodeInvoice = (paymentRequest) => {
if (!paymentRequest)
return null;
try {
const decoded = bolt11Exports.decode(paymentRequest);
if (!decoded || !decoded.sections)
return null;
const hashTag = decoded.sections.find((value) => value.name === "payment_hash");
if (hashTag?.name !== "payment_hash" || !hashTag.value)
return null;
const paymentHash = hashTag.value;
let satoshi = 0;
const amountTag = decoded.sections.find((value) => value.name === "amount");
if (amountTag?.name === "amount" && amountTag.value) {
satoshi = parseInt(amountTag.value) / 1000; // millisats
}
const timestampTag = decoded.sections.find((value) => value.name === "timestamp");
if (timestampTag?.name !== "timestamp" || !timestampTag.value)
return null;
const timestamp = timestampTag.value;
let expiry;
const expiryTag = decoded.sections.find((value) => value.name === "expiry");
if (expiryTag?.name === "expiry") {
expiry = expiryTag.value;
}
const descriptionTag = decoded.sections.find((value) => value.name === "description");
const description = descriptionTag?.name === "description"
? descriptionTag?.value
: undefined;
return {
paymentHash,
satoshi,
timestamp,
expiry,
description,
};
}
catch {
return null;
}
};
class Invoice {
constructor(args) {
this.paymentRequest = args.pr;
if (!this.paymentRequest) {
throw new Error("Invalid payment request");
}
const decodedInvoice = decodeInvoice(this.paymentRequest);
if (!decodedInvoice) {
throw new Error("Failed to decode payment request");
}
this.paymentHash = decodedInvoice.paymentHash;
this.satoshi = decodedInvoice.satoshi;
this.timestamp = decodedInvoice.timestamp;
this.expiry = decodedInvoice.expiry;
this.createdDate = new Date(this.timestamp * 1000);
this.expiryDate = this.expiry
? new Date((this.timestamp + this.expiry) * 1000)
: undefined;
this.description = decodedInvoice.description ?? null;
this.verify = args.verify ?? null;
this.preimage = args.preimage ?? null;
this.successAction = args.successAction ?? null;
}
async isPaid() {
if (this.preimage)
return this.validatePreimage(this.preimage);
else if (this.verify) {
return await this.verifyPayment();
}
else {
throw new Error("Could not verify payment");
}
}
validatePreimage(preimage) {
if (!preimage || !this.paymentHash)
return false;
try {
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
return this.paymentHash === preimageHash;
}
catch {
return false;
}
}
async verifyPayment() {
try {
if (!this.verify) {
throw new Error("LNURL verify not available");
}
const response = await fetch(this.verify);
if (!response.ok) {
throw new Error(`Verification request failed: ${response.status} ${response.statusText}`);
}
const json = await response.json();
if (json.preimage) {
this.preimage = json.preimage;
}
return json.settled;
}
catch (error) {
console.error("Failed to check LNURL-verify", error);
return false;
}
}
hasExpired() {
const { expiryDate } = this;
if (expiryDate) {
return expiryDate.getTime() < Date.now();
}
return false;
}
}
const sendBoostagram = async (args, options) => {
const { boost } = args;
if (!options) {
options = {};
}
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN not available");
}
if (!webln.keysend) {
throw new Error("Keysend not available in current WebLN provider");
}
const amount = args.amount || Math.floor(boost.value_msat / 1000);
const weblnParams = {
destination: args.destination,
amount: amount,
customRecords: {
"7629169": JSON.stringify(boost),
},
};
if (args.customKey && args.customValue) {
weblnParams.customRecords[args.customKey] = args.customValue;
}
await webln.enable();
const response = await webln.keysend(weblnParams);
return response;
};
const LN_ADDRESS_REGEX = /^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const DEFAULT_PROXY = "https://api.getalby.com/lnurl";
class LightningAddress {
constructor(address, options) {
this.address = address;
this.options = { proxy: DEFAULT_PROXY };
this.options = Object.assign(this.options, options);
this.parse();
this.webln = this.options.webln;
}
parse() {
const result = LN_ADDRESS_REGEX.exec(this.address.toLowerCase());
if (result) {
this.username = result[1];
this.domain = result[2];
}
}
getWebLN() {
return this.webln || globalThis.webln;
}
async fetch() {
if (this.options.proxy) {
return this.fetchWithProxy();
}
else {
return this.fetchWithoutProxy();
}
}
async fetchWithProxy() {
const response = await fetch(`${this.options.proxy}/lightning-address-details?${new URLSearchParams({
ln: this.address,
}).toString()}`);
if (!response.ok) {
throw new Error(`Failed to fetch lnurl info: ${response.status} ${response.statusText}`);
}
const json = await response.json();
await this.parseLnUrlPayResponse(json.lnurlp);
this.parseKeysendResponse(json.keysend);
this.parseNostrResponse(json.nostr);
}
async fetchWithoutProxy() {
if (!this.domain || !this.username) {
return;
}
await Promise.all([
this.fetchLnurlData(),
this.fetchKeysendData(),
this.fetchNostrData(),
]);
}
async fetchLnurlData() {
const lnurlResult = await fetch(this.lnurlpUrl());
if (lnurlResult.ok) {
const lnurlData = await lnurlResult.json();
await this.parseLnUrlPayResponse(lnurlData);
}
}
async fetchKeysendData() {
const keysendResult = await fetch(this.keysendUrl());
if (keysendResult.ok) {
const keysendData = await keysendResult.json();
this.parseKeysendResponse(keysendData);
}
}
async fetchNostrData() {
const nostrResult = await fetch(this.nostrUrl());
if (nostrResult.ok) {
const nostrData = await nostrResult.json();
this.parseNostrResponse(nostrData);
}
}
lnurlpUrl() {
return `https://${this.domain}/.well-known/lnurlp/${this.username}`;
}
keysendUrl() {
return `https://${this.domain}/.well-known/keysend/${this.username}`;
}
nostrUrl() {
return `https://${this.domain}/.well-known/nostr.json?name=${this.username}`;
}
async generateInvoice(params) {
let data;
if (this.options.proxy) {
const invoiceResponse = await fetch(`${this.options.proxy}/generate-invoice?${new URLSearchParams({
ln: this.address,
...params,
}).toString()}`);
if (!invoiceResponse.ok) {
throw new Error(`Failed to generate invoice: ${invoiceResponse.status} ${invoiceResponse.statusText}`);
}
const json = await invoiceResponse.json();
data = json.invoice;
}
else {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
if (!this.lnurlpData.callback || !isUrl(this.lnurlpData.callback))
throw new Error("Valid callback does not exist in lnurlpData");
const callbackUrl = new URL(this.lnurlpData.callback);
callbackUrl.search = new URLSearchParams(params).toString();
const invoiceResponse = await fetch(callbackUrl.toString());
if (!invoiceResponse.ok) {
throw new Error(`Failed to generate invoice: ${invoiceResponse.status} ${invoiceResponse.statusText}`);
}
data = await invoiceResponse.json();
}
const paymentRequest = data && data.pr && data.pr.toString();
if (!paymentRequest)
throw new Error("Invalid pay service invoice");
const invoiceArgs = { pr: paymentRequest };
if (data && data.verify)
invoiceArgs.verify = data.verify.toString();
if (data && data.successAction && typeof data.successAction === "object") {
const { tag, message, description, url } = data.successAction;
if (tag === "message") {
invoiceArgs.successAction = { tag, message };
}
else if (tag === "url") {
invoiceArgs.successAction = { tag, description, url };
}
}
return new Invoice(invoiceArgs);
}
async requestInvoice(args) {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
const msat = args.satoshi * 1000;
const { commentAllowed, min, max } = this.lnurlpData;
if (!isValidAmount({ amount: msat, min, max }))
throw new Error("Invalid amount");
if (args.comment &&
commentAllowed &&
commentAllowed > 0 &&
args.comment.length > commentAllowed)
throw new Error(`The comment length must be ${commentAllowed} characters or fewer`);
const invoiceParams = { amount: msat.toString() };
if (args.comment)
invoiceParams.comment = args.comment;
if (args.payerdata)
invoiceParams.payerdata = JSON.stringify(args.payerdata);
return this.generateInvoice(invoiceParams);
}
async boost(boost, amount = 0) {
if (!this.keysendData) {
throw new Error("No keysendData available. Please call fetch() first.");
}
const { destination, customKey, customValue } = this.keysendData;
const webln = this.getWebLN();
if (!webln) {
throw new Error("WebLN not available");
}
return sendBoostagram({
destination,
customKey,
customValue,
amount,
boost,
}, { webln });
}
async zapInvoice({ satoshi, comment, relays, e }, options = {}) {
if (!this.lnurlpData) {
throw new Error("No lnurlpData available. Please call fetch() first.");
}
if (!this.nostrPubkey) {
throw new Error("Nostr Pubkey is missing");
}
const p = this.nostrPubkey;
const msat = satoshi * 1000;
const { allowsNostr, min, max } = this.lnurlpData;
if (!isValidAmount({ amount: msat, min, max }))
throw new Error("Invalid amount");
if (!allowsNostr)
throw new Error("Your provider does not support zaps");
const event = await generateZapEvent({
satoshi: msat,
comment,
p,
e,
relays,
}, options);
const zapParams = {
amount: msat.toString(),
nostr: JSON.stringify(event),
};
const invoice = await this.generateInvoice(zapParams);
return invoice;
}
async zap(args, options = {}) {
const invoice = this.zapInvoice(args, options);
const webln = this.getWebLN();
if (!webln) {
throw new Error("WebLN not available");
}
await webln.enable();
const response = webln.sendPayment((await invoice).paymentRequest);
return response;
}
async parseLnUrlPayResponse(lnurlpData) {
if (lnurlpData) {
this.lnurlpData = await parseLnUrlPayResponse(lnurlpData);
}
}
parseKeysendResponse(keysendData) {
if (keysendData) {
this.keysendData = parseKeysendResponse(keysendData);
}
}
parseNostrResponse(nostrData) {
if (nostrData) {
[this.nostrData, this.nostrPubkey, this.nostrRelays] = parseNostrResponse(nostrData, this.username);
}
}
}
export { DEFAULT_PROXY, LN_ADDRESS_REGEX, LightningAddress, generateZapEvent, getEventHash, isUrl, isValidAmount, parseKeysendResponse, parseLnUrlPayResponse, parseNostrResponse, serializeEvent, validateEvent };
//# sourceMappingURL=lnurl.js.map

Sorry, the diff of this file is too big to display

const sendBoostagram = async (args, options) => {
const { boost } = args;
if (!options) {
options = {};
}
const webln = options.webln || globalThis.webln;
if (!webln) {
throw new Error("WebLN not available");
}
if (!webln.keysend) {
throw new Error("Keysend not available in current WebLN provider");
}
const amount = args.amount || Math.floor(boost.value_msat / 1000);
const weblnParams = {
destination: args.destination,
amount: amount,
customRecords: {
"7629169": JSON.stringify(boost),
},
};
if (args.customKey && args.customValue) {
weblnParams.customRecords[args.customKey] = args.customValue;
}
await webln.enable();
const response = await webln.keysend(weblnParams);
return response;
};
export { sendBoostagram };
//# sourceMappingURL=podcasting2.js.map
{"version":3,"file":"podcasting2.js","sources":["../../src/podcasting2/boostagrams.ts"],"sourcesContent":["import { WebLNProvider } from \"@webbtc/webln-types\";\nimport { BoostArguments, BoostOptions, WeblnBoostParams } from \"./types\";\n\nexport const sendBoostagram = async (\n args: BoostArguments,\n options?: BoostOptions,\n) => {\n const { boost } = args;\n if (!options) {\n options = {};\n }\n const webln: WebLNProvider = options.webln || globalThis.webln;\n\n if (!webln) {\n throw new Error(\"WebLN not available\");\n }\n if (!webln.keysend) {\n throw new Error(\"Keysend not available in current WebLN provider\");\n }\n\n const amount = args.amount || Math.floor(boost.value_msat / 1000);\n\n const weblnParams: WeblnBoostParams = {\n destination: args.destination,\n amount: amount,\n customRecords: {\n \"7629169\": JSON.stringify(boost),\n },\n };\n if (args.customKey && args.customValue) {\n weblnParams.customRecords[args.customKey] = args.customValue;\n }\n await webln.enable();\n const response = await webln.keysend(weblnParams);\n return response;\n};\n"],"names":[],"mappings":"AAGO,MAAM,cAAc,GAAG,OAC5B,IAAoB,EACpB,OAAsB,KACpB;AACF,IAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;IACtB,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,GAAG,EAAE;IACd;IACA,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK;IAE9D,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;IACxC;AACA,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AAClB,QAAA,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC;IACpE;AAEA,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;AAEjE,IAAA,MAAM,WAAW,GAAqB;QACpC,WAAW,EAAE,IAAI,CAAC,WAAW;AAC7B,QAAA,MAAM,EAAE,MAAM;AACd,QAAA,aAAa,EAAE;AACb,YAAA,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;AACjC,SAAA;KACF;IACD,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE;QACtC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW;IAC9D;AACA,IAAA,MAAM,KAAK,CAAC,MAAM,EAAE;IACpB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;AACjD,IAAA,OAAO,QAAQ;AACjB;;;;"}
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).LightningTools={})}(this,function(e){"use strict";var t,r,n,o={};var s=function(){if(n)return r;n=1;const{bech32:e,hex:s,utf8:i}=(t||(t=1,function(e){function t(e){if(!Number.isSafeInteger(e))throw new Error(`Wrong integer: ${e}`)}function r(...e){const t=(e,t)=>r=>e(t(r));return{encode:Array.from(e).reverse().reduce((e,r)=>e?t(e,r.encode):r.encode,void 0),decode:e.reduce((e,r)=>e?t(e,r.decode):r.decode,void 0)}}function n(e){return{encode:r=>{if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("alphabet.encode input should be an array of numbers");return r.map(r=>{if(t(r),r<0||r>=e.length)throw new Error(`Digit index outside alphabet: ${r} (alphabet: ${e.length})`);return e[r]})},decode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("alphabet.decode input should be array of strings");return t.map(t=>{if("string"!=typeof t)throw new Error(`alphabet.decode: not string element=${t}`);const r=e.indexOf(t);if(-1===r)throw new Error(`Unknown letter: "${t}". Allowed: ${e}`);return r})}}}function o(e=""){if("string"!=typeof e)throw new Error("join separator should be string");return{encode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("join.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`join.encode: non-string input=${e}`);return t.join(e)},decode:t=>{if("string"!=typeof t)throw new Error("join.decode input should be string");return t.split(e)}}}function s(e,r="="){if(t(e),"string"!=typeof r)throw new Error("padding chr should be string");return{encode(t){if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("padding.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`padding.encode: non-string input=${e}`);for(;t.length*e%8;)t.push(r);return t},decode(t){if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("padding.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`padding.decode: non-string input=${e}`);let n=t.length;if(n*e%8)throw new Error("Invalid padding: string should have whole number of bytes");for(;n>0&&t[n-1]===r;n--)if(!((n-1)*e%8))throw new Error("Invalid padding: string has too much padding");return t.slice(0,n)}}}function i(e){if("function"!=typeof e)throw new Error("normalize fn should be function");return{encode:e=>e,decode:t=>e(t)}}function a(e,r,n){if(r<2)throw new Error(`convertRadix: wrong from=${r}, base cannot be less than 2`);if(n<2)throw new Error(`convertRadix: wrong to=${n}, base cannot be less than 2`);if(!Array.isArray(e))throw new Error("convertRadix: data should be array");if(!e.length)return[];let o=0;const s=[],i=Array.from(e);for(i.forEach(e=>{if(t(e),e<0||e>=r)throw new Error(`Wrong integer: ${e}`)});;){let e=0,t=!0;for(let s=o;s<i.length;s++){const a=i[s],c=r*e+a;if(!Number.isSafeInteger(c)||r*e/r!==e||c-a!==r*e)throw new Error("convertRadix: carry overflow");if(e=c%n,i[s]=Math.floor(c/n),!Number.isSafeInteger(i[s])||i[s]*n+e!==c)throw new Error("convertRadix: carry overflow");t&&(i[s]?t=!1:o=s)}if(s.push(e),t)break}for(let t=0;t<e.length-1&&0===e[t];t++)s.push(0);return s.reverse()}
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Object.defineProperty(e,"__esModule",{value:!0}),e.bytes=e.stringToBytes=e.str=e.bytesToString=e.hex=e.utf8=e.bech32m=e.bech32=e.base58check=e.base58xmr=e.base58xrp=e.base58flickr=e.base58=e.base64url=e.base64=e.base32crockford=e.base32hex=e.base32=e.base16=e.utils=e.assertNumber=void 0,e.assertNumber=t;const c=(e,t)=>t?c(t,e%t):e,h=(e,t)=>e+(t-c(e,t));function l(e,r,n,o){if(!Array.isArray(e))throw new Error("convertRadix2: data should be array");if(r<=0||r>32)throw new Error(`convertRadix2: wrong from=${r}`);if(n<=0||n>32)throw new Error(`convertRadix2: wrong to=${n}`);if(h(r,n)>32)throw new Error(`convertRadix2: carry overflow from=${r} to=${n} carryBits=${h(r,n)}`);let s=0,i=0;const a=2**n-1,c=[];for(const o of e){if(t(o),o>=2**r)throw new Error(`convertRadix2: invalid data word=${o} from=${r}`);if(s=s<<r|o,i+r>32)throw new Error(`convertRadix2: carry overflow pos=${i} from=${r}`);for(i+=r;i>=n;i-=n)c.push((s>>i-n&a)>>>0);s&=2**i-1}if(s=s<<n-i&a,!o&&i>=r)throw new Error("Excess padding");if(!o&&s)throw new Error(`Non-zero padding: ${s}`);return o&&i>0&&c.push(s>>>0),c}function u(e){return t(e),{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix.encode input should be Uint8Array");return a(Array.from(t),256,e)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix.decode input should be array of strings");return Uint8Array.from(a(t,e,256))}}}function f(e,r=!1){if(t(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(h(8,e)>32||h(e,8)>32)throw new Error("radix2: carry overflow");return{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix2.encode input should be Uint8Array");return l(Array.from(t),8,e,!r)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix2.decode input should be array of strings");return Uint8Array.from(l(t,e,8,r))}}}function d(e){if("function"!=typeof e)throw new Error("unsafeWrapper fn should be function");return function(...t){try{return e.apply(null,t)}catch(e){}}}function p(e,r){if(t(e),"function"!=typeof r)throw new Error("checksum fn should be function");return{encode(t){if(!(t instanceof Uint8Array))throw new Error("checksum.encode: input should be Uint8Array");const n=r(t).slice(0,e),o=new Uint8Array(t.length+e);return o.set(t),o.set(n,t.length),o},decode(t){if(!(t instanceof Uint8Array))throw new Error("checksum.decode: input should be Uint8Array");const n=t.slice(0,-e),o=r(n).slice(0,e),s=t.slice(-e);for(let t=0;t<e;t++)if(o[t]!==s[t])throw new Error("Invalid checksum");return n}}}e.utils={alphabet:n,chain:r,checksum:p,radix:u,radix2:f,join:o,padding:s},e.base16=r(f(4),n("0123456789ABCDEF"),o("")),e.base32=r(f(5),n("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),s(5),o("")),e.base32hex=r(f(5),n("0123456789ABCDEFGHIJKLMNOPQRSTUV"),s(5),o("")),e.base32crockford=r(f(5),n("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),o(""),i(e=>e.toUpperCase().replace(/O/g,"0").replace(/[IL]/g,"1"))),e.base64=r(f(6),n("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),s(6),o("")),e.base64url=r(f(6),n("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),s(6),o(""));const w=e=>r(u(58),n(e),o(""));e.base58=w("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"),e.base58flickr=w("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"),e.base58xrp=w("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");const y=[0,2,3,5,6,7,9,10,11];e.base58xmr={encode(t){let r="";for(let n=0;n<t.length;n+=8){const o=t.subarray(n,n+8);r+=e.base58.encode(o).padStart(y[o.length],"1")}return r},decode(t){let r=[];for(let n=0;n<t.length;n+=11){const o=t.slice(n,n+11),s=y.indexOf(o.length),i=e.base58.decode(o);for(let e=0;e<i.length-s;e++)if(0!==i[e])throw new Error("base58xmr: wrong padding");r=r.concat(Array.from(i.slice(i.length-s)))}return Uint8Array.from(r)}},e.base58check=t=>r(p(4,e=>t(t(e))),e.base58);const m=r(n("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),o("")),g=[996825010,642813549,513874426,1027748829,705979059];function b(e){const t=e>>25;let r=(33554431&e)<<5;for(let e=0;e<g.length;e++)1==(t>>e&1)&&(r^=g[e]);return r}function E(e,t,r=1){const n=e.length;let o=1;for(let t=0;t<n;t++){const r=e.charCodeAt(t);if(r<33||r>126)throw new Error(`Invalid prefix (${e})`);o=b(o)^r>>5}o=b(o);for(let t=0;t<n;t++)o=b(o)^31&e.charCodeAt(t);for(let e of t)o=b(o)^e;for(let e=0;e<6;e++)o=b(o);return o^=r,m.encode(l([o%2**30],30,5,!1))}function v(e){const t="bech32"===e?1:734539939,r=f(5),n=r.decode,o=r.encode,s=d(n);function i(e,r=90){if("string"!=typeof e)throw new Error("bech32.decode input should be string, not "+typeof e);if(e.length<8||!1!==r&&e.length>r)throw new TypeError(`Wrong string length: ${e.length} (${e}). Expected (8..${r})`);const n=e.toLowerCase();if(e!==n&&e!==e.toUpperCase())throw new Error("String must be lowercase or uppercase");const o=(e=n).lastIndexOf("1");if(0===o||-1===o)throw new Error('Letter "1" must be present between prefix and data only');const s=e.slice(0,o),i=e.slice(o+1);if(i.length<6)throw new Error("Data must be at least 6 characters long");const a=m.decode(i).slice(0,-6),c=E(s,a,t);if(!i.endsWith(c))throw new Error(`Invalid checksum in ${e}: expected "${c}"`);return{prefix:s,words:a}}return{encode:function(e,r,n=90){if("string"!=typeof e)throw new Error("bech32.encode prefix should be string, not "+typeof e);if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("bech32.encode words should be array of numbers, not "+typeof r);const o=e.length+7+r.length;if(!1!==n&&o>n)throw new TypeError(`Length ${o} exceeds limit ${n}`);return`${e=e.toLowerCase()}1${m.encode(r)}${E(e,r,t)}`},decode:i,decodeToBytes:function(e){const{prefix:t,words:r}=i(e,!1);return{prefix:t,words:r,bytes:n(r)}},decodeUnsafe:d(i),fromWords:n,fromWordsUnsafe:s,toWords:o}}e.bech32=v("bech32"),e.bech32m=v("bech32m"),e.utf8={encode:e=>(new TextDecoder).decode(e),decode:e=>(new TextEncoder).encode(e)},e.hex=r(f(4),n("0123456789abcdef"),o(""),i(e=>{if("string"!=typeof e||e.length%2)throw new TypeError(`hex.decode: expected string, got ${typeof e} with length ${e.length}`);return e.toLowerCase()}));const x={utf8:e.utf8,hex:e.hex,base16:e.base16,base32:e.base32,base64:e.base64,base64url:e.base64url,base58:e.base58,base58xmr:e.base58xmr},A=`Invalid encoding type. Available types: ${Object.keys(x).join(", ")}`;e.bytesToString=(e,t)=>{if("string"!=typeof e||!x.hasOwnProperty(e))throw new TypeError(A);if(!(t instanceof Uint8Array))throw new TypeError("bytesToString() expects Uint8Array");return x[e].encode(t)},e.str=e.bytesToString,e.stringToBytes=(e,t)=>{if(!x.hasOwnProperty(e))throw new TypeError(A);if("string"!=typeof t)throw new TypeError("stringToBytes() expects string");return x[e].decode(t)},e.bytes=e.stringToBytes}(o)),o),a={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},c={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},h={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},l={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},u={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},f=["option_data_loss_protect","initial_routing_sync","option_upfront_shutdown_script","gossip_queries","var_onion_optin","gossip_queries_ex","option_static_remotekey","payment_secret","basic_mpp","option_support_large_channel"],d={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},p=BigInt("2100000000000000000"),w=BigInt(1e11),y={payment_hash:1,payment_secret:16,description:13,payee:19,description_hash:23,expiry:6,min_final_cltv_expiry:24,fallback_address:9,route_hint:3,feature_bits:5,metadata:27},m={};for(let e=0,t=Object.keys(y);e<t.length;e++){const r=t[e],n=y[t[e]].toString();m[n]=r}const g={1:t=>s.encode(e.fromWordsUnsafe(t)),16:t=>s.encode(e.fromWordsUnsafe(t)),13:t=>i.encode(e.fromWordsUnsafe(t)),19:t=>s.encode(e.fromWordsUnsafe(t)),23:t=>s.encode(e.fromWordsUnsafe(t)),27:t=>s.encode(e.fromWordsUnsafe(t)),6:E,24:E,3:function(t){const r=[];let n,o,i,a,c,h=e.fromWordsUnsafe(t);for(;h.length>0;)n=s.encode(h.slice(0,33)),o=s.encode(h.slice(33,41)),i=parseInt(s.encode(h.slice(41,45)),16),a=parseInt(s.encode(h.slice(45,49)),16),c=parseInt(s.encode(h.slice(49,51)),16),h=h.slice(51),r.push({pubkey:n,short_channel_id:o,fee_base_msat:i,fee_proportional_millionths:a,cltv_expiry_delta:c});return r},5:function(e){const t=e.slice().reverse().map(e=>[!!(1&e),!!(2&e),!!(4&e),!!(8&e),!!(16&e)]).reduce((e,t)=>e.concat(t),[]);for(;t.length<2*f.length;)t.push(!1);const r={};f.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*f.length);return r.extra_bits={start_bit:2*f.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function b(t){return r=>({tagCode:parseInt(t),words:e.encode("unknown",r,Number.MAX_SAFE_INTEGER)})}function E(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}function v(e,t){let r,n;if(e.slice(-1).match(/^[munp]$/))r=e.slice(-1),n=e.slice(0,-1);else{if(e.slice(-1).match(/^[^munp0-9]$/))throw new Error("Not a valid multiplier for the amount");n=e}if(!n.match(/^\d+$/))throw new Error("Not a valid human readable amount");const o=BigInt(n),s=r?o*w/d[r]:o*w;if("p"===r&&o%BigInt(10)!==BigInt(0)||s>p)throw new Error("Amount is outside of valid range");return t?s.toString():s}return r={decode:function(t,r){if("string"!=typeof t)throw new Error("Lightning Payment Request must be string");if("ln"!==t.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const n=[],o=e.decode(t,Number.MAX_SAFE_INTEGER);t=t.toLowerCase();const i=o.prefix;let f=o.words,d=t.slice(i.length+1),p=f.slice(-104);f=f.slice(0,-104);let w=i.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(w&&!w[2]&&(w=i.match(/^ln(\S+)$/)),!w)throw new Error("Not a proper lightning payment request");n.push({name:"lightning_network",letters:"ln"});const x=w[1];let A;if(r){if(void 0===r.bech32||void 0===r.pubKeyHash||void 0===r.scriptHash||!Array.isArray(r.validWitnessVersions))throw new Error("Invalid network");A=r}else switch(x){case a.bech32:A=a;break;case c.bech32:A=c;break;case h.bech32:A=h;break;case l.bech32:A=l;break;case u.bech32:A=u}if(!A||A.bech32!==x)throw new Error("Unknown coin bech32 prefix");n.push({name:"coin_network",letters:x,value:A});const k=w[2];let U;if(k){U=v(k+w[3],!0),n.push({name:"amount",letters:w[2]+w[3],value:U})}else U=null;n.push({name:"separator",letters:"1"});const $=E(f.slice(0,7));let _,L,N,I;for(f=f.slice(7),n.push({name:"timestamp",letters:d.slice(0,7),value:$}),d=d.slice(7);f.length>0;){const e=f[0].toString();_=m[e]||"unknown_tag",L=g[e]||b(e),f=f.slice(1),N=E(f.slice(0,2)),f=f.slice(2),I=f.slice(0,N),f=f.slice(N),n.push({name:_,tag:d[0],letters:d.slice(0,3+N),value:L(I)}),d=d.slice(3+N)}n.push({name:"signature",letters:d.slice(0,104),value:s.encode(e.fromWordsUnsafe(p))}),d=d.slice(104),n.push({name:"checksum",letters:d});let D={paymentRequest:t,sections:n,get expiry(){let e=n.find(e=>"expiry"===e.name);if(e)return S("timestamp")+e.value},get route_hints(){return n.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in y)"route_hint"!==e&&Object.defineProperty(D,e,{get:()=>S(e)});return D;function S(e){let t=n.find(t=>t.name===e);return t?t.value:void 0}},hrpToMillisat:v}}();const i=e=>Uint8Array.from(e.match(/.{1,2}/g).map(e=>parseInt(e,16))),a=e=>{if(!e)return null;try{const t=s.decode(e);if(!t||!t.sections)return null;const r=t.sections.find(e=>"payment_hash"===e.name);if("payment_hash"!==r?.name||!r.value)return null;const n=r.value;let o=0;const i=t.sections.find(e=>"amount"===e.name);"amount"===i?.name&&i.value&&(o=parseInt(i.value)/1e3);const a=t.sections.find(e=>"timestamp"===e.name);if("timestamp"!==a?.name||!a.value)return null;const c=a.value;let h;const l=t.sections.find(e=>"expiry"===e.name);"expiry"===l?.name&&(h=l.value);const u=t.sections.find(e=>"description"===e.name);return{paymentHash:n,satoshi:o,timestamp:c,expiry:h,description:"description"===u?.name?u?.value:void 0}}catch{return null}};function c(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function h(e,t){!function(e,...t){if(!(e instanceof Uint8Array))throw new Error("Expected Uint8Array");if(t.length>0&&!t.includes(e.length))throw new Error(`Expected Uint8Array of length ${t}, not of length=${e.length}`)}(e);const r=t.outputLen;if(e.length<r)throw new Error(`digestInto() expects output buffer of length at least ${r}`)}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */const l=e=>e instanceof Uint8Array,u=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),f=(e,t)=>e<<32-t|e>>>t;if(!(68===new Uint8Array(new Uint32Array([287454020]).buffer)[0]))throw new Error("Non little-endian hardware is not supported");const d=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function p(e){if(!l(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=d[e[r]];return t}function w(e){if("string"==typeof e&&(e=function(e){if("string"!=typeof e)throw new Error("utf8ToBytes expected string, got "+typeof e);return new Uint8Array((new TextEncoder).encode(e))}(e)),!l(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class y{clone(){return this._cloneInto()}}function m(e){const t=t=>e().update(w(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class g extends y{constructor(e,t,r,n){super(),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(e),this.view=u(this.buffer)}update(e){c(this);const{view:t,buffer:r,blockLen:n}=this,o=(e=w(e)).length;for(let s=0;s<o;){const i=Math.min(n-this.pos,o-s);if(i===n){const t=u(e);for(;n<=o-s;s+=n)this.process(t,s);continue}r.set(e.subarray(s,s+i),this.pos),this.pos+=i,s+=i,this.pos===n&&(this.process(t,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){c(this),h(e,this),this.finished=!0;const{buffer:t,view:r,blockLen:n,isLE:o}=this;let{pos:s}=this;t[s++]=128,this.buffer.subarray(s).fill(0),this.padOffset>n-s&&(this.process(r,0),s=0);for(let e=s;e<n;e++)t[e]=0;!function(e,t,r,n){if("function"==typeof e.setBigUint64)return e.setBigUint64(t,r,n);const o=BigInt(32),s=BigInt(4294967295),i=Number(r>>o&s),a=Number(r&s),c=n?4:0,h=n?0:4;e.setUint32(t+c,i,n),e.setUint32(t+h,a,n)}(r,n-8,BigInt(8*this.length),o),this.process(r,0);const i=u(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const l=a/4,f=this.get();if(l>f.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<l;e++)i.setUint32(4*e,f[e],o)}digest(){const{buffer:e,outputLen:t}=this;this.digestInto(e);const r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());const{blockLen:t,buffer:r,length:n,finished:o,destroyed:s,pos:i}=this;return e.length=n,e.pos=i,e.finished=o,e.destroyed=s,n%t&&e.buffer.set(r),e}}const b=(e,t,r)=>e&t^~e&r,E=(e,t,r)=>e&t^e&r^t&r,v=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),x=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),A=new Uint32Array(64);class k extends g{constructor(){super(64,32,8,!1),this.A=0|x[0],this.B=0|x[1],this.C=0|x[2],this.D=0|x[3],this.E=0|x[4],this.F=0|x[5],this.G=0|x[6],this.H=0|x[7]}get(){const{A:e,B:t,C:r,D:n,E:o,F:s,G:i,H:a}=this;return[e,t,r,n,o,s,i,a]}set(e,t,r,n,o,s,i,a){this.A=0|e,this.B=0|t,this.C=0|r,this.D=0|n,this.E=0|o,this.F=0|s,this.G=0|i,this.H=0|a}process(e,t){for(let r=0;r<16;r++,t+=4)A[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=A[e-15],r=A[e-2],n=f(t,7)^f(t,18)^t>>>3,o=f(r,17)^f(r,19)^r>>>10;A[e]=o+A[e-7]+n+A[e-16]|0}let{A:r,B:n,C:o,D:s,E:i,F:a,G:c,H:h}=this;for(let e=0;e<64;e++){const t=h+(f(i,6)^f(i,11)^f(i,25))+b(i,a,c)+v[e]+A[e]|0,l=(f(r,2)^f(r,13)^f(r,22))+E(r,n,o)|0;h=c,c=a,a=i,i=s+t|0,s=o,o=n,n=r,r=t+l|0}r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,s=s+this.D|0,i=i+this.E|0,a=a+this.F|0,c=c+this.G|0,h=h+this.H|0,this.set(r,n,o,s,i,a,c,h)}roundClean(){A.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const U=m(()=>new k);class ${constructor(e){if(this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");const t=a(this.paymentRequest);if(!t)throw new Error("Failed to decode payment request");this.paymentHash=t.paymentHash,this.satoshi=t.satoshi,this.timestamp=t.timestamp,this.expiry=t.expiry,this.createdDate=new Date(1e3*this.timestamp),this.expiryDate=this.expiry?new Date(1e3*(this.timestamp+this.expiry)):void 0,this.description=t.description??null,this.verify=e.verify??null,this.preimage=e.preimage??null,this.successAction=e.successAction??null}async isPaid(){if(this.preimage)return this.validatePreimage(this.preimage);if(this.verify)return await this.verifyPayment();throw new Error("Could not verify payment")}validatePreimage(e){if(!e||!this.paymentHash)return!1;try{const t=p(U(i(e)));return this.paymentHash===t}catch{return!1}}async verifyPayment(){try{if(!this.verify)throw new Error("LNURL verify not available");const e=await fetch(this.verify);if(!e.ok)throw new Error(`Verification request failed: ${e.status} ${e.statusText}`);const t=await e.json();return t.preimage&&(this.preimage=t.preimage),t.settled}catch(e){return console.error("Failed to check LNURL-verify",e),!1}}hasExpired(){const{expiryDate:e}=this;return!!e&&e.getTime()<Date.now()}}const _=e=>{if("keysend"!==e.tag)throw new Error("Invalid keysend params");if("OK"!==e.status)throw new Error("Keysend status not OK");if(!e.pubkey)throw new Error("Pubkey does not exist");const t=e.pubkey;let r,n;return e.customData&&e.customData[0]&&(r=e.customData[0].customKey,n=e.customData[0].customValue),{destination:t,customKey:r,customValue:n}};async function L({satoshi:e,comment:t,p:r,e:n,relays:o},s={}){const i=s.nostr||globalThis.nostr;if(!i)throw new Error("nostr option or window.nostr is not available");const a=[["relays",...o],["amount",e.toString()]];r&&a.push(["p",r]),n&&a.push(["e",n]);const c={pubkey:await i.getPublicKey(),created_at:Math.floor(Date.now()/1e3),kind:9734,tags:a,content:t??""};return c.id=D(c),await i.signEvent(c)}function N(e){if("string"!=typeof e.content)return!1;if("number"!=typeof e.created_at)return!1;if(!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){const r=e.tags[t];if(!Array.isArray(r))return!1;for(let e=0;e<r.length;e++)if("object"==typeof r[e])return!1}return!0}function I(e){if(!N(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function D(e){return p(U(I(e)))}function S(e,t){let r,n;return t&&e&&(r=e.names?.[t],n=r?e.relays?.[r]:void 0),[e,r,n]}const R=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,T=e=>!!e&&R.test(e),P=({amount:e,min:t,max:r})=>e>0&&e>=t&&e<=r,W=async e=>{if("payRequest"!==e.tag)throw new Error("Invalid pay service params");const t=(e.callback+"").trim();if(!T(t))throw new Error("Callback must be a valid url");const r=Math.ceil(Number(e.minSendable||0)),n=Math.floor(Number(e.maxSendable));if(!r||!n||r>n)throw new Error("Invalid pay service params");let o,s;try{o=JSON.parse(e.metadata+""),s=p(U(e.metadata+""))}catch{o=[],s=p(U("[]"))}let i="",a="",c="",h="";for(let e=0;e<o.length;e++){const[t,r]=o[e];switch(t){case"text/plain":c=r;break;case"text/identifier":h=r;break;case"text/email":i=r;break;case"image/png;base64":case"image/jpeg;base64":a="data:"+t+","+r}}const l=e.payerData;let u;try{u=new URL(t).hostname}catch{}return{callback:t,fixed:r===n,min:r,max:n,domain:u,metadata:o,metadataHash:s,identifier:h,email:i,description:c,image:a,payerData:l,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1}},B=async(e,t)=>{const{boost:r}=e;t||(t={});const n=t.webln||globalThis.webln;if(!n)throw new Error("WebLN not available");if(!n.keysend)throw new Error("Keysend not available in current WebLN provider");const o=e.amount||Math.floor(r.value_msat/1e3),s={destination:e.destination,amount:o,customRecords:{7629169:JSON.stringify(r)}};e.customKey&&e.customValue&&(s.customRecords[e.customKey]=e.customValue),await n.enable();return await n.keysend(s)},H=/^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,j="https://api.getalby.com/lnurl";class K{constructor(e){this.storage=e||{}}getItem(e){return this.storage[e]}setItem(e,t){this.storage[e]=t}}const C=e=>{const t=e.replace("L402","").replace("LSAT","").trim(),r={},n=/(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;let o;for(;null!==(o=n.exec(t));)r[o[1]]=o[3]||o[4]||o[5];return r},O=new K,F=async e=>{const t="https://getalby.com/api/rates/"+e.toLowerCase()+".json",r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch rate: ${r.status} ${r.statusText}`);return(await r.json()).rate_float/1e8},V=async({satoshi:e,currency:t})=>{const r=await F(t);return Number(e)*r};e.DEFAULT_PROXY=j,e.Invoice=$,e.LN_ADDRESS_REGEX=H,e.LightningAddress=class{constructor(e,t){this.address=e,this.options={proxy:j},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}parse(){const e=H.exec(this.address.toLowerCase());e&&(this.username=e[1],this.domain=e[2])}getWebLN(){return this.webln||globalThis.webln}async fetch(){return this.options.proxy?this.fetchWithProxy():this.fetchWithoutProxy()}async fetchWithProxy(){const e=await fetch(`${this.options.proxy}/lightning-address-details?${new URLSearchParams({ln:this.address}).toString()}`);if(!e.ok)throw new Error(`Failed to fetch lnurl info: ${e.status} ${e.statusText}`);const t=await e.json();await this.parseLnUrlPayResponse(t.lnurlp),this.parseKeysendResponse(t.keysend),this.parseNostrResponse(t.nostr)}async fetchWithoutProxy(){this.domain&&this.username&&await Promise.all([this.fetchLnurlData(),this.fetchKeysendData(),this.fetchNostrData()])}async fetchLnurlData(){const e=await fetch(this.lnurlpUrl());if(e.ok){const t=await e.json();await this.parseLnUrlPayResponse(t)}}async fetchKeysendData(){const e=await fetch(this.keysendUrl());if(e.ok){const t=await e.json();this.parseKeysendResponse(t)}}async fetchNostrData(){const e=await fetch(this.nostrUrl());if(e.ok){const t=await e.json();this.parseNostrResponse(t)}}lnurlpUrl(){return`https://${this.domain}/.well-known/lnurlp/${this.username}`}keysendUrl(){return`https://${this.domain}/.well-known/keysend/${this.username}`}nostrUrl(){return`https://${this.domain}/.well-known/nostr.json?name=${this.username}`}async generateInvoice(e){let t;if(this.options.proxy){const r=await fetch(`${this.options.proxy}/generate-invoice?${new URLSearchParams({ln:this.address,...e}).toString()}`);if(!r.ok)throw new Error(`Failed to generate invoice: ${r.status} ${r.statusText}`);t=(await r.json()).invoice}else{if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!this.lnurlpData.callback||!T(this.lnurlpData.callback))throw new Error("Valid callback does not exist in lnurlpData");const r=new URL(this.lnurlpData.callback);r.search=new URLSearchParams(e).toString();const n=await fetch(r.toString());if(!n.ok)throw new Error(`Failed to generate invoice: ${n.status} ${n.statusText}`);t=await n.json()}const r=t&&t.pr&&t.pr.toString();if(!r)throw new Error("Invalid pay service invoice");const n={pr:r};if(t&&t.verify&&(n.verify=t.verify.toString()),t&&t.successAction&&"object"==typeof t.successAction){const{tag:e,message:r,description:o,url:s}=t.successAction;"message"===e?n.successAction={tag:e,message:r}:"url"===e&&(n.successAction={tag:e,description:o,url:s})}return new $(n)}async requestInvoice(e){if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");const t=1e3*e.satoshi,{commentAllowed:r,min:n,max:o}=this.lnurlpData;if(!P({amount:t,min:n,max:o}))throw new Error("Invalid amount");if(e.comment&&r&&r>0&&e.comment.length>r)throw new Error(`The comment length must be ${r} characters or fewer`);const s={amount:t.toString()};return e.comment&&(s.comment=e.comment),e.payerdata&&(s.payerdata=JSON.stringify(e.payerdata)),this.generateInvoice(s)}async boost(e,t=0){if(!this.keysendData)throw new Error("No keysendData available. Please call fetch() first.");const{destination:r,customKey:n,customValue:o}=this.keysendData,s=this.getWebLN();if(!s)throw new Error("WebLN not available");return B({destination:r,customKey:n,customValue:o,amount:t,boost:e},{webln:s})}async zapInvoice({satoshi:e,comment:t,relays:r,e:n},o={}){if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!this.nostrPubkey)throw new Error("Nostr Pubkey is missing");const s=this.nostrPubkey,i=1e3*e,{allowsNostr:a,min:c,max:h}=this.lnurlpData;if(!P({amount:i,min:c,max:h}))throw new Error("Invalid amount");if(!a)throw new Error("Your provider does not support zaps");const l=await L({satoshi:i,comment:t,p:s,e:n,relays:r},o),u={amount:i.toString(),nostr:JSON.stringify(l)};return await this.generateInvoice(u)}async zap(e,t={}){const r=this.zapInvoice(e,t),n=this.getWebLN();if(!n)throw new Error("WebLN not available");await n.enable();return n.sendPayment((await r).paymentRequest)}async parseLnUrlPayResponse(e){e&&(this.lnurlpData=await W(e))}parseKeysendResponse(e){e&&(this.keysendData=_(e))}parseNostrResponse(e){e&&([this.nostrData,this.nostrPubkey,this.nostrRelays]=S(e,this.username))}},e.MemoryStorage=K,e.NoStorage=class{constructor(e){}getItem(e){return null}setItem(e,t){}},e.decodeInvoice=a,e.fetchWithL402=async(e,t,r)=>{r||(r={});const n=r.headerKey||"L402",o=r.webln||globalThis.webln;if(!o)throw new Error("WebLN is missing");const s=r.store||O;t||(t={}),t.cache="no-store",t.mode="cors",t.headers||(t.headers={});const i=s.getItem(e);if(i){const r=JSON.parse(i);return t.headers.Authorization=`${n} ${r.token}:${r.preimage}`,await fetch(e,t)}t.headers["Accept-Authenticate"]=n;const a=await fetch(e,t),c=a.headers.get("www-authenticate");if(!c)return a;const h=C(c),l=h.token||h.macaroon,u=h.invoice;await o.enable();const f=await o.sendPayment(u);return s.setItem(e,JSON.stringify({token:l,preimage:f.preimage})),t.headers.Authorization=`${n} ${l}:${f.preimage}`,await fetch(e,t)},e.fromHexString=i,e.generateZapEvent=L,e.getEventHash=D,e.getFiatBtcRate=F,e.getFiatValue=V,e.getFormattedFiatValue=async({satoshi:e,currency:t,locale:r})=>{r||(r="en");return(await V({satoshi:e,currency:t})).toLocaleString(r,{style:"currency",currency:t})},e.getSatoshiValue=async({amount:e,currency:t})=>{const r=await F(t);return Math.floor(Number(e)/r)},e.isUrl=T,e.isValidAmount=P,e.parseKeysendResponse=_,e.parseL402=C,e.parseLnUrlPayResponse=W,e.parseNostrResponse=S,e.sendBoostagram=B,e.serializeEvent=I,e.validateEvent=N});
//# sourceMappingURL=lightning-tools.umd.js.map

Sorry, the diff of this file is too big to display

type InvoiceArgs = {
pr: string;
verify?: string;
preimage?: string;
successAction?: SuccessAction;
};
type SuccessAction = {
tag: "message";
message: string;
} | {
tag: "url";
description: string;
url: string;
};
declare const fromHexString: (hexString: string) => Uint8Array<ArrayBuffer>;
type DecodedInvoice = {
paymentHash: string;
satoshi: number;
timestamp: number;
expiry: number | undefined;
description: string | undefined;
};
declare const decodeInvoice: (paymentRequest: string) => DecodedInvoice | null;
declare class Invoice {
paymentRequest: string;
paymentHash: string;
preimage: string | null;
verify: string | null;
satoshi: number;
expiry: number | undefined;
timestamp: number;
createdDate: Date;
expiryDate: Date | undefined;
description: string | null;
successAction: SuccessAction | null;
constructor(args: InvoiceArgs);
isPaid(): Promise<boolean>;
validatePreimage(preimage: string): boolean;
verifyPayment(): Promise<boolean>;
hasExpired(): boolean;
}
export { Invoice, decodeInvoice, fromHexString };
export type { InvoiceArgs, SuccessAction };
declare const getFiatBtcRate: (currency: string) => Promise<number>;
declare const getFiatValue: ({ satoshi, currency, }: {
satoshi: number | string;
currency: string;
}) => Promise<number>;
declare const getSatoshiValue: ({ amount, currency, }: {
amount: number | string;
currency: string;
}) => Promise<number>;
declare const getFormattedFiatValue: ({ satoshi, currency, locale, }: {
satoshi: number | string;
currency: string;
locale: string;
}) => Promise<string>;
export { getFiatBtcRate, getFiatValue, getFormattedFiatValue, getSatoshiValue };
import * as _webbtc_webln_types from '@webbtc/webln-types';
import { WebLNProvider, SendPaymentResponse } from '@webbtc/webln-types';
type InvoiceArgs = {
pr: string;
verify?: string;
preimage?: string;
successAction?: SuccessAction;
};
type SuccessAction = {
tag: "message";
message: string;
} | {
tag: "url";
description: string;
url: string;
};
declare const fromHexString: (hexString: string) => Uint8Array<ArrayBuffer>;
type DecodedInvoice = {
paymentHash: string;
satoshi: number;
timestamp: number;
expiry: number | undefined;
description: string | undefined;
};
declare const decodeInvoice: (paymentRequest: string) => DecodedInvoice | null;
declare class Invoice {
paymentRequest: string;
paymentHash: string;
preimage: string | null;
verify: string | null;
satoshi: number;
expiry: number | undefined;
timestamp: number;
createdDate: Date;
expiryDate: Date | undefined;
description: string | null;
successAction: SuccessAction | null;
constructor(args: InvoiceArgs);
isPaid(): Promise<boolean>;
validatePreimage(preimage: string): boolean;
verifyPayment(): Promise<boolean>;
hasExpired(): boolean;
}
type LnUrlRawData = {
tag: string;
callback: string;
minSendable: number;
maxSendable: number;
metadata: string;
payerData?: LUD18ServicePayerData;
commentAllowed?: number;
allowsNostr?: boolean;
};
type LnUrlPayResponse = {
callback: string;
fixed: boolean;
min: number;
max: number;
domain?: string;
metadata: Array<Array<string>>;
metadataHash: string;
identifier: string;
email: string;
description: string;
image: string;
commentAllowed?: number;
rawData: LnUrlRawData;
allowsNostr: boolean;
payerData?: LUD18ServicePayerData;
};
type LUD18ServicePayerData = Partial<{
name: {
mandatory: boolean;
};
pubkey: {
mandatory: boolean;
};
identifier: {
mandatory: boolean;
};
email: {
mandatory: boolean;
};
auth: {
mandatory: boolean;
k1: string;
};
}> & Record<string, unknown>;
type LUD18PayerData = Partial<{
name?: string;
pubkey?: string;
identifier?: string;
email?: string;
auth?: {
key: string;
sig: string;
};
}> & Record<string, unknown>;
type NostrResponse = {
names: Record<string, string>;
relays: Record<string, string[]>;
};
type Event = {
id?: string;
kind: number;
pubkey?: string;
content: string;
tags: string[][];
created_at: number;
sig?: string;
};
type ZapArgs = {
satoshi: number;
comment?: string;
relays: string[];
p?: string;
e?: string;
};
type NostrProvider = {
getPublicKey(): Promise<string>;
signEvent(event: Event & {
pubkey: string;
id: string;
}): Promise<Event>;
};
type ZapOptions = {
nostr?: NostrProvider;
};
type RequestInvoiceArgs = {
satoshi: number;
comment?: string;
payerdata?: LUD18PayerData;
};
type KeysendResponse = {
customKey: string;
customValue: string;
destination: string;
};
type KeySendRawData = {
tag: string;
status: string;
customData?: {
customKey?: string;
customValue?: string;
}[];
pubkey: string;
};
declare const parseKeysendResponse: (data: KeySendRawData) => KeysendResponse;
declare function generateZapEvent({ satoshi, comment, p, e, relays }: ZapArgs, options?: ZapOptions): Promise<Event>;
declare function validateEvent(event: Event): boolean;
declare function serializeEvent(evt: Event): string;
declare function getEventHash(event: Event): string;
declare function parseNostrResponse(nostrData: NostrResponse, username: string | undefined): readonly [NostrResponse, string | undefined, string[] | undefined];
declare const isUrl: (url: string | null) => url is string;
declare const isValidAmount: ({ amount, min, max, }: {
amount: number;
min: number;
max: number;
}) => boolean;
declare const parseLnUrlPayResponse: (data: LnUrlRawData) => Promise<LnUrlPayResponse>;
type BoostOptions = {
webln?: unknown;
};
type BoostArguments = {
destination: string;
customKey?: string;
customValue?: string;
amount?: number;
boost: Boost;
};
type WeblnBoostParams = {
destination: string;
amount: number;
customRecords: Record<string, string>;
};
type Boost = {
action: string;
value_msat: number;
value_msat_total: number;
app_name: string;
app_version: string;
feedId: string;
podcast: string;
episode: string;
ts: number;
name: string;
sender_name: string;
};
declare const sendBoostagram: (args: BoostArguments, options?: BoostOptions) => Promise<_webbtc_webln_types.SendPaymentResponse>;
declare const LN_ADDRESS_REGEX: RegExp;
declare const DEFAULT_PROXY = "https://api.getalby.com/lnurl";
type LightningAddressOptions = {
proxy?: string | false;
webln?: WebLNProvider;
};
declare class LightningAddress {
address: string;
options: LightningAddressOptions;
username: string | undefined;
domain: string | undefined;
pubkey: string | undefined;
lnurlpData: LnUrlPayResponse | undefined;
keysendData: KeysendResponse | undefined;
nostrData: NostrResponse | undefined;
nostrPubkey: string | undefined;
nostrRelays: string[] | undefined;
webln: WebLNProvider | undefined;
constructor(address: string, options?: LightningAddressOptions);
parse(): void;
getWebLN(): any;
fetch(): Promise<void>;
fetchWithProxy(): Promise<void>;
fetchWithoutProxy(): Promise<void>;
fetchLnurlData(): Promise<void>;
fetchKeysendData(): Promise<void>;
fetchNostrData(): Promise<void>;
lnurlpUrl(): string;
keysendUrl(): string;
nostrUrl(): string;
generateInvoice(params: Record<string, string>): Promise<Invoice>;
requestInvoice(args: RequestInvoiceArgs): Promise<Invoice>;
boost(boost: Boost, amount?: number): Promise<SendPaymentResponse>;
zapInvoice({ satoshi, comment, relays, e }: ZapArgs, options?: ZapOptions): Promise<Invoice>;
zap(args: ZapArgs, options?: ZapOptions): Promise<SendPaymentResponse>;
private parseLnUrlPayResponse;
private parseKeysendResponse;
private parseNostrResponse;
}
interface KVStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
}
declare class MemoryStorage implements KVStorage {
storage: any;
constructor(initial?: Record<string, unknown>);
getItem(key: string): any;
setItem(key: string, value: unknown): void;
}
declare class NoStorage implements KVStorage {
constructor(initial?: unknown);
getItem(key: string): null;
setItem(key: string, value: unknown): void;
}
declare const parseL402: (input: string) => Record<string, string>;
declare const fetchWithL402: (url: string, fetchArgs: RequestInit, options: {
headerKey?: string;
webln?: WebLNProvider;
store?: KVStorage;
}) => Promise<Response>;
declare const getFiatBtcRate: (currency: string) => Promise<number>;
declare const getFiatValue: ({ satoshi, currency, }: {
satoshi: number | string;
currency: string;
}) => Promise<number>;
declare const getSatoshiValue: ({ amount, currency, }: {
amount: number | string;
currency: string;
}) => Promise<number>;
declare const getFormattedFiatValue: ({ satoshi, currency, locale, }: {
satoshi: number | string;
currency: string;
locale: string;
}) => Promise<string>;
export { DEFAULT_PROXY, Invoice, LN_ADDRESS_REGEX, LightningAddress, MemoryStorage, NoStorage, decodeInvoice, fetchWithL402, fromHexString, generateZapEvent, getEventHash, getFiatBtcRate, getFiatValue, getFormattedFiatValue, getSatoshiValue, isUrl, isValidAmount, parseKeysendResponse, parseL402, parseLnUrlPayResponse, parseNostrResponse, sendBoostagram, serializeEvent, validateEvent };
export type { Boost, BoostArguments, BoostOptions, Event, InvoiceArgs, KVStorage, KeySendRawData, KeysendResponse, LUD18PayerData, LUD18ServicePayerData, LnUrlPayResponse, LnUrlRawData, NostrProvider, NostrResponse, RequestInvoiceArgs, SuccessAction, WeblnBoostParams, ZapArgs, ZapOptions };
import { WebLNProvider } from '@webbtc/webln-types';
interface KVStorage {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
}
declare class MemoryStorage implements KVStorage {
storage: any;
constructor(initial?: Record<string, unknown>);
getItem(key: string): any;
setItem(key: string, value: unknown): void;
}
declare class NoStorage implements KVStorage {
constructor(initial?: unknown);
getItem(key: string): null;
setItem(key: string, value: unknown): void;
}
declare const parseL402: (input: string) => Record<string, string>;
declare const fetchWithL402: (url: string, fetchArgs: RequestInit, options: {
headerKey?: string;
webln?: WebLNProvider;
store?: KVStorage;
}) => Promise<Response>;
export { MemoryStorage, NoStorage, fetchWithL402, parseL402 };
export type { KVStorage };
import { WebLNProvider, SendPaymentResponse } from '@webbtc/webln-types';
type LnUrlRawData = {
tag: string;
callback: string;
minSendable: number;
maxSendable: number;
metadata: string;
payerData?: LUD18ServicePayerData;
commentAllowed?: number;
allowsNostr?: boolean;
};
type LnUrlPayResponse = {
callback: string;
fixed: boolean;
min: number;
max: number;
domain?: string;
metadata: Array<Array<string>>;
metadataHash: string;
identifier: string;
email: string;
description: string;
image: string;
commentAllowed?: number;
rawData: LnUrlRawData;
allowsNostr: boolean;
payerData?: LUD18ServicePayerData;
};
type LUD18ServicePayerData = Partial<{
name: {
mandatory: boolean;
};
pubkey: {
mandatory: boolean;
};
identifier: {
mandatory: boolean;
};
email: {
mandatory: boolean;
};
auth: {
mandatory: boolean;
k1: string;
};
}> & Record<string, unknown>;
type LUD18PayerData = Partial<{
name?: string;
pubkey?: string;
identifier?: string;
email?: string;
auth?: {
key: string;
sig: string;
};
}> & Record<string, unknown>;
type NostrResponse = {
names: Record<string, string>;
relays: Record<string, string[]>;
};
type Event = {
id?: string;
kind: number;
pubkey?: string;
content: string;
tags: string[][];
created_at: number;
sig?: string;
};
type ZapArgs = {
satoshi: number;
comment?: string;
relays: string[];
p?: string;
e?: string;
};
type NostrProvider = {
getPublicKey(): Promise<string>;
signEvent(event: Event & {
pubkey: string;
id: string;
}): Promise<Event>;
};
type ZapOptions = {
nostr?: NostrProvider;
};
type RequestInvoiceArgs = {
satoshi: number;
comment?: string;
payerdata?: LUD18PayerData;
};
type KeysendResponse = {
customKey: string;
customValue: string;
destination: string;
};
type KeySendRawData = {
tag: string;
status: string;
customData?: {
customKey?: string;
customValue?: string;
}[];
pubkey: string;
};
declare const parseKeysendResponse: (data: KeySendRawData) => KeysendResponse;
declare function generateZapEvent({ satoshi, comment, p, e, relays }: ZapArgs, options?: ZapOptions): Promise<Event>;
declare function validateEvent(event: Event): boolean;
declare function serializeEvent(evt: Event): string;
declare function getEventHash(event: Event): string;
declare function parseNostrResponse(nostrData: NostrResponse, username: string | undefined): readonly [NostrResponse, string | undefined, string[] | undefined];
declare const isUrl: (url: string | null) => url is string;
declare const isValidAmount: ({ amount, min, max, }: {
amount: number;
min: number;
max: number;
}) => boolean;
declare const parseLnUrlPayResponse: (data: LnUrlRawData) => Promise<LnUrlPayResponse>;
type InvoiceArgs = {
pr: string;
verify?: string;
preimage?: string;
successAction?: SuccessAction;
};
type SuccessAction = {
tag: "message";
message: string;
} | {
tag: "url";
description: string;
url: string;
};
declare class Invoice {
paymentRequest: string;
paymentHash: string;
preimage: string | null;
verify: string | null;
satoshi: number;
expiry: number | undefined;
timestamp: number;
createdDate: Date;
expiryDate: Date | undefined;
description: string | null;
successAction: SuccessAction | null;
constructor(args: InvoiceArgs);
isPaid(): Promise<boolean>;
validatePreimage(preimage: string): boolean;
verifyPayment(): Promise<boolean>;
hasExpired(): boolean;
}
type Boost = {
action: string;
value_msat: number;
value_msat_total: number;
app_name: string;
app_version: string;
feedId: string;
podcast: string;
episode: string;
ts: number;
name: string;
sender_name: string;
};
declare const LN_ADDRESS_REGEX: RegExp;
declare const DEFAULT_PROXY = "https://api.getalby.com/lnurl";
type LightningAddressOptions = {
proxy?: string | false;
webln?: WebLNProvider;
};
declare class LightningAddress {
address: string;
options: LightningAddressOptions;
username: string | undefined;
domain: string | undefined;
pubkey: string | undefined;
lnurlpData: LnUrlPayResponse | undefined;
keysendData: KeysendResponse | undefined;
nostrData: NostrResponse | undefined;
nostrPubkey: string | undefined;
nostrRelays: string[] | undefined;
webln: WebLNProvider | undefined;
constructor(address: string, options?: LightningAddressOptions);
parse(): void;
getWebLN(): any;
fetch(): Promise<void>;
fetchWithProxy(): Promise<void>;
fetchWithoutProxy(): Promise<void>;
fetchLnurlData(): Promise<void>;
fetchKeysendData(): Promise<void>;
fetchNostrData(): Promise<void>;
lnurlpUrl(): string;
keysendUrl(): string;
nostrUrl(): string;
generateInvoice(params: Record<string, string>): Promise<Invoice>;
requestInvoice(args: RequestInvoiceArgs): Promise<Invoice>;
boost(boost: Boost, amount?: number): Promise<SendPaymentResponse>;
zapInvoice({ satoshi, comment, relays, e }: ZapArgs, options?: ZapOptions): Promise<Invoice>;
zap(args: ZapArgs, options?: ZapOptions): Promise<SendPaymentResponse>;
private parseLnUrlPayResponse;
private parseKeysendResponse;
private parseNostrResponse;
}
export { DEFAULT_PROXY, LN_ADDRESS_REGEX, LightningAddress, generateZapEvent, getEventHash, isUrl, isValidAmount, parseKeysendResponse, parseLnUrlPayResponse, parseNostrResponse, serializeEvent, validateEvent };
export type { Event, KeySendRawData, KeysendResponse, LUD18PayerData, LUD18ServicePayerData, LnUrlPayResponse, LnUrlRawData, NostrProvider, NostrResponse, RequestInvoiceArgs, ZapArgs, ZapOptions };
import * as _webbtc_webln_types from '@webbtc/webln-types';
type BoostOptions = {
webln?: unknown;
};
type BoostArguments = {
destination: string;
customKey?: string;
customValue?: string;
amount?: number;
boost: Boost;
};
type WeblnBoostParams = {
destination: string;
amount: number;
customRecords: Record<string, string>;
};
type Boost = {
action: string;
value_msat: number;
value_msat_total: number;
app_name: string;
app_version: string;
feedId: string;
podcast: string;
episode: string;
ts: number;
name: string;
sender_name: string;
};
declare const sendBoostagram: (args: BoostArguments, options?: BoostOptions) => Promise<_webbtc_webln_types.SendPaymentResponse>;
export { sendBoostagram };
export type { Boost, BoostArguments, BoostOptions, WeblnBoostParams };
+51
-17
{
"name": "@getalby/lightning-tools",
"version": "5.2.1",
"version": "6.0.0",
"description": "Collection of helpful building blocks and tools to develop Bitcoin Lightning web apps",
"type": "module",
"source": "src/index.ts",
"main": "./dist/index.cjs",
"module": "./dist/index.module.js",
"unpkg": "./dist/index.umd.js",
"types": "./dist/index.d.ts",
"repository": "https://github.com/getAlby/js-lightning-tools.git",

@@ -18,3 +13,3 @@ "bugs": "https://github.com/getAlby/js-lightning-tools/issues",

"files": [
"dist/**/*"
"dist"
],

@@ -26,6 +21,39 @@ "keywords": [

],
"sideEffects": false,
"source": "src/index.ts",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.cjs",
"types": "./dist/types/index.d.ts",
"unpkg": "./dist/types/lightning-tools.umd.js",
"exports": {
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts",
"default": "./dist/index.modern.js"
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.cjs",
"types": "./dist/types/index.d.ts"
},
"./bolt11": {
"import": "./dist/esm/bolt11.js",
"require": "./dist/cjs/bolt11.cjs",
"types": "./dist/types/bolt11.d.ts"
},
"./fiat": {
"import": "./dist/esm/fiat.js",
"require": "./dist/cjs/fiat.cjs",
"types": "./dist/types/fiat.d.ts"
},
"./l402": {
"import": "./dist/esm/l402.js",
"require": "./dist/cjs/l402.cjs",
"types": "./dist/types/l402.d.ts"
},
"./lnurl": {
"import": "./dist/esm/lnurl.js",
"require": "./dist/cjs/lnurl.cjs",
"types": "./dist/types/lnurl.d.ts"
},
"./podcasting": {
"import": "./dist/esm/podcasting2.js",
"require": "./dist/cjs/podcasting2.cjs",
"types": "./dist/types/podcasting2.d.ts"
}
},

@@ -43,3 +71,3 @@ "scripts": {

"clean": "rm -rf dist",
"build": "microbundle --no-sourcemap",
"build": "rollup -c",
"dev": "microbundle watch",

@@ -52,4 +80,8 @@ "prepare": "husky"

"@commitlint/config-conventional": "^19.8.1",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.4",
"@types/jest": "^30.0.0",
"@types/node": "^24.0.10",
"@types/node": "^24.2.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",

@@ -64,9 +96,11 @@ "@typescript-eslint/parser": "^6.21.0",

"light-bolt11-decoder": "^3.2.0",
"lint-staged": "^16.1.2",
"microbundle": "^0.15.1",
"nostr-tools": "^2.15.0",
"lint-staged": "^16.1.4",
"nostr-tools": "^2.16.1",
"prettier": "^3.6.2",
"ts-jest": "^29.4.0",
"rollup": "^4.46.2",
"rollup-plugin-dts": "^6.2.1",
"ts-jest": "^29.4.1",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
"tslib": "^2.8.1",
"typescript": "^5.9.2"
},

@@ -73,0 +107,0 @@ "engines": {

+15
-17

@@ -47,3 +47,3 @@ <p align="center">

```js
import { LightningAddress } from "@getalby/lightning-tools";
import { LightningAddress } from "@getalby/lightning-tools/lnurl";

@@ -64,3 +64,3 @@ const ln = new LightningAddress("hello@getalby.com");

```js
import { LightningAddress } from "@getalby/lightning-tools";
import { LightningAddress } from "@getalby/lightning-tools/lnurl";

@@ -81,3 +81,3 @@ const ln = new LightningAddress("hello@getalby.com");

```js
import { LightningAddress } from "@getalby/lightning-tools";
import { LightningAddress } from "@getalby/lightning-tools/lnurl";
const ln = new LightningAddress("hello@getalby.com");

@@ -102,3 +102,3 @@ await ln.fetch();

// or use the convenenice method:
// or use the convenient method:
await invoice.isPaid();

@@ -110,3 +110,3 @@ ```

```js
const { Invoice } = require("alby-tools");
import { Invoice } from "@getalby/lightning-tools/bolt11";

@@ -122,3 +122,3 @@ const invoice = new Invoice({ pr: pr, preimage: preimage });

```js
import { LightningAddress } from "@getalby/lightning-tools";
import { LightningAddress } from "@getalby/lightning-tools/lnurl";
const ln = new LightningAddress("hello@getalby.com");

@@ -150,3 +150,3 @@ await ln.fetch();

```js
import { LightningAddress } from "@getalby/lightning-tools";
import { LightningAddress } from "@getalby/lightning-tools/lnurl";
const ln = new LightningAddress("hello@getalby.com");

@@ -192,3 +192,3 @@ await ln.fetch();

```js
import { fetchWithL402 } from "@getalby/lightning-tools";
import { fetchWithL402 } from "@getalby/lightning-tools/l402";

@@ -207,7 +207,7 @@ // this will fetch the resource and pay the invoice with window.webln.

```js
import { fetchWithL402 } from "@getalby/lightning-tools";
import { webln } from "@getalby/sdk";
import { fetchWithL402 } from "@getalby/lightning-tools/l402";
import { NostrWebLNProvider } from "@getalby/sdk";
// use a NWC WebLN provide to do the payments
const nwc = new webln.NostrWebLNProvider({
const nwc = new NostrWebLNProvider({
nostrWalletConnectUrl: loadNWCUrl(),

@@ -227,10 +227,9 @@ });

```js
import { l402 } from "@getalby/lightning-tools";
import { fiat } from "@getalby/lightning-tools";
import { fetchWithL402, NoStorage } from "@getalby/lightning-tools/l402";
// do not store the tokens
await l402.fetchWithL402(
await fetchWithL402(
"https://lsat-weather-api.getalby.repl.co/kigali",
{},
{ store: new l402.storage.NoStorage() },
{ store: new NoStorage() },
);

@@ -244,6 +243,5 @@ ```

```js
const { Invoice } = require("alby-tools");
import { Invoice } from "@getalby/lightning-tools/bolt11";
const invoice = new Invoice({ pr });
const { paymentHash, satoshi, description, createdDate, expiryDate } = invoice;

@@ -250,0 +248,0 @@ ```

export * from "./types";
export * from "./utils";
export * from "./Invoice";
import { InvoiceArgs, SuccessAction } from "./types";
export declare class Invoice {
paymentRequest: string;
paymentHash: string;
preimage: string | null;
verify: string | null;
satoshi: number;
expiry: number | undefined;
timestamp: number;
createdDate: Date;
expiryDate: Date | undefined;
description: string | null;
successAction: SuccessAction | null;
constructor(args: InvoiceArgs);
isPaid(): Promise<boolean>;
validatePreimage(preimage: string): boolean;
verifyPayment(): Promise<boolean>;
hasExpired(): boolean;
}
export type InvoiceArgs = {
pr: string;
verify?: string;
preimage?: string;
successAction?: SuccessAction;
};
export type SuccessAction = {
tag: "message";
message: string;
} | {
tag: "url";
description: string;
url: string;
};
export declare const fromHexString: (hexString: string) => Uint8Array<ArrayBuffer>;
type DecodedInvoice = {
paymentHash: string;
satoshi: number;
timestamp: number;
expiry: number | undefined;
description: string | undefined;
};
export declare const decodeInvoice: (paymentRequest: string) => DecodedInvoice | null;
export {};
export declare const getFiatBtcRate: (currency: string) => Promise<number>;
export declare const getFiatValue: ({ satoshi, currency, }: {
satoshi: number | string;
currency: string;
}) => Promise<number>;
export declare const getSatoshiValue: ({ amount, currency, }: {
amount: number | string;
currency: string;
}) => Promise<number>;
export declare const getFormattedFiatValue: ({ satoshi, currency, locale, }: {
satoshi: number | string;
currency: string;
locale: string;
}) => Promise<string>;
export * from "./fiat";
var e,t,r=(e=function(e,t){function r(e){if(!Number.isSafeInteger(e))throw new Error(`Wrong integer: ${e}`)}function n(...e){const t=(e,t)=>r=>e(t(r));return{encode:Array.from(e).reverse().reduce((e,r)=>e?t(e,r.encode):r.encode,void 0),decode:e.reduce((e,r)=>e?t(e,r.decode):r.decode,void 0)}}function o(e){return{encode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("alphabet.encode input should be an array of numbers");return t.map(t=>{if(r(t),t<0||t>=e.length)throw new Error(`Digit index outside alphabet: ${t} (alphabet: ${e.length})`);return e[t]})},decode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("alphabet.decode input should be array of strings");return t.map(t=>{if("string"!=typeof t)throw new Error(`alphabet.decode: not string element=${t}`);const r=e.indexOf(t);if(-1===r)throw new Error(`Unknown letter: "${t}". Allowed: ${e}`);return r})}}}function s(e=""){if("string"!=typeof e)throw new Error("join separator should be string");return{encode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("join.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`join.encode: non-string input=${e}`);return t.join(e)},decode:t=>{if("string"!=typeof t)throw new Error("join.decode input should be string");return t.split(e)}}}function i(e,t="="){if(r(e),"string"!=typeof t)throw new Error("padding chr should be string");return{encode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.encode: non-string input=${e}`);for(;r.length*e%8;)r.push(t);return r},decode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.decode: non-string input=${e}`);let n=r.length;if(n*e%8)throw new Error("Invalid padding: string should have whole number of bytes");for(;n>0&&r[n-1]===t;n--)if(!((n-1)*e%8))throw new Error("Invalid padding: string has too much padding");return r.slice(0,n)}}}function a(e){if("function"!=typeof e)throw new Error("normalize fn should be function");return{encode:e=>e,decode:t=>e(t)}}function c(e,t,n){if(t<2)throw new Error(`convertRadix: wrong from=${t}, base cannot be less than 2`);if(n<2)throw new Error(`convertRadix: wrong to=${n}, base cannot be less than 2`);if(!Array.isArray(e))throw new Error("convertRadix: data should be array");if(!e.length)return[];let o=0;const s=[],i=Array.from(e);for(i.forEach(e=>{if(r(e),e<0||e>=t)throw new Error(`Wrong integer: ${e}`)});;){let e=0,r=!0;for(let s=o;s<i.length;s++){const a=i[s],c=t*e+a;if(!Number.isSafeInteger(c)||t*e/t!==e||c-a!=t*e)throw new Error("convertRadix: carry overflow");if(e=c%n,i[s]=Math.floor(c/n),!Number.isSafeInteger(i[s])||i[s]*n+e!==c)throw new Error("convertRadix: carry overflow");r&&(i[s]?r=!1:o=s)}if(s.push(e),r)break}for(let t=0;t<e.length-1&&0===e[t];t++)s.push(0);return s.reverse()}Object.defineProperty(t,"__esModule",{value:!0}),t.bytes=t.stringToBytes=t.str=t.bytesToString=t.hex=t.utf8=t.bech32m=t.bech32=t.base58check=t.base58xmr=t.base58xrp=t.base58flickr=t.base58=t.base64url=t.base64=t.base32crockford=t.base32hex=t.base32=t.base16=t.utils=t.assertNumber=void 0,t.assertNumber=r;const u=(e,t)=>t?u(t,e%t):e,h=(e,t)=>e+(t-u(e,t));function l(e,t,n,o){if(!Array.isArray(e))throw new Error("convertRadix2: data should be array");if(t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(n<=0||n>32)throw new Error(`convertRadix2: wrong to=${n}`);if(h(t,n)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${n} carryBits=${h(t,n)}`);let s=0,i=0;const a=2**n-1,c=[];for(const o of e){if(r(o),o>=2**t)throw new Error(`convertRadix2: invalid data word=${o} from=${t}`);if(s=s<<t|o,i+t>32)throw new Error(`convertRadix2: carry overflow pos=${i} from=${t}`);for(i+=t;i>=n;i-=n)c.push((s>>i-n&a)>>>0);s&=2**i-1}if(s=s<<n-i&a,!o&&i>=t)throw new Error("Excess padding");if(!o&&s)throw new Error(`Non-zero padding: ${s}`);return o&&i>0&&c.push(s>>>0),c}function f(e){return r(e),{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix.encode input should be Uint8Array");return c(Array.from(t),256,e)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix.decode input should be array of strings");return Uint8Array.from(c(t,e,256))}}}function d(e,t=!1){if(r(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(h(8,e)>32||h(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!(r instanceof Uint8Array))throw new Error("radix2.encode input should be Uint8Array");return l(Array.from(r),8,e,!t)},decode:r=>{if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("radix2.decode input should be array of strings");return Uint8Array.from(l(r,e,8,t))}}}function p(e){if("function"!=typeof e)throw new Error("unsafeWrapper fn should be function");return function(...t){try{return e.apply(null,t)}catch(e){}}}function m(e,t){if(r(e),"function"!=typeof t)throw new Error("checksum fn should be function");return{encode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.encode: input should be Uint8Array");const n=t(r).slice(0,e),o=new Uint8Array(r.length+e);return o.set(r),o.set(n,r.length),o},decode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.decode: input should be Uint8Array");const n=r.slice(0,-e),o=t(n).slice(0,e),s=r.slice(-e);for(let t=0;t<e;t++)if(o[t]!==s[t])throw new Error("Invalid checksum");return n}}}t.utils={alphabet:o,chain:n,checksum:m,radix:f,radix2:d,join:s,padding:i},t.base16=n(d(4),o("0123456789ABCDEF"),s("")),t.base32=n(d(5),o("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),i(5),s("")),t.base32hex=n(d(5),o("0123456789ABCDEFGHIJKLMNOPQRSTUV"),i(5),s("")),t.base32crockford=n(d(5),o("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),s(""),a(e=>e.toUpperCase().replace(/O/g,"0").replace(/[IL]/g,"1"))),t.base64=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),i(6),s("")),t.base64url=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),i(6),s(""));const y=e=>n(f(58),o(e),s(""));t.base58=y("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"),t.base58flickr=y("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"),t.base58xrp=y("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");const w=[0,2,3,5,6,7,9,10,11];t.base58xmr={encode(e){let r="";for(let n=0;n<e.length;n+=8){const o=e.subarray(n,n+8);r+=t.base58.encode(o).padStart(w[o.length],"1")}return r},decode(e){let r=[];for(let n=0;n<e.length;n+=11){const o=e.slice(n,n+11),s=w.indexOf(o.length),i=t.base58.decode(o);for(let e=0;e<i.length-s;e++)if(0!==i[e])throw new Error("base58xmr: wrong padding");r=r.concat(Array.from(i.slice(i.length-s)))}return Uint8Array.from(r)}},t.base58check=e=>n(m(4,t=>e(e(t))),t.base58);const g=n(o("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),s("")),v=[996825010,642813549,513874426,1027748829,705979059];function b(e){const t=e>>25;let r=(33554431&e)<<5;for(let e=0;e<v.length;e++)1==(t>>e&1)&&(r^=v[e]);return r}function E(e,t,r=1){const n=e.length;let o=1;for(let t=0;t<n;t++){const r=e.charCodeAt(t);if(r<33||r>126)throw new Error(`Invalid prefix (${e})`);o=b(o)^r>>5}o=b(o);for(let t=0;t<n;t++)o=b(o)^31&e.charCodeAt(t);for(let e of t)o=b(o)^e;for(let e=0;e<6;e++)o=b(o);return o^=r,g.encode(l([o%2**30],30,5,!1))}function x(e){const t="bech32"===e?1:734539939,r=d(5),n=r.decode,o=r.encode,s=p(n);function i(e,r=90){if("string"!=typeof e)throw new Error("bech32.decode input should be string, not "+typeof e);if(e.length<8||!1!==r&&e.length>r)throw new TypeError(`Wrong string length: ${e.length} (${e}). Expected (8..${r})`);const n=e.toLowerCase();if(e!==n&&e!==e.toUpperCase())throw new Error("String must be lowercase or uppercase");const o=(e=n).lastIndexOf("1");if(0===o||-1===o)throw new Error('Letter "1" must be present between prefix and data only');const s=e.slice(0,o),i=e.slice(o+1);if(i.length<6)throw new Error("Data must be at least 6 characters long");const a=g.decode(i).slice(0,-6),c=E(s,a,t);if(!i.endsWith(c))throw new Error(`Invalid checksum in ${e}: expected "${c}"`);return{prefix:s,words:a}}return{encode:function(e,r,n=90){if("string"!=typeof e)throw new Error("bech32.encode prefix should be string, not "+typeof e);if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("bech32.encode words should be array of numbers, not "+typeof r);const o=e.length+7+r.length;if(!1!==n&&o>n)throw new TypeError(`Length ${o} exceeds limit ${n}`);return`${e=e.toLowerCase()}1${g.encode(r)}${E(e,r,t)}`},decode:i,decodeToBytes:function(e){const{prefix:t,words:r}=i(e,!1);return{prefix:t,words:r,bytes:n(r)}},decodeUnsafe:p(i),fromWords:n,fromWordsUnsafe:s,toWords:o}}t.bech32=x("bech32"),t.bech32m=x("bech32m"),t.utf8={encode:e=>(new TextDecoder).decode(e),decode:e=>(new TextEncoder).encode(e)},t.hex=n(d(4),o("0123456789abcdef"),s(""),a(e=>{if("string"!=typeof e||e.length%2)throw new TypeError(`hex.decode: expected string, got ${typeof e} with length ${e.length}`);return e.toLowerCase()}));const P={utf8:t.utf8,hex:t.hex,base16:t.base16,base32:t.base32,base64:t.base64,base64url:t.base64url,base58:t.base58,base58xmr:t.base58xmr},A=`Invalid encoding type. Available types: ${Object.keys(P).join(", ")}`;t.bytesToString=(e,t)=>{if("string"!=typeof e||!P.hasOwnProperty(e))throw new TypeError(A);if(!(t instanceof Uint8Array))throw new TypeError("bytesToString() expects Uint8Array");return P[e].encode(t)},t.str=t.bytesToString,t.stringToBytes=(e,t)=>{if(!P.hasOwnProperty(e))throw new TypeError(A);if("string"!=typeof t)throw new TypeError("stringToBytes() expects string");return P[e].decode(t)},t.bytes=t.stringToBytes},e(t={exports:{}},t.exports),t.exports);const{bech32:n,hex:o,utf8:s}=r,i={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},a={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},c={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},u={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},h={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},l=["option_data_loss_protect","initial_routing_sync","option_upfront_shutdown_script","gossip_queries","var_onion_optin","gossip_queries_ex","option_static_remotekey","payment_secret","basic_mpp","option_support_large_channel"],f={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},d=BigInt("2100000000000000000"),p=BigInt(1e11),m={payment_hash:1,payment_secret:16,description:13,payee:19,description_hash:23,expiry:6,min_final_cltv_expiry:24,fallback_address:9,route_hint:3,feature_bits:5,metadata:27},y={};for(let e=0,t=Object.keys(m);e<t.length;e++){const r=t[e],n=m[t[e]].toString();y[n]=r}const w={1:e=>o.encode(n.fromWordsUnsafe(e)),16:e=>o.encode(n.fromWordsUnsafe(e)),13:e=>s.encode(n.fromWordsUnsafe(e)),19:e=>o.encode(n.fromWordsUnsafe(e)),23:e=>o.encode(n.fromWordsUnsafe(e)),27:e=>o.encode(n.fromWordsUnsafe(e)),6:v,24:v,3:function(e){const t=[];let r,s,i,a,c,u=n.fromWordsUnsafe(e);for(;u.length>0;)r=o.encode(u.slice(0,33)),s=o.encode(u.slice(33,41)),i=parseInt(o.encode(u.slice(41,45)),16),a=parseInt(o.encode(u.slice(45,49)),16),c=parseInt(o.encode(u.slice(49,51)),16),u=u.slice(51),t.push({pubkey:r,short_channel_id:s,fee_base_msat:i,fee_proportional_millionths:a,cltv_expiry_delta:c});return t},5:function(e){const t=e.slice().reverse().map(e=>[!!(1&e),!!(2&e),!!(4&e),!!(8&e),!!(16&e)]).reduce((e,t)=>e.concat(t),[]);for(;t.length<2*l.length;)t.push(!1);const r={};l.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*l.length);return r.extra_bits={start_bit:2*l.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function g(e){return t=>({tagCode:parseInt(e),words:n.encode("unknown",t,Number.MAX_SAFE_INTEGER)})}function v(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}var b=function(e){return Uint8Array.from(e.match(/.{1,2}/g).map(function(e){return parseInt(e,16)}))},E=function(e){if(!e)return null;try{var t=function(e,t){if("string"!=typeof e)throw new Error("Lightning Payment Request must be string");if("ln"!==e.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const r=[],s=n.decode(e,Number.MAX_SAFE_INTEGER);e=e.toLowerCase();const l=s.prefix;let b=s.words,E=e.slice(l.length+1),x=b.slice(-104);b=b.slice(0,-104);let P=l.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(P&&!P[2]&&(P=l.match(/^ln(\S+)$/)),!P)throw new Error("Not a proper lightning payment request");r.push({name:"lightning_network",letters:"ln"});const A=P[1];let k;switch(A){case i.bech32:k=i;break;case a.bech32:k=a;break;case c.bech32:k=c;break;case u.bech32:k=u;break;case h.bech32:k=h}if(!k||k.bech32!==A)throw new Error("Unknown coin bech32 prefix");r.push({name:"coin_network",letters:A,value:k});const _=P[2];let U;_?(U=function(e,t){let r,n;if(e.slice(-1).match(/^[munp]$/))r=e.slice(-1),n=e.slice(0,-1);else{if(e.slice(-1).match(/^[^munp0-9]$/))throw new Error("Not a valid multiplier for the amount");n=e}if(!n.match(/^\d+$/))throw new Error("Not a valid human readable amount");const o=BigInt(n),s=r?o*p/f[r]:o*p;if("p"===r&&o%BigInt(10)!==BigInt(0)||s>d)throw new Error("Amount is outside of valid range");return s.toString()}(_+P[3]),r.push({name:"amount",letters:P[2]+P[3],value:U})):U=null,r.push({name:"separator",letters:"1"});const L=v(b.slice(0,7));let D,N,I,S;for(b=b.slice(7),r.push({name:"timestamp",letters:E.slice(0,7),value:L}),E=E.slice(7);b.length>0;){const e=b[0].toString();D=y[e]||"unknown_tag",N=w[e]||g(e),b=b.slice(1),I=v(b.slice(0,2)),b=b.slice(2),S=b.slice(0,I),b=b.slice(I),r.push({name:D,tag:E[0],letters:E.slice(0,3+I),value:N(S)}),E=E.slice(3+I)}r.push({name:"signature",letters:E.slice(0,104),value:o.encode(n.fromWordsUnsafe(x))}),E=E.slice(104),r.push({name:"checksum",letters:E});let R={paymentRequest:e,sections:r,get expiry(){let e=r.find(e=>"expiry"===e.name);if(e)return j("timestamp")+e.value},get route_hints(){return r.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in m)"route_hint"!==e&&Object.defineProperty(R,e,{get:()=>j(e)});return R;function j(e){let t=r.find(t=>t.name===e);return t?t.value:void 0}}(e);if(!t||!t.sections)return null;var r=t.sections.find(function(e){return"payment_hash"===e.name});if("payment_hash"!==(null==r?void 0:r.name)||!r.value)return null;var s=r.value,l=0,b=t.sections.find(function(e){return"amount"===e.name});"amount"===(null==b?void 0:b.name)&&b.value&&(l=parseInt(b.value)/1e3);var E=t.sections.find(function(e){return"timestamp"===e.name});if("timestamp"!==(null==E?void 0:E.name)||!E.value)return null;var x,P=E.value,A=t.sections.find(function(e){return"expiry"===e.name});"expiry"===(null==A?void 0:A.name)&&(x=A.value);var k=t.sections.find(function(e){return"description"===e.name});return{paymentHash:s,satoshi:l,timestamp:P,expiry:x,description:"description"===(null==k?void 0:k.name)?null==k?void 0:k.value:void 0}}catch(e){return null}};function x(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}const P=e=>e instanceof Uint8Array,A=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),k=(e,t)=>e<<32-t|e>>>t;if(68!==new Uint8Array(new Uint32Array([287454020]).buffer)[0])throw new Error("Non little-endian hardware is not supported");const _=/* @__PURE__ */Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function U(e){if(!P(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=_[e[r]];return t}function L(e){if("string"==typeof e&&(e=function(e){if("string"!=typeof e)throw new Error("utf8ToBytes expected string, got "+typeof e);return new Uint8Array((new TextEncoder).encode(e))}(e)),!P(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class D{clone(){return this._cloneInto()}}function N(e){const t=t=>e().update(L(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class I extends D{constructor(e,t,r,n){super(),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(e),this.view=A(this.buffer)}update(e){x(this);const{view:t,buffer:r,blockLen:n}=this,o=(e=L(e)).length;for(let s=0;s<o;){const i=Math.min(n-this.pos,o-s);if(i!==n)r.set(e.subarray(s,s+i),this.pos),this.pos+=i,s+=i,this.pos===n&&(this.process(t,0),this.pos=0);else{const t=A(e);for(;n<=o-s;s+=n)this.process(t,s)}}return this.length+=e.length,this.roundClean(),this}digestInto(e){x(this),function(e,t){!function(e,...t){if(!(e instanceof Uint8Array))throw new Error("Expected Uint8Array");if(t.length>0&&!t.includes(e.length))throw new Error(`Expected Uint8Array of length ${t}, not of length=${e.length}`)}(e);const r=t.outputLen;if(e.length<r)throw new Error(`digestInto() expects output buffer of length at least ${r}`)}(e,this),this.finished=!0;const{buffer:t,view:r,blockLen:n,isLE:o}=this;let{pos:s}=this;t[s++]=128,this.buffer.subarray(s).fill(0),this.padOffset>n-s&&(this.process(r,0),s=0);for(let e=s;e<n;e++)t[e]=0;!function(e,t,r,n){if("function"==typeof e.setBigUint64)return e.setBigUint64(t,r,n);const o=BigInt(32),s=BigInt(4294967295),i=Number(r>>o&s),a=Number(r&s),c=n?0:4;e.setUint32(t+(n?4:0),i,n),e.setUint32(t+c,a,n)}(r,n-8,BigInt(8*this.length),o),this.process(r,0);const i=A(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const c=a/4,u=this.get();if(c>u.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<c;e++)i.setUint32(4*e,u[e],o)}digest(){const{buffer:e,outputLen:t}=this;this.digestInto(e);const r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());const{blockLen:t,buffer:r,length:n,finished:o,destroyed:s,pos:i}=this;return e.length=n,e.pos=i,e.finished=o,e.destroyed=s,n%t&&e.buffer.set(r),e}}const S=(e,t,r)=>e&t^e&r^t&r,R=/* @__PURE__ */new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),j=/* @__PURE__ */new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),$=/* @__PURE__ */new Uint32Array(64);class T extends I{constructor(){super(64,32,8,!1),this.A=0|j[0],this.B=0|j[1],this.C=0|j[2],this.D=0|j[3],this.E=0|j[4],this.F=0|j[5],this.G=0|j[6],this.H=0|j[7]}get(){const{A:e,B:t,C:r,D:n,E:o,F:s,G:i,H:a}=this;return[e,t,r,n,o,s,i,a]}set(e,t,r,n,o,s,i,a){this.A=0|e,this.B=0|t,this.C=0|r,this.D=0|n,this.E=0|o,this.F=0|s,this.G=0|i,this.H=0|a}process(e,t){for(let r=0;r<16;r++,t+=4)$[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=$[e-15],r=$[e-2],n=k(t,7)^k(t,18)^t>>>3,o=k(r,17)^k(r,19)^r>>>10;$[e]=o+$[e-7]+n+$[e-16]|0}let{A:r,B:n,C:o,D:s,E:i,F:a,G:c,H:u}=this;for(let e=0;e<64;e++){const t=u+(k(i,6)^k(i,11)^k(i,25))+((h=i)&a^~h&c)+R[e]+$[e]|0,l=(k(r,2)^k(r,13)^k(r,22))+S(r,n,o)|0;u=c,c=a,a=i,i=s+t|0,s=o,o=n,n=r,r=t+l|0}var h;r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,s=s+this.D|0,i=i+this.E|0,a=a+this.F|0,c=c+this.G|0,u=u+this.H|0,this.set(r,n,o,s,i,a,c,u)}roundClean(){$.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const W=/* @__PURE__ */N(()=>new T);var B=/*#__PURE__*/function(){function e(e){var t,r,n,o;if(this.paymentRequest=void 0,this.paymentHash=void 0,this.preimage=void 0,this.verify=void 0,this.satoshi=void 0,this.expiry=void 0,this.timestamp=void 0,this.createdDate=void 0,this.expiryDate=void 0,this.description=void 0,this.successAction=void 0,this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");var s=E(this.paymentRequest);if(!s)throw new Error("Failed to decode payment request");this.paymentHash=s.paymentHash,this.satoshi=s.satoshi,this.timestamp=s.timestamp,this.expiry=s.expiry,this.createdDate=new Date(1e3*this.timestamp),this.expiryDate=this.expiry?new Date(1e3*(this.timestamp+this.expiry)):void 0,this.description=null!=(t=s.description)?t:null,this.verify=null!=(r=e.verify)?r:null,this.preimage=null!=(n=e.preimage)?n:null,this.successAction=null!=(o=e.successAction)?o:null}var t=e.prototype;return t.isPaid=function(){try{var e=this;if(e.preimage)return Promise.resolve(e.validatePreimage(e.preimage));if(e.verify)return Promise.resolve(e.verifyPayment());throw new Error("Could not verify payment")}catch(e){return Promise.reject(e)}},t.validatePreimage=function(e){if(!e||!this.paymentHash)return!1;try{var t=U(W(b(e)));return this.paymentHash===t}catch(e){return!1}},t.verifyPayment=function(){try{var e=this;return Promise.resolve(function(t,r){try{var n=function(){if(!e.verify)throw new Error("LNURL verify not available");return Promise.resolve(fetch(e.verify)).then(function(t){if(!t.ok)throw new Error("Verification request failed: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return t.preimage&&(e.preimage=t.preimage),t.settled})})}()}catch(e){return r(e)}return n&&n.then?n.then(void 0,r):n}(0,function(e){return console.error("Failed to check LNURL-verify",e),!1}))}catch(e){return Promise.reject(e)}},t.hasExpired=function(){var e=this.expiryDate;return!!e&&e.getTime()<Date.now()},e}(),H=function(e,t){var r=e.satoshi,n=e.comment,o=e.p,s=e.e,i=e.relays;void 0===t&&(t={});try{var a=t.nostr||globalThis.nostr;if(!a)throw new Error("nostr option or window.nostr is not available");var c=[["relays"].concat(i),["amount",r.toString()]];return o&&c.push(["p",o]),s&&c.push(["e",s]),Promise.resolve(a.getPublicKey()).then(function(e){var t={pubkey:e,created_at:Math.floor(Date.now()/1e3),kind:9734,tags:c,content:null!=n?n:""};return t.id=C(t),Promise.resolve(a.signEvent(t))})}catch(s){return Promise.reject(s)}},O=function(e){if("keysend"!==e.tag)throw new Error("Invalid keysend params");if("OK"!==e.status)throw new Error("Keysend status not OK");if(!e.pubkey)throw new Error("Pubkey does not exist");var t,r;return e.customData&&e.customData[0]&&(t=e.customData[0].customKey,r=e.customData[0].customValue),{destination:e.pubkey,customKey:t,customValue:r}};function F(e){if("string"!=typeof e.content)return!1;if("number"!=typeof e.created_at)return!1;if(!Array.isArray(e.tags))return!1;for(var t=0;t<e.tags.length;t++){var r=e.tags[t];if(!Array.isArray(r))return!1;for(var n=0;n<r.length;n++)if("object"==typeof r[n])return!1}return!0}function K(e){if(!F(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function C(e){return U(W(K(e)))}function V(e,t){var r,n,o,s;return t&&e&&(n=(r=null==(o=e.names)?void 0:o[t])?null==(s=e.relays)?void 0:s[r]:void 0),[e,r,n]}var q=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,z=function(e){return!!e&&q.test(e)},M=function(e){var t=e.amount;return t>0&&t>=e.min&&t<=e.max},G=function(e){try{if("payRequest"!==e.tag)throw new Error("Invalid pay service params");var t=(e.callback+"").trim();if(!z(t))throw new Error("Callback must be a valid url");var r,n,o=Math.ceil(Number(e.minSendable||0)),s=Math.floor(Number(e.maxSendable));if(!o||!s||o>s)throw new Error("Invalid pay service params");try{r=JSON.parse(e.metadata+""),n=U(W(e.metadata+""))}catch(e){r=[],n=U(W("[]"))}for(var i="",a="",c="",u="",h=0;h<r.length;h++){var l=r[h],f=l[0],d=l[1];switch(f){case"text/plain":c=d;break;case"text/identifier":u=d;break;case"text/email":i=d;break;case"image/png;base64":case"image/jpeg;base64":a="data:"+f+","+d}}var p,m=e.payerData;try{p=new URL(t).hostname}catch(e){}return Promise.resolve({callback:t,fixed:o===s,min:o,max:s,domain:p,metadata:r,metadataHash:n,identifier:u,email:i,description:c,image:a,payerData:m,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1})}catch(e){return Promise.reject(e)}};function J(){return J=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},J.apply(this,arguments)}var Z=function(e,t){try{var r=e.boost;t||(t={});var n=t.webln||globalThis.webln;if(!n)throw new Error("WebLN not available");if(!n.keysend)throw new Error("Keysend not available in current WebLN provider");var o=e.amount||Math.floor(r.value_msat/1e3),s={destination:e.destination,amount:o,customRecords:{7629169:JSON.stringify(r)}};return e.customKey&&e.customValue&&(s.customRecords[e.customKey]=e.customValue),Promise.resolve(n.enable()).then(function(){return Promise.resolve(n.keysend(s))})}catch(e){return Promise.reject(e)}},X=/^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,Y=/*#__PURE__*/function(){function e(e,t){this.address=void 0,this.options=void 0,this.username=void 0,this.domain=void 0,this.pubkey=void 0,this.lnurlpData=void 0,this.keysendData=void 0,this.nostrData=void 0,this.nostrPubkey=void 0,this.nostrRelays=void 0,this.webln=void 0,this.address=e,this.options={proxy:"https://api.getalby.com/lnurl"},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}var t=e.prototype;return t.parse=function(){var e=X.exec(this.address.toLowerCase());e&&(this.username=e[1],this.domain=e[2])},t.getWebLN=function(){return this.webln||globalThis.webln},t.fetch=function(){try{var e=this;return Promise.resolve(e.options.proxy?e.fetchWithProxy():e.fetchWithoutProxy())}catch(e){return Promise.reject(e)}},t.fetchWithProxy=function(){try{var e=this;return Promise.resolve(fetch(e.options.proxy+"/lightning-address-details?"+new URLSearchParams({ln:e.address}).toString())).then(function(t){if(!t.ok)throw new Error("Failed to fetch lnurl info: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t.lnurlp)).then(function(){e.parseKeysendResponse(t.keysend),e.parseNostrResponse(t.nostr)})})})}catch(e){return Promise.reject(e)}},t.fetchWithoutProxy=function(){try{var e=this;return e.domain&&e.username?Promise.resolve(Promise.all([e.fetchLnurlData(),e.fetchKeysendData(),e.fetchNostrData()])).then(function(){}):Promise.resolve()}catch(e){return Promise.reject(e)}},t.fetchLnurlData=function(){try{var e=this;return Promise.resolve(fetch(e.lnurlpUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t)).then(function(){})})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchKeysendData=function(){try{var e=this;return Promise.resolve(fetch(e.keysendUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseKeysendResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchNostrData=function(){try{var e=this;return Promise.resolve(fetch(e.nostrUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseNostrResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.lnurlpUrl=function(){return"https://"+this.domain+"/.well-known/lnurlp/"+this.username},t.keysendUrl=function(){return"https://"+this.domain+"/.well-known/keysend/"+this.username},t.nostrUrl=function(){return"https://"+this.domain+"/.well-known/nostr.json?name="+this.username},t.generateInvoice=function(e){try{var t,r=function(e){var r=t&&t.pr&&t.pr.toString();if(!r)throw new Error("Invalid pay service invoice");var n={pr:r};if(t&&t.verify&&(n.verify=t.verify.toString()),t&&t.successAction&&"object"==typeof t.successAction){var o=t.successAction,s=o.tag,i=o.description,a=o.url;"message"===s?n.successAction={tag:s,message:o.message}:"url"===s&&(n.successAction={tag:s,description:i,url:a})}return new B(n)},n=this,o=function(){if(n.options.proxy)return Promise.resolve(fetch(n.options.proxy+"/generate-invoice?"+new URLSearchParams(J({ln:n.address},e)).toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e.invoice})});if(!n.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!n.lnurlpData.callback||!z(n.lnurlpData.callback))throw new Error("Valid callback does not exist in lnurlpData");var r=new URL(n.lnurlpData.callback);return r.search=new URLSearchParams(e).toString(),Promise.resolve(fetch(r.toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e})})}();return Promise.resolve(o&&o.then?o.then(r):r())}catch(e){return Promise.reject(e)}},t.requestInvoice=function(e){try{var t=this;if(!t.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");var r=1e3*e.satoshi,n=t.lnurlpData,o=n.commentAllowed;if(!M({amount:r,min:n.min,max:n.max}))throw new Error("Invalid amount");if(e.comment&&o&&o>0&&e.comment.length>o)throw new Error("The comment length must be "+o+" characters or fewer");var s={amount:r.toString()};return e.comment&&(s.comment=e.comment),e.payerdata&&(s.payerdata=JSON.stringify(e.payerdata)),Promise.resolve(t.generateInvoice(s))}catch(e){return Promise.reject(e)}},t.boost=function(e,t){void 0===t&&(t=0);try{var r=this;if(!r.keysendData)throw new Error("No keysendData available. Please call fetch() first.");var n=r.keysendData,o=n.destination,s=n.customKey,i=n.customValue,a=r.getWebLN();if(!a)throw new Error("WebLN not available");return Promise.resolve(Z({destination:o,customKey:s,customValue:i,amount:t,boost:e},{webln:a}))}catch(e){return Promise.reject(e)}},t.zapInvoice=function(e,t){var r=e.satoshi,n=e.comment,o=e.relays,s=e.e;void 0===t&&(t={});try{var i=this;if(!i.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!i.nostrPubkey)throw new Error("Nostr Pubkey is missing");var a=i.nostrPubkey,c=1e3*r,u=i.lnurlpData,h=u.allowsNostr;if(!M({amount:c,min:u.min,max:u.max}))throw new Error("Invalid amount");if(!h)throw new Error("Your provider does not support zaps");return Promise.resolve(H({satoshi:c,comment:n,p:a,e:s,relays:o},t)).then(function(e){var t={amount:c.toString(),nostr:JSON.stringify(e)};return Promise.resolve(i.generateInvoice(t))})}catch(s){return Promise.reject(s)}},t.zap=function(e,t){void 0===t&&(t={});try{var r=this.zapInvoice(e,t),n=this.getWebLN();if(!n)throw new Error("WebLN not available");return Promise.resolve(n.enable()).then(function(){var e=n.sendPayment;return Promise.resolve(r).then(function(t){return e.call(n,t.paymentRequest)})})}catch(e){return Promise.reject(e)}},t.parseLnUrlPayResponse=function(e){try{var t=this,r=function(){if(e)return Promise.resolve(G(e)).then(function(e){t.lnurlpData=e})}();return Promise.resolve(r&&r.then?r.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},t.parseKeysendResponse=function(e){e&&(this.keysendData=O(e))},t.parseNostrResponse=function(e){if(e){var t=V(e,this.username);this.nostrData=t[0],this.nostrPubkey=t[1],this.nostrRelays=t[2]}},e}(),Q=/*#__PURE__*/function(){function e(e){this.storage=void 0,this.storage=e||{}}var t=e.prototype;return t.getItem=function(e){return this.storage[e]},t.setItem=function(e,t){this.storage[e]=t},e}(),ee=/*#__PURE__*/function(){function e(e){}var t=e.prototype;return t.getItem=function(e){return null},t.setItem=function(e,t){},e}(),te=function(e){for(var t,r=e.replace("L402","").replace("LSAT","").trim(),n={},o=/(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;null!==(t=o.exec(r));)n[t[1]]=t[3]||t[4]||t[5];return n},re=new Q,ne=function(e,t,r){try{var n,o=function(r){return n?r:(t.headers["Accept-Authenticate"]=s,Promise.resolve(fetch(e,t)).then(function(r){var n=r.headers.get("www-authenticate");if(!n)return r;var o=te(n),c=o.token||o.macaroon,u=o.invoice;return Promise.resolve(i.enable()).then(function(){return Promise.resolve(i.sendPayment(u)).then(function(r){return a.setItem(e,JSON.stringify({token:c,preimage:r.preimage})),t.headers.Authorization=s+" "+c+":"+r.preimage,Promise.resolve(fetch(e,t))})})}))};r||(r={});var s=r.headerKey||"L402",i=r.webln||globalThis.webln;if(!i)throw new Error("WebLN is missing");var a=r.store||re;t||(t={}),t.cache="no-store",t.mode="cors",t.headers||(t.headers={});var c=a.getItem(e),u=function(){if(c){var r=JSON.parse(c);return t.headers.Authorization=s+" "+r.token+":"+r.preimage,Promise.resolve(fetch(e,t)).then(function(e){return n=1,e})}}();return Promise.resolve(u&&u.then?u.then(o):o(u))}catch(e){return Promise.reject(e)}},oe={__proto__:null,fetchWithL402:ne,MemoryStorage:Q,NoStorage:ee,parseL402:te},se=function(e){try{var t="https://getalby.com/api/rates/"+e.toLowerCase()+".json";return Promise.resolve(fetch(t)).then(function(e){if(!e.ok)throw new Error("Failed to fetch rate: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){return e.rate_float/1e8})})}catch(e){return Promise.reject(e)}},ie=function(e){var t=e.satoshi;return Promise.resolve(se(e.currency)).then(function(e){return Number(t)*e})},ae=function(e){var t=e.amount;return Promise.resolve(se(e.currency)).then(function(e){return Math.floor(Number(t)/e)})},ce=function(e){var t=e.currency,r=e.locale;return r||(r="en"),Promise.resolve(ie({satoshi:e.satoshi,currency:t})).then(function(e){return e.toLocaleString(r,{style:"currency",currency:t})})},ue={__proto__:null,getFiatBtcRate:se,getFiatValue:ie,getSatoshiValue:ae,getFormattedFiatValue:ce};exports.DEFAULT_PROXY="https://api.getalby.com/lnurl",exports.Invoice=B,exports.LN_ADDRESS_REGEX=X,exports.LightningAddress=Y,exports.MemoryStorage=Q,exports.NoStorage=ee,exports.decodeInvoice=E,exports.fetchWithL402=ne,exports.fiat=ue,exports.fromHexString=b,exports.generateZapEvent=H,exports.getEventHash=C,exports.getFiatBtcRate=se,exports.getFiatValue=ie,exports.getFormattedFiatValue=ce,exports.getSatoshiValue=ae,exports.isUrl=z,exports.isValidAmount=M,exports.l402=oe,exports.parseKeysendResponse=O,exports.parseL402=te,exports.parseLnUrlPayResponse=G,exports.parseNostrResponse=V,exports.sendBoostagram=Z,exports.serializeEvent=K,exports.validateEvent=F;
export * from "./bolt11";
export * from "./lnurl";
export * from "./podcasting2";
export * from "./l402";
export * from "./fiat";
export * as l402 from "./l402";
export * as fiat from "./fiat";
var e,t,r=(e=function(e,t){function r(e){if(!Number.isSafeInteger(e))throw new Error(`Wrong integer: ${e}`)}function n(...e){const t=(e,t)=>r=>e(t(r));return{encode:Array.from(e).reverse().reduce((e,r)=>e?t(e,r.encode):r.encode,void 0),decode:e.reduce((e,r)=>e?t(e,r.decode):r.decode,void 0)}}function o(e){return{encode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("alphabet.encode input should be an array of numbers");return t.map(t=>{if(r(t),t<0||t>=e.length)throw new Error(`Digit index outside alphabet: ${t} (alphabet: ${e.length})`);return e[t]})},decode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("alphabet.decode input should be array of strings");return t.map(t=>{if("string"!=typeof t)throw new Error(`alphabet.decode: not string element=${t}`);const r=e.indexOf(t);if(-1===r)throw new Error(`Unknown letter: "${t}". Allowed: ${e}`);return r})}}}function s(e=""){if("string"!=typeof e)throw new Error("join separator should be string");return{encode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("join.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`join.encode: non-string input=${e}`);return t.join(e)},decode:t=>{if("string"!=typeof t)throw new Error("join.decode input should be string");return t.split(e)}}}function i(e,t="="){if(r(e),"string"!=typeof t)throw new Error("padding chr should be string");return{encode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.encode: non-string input=${e}`);for(;r.length*e%8;)r.push(t);return r},decode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.decode: non-string input=${e}`);let n=r.length;if(n*e%8)throw new Error("Invalid padding: string should have whole number of bytes");for(;n>0&&r[n-1]===t;n--)if(!((n-1)*e%8))throw new Error("Invalid padding: string has too much padding");return r.slice(0,n)}}}function a(e){if("function"!=typeof e)throw new Error("normalize fn should be function");return{encode:e=>e,decode:t=>e(t)}}function c(e,t,n){if(t<2)throw new Error(`convertRadix: wrong from=${t}, base cannot be less than 2`);if(n<2)throw new Error(`convertRadix: wrong to=${n}, base cannot be less than 2`);if(!Array.isArray(e))throw new Error("convertRadix: data should be array");if(!e.length)return[];let o=0;const s=[],i=Array.from(e);for(i.forEach(e=>{if(r(e),e<0||e>=t)throw new Error(`Wrong integer: ${e}`)});;){let e=0,r=!0;for(let s=o;s<i.length;s++){const a=i[s],c=t*e+a;if(!Number.isSafeInteger(c)||t*e/t!==e||c-a!=t*e)throw new Error("convertRadix: carry overflow");if(e=c%n,i[s]=Math.floor(c/n),!Number.isSafeInteger(i[s])||i[s]*n+e!==c)throw new Error("convertRadix: carry overflow");r&&(i[s]?r=!1:o=s)}if(s.push(e),r)break}for(let t=0;t<e.length-1&&0===e[t];t++)s.push(0);return s.reverse()}Object.defineProperty(t,"__esModule",{value:!0}),t.bytes=t.stringToBytes=t.str=t.bytesToString=t.hex=t.utf8=t.bech32m=t.bech32=t.base58check=t.base58xmr=t.base58xrp=t.base58flickr=t.base58=t.base64url=t.base64=t.base32crockford=t.base32hex=t.base32=t.base16=t.utils=t.assertNumber=void 0,t.assertNumber=r;const h=(e,t)=>t?h(t,e%t):e,l=(e,t)=>e+(t-h(e,t));function u(e,t,n,o){if(!Array.isArray(e))throw new Error("convertRadix2: data should be array");if(t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(n<=0||n>32)throw new Error(`convertRadix2: wrong to=${n}`);if(l(t,n)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${n} carryBits=${l(t,n)}`);let s=0,i=0;const a=2**n-1,c=[];for(const o of e){if(r(o),o>=2**t)throw new Error(`convertRadix2: invalid data word=${o} from=${t}`);if(s=s<<t|o,i+t>32)throw new Error(`convertRadix2: carry overflow pos=${i} from=${t}`);for(i+=t;i>=n;i-=n)c.push((s>>i-n&a)>>>0);s&=2**i-1}if(s=s<<n-i&a,!o&&i>=t)throw new Error("Excess padding");if(!o&&s)throw new Error(`Non-zero padding: ${s}`);return o&&i>0&&c.push(s>>>0),c}function f(e){return r(e),{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix.encode input should be Uint8Array");return c(Array.from(t),256,e)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix.decode input should be array of strings");return Uint8Array.from(c(t,e,256))}}}function d(e,t=!1){if(r(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(l(8,e)>32||l(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!(r instanceof Uint8Array))throw new Error("radix2.encode input should be Uint8Array");return u(Array.from(r),8,e,!t)},decode:r=>{if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("radix2.decode input should be array of strings");return Uint8Array.from(u(r,e,8,t))}}}function p(e){if("function"!=typeof e)throw new Error("unsafeWrapper fn should be function");return function(...t){try{return e.apply(null,t)}catch(e){}}}function w(e,t){if(r(e),"function"!=typeof t)throw new Error("checksum fn should be function");return{encode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.encode: input should be Uint8Array");const n=t(r).slice(0,e),o=new Uint8Array(r.length+e);return o.set(r),o.set(n,r.length),o},decode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.decode: input should be Uint8Array");const n=r.slice(0,-e),o=t(n).slice(0,e),s=r.slice(-e);for(let t=0;t<e;t++)if(o[t]!==s[t])throw new Error("Invalid checksum");return n}}}t.utils={alphabet:o,chain:n,checksum:w,radix:f,radix2:d,join:s,padding:i},t.base16=n(d(4),o("0123456789ABCDEF"),s("")),t.base32=n(d(5),o("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),i(5),s("")),t.base32hex=n(d(5),o("0123456789ABCDEFGHIJKLMNOPQRSTUV"),i(5),s("")),t.base32crockford=n(d(5),o("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),s(""),a(e=>e.toUpperCase().replace(/O/g,"0").replace(/[IL]/g,"1"))),t.base64=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),i(6),s("")),t.base64url=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),i(6),s(""));const y=e=>n(f(58),o(e),s(""));t.base58=y("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"),t.base58flickr=y("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"),t.base58xrp=y("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");const m=[0,2,3,5,6,7,9,10,11];t.base58xmr={encode(e){let r="";for(let n=0;n<e.length;n+=8){const o=e.subarray(n,n+8);r+=t.base58.encode(o).padStart(m[o.length],"1")}return r},decode(e){let r=[];for(let n=0;n<e.length;n+=11){const o=e.slice(n,n+11),s=m.indexOf(o.length),i=t.base58.decode(o);for(let e=0;e<i.length-s;e++)if(0!==i[e])throw new Error("base58xmr: wrong padding");r=r.concat(Array.from(i.slice(i.length-s)))}return Uint8Array.from(r)}},t.base58check=e=>n(w(4,t=>e(e(t))),t.base58);const g=n(o("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),s("")),b=[996825010,642813549,513874426,1027748829,705979059];function v(e){const t=e>>25;let r=(33554431&e)<<5;for(let e=0;e<b.length;e++)1==(t>>e&1)&&(r^=b[e]);return r}function E(e,t,r=1){const n=e.length;let o=1;for(let t=0;t<n;t++){const r=e.charCodeAt(t);if(r<33||r>126)throw new Error(`Invalid prefix (${e})`);o=v(o)^r>>5}o=v(o);for(let t=0;t<n;t++)o=v(o)^31&e.charCodeAt(t);for(let e of t)o=v(o)^e;for(let e=0;e<6;e++)o=v(o);return o^=r,g.encode(u([o%2**30],30,5,!1))}function x(e){const t="bech32"===e?1:734539939,r=d(5),n=r.decode,o=r.encode,s=p(n);function i(e,r=90){if("string"!=typeof e)throw new Error("bech32.decode input should be string, not "+typeof e);if(e.length<8||!1!==r&&e.length>r)throw new TypeError(`Wrong string length: ${e.length} (${e}). Expected (8..${r})`);const n=e.toLowerCase();if(e!==n&&e!==e.toUpperCase())throw new Error("String must be lowercase or uppercase");const o=(e=n).lastIndexOf("1");if(0===o||-1===o)throw new Error('Letter "1" must be present between prefix and data only');const s=e.slice(0,o),i=e.slice(o+1);if(i.length<6)throw new Error("Data must be at least 6 characters long");const a=g.decode(i).slice(0,-6),c=E(s,a,t);if(!i.endsWith(c))throw new Error(`Invalid checksum in ${e}: expected "${c}"`);return{prefix:s,words:a}}return{encode:function(e,r,n=90){if("string"!=typeof e)throw new Error("bech32.encode prefix should be string, not "+typeof e);if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("bech32.encode words should be array of numbers, not "+typeof r);const o=e.length+7+r.length;if(!1!==n&&o>n)throw new TypeError(`Length ${o} exceeds limit ${n}`);return`${e=e.toLowerCase()}1${g.encode(r)}${E(e,r,t)}`},decode:i,decodeToBytes:function(e){const{prefix:t,words:r}=i(e,!1);return{prefix:t,words:r,bytes:n(r)}},decodeUnsafe:p(i),fromWords:n,fromWordsUnsafe:s,toWords:o}}t.bech32=x("bech32"),t.bech32m=x("bech32m"),t.utf8={encode:e=>(new TextDecoder).decode(e),decode:e=>(new TextEncoder).encode(e)},t.hex=n(d(4),o("0123456789abcdef"),s(""),a(e=>{if("string"!=typeof e||e.length%2)throw new TypeError(`hex.decode: expected string, got ${typeof e} with length ${e.length}`);return e.toLowerCase()}));const A={utf8:t.utf8,hex:t.hex,base16:t.base16,base32:t.base32,base64:t.base64,base64url:t.base64url,base58:t.base58,base58xmr:t.base58xmr},k=`Invalid encoding type. Available types: ${Object.keys(A).join(", ")}`;t.bytesToString=(e,t)=>{if("string"!=typeof e||!A.hasOwnProperty(e))throw new TypeError(k);if(!(t instanceof Uint8Array))throw new TypeError("bytesToString() expects Uint8Array");return A[e].encode(t)},t.str=t.bytesToString,t.stringToBytes=(e,t)=>{if(!A.hasOwnProperty(e))throw new TypeError(k);if("string"!=typeof t)throw new TypeError("stringToBytes() expects string");return A[e].decode(t)},t.bytes=t.stringToBytes},e(t={exports:{}},t.exports),t.exports);const{bech32:n,hex:o,utf8:s}=r,i={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},a={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},c={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},h={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},l={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},u=["option_data_loss_protect","initial_routing_sync","option_upfront_shutdown_script","gossip_queries","var_onion_optin","gossip_queries_ex","option_static_remotekey","payment_secret","basic_mpp","option_support_large_channel"],f={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},d=BigInt("2100000000000000000"),p=BigInt(1e11),w={payment_hash:1,payment_secret:16,description:13,payee:19,description_hash:23,expiry:6,min_final_cltv_expiry:24,fallback_address:9,route_hint:3,feature_bits:5,metadata:27},y={};for(let e=0,t=Object.keys(w);e<t.length;e++){const r=t[e],n=w[t[e]].toString();y[n]=r}const m={1:e=>o.encode(n.fromWordsUnsafe(e)),16:e=>o.encode(n.fromWordsUnsafe(e)),13:e=>s.encode(n.fromWordsUnsafe(e)),19:e=>o.encode(n.fromWordsUnsafe(e)),23:e=>o.encode(n.fromWordsUnsafe(e)),27:e=>o.encode(n.fromWordsUnsafe(e)),6:b,24:b,3:function(e){const t=[];let r,s,i,a,c,h=n.fromWordsUnsafe(e);for(;h.length>0;)r=o.encode(h.slice(0,33)),s=o.encode(h.slice(33,41)),i=parseInt(o.encode(h.slice(41,45)),16),a=parseInt(o.encode(h.slice(45,49)),16),c=parseInt(o.encode(h.slice(49,51)),16),h=h.slice(51),t.push({pubkey:r,short_channel_id:s,fee_base_msat:i,fee_proportional_millionths:a,cltv_expiry_delta:c});return t},5:function(e){const t=e.slice().reverse().map(e=>[!!(1&e),!!(2&e),!!(4&e),!!(8&e),!!(16&e)]).reduce((e,t)=>e.concat(t),[]);for(;t.length<2*u.length;)t.push(!1);const r={};u.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*u.length);return r.extra_bits={start_bit:2*u.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function g(e){return t=>({tagCode:parseInt(e),words:n.encode("unknown",t,Number.MAX_SAFE_INTEGER)})}function b(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}const v=e=>Uint8Array.from(e.match(/.{1,2}/g).map(e=>parseInt(e,16))),E=e=>{if(!e)return null;try{const t=function(e,t){if("string"!=typeof e)throw new Error("Lightning Payment Request must be string");if("ln"!==e.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const r=[],s=n.decode(e,Number.MAX_SAFE_INTEGER);e=e.toLowerCase();const u=s.prefix;let v=s.words,E=e.slice(u.length+1),x=v.slice(-104);v=v.slice(0,-104);let A=u.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(A&&!A[2]&&(A=u.match(/^ln(\S+)$/)),!A)throw new Error("Not a proper lightning payment request");r.push({name:"lightning_network",letters:"ln"});const k=A[1];let $;switch(k){case i.bech32:$=i;break;case a.bech32:$=a;break;case c.bech32:$=c;break;case h.bech32:$=h;break;case l.bech32:$=l}if(!$||$.bech32!==k)throw new Error("Unknown coin bech32 prefix");r.push({name:"coin_network",letters:k,value:$});const _=A[2];let U;_?(U=function(e,t){let r,n;if(e.slice(-1).match(/^[munp]$/))r=e.slice(-1),n=e.slice(0,-1);else{if(e.slice(-1).match(/^[^munp0-9]$/))throw new Error("Not a valid multiplier for the amount");n=e}if(!n.match(/^\d+$/))throw new Error("Not a valid human readable amount");const o=BigInt(n),s=r?o*p/f[r]:o*p;if("p"===r&&o%BigInt(10)!==BigInt(0)||s>d)throw new Error("Amount is outside of valid range");return s.toString()}(_+A[3]),r.push({name:"amount",letters:A[2]+A[3],value:U})):U=null,r.push({name:"separator",letters:"1"});const L=b(v.slice(0,7));let D,N,I,S;for(v=v.slice(7),r.push({name:"timestamp",letters:E.slice(0,7),value:L}),E=E.slice(7);v.length>0;){const e=v[0].toString();D=y[e]||"unknown_tag",N=m[e]||g(e),v=v.slice(1),I=b(v.slice(0,2)),v=v.slice(2),S=v.slice(0,I),v=v.slice(I),r.push({name:D,tag:E[0],letters:E.slice(0,3+I),value:N(S)}),E=E.slice(3+I)}r.push({name:"signature",letters:E.slice(0,104),value:o.encode(n.fromWordsUnsafe(x))}),E=E.slice(104),r.push({name:"checksum",letters:E});let R={paymentRequest:e,sections:r,get expiry(){let e=r.find(e=>"expiry"===e.name);if(e)return P("timestamp")+e.value},get route_hints(){return r.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in w)"route_hint"!==e&&Object.defineProperty(R,e,{get:()=>P(e)});return R;function P(e){let t=r.find(t=>t.name===e);return t?t.value:void 0}}(e);if(!t||!t.sections)return null;const r=t.sections.find(e=>"payment_hash"===e.name);if("payment_hash"!==(null==r?void 0:r.name)||!r.value)return null;const s=r.value;let u=0;const v=t.sections.find(e=>"amount"===e.name);"amount"===(null==v?void 0:v.name)&&v.value&&(u=parseInt(v.value)/1e3);const E=t.sections.find(e=>"timestamp"===e.name);if("timestamp"!==(null==E?void 0:E.name)||!E.value)return null;const x=E.value;let A;const k=t.sections.find(e=>"expiry"===e.name);"expiry"===(null==k?void 0:k.name)&&(A=k.value);const $=t.sections.find(e=>"description"===e.name);return{paymentHash:s,satoshi:u,timestamp:x,expiry:A,description:"description"===(null==$?void 0:$.name)?null==$?void 0:$.value:void 0}}catch(e){return null}};function x(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}const A=e=>e instanceof Uint8Array,k=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),$=(e,t)=>e<<32-t|e>>>t;if(68!==new Uint8Array(new Uint32Array([287454020]).buffer)[0])throw new Error("Non little-endian hardware is not supported");const _=/* @__PURE__ */Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function U(e){if(!A(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=_[e[r]];return t}function L(e){if("string"==typeof e&&(e=function(e){if("string"!=typeof e)throw new Error("utf8ToBytes expected string, got "+typeof e);return new Uint8Array((new TextEncoder).encode(e))}(e)),!A(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class D{clone(){return this._cloneInto()}}function N(e){const t=t=>e().update(L(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class I extends D{constructor(e,t,r,n){super(),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(e),this.view=k(this.buffer)}update(e){x(this);const{view:t,buffer:r,blockLen:n}=this,o=(e=L(e)).length;for(let s=0;s<o;){const i=Math.min(n-this.pos,o-s);if(i!==n)r.set(e.subarray(s,s+i),this.pos),this.pos+=i,s+=i,this.pos===n&&(this.process(t,0),this.pos=0);else{const t=k(e);for(;n<=o-s;s+=n)this.process(t,s)}}return this.length+=e.length,this.roundClean(),this}digestInto(e){x(this),function(e,t){!function(e,...t){if(!(e instanceof Uint8Array))throw new Error("Expected Uint8Array");if(t.length>0&&!t.includes(e.length))throw new Error(`Expected Uint8Array of length ${t}, not of length=${e.length}`)}(e);const r=t.outputLen;if(e.length<r)throw new Error(`digestInto() expects output buffer of length at least ${r}`)}(e,this),this.finished=!0;const{buffer:t,view:r,blockLen:n,isLE:o}=this;let{pos:s}=this;t[s++]=128,this.buffer.subarray(s).fill(0),this.padOffset>n-s&&(this.process(r,0),s=0);for(let e=s;e<n;e++)t[e]=0;!function(e,t,r,n){if("function"==typeof e.setBigUint64)return e.setBigUint64(t,r,n);const o=BigInt(32),s=BigInt(4294967295),i=Number(r>>o&s),a=Number(r&s),c=n?0:4;e.setUint32(t+(n?4:0),i,n),e.setUint32(t+c,a,n)}(r,n-8,BigInt(8*this.length),o),this.process(r,0);const i=k(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const c=a/4,h=this.get();if(c>h.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<c;e++)i.setUint32(4*e,h[e],o)}digest(){const{buffer:e,outputLen:t}=this;this.digestInto(e);const r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());const{blockLen:t,buffer:r,length:n,finished:o,destroyed:s,pos:i}=this;return e.length=n,e.pos=i,e.finished=o,e.destroyed=s,n%t&&e.buffer.set(r),e}}const S=(e,t,r)=>e&t^e&r^t&r,R=/* @__PURE__ */new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),P=/* @__PURE__ */new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),T=/* @__PURE__ */new Uint32Array(64);class W extends I{constructor(){super(64,32,8,!1),this.A=0|P[0],this.B=0|P[1],this.C=0|P[2],this.D=0|P[3],this.E=0|P[4],this.F=0|P[5],this.G=0|P[6],this.H=0|P[7]}get(){const{A:e,B:t,C:r,D:n,E:o,F:s,G:i,H:a}=this;return[e,t,r,n,o,s,i,a]}set(e,t,r,n,o,s,i,a){this.A=0|e,this.B=0|t,this.C=0|r,this.D=0|n,this.E=0|o,this.F=0|s,this.G=0|i,this.H=0|a}process(e,t){for(let r=0;r<16;r++,t+=4)T[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=T[e-15],r=T[e-2],n=$(t,7)^$(t,18)^t>>>3,o=$(r,17)^$(r,19)^r>>>10;T[e]=o+T[e-7]+n+T[e-16]|0}let{A:r,B:n,C:o,D:s,E:i,F:a,G:c,H:h}=this;for(let e=0;e<64;e++){const t=h+($(i,6)^$(i,11)^$(i,25))+((l=i)&a^~l&c)+R[e]+T[e]|0,u=($(r,2)^$(r,13)^$(r,22))+S(r,n,o)|0;h=c,c=a,a=i,i=s+t|0,s=o,o=n,n=r,r=t+u|0}var l;r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,s=s+this.D|0,i=i+this.E|0,a=a+this.F|0,c=c+this.G|0,h=h+this.H|0,this.set(r,n,o,s,i,a,c,h)}roundClean(){T.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const B=/* @__PURE__ */N(()=>new W);class j{constructor(e){var t,r,n,o;if(this.paymentRequest=void 0,this.paymentHash=void 0,this.preimage=void 0,this.verify=void 0,this.satoshi=void 0,this.expiry=void 0,this.timestamp=void 0,this.createdDate=void 0,this.expiryDate=void 0,this.description=void 0,this.successAction=void 0,this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");const s=E(this.paymentRequest);if(!s)throw new Error("Failed to decode payment request");this.paymentHash=s.paymentHash,this.satoshi=s.satoshi,this.timestamp=s.timestamp,this.expiry=s.expiry,this.createdDate=new Date(1e3*this.timestamp),this.expiryDate=this.expiry?new Date(1e3*(this.timestamp+this.expiry)):void 0,this.description=null!=(t=s.description)?t:null,this.verify=null!=(r=e.verify)?r:null,this.preimage=null!=(n=e.preimage)?n:null,this.successAction=null!=(o=e.successAction)?o:null}async isPaid(){if(this.preimage)return this.validatePreimage(this.preimage);if(this.verify)return await this.verifyPayment();throw new Error("Could not verify payment")}validatePreimage(e){if(!e||!this.paymentHash)return!1;try{const t=U(B(v(e)));return this.paymentHash===t}catch(e){return!1}}async verifyPayment(){try{if(!this.verify)throw new Error("LNURL verify not available");const e=await fetch(this.verify);if(!e.ok)throw new Error(`Verification request failed: ${e.status} ${e.statusText}`);const t=await e.json();return t.preimage&&(this.preimage=t.preimage),t.settled}catch(e){return console.error("Failed to check LNURL-verify",e),!1}}hasExpired(){const{expiryDate:e}=this;return!!e&&e.getTime()<Date.now()}}const H=e=>{if("keysend"!==e.tag)throw new Error("Invalid keysend params");if("OK"!==e.status)throw new Error("Keysend status not OK");if(!e.pubkey)throw new Error("Pubkey does not exist");let t,r;return e.customData&&e.customData[0]&&(t=e.customData[0].customKey,r=e.customData[0].customValue),{destination:e.pubkey,customKey:t,customValue:r}};async function O({satoshi:e,comment:t,p:r,e:n,relays:o},s={}){const i=s.nostr||globalThis.nostr;if(!i)throw new Error("nostr option or window.nostr is not available");const a=[["relays",...o],["amount",e.toString()]];r&&a.push(["p",r]),n&&a.push(["e",n]);const c={pubkey:await i.getPublicKey(),created_at:Math.floor(Date.now()/1e3),kind:9734,tags:a,content:null!=t?t:""};return c.id=F(c),await i.signEvent(c)}function C(e){if("string"!=typeof e.content)return!1;if("number"!=typeof e.created_at)return!1;if(!Array.isArray(e.tags))return!1;for(let t=0;t<e.tags.length;t++){const r=e.tags[t];if(!Array.isArray(r))return!1;for(let e=0;e<r.length;e++)if("object"==typeof r[e])return!1}return!0}function K(e){if(!C(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function F(e){return U(B(K(e)))}function V(e,t){let r,n;var o,s;return t&&e&&(r=null==(o=e.names)?void 0:o[t],n=r?null==(s=e.relays)?void 0:s[r]:void 0),[e,r,n]}const q=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,z=e=>!!e&&q.test(e),M=({amount:e,min:t,max:r})=>e>0&&e>=t&&e<=r,G=async e=>{if("payRequest"!==e.tag)throw new Error("Invalid pay service params");const t=(e.callback+"").trim();if(!z(t))throw new Error("Callback must be a valid url");const r=Math.ceil(Number(e.minSendable||0)),n=Math.floor(Number(e.maxSendable));if(!r||!n||r>n)throw new Error("Invalid pay service params");let o,s;try{o=JSON.parse(e.metadata+""),s=U(B(e.metadata+""))}catch(e){o=[],s=U(B("[]"))}let i="",a="",c="",h="";for(let e=0;e<o.length;e++){const[t,r]=o[e];switch(t){case"text/plain":c=r;break;case"text/identifier":h=r;break;case"text/email":i=r;break;case"image/png;base64":case"image/jpeg;base64":a="data:"+t+","+r}}const l=e.payerData;let u;try{u=new URL(t).hostname}catch(e){}return{callback:t,fixed:r===n,min:r,max:n,domain:u,metadata:o,metadataHash:s,identifier:h,email:i,description:c,image:a,payerData:l,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1}};function J(){return J=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},J.apply(this,arguments)}const Z=async(e,t)=>{const{boost:r}=e;t||(t={});const n=t.webln||globalThis.webln;if(!n)throw new Error("WebLN not available");if(!n.keysend)throw new Error("Keysend not available in current WebLN provider");const o=e.amount||Math.floor(r.value_msat/1e3),s={destination:e.destination,amount:o,customRecords:{7629169:JSON.stringify(r)}};return e.customKey&&e.customValue&&(s.customRecords[e.customKey]=e.customValue),await n.enable(),await n.keysend(s)},X=/^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,Q="https://api.getalby.com/lnurl";class Y{constructor(e,t){this.address=void 0,this.options=void 0,this.username=void 0,this.domain=void 0,this.pubkey=void 0,this.lnurlpData=void 0,this.keysendData=void 0,this.nostrData=void 0,this.nostrPubkey=void 0,this.nostrRelays=void 0,this.webln=void 0,this.address=e,this.options={proxy:"https://api.getalby.com/lnurl"},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}parse(){const e=X.exec(this.address.toLowerCase());e&&(this.username=e[1],this.domain=e[2])}getWebLN(){return this.webln||globalThis.webln}async fetch(){return this.options.proxy?this.fetchWithProxy():this.fetchWithoutProxy()}async fetchWithProxy(){const e=await fetch(`${this.options.proxy}/lightning-address-details?${new URLSearchParams({ln:this.address}).toString()}`);if(!e.ok)throw new Error(`Failed to fetch lnurl info: ${e.status} ${e.statusText}`);const t=await e.json();await this.parseLnUrlPayResponse(t.lnurlp),this.parseKeysendResponse(t.keysend),this.parseNostrResponse(t.nostr)}async fetchWithoutProxy(){this.domain&&this.username&&await Promise.all([this.fetchLnurlData(),this.fetchKeysendData(),this.fetchNostrData()])}async fetchLnurlData(){const e=await fetch(this.lnurlpUrl());if(e.ok){const t=await e.json();await this.parseLnUrlPayResponse(t)}}async fetchKeysendData(){const e=await fetch(this.keysendUrl());if(e.ok){const t=await e.json();this.parseKeysendResponse(t)}}async fetchNostrData(){const e=await fetch(this.nostrUrl());if(e.ok){const t=await e.json();this.parseNostrResponse(t)}}lnurlpUrl(){return`https://${this.domain}/.well-known/lnurlp/${this.username}`}keysendUrl(){return`https://${this.domain}/.well-known/keysend/${this.username}`}nostrUrl(){return`https://${this.domain}/.well-known/nostr.json?name=${this.username}`}async generateInvoice(e){let t;if(this.options.proxy){const r=await fetch(`${this.options.proxy}/generate-invoice?${new URLSearchParams(J({ln:this.address},e)).toString()}`);if(!r.ok)throw new Error(`Failed to generate invoice: ${r.status} ${r.statusText}`);t=(await r.json()).invoice}else{if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!this.lnurlpData.callback||!z(this.lnurlpData.callback))throw new Error("Valid callback does not exist in lnurlpData");const r=new URL(this.lnurlpData.callback);r.search=new URLSearchParams(e).toString();const n=await fetch(r.toString());if(!n.ok)throw new Error(`Failed to generate invoice: ${n.status} ${n.statusText}`);t=await n.json()}const r=t&&t.pr&&t.pr.toString();if(!r)throw new Error("Invalid pay service invoice");const n={pr:r};if(t&&t.verify&&(n.verify=t.verify.toString()),t&&t.successAction&&"object"==typeof t.successAction){const{tag:e,message:r,description:o,url:s}=t.successAction;"message"===e?n.successAction={tag:e,message:r}:"url"===e&&(n.successAction={tag:e,description:o,url:s})}return new j(n)}async requestInvoice(e){if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");const t=1e3*e.satoshi,{commentAllowed:r,min:n,max:o}=this.lnurlpData;if(!M({amount:t,min:n,max:o}))throw new Error("Invalid amount");if(e.comment&&r&&r>0&&e.comment.length>r)throw new Error(`The comment length must be ${r} characters or fewer`);const s={amount:t.toString()};return e.comment&&(s.comment=e.comment),e.payerdata&&(s.payerdata=JSON.stringify(e.payerdata)),this.generateInvoice(s)}async boost(e,t=0){if(!this.keysendData)throw new Error("No keysendData available. Please call fetch() first.");const{destination:r,customKey:n,customValue:o}=this.keysendData,s=this.getWebLN();if(!s)throw new Error("WebLN not available");return Z({destination:r,customKey:n,customValue:o,amount:t,boost:e},{webln:s})}async zapInvoice({satoshi:e,comment:t,relays:r,e:n},o={}){if(!this.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!this.nostrPubkey)throw new Error("Nostr Pubkey is missing");const s=this.nostrPubkey,i=1e3*e,{allowsNostr:a,min:c,max:h}=this.lnurlpData;if(!M({amount:i,min:c,max:h}))throw new Error("Invalid amount");if(!a)throw new Error("Your provider does not support zaps");const l=await O({satoshi:i,comment:t,p:s,e:n,relays:r},o),u={amount:i.toString(),nostr:JSON.stringify(l)};return await this.generateInvoice(u)}async zap(e,t={}){const r=this.zapInvoice(e,t),n=this.getWebLN();if(!n)throw new Error("WebLN not available");return await n.enable(),n.sendPayment((await r).paymentRequest)}async parseLnUrlPayResponse(e){e&&(this.lnurlpData=await G(e))}parseKeysendResponse(e){e&&(this.keysendData=H(e))}parseNostrResponse(e){e&&([this.nostrData,this.nostrPubkey,this.nostrRelays]=V(e,this.username))}}class ee{constructor(e){this.storage=void 0,this.storage=e||{}}getItem(e){return this.storage[e]}setItem(e,t){this.storage[e]=t}}class te{constructor(e){}getItem(e){return null}setItem(e,t){}}const re=e=>{const t=e.replace("L402","").replace("LSAT","").trim(),r={},n=/(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;let o;for(;null!==(o=n.exec(t));)r[o[1]]=o[3]||o[4]||o[5];return r},ne=new ee,oe=async(e,t,r)=>{r||(r={});const n=r.headerKey||"L402",o=r.webln||globalThis.webln;if(!o)throw new Error("WebLN is missing");const s=r.store||ne;t||(t={}),t.cache="no-store",t.mode="cors",t.headers||(t.headers={});const i=s.getItem(e);if(i){const r=JSON.parse(i);return t.headers.Authorization=`${n} ${r.token}:${r.preimage}`,await fetch(e,t)}t.headers["Accept-Authenticate"]=n;const a=await fetch(e,t),c=a.headers.get("www-authenticate");if(!c)return a;const h=re(c),l=h.token||h.macaroon,u=h.invoice;await o.enable();const f=await o.sendPayment(u);return s.setItem(e,JSON.stringify({token:l,preimage:f.preimage})),t.headers.Authorization=`${n} ${l}:${f.preimage}`,await fetch(e,t)};var se={__proto__:null,fetchWithL402:oe,MemoryStorage:ee,NoStorage:te,parseL402:re};const ie=async e=>{const t="https://getalby.com/api/rates/"+e.toLowerCase()+".json",r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch rate: ${r.status} ${r.statusText}`);return(await r.json()).rate_float/1e8},ae=async({satoshi:e,currency:t})=>{const r=await ie(t);return Number(e)*r},ce=async({amount:e,currency:t})=>{const r=await ie(t);return Math.floor(Number(e)/r)},he=async({satoshi:e,currency:t,locale:r})=>(r||(r="en"),(await ae({satoshi:e,currency:t})).toLocaleString(r,{style:"currency",currency:t}));var le={__proto__:null,getFiatBtcRate:ie,getFiatValue:ae,getSatoshiValue:ce,getFormattedFiatValue:he};export{Q as DEFAULT_PROXY,j as Invoice,X as LN_ADDRESS_REGEX,Y as LightningAddress,ee as MemoryStorage,te as NoStorage,E as decodeInvoice,oe as fetchWithL402,le as fiat,v as fromHexString,O as generateZapEvent,F as getEventHash,ie as getFiatBtcRate,ae as getFiatValue,he as getFormattedFiatValue,ce as getSatoshiValue,z as isUrl,M as isValidAmount,se as l402,H as parseKeysendResponse,re as parseL402,G as parseLnUrlPayResponse,V as parseNostrResponse,Z as sendBoostagram,K as serializeEvent,C as validateEvent};
var e,t,r=(e=function(e,t){function r(e){if(!Number.isSafeInteger(e))throw new Error(`Wrong integer: ${e}`)}function n(...e){const t=(e,t)=>r=>e(t(r));return{encode:Array.from(e).reverse().reduce((e,r)=>e?t(e,r.encode):r.encode,void 0),decode:e.reduce((e,r)=>e?t(e,r.decode):r.decode,void 0)}}function o(e){return{encode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("alphabet.encode input should be an array of numbers");return t.map(t=>{if(r(t),t<0||t>=e.length)throw new Error(`Digit index outside alphabet: ${t} (alphabet: ${e.length})`);return e[t]})},decode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("alphabet.decode input should be array of strings");return t.map(t=>{if("string"!=typeof t)throw new Error(`alphabet.decode: not string element=${t}`);const r=e.indexOf(t);if(-1===r)throw new Error(`Unknown letter: "${t}". Allowed: ${e}`);return r})}}}function i(e=""){if("string"!=typeof e)throw new Error("join separator should be string");return{encode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("join.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`join.encode: non-string input=${e}`);return t.join(e)},decode:t=>{if("string"!=typeof t)throw new Error("join.decode input should be string");return t.split(e)}}}function s(e,t="="){if(r(e),"string"!=typeof t)throw new Error("padding chr should be string");return{encode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.encode: non-string input=${e}`);for(;r.length*e%8;)r.push(t);return r},decode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.decode: non-string input=${e}`);let n=r.length;if(n*e%8)throw new Error("Invalid padding: string should have whole number of bytes");for(;n>0&&r[n-1]===t;n--)if(!((n-1)*e%8))throw new Error("Invalid padding: string has too much padding");return r.slice(0,n)}}}function a(e){if("function"!=typeof e)throw new Error("normalize fn should be function");return{encode:e=>e,decode:t=>e(t)}}function c(e,t,n){if(t<2)throw new Error(`convertRadix: wrong from=${t}, base cannot be less than 2`);if(n<2)throw new Error(`convertRadix: wrong to=${n}, base cannot be less than 2`);if(!Array.isArray(e))throw new Error("convertRadix: data should be array");if(!e.length)return[];let o=0;const i=[],s=Array.from(e);for(s.forEach(e=>{if(r(e),e<0||e>=t)throw new Error(`Wrong integer: ${e}`)});;){let e=0,r=!0;for(let i=o;i<s.length;i++){const a=s[i],c=t*e+a;if(!Number.isSafeInteger(c)||t*e/t!==e||c-a!=t*e)throw new Error("convertRadix: carry overflow");if(e=c%n,s[i]=Math.floor(c/n),!Number.isSafeInteger(s[i])||s[i]*n+e!==c)throw new Error("convertRadix: carry overflow");r&&(s[i]?r=!1:o=i)}if(i.push(e),r)break}for(let t=0;t<e.length-1&&0===e[t];t++)i.push(0);return i.reverse()}Object.defineProperty(t,"__esModule",{value:!0}),t.bytes=t.stringToBytes=t.str=t.bytesToString=t.hex=t.utf8=t.bech32m=t.bech32=t.base58check=t.base58xmr=t.base58xrp=t.base58flickr=t.base58=t.base64url=t.base64=t.base32crockford=t.base32hex=t.base32=t.base16=t.utils=t.assertNumber=void 0,t.assertNumber=r;const u=(e,t)=>t?u(t,e%t):e,h=(e,t)=>e+(t-u(e,t));function l(e,t,n,o){if(!Array.isArray(e))throw new Error("convertRadix2: data should be array");if(t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(n<=0||n>32)throw new Error(`convertRadix2: wrong to=${n}`);if(h(t,n)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${n} carryBits=${h(t,n)}`);let i=0,s=0;const a=2**n-1,c=[];for(const o of e){if(r(o),o>=2**t)throw new Error(`convertRadix2: invalid data word=${o} from=${t}`);if(i=i<<t|o,s+t>32)throw new Error(`convertRadix2: carry overflow pos=${s} from=${t}`);for(s+=t;s>=n;s-=n)c.push((i>>s-n&a)>>>0);i&=2**s-1}if(i=i<<n-s&a,!o&&s>=t)throw new Error("Excess padding");if(!o&&i)throw new Error(`Non-zero padding: ${i}`);return o&&s>0&&c.push(i>>>0),c}function f(e){return r(e),{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix.encode input should be Uint8Array");return c(Array.from(t),256,e)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix.decode input should be array of strings");return Uint8Array.from(c(t,e,256))}}}function d(e,t=!1){if(r(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(h(8,e)>32||h(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!(r instanceof Uint8Array))throw new Error("radix2.encode input should be Uint8Array");return l(Array.from(r),8,e,!t)},decode:r=>{if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("radix2.decode input should be array of strings");return Uint8Array.from(l(r,e,8,t))}}}function p(e){if("function"!=typeof e)throw new Error("unsafeWrapper fn should be function");return function(...t){try{return e.apply(null,t)}catch(e){}}}function m(e,t){if(r(e),"function"!=typeof t)throw new Error("checksum fn should be function");return{encode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.encode: input should be Uint8Array");const n=t(r).slice(0,e),o=new Uint8Array(r.length+e);return o.set(r),o.set(n,r.length),o},decode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.decode: input should be Uint8Array");const n=r.slice(0,-e),o=t(n).slice(0,e),i=r.slice(-e);for(let t=0;t<e;t++)if(o[t]!==i[t])throw new Error("Invalid checksum");return n}}}t.utils={alphabet:o,chain:n,checksum:m,radix:f,radix2:d,join:i,padding:s},t.base16=n(d(4),o("0123456789ABCDEF"),i("")),t.base32=n(d(5),o("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),s(5),i("")),t.base32hex=n(d(5),o("0123456789ABCDEFGHIJKLMNOPQRSTUV"),s(5),i("")),t.base32crockford=n(d(5),o("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),i(""),a(e=>e.toUpperCase().replace(/O/g,"0").replace(/[IL]/g,"1"))),t.base64=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),s(6),i("")),t.base64url=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),s(6),i(""));const y=e=>n(f(58),o(e),i(""));t.base58=y("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"),t.base58flickr=y("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"),t.base58xrp=y("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");const w=[0,2,3,5,6,7,9,10,11];t.base58xmr={encode(e){let r="";for(let n=0;n<e.length;n+=8){const o=e.subarray(n,n+8);r+=t.base58.encode(o).padStart(w[o.length],"1")}return r},decode(e){let r=[];for(let n=0;n<e.length;n+=11){const o=e.slice(n,n+11),i=w.indexOf(o.length),s=t.base58.decode(o);for(let e=0;e<s.length-i;e++)if(0!==s[e])throw new Error("base58xmr: wrong padding");r=r.concat(Array.from(s.slice(s.length-i)))}return Uint8Array.from(r)}},t.base58check=e=>n(m(4,t=>e(e(t))),t.base58);const g=n(o("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),i("")),v=[996825010,642813549,513874426,1027748829,705979059];function b(e){const t=e>>25;let r=(33554431&e)<<5;for(let e=0;e<v.length;e++)1==(t>>e&1)&&(r^=v[e]);return r}function E(e,t,r=1){const n=e.length;let o=1;for(let t=0;t<n;t++){const r=e.charCodeAt(t);if(r<33||r>126)throw new Error(`Invalid prefix (${e})`);o=b(o)^r>>5}o=b(o);for(let t=0;t<n;t++)o=b(o)^31&e.charCodeAt(t);for(let e of t)o=b(o)^e;for(let e=0;e<6;e++)o=b(o);return o^=r,g.encode(l([o%2**30],30,5,!1))}function x(e){const t="bech32"===e?1:734539939,r=d(5),n=r.decode,o=r.encode,i=p(n);function s(e,r=90){if("string"!=typeof e)throw new Error("bech32.decode input should be string, not "+typeof e);if(e.length<8||!1!==r&&e.length>r)throw new TypeError(`Wrong string length: ${e.length} (${e}). Expected (8..${r})`);const n=e.toLowerCase();if(e!==n&&e!==e.toUpperCase())throw new Error("String must be lowercase or uppercase");const o=(e=n).lastIndexOf("1");if(0===o||-1===o)throw new Error('Letter "1" must be present between prefix and data only');const i=e.slice(0,o),s=e.slice(o+1);if(s.length<6)throw new Error("Data must be at least 6 characters long");const a=g.decode(s).slice(0,-6),c=E(i,a,t);if(!s.endsWith(c))throw new Error(`Invalid checksum in ${e}: expected "${c}"`);return{prefix:i,words:a}}return{encode:function(e,r,n=90){if("string"!=typeof e)throw new Error("bech32.encode prefix should be string, not "+typeof e);if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("bech32.encode words should be array of numbers, not "+typeof r);const o=e.length+7+r.length;if(!1!==n&&o>n)throw new TypeError(`Length ${o} exceeds limit ${n}`);return`${e=e.toLowerCase()}1${g.encode(r)}${E(e,r,t)}`},decode:s,decodeToBytes:function(e){const{prefix:t,words:r}=s(e,!1);return{prefix:t,words:r,bytes:n(r)}},decodeUnsafe:p(s),fromWords:n,fromWordsUnsafe:i,toWords:o}}t.bech32=x("bech32"),t.bech32m=x("bech32m"),t.utf8={encode:e=>(new TextDecoder).decode(e),decode:e=>(new TextEncoder).encode(e)},t.hex=n(d(4),o("0123456789abcdef"),i(""),a(e=>{if("string"!=typeof e||e.length%2)throw new TypeError(`hex.decode: expected string, got ${typeof e} with length ${e.length}`);return e.toLowerCase()}));const P={utf8:t.utf8,hex:t.hex,base16:t.base16,base32:t.base32,base64:t.base64,base64url:t.base64url,base58:t.base58,base58xmr:t.base58xmr},A=`Invalid encoding type. Available types: ${Object.keys(P).join(", ")}`;t.bytesToString=(e,t)=>{if("string"!=typeof e||!P.hasOwnProperty(e))throw new TypeError(A);if(!(t instanceof Uint8Array))throw new TypeError("bytesToString() expects Uint8Array");return P[e].encode(t)},t.str=t.bytesToString,t.stringToBytes=(e,t)=>{if(!P.hasOwnProperty(e))throw new TypeError(A);if("string"!=typeof t)throw new TypeError("stringToBytes() expects string");return P[e].decode(t)},t.bytes=t.stringToBytes},e(t={exports:{}},t.exports),t.exports);const{bech32:n,hex:o,utf8:i}=r,s={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},a={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},c={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},u={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},h={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},l=["option_data_loss_protect","initial_routing_sync","option_upfront_shutdown_script","gossip_queries","var_onion_optin","gossip_queries_ex","option_static_remotekey","payment_secret","basic_mpp","option_support_large_channel"],f={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},d=BigInt("2100000000000000000"),p=BigInt(1e11),m={payment_hash:1,payment_secret:16,description:13,payee:19,description_hash:23,expiry:6,min_final_cltv_expiry:24,fallback_address:9,route_hint:3,feature_bits:5,metadata:27},y={};for(let e=0,t=Object.keys(m);e<t.length;e++){const r=t[e],n=m[t[e]].toString();y[n]=r}const w={1:e=>o.encode(n.fromWordsUnsafe(e)),16:e=>o.encode(n.fromWordsUnsafe(e)),13:e=>i.encode(n.fromWordsUnsafe(e)),19:e=>o.encode(n.fromWordsUnsafe(e)),23:e=>o.encode(n.fromWordsUnsafe(e)),27:e=>o.encode(n.fromWordsUnsafe(e)),6:v,24:v,3:function(e){const t=[];let r,i,s,a,c,u=n.fromWordsUnsafe(e);for(;u.length>0;)r=o.encode(u.slice(0,33)),i=o.encode(u.slice(33,41)),s=parseInt(o.encode(u.slice(41,45)),16),a=parseInt(o.encode(u.slice(45,49)),16),c=parseInt(o.encode(u.slice(49,51)),16),u=u.slice(51),t.push({pubkey:r,short_channel_id:i,fee_base_msat:s,fee_proportional_millionths:a,cltv_expiry_delta:c});return t},5:function(e){const t=e.slice().reverse().map(e=>[!!(1&e),!!(2&e),!!(4&e),!!(8&e),!!(16&e)]).reduce((e,t)=>e.concat(t),[]);for(;t.length<2*l.length;)t.push(!1);const r={};l.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*l.length);return r.extra_bits={start_bit:2*l.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function g(e){return t=>({tagCode:parseInt(e),words:n.encode("unknown",t,Number.MAX_SAFE_INTEGER)})}function v(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}var b=function(e){return Uint8Array.from(e.match(/.{1,2}/g).map(function(e){return parseInt(e,16)}))},E=function(e){if(!e)return null;try{var t=function(e,t){if("string"!=typeof e)throw new Error("Lightning Payment Request must be string");if("ln"!==e.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const r=[],i=n.decode(e,Number.MAX_SAFE_INTEGER);e=e.toLowerCase();const l=i.prefix;let b=i.words,E=e.slice(l.length+1),x=b.slice(-104);b=b.slice(0,-104);let P=l.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(P&&!P[2]&&(P=l.match(/^ln(\S+)$/)),!P)throw new Error("Not a proper lightning payment request");r.push({name:"lightning_network",letters:"ln"});const A=P[1];let k;switch(A){case s.bech32:k=s;break;case a.bech32:k=a;break;case c.bech32:k=c;break;case u.bech32:k=u;break;case h.bech32:k=h}if(!k||k.bech32!==A)throw new Error("Unknown coin bech32 prefix");r.push({name:"coin_network",letters:A,value:k});const _=P[2];let U;_?(U=function(e,t){let r,n;if(e.slice(-1).match(/^[munp]$/))r=e.slice(-1),n=e.slice(0,-1);else{if(e.slice(-1).match(/^[^munp0-9]$/))throw new Error("Not a valid multiplier for the amount");n=e}if(!n.match(/^\d+$/))throw new Error("Not a valid human readable amount");const o=BigInt(n),i=r?o*p/f[r]:o*p;if("p"===r&&o%BigInt(10)!==BigInt(0)||i>d)throw new Error("Amount is outside of valid range");return i.toString()}(_+P[3]),r.push({name:"amount",letters:P[2]+P[3],value:U})):U=null,r.push({name:"separator",letters:"1"});const L=v(b.slice(0,7));let D,N,I,j;for(b=b.slice(7),r.push({name:"timestamp",letters:E.slice(0,7),value:L}),E=E.slice(7);b.length>0;){const e=b[0].toString();D=y[e]||"unknown_tag",N=w[e]||g(e),b=b.slice(1),I=v(b.slice(0,2)),b=b.slice(2),j=b.slice(0,I),b=b.slice(I),r.push({name:D,tag:E[0],letters:E.slice(0,3+I),value:N(j)}),E=E.slice(3+I)}r.push({name:"signature",letters:E.slice(0,104),value:o.encode(n.fromWordsUnsafe(x))}),E=E.slice(104),r.push({name:"checksum",letters:E});let S={paymentRequest:e,sections:r,get expiry(){let e=r.find(e=>"expiry"===e.name);if(e)return R("timestamp")+e.value},get route_hints(){return r.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in m)"route_hint"!==e&&Object.defineProperty(S,e,{get:()=>R(e)});return S;function R(e){let t=r.find(t=>t.name===e);return t?t.value:void 0}}(e);if(!t||!t.sections)return null;var r=t.sections.find(function(e){return"payment_hash"===e.name});if("payment_hash"!==(null==r?void 0:r.name)||!r.value)return null;var i=r.value,l=0,b=t.sections.find(function(e){return"amount"===e.name});"amount"===(null==b?void 0:b.name)&&b.value&&(l=parseInt(b.value)/1e3);var E=t.sections.find(function(e){return"timestamp"===e.name});if("timestamp"!==(null==E?void 0:E.name)||!E.value)return null;var x,P=E.value,A=t.sections.find(function(e){return"expiry"===e.name});"expiry"===(null==A?void 0:A.name)&&(x=A.value);var k=t.sections.find(function(e){return"description"===e.name});return{paymentHash:i,satoshi:l,timestamp:P,expiry:x,description:"description"===(null==k?void 0:k.name)?null==k?void 0:k.value:void 0}}catch(e){return null}};function x(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}const P=e=>e instanceof Uint8Array,A=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),k=(e,t)=>e<<32-t|e>>>t;if(68!==new Uint8Array(new Uint32Array([287454020]).buffer)[0])throw new Error("Non little-endian hardware is not supported");const _=/* @__PURE__ */Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function U(e){if(!P(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=_[e[r]];return t}function L(e){if("string"==typeof e&&(e=function(e){if("string"!=typeof e)throw new Error("utf8ToBytes expected string, got "+typeof e);return new Uint8Array((new TextEncoder).encode(e))}(e)),!P(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class D{clone(){return this._cloneInto()}}function N(e){const t=t=>e().update(L(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class I extends D{constructor(e,t,r,n){super(),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(e),this.view=A(this.buffer)}update(e){x(this);const{view:t,buffer:r,blockLen:n}=this,o=(e=L(e)).length;for(let i=0;i<o;){const s=Math.min(n-this.pos,o-i);if(s!==n)r.set(e.subarray(i,i+s),this.pos),this.pos+=s,i+=s,this.pos===n&&(this.process(t,0),this.pos=0);else{const t=A(e);for(;n<=o-i;i+=n)this.process(t,i)}}return this.length+=e.length,this.roundClean(),this}digestInto(e){x(this),function(e,t){!function(e,...t){if(!(e instanceof Uint8Array))throw new Error("Expected Uint8Array");if(t.length>0&&!t.includes(e.length))throw new Error(`Expected Uint8Array of length ${t}, not of length=${e.length}`)}(e);const r=t.outputLen;if(e.length<r)throw new Error(`digestInto() expects output buffer of length at least ${r}`)}(e,this),this.finished=!0;const{buffer:t,view:r,blockLen:n,isLE:o}=this;let{pos:i}=this;t[i++]=128,this.buffer.subarray(i).fill(0),this.padOffset>n-i&&(this.process(r,0),i=0);for(let e=i;e<n;e++)t[e]=0;!function(e,t,r,n){if("function"==typeof e.setBigUint64)return e.setBigUint64(t,r,n);const o=BigInt(32),i=BigInt(4294967295),s=Number(r>>o&i),a=Number(r&i),c=n?0:4;e.setUint32(t+(n?4:0),s,n),e.setUint32(t+c,a,n)}(r,n-8,BigInt(8*this.length),o),this.process(r,0);const s=A(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const c=a/4,u=this.get();if(c>u.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<c;e++)s.setUint32(4*e,u[e],o)}digest(){const{buffer:e,outputLen:t}=this;this.digestInto(e);const r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());const{blockLen:t,buffer:r,length:n,finished:o,destroyed:i,pos:s}=this;return e.length=n,e.pos=s,e.finished=o,e.destroyed=i,n%t&&e.buffer.set(r),e}}const j=(e,t,r)=>e&t^e&r^t&r,S=/* @__PURE__ */new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),R=/* @__PURE__ */new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),$=/* @__PURE__ */new Uint32Array(64);class T extends I{constructor(){super(64,32,8,!1),this.A=0|R[0],this.B=0|R[1],this.C=0|R[2],this.D=0|R[3],this.E=0|R[4],this.F=0|R[5],this.G=0|R[6],this.H=0|R[7]}get(){const{A:e,B:t,C:r,D:n,E:o,F:i,G:s,H:a}=this;return[e,t,r,n,o,i,s,a]}set(e,t,r,n,o,i,s,a){this.A=0|e,this.B=0|t,this.C=0|r,this.D=0|n,this.E=0|o,this.F=0|i,this.G=0|s,this.H=0|a}process(e,t){for(let r=0;r<16;r++,t+=4)$[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=$[e-15],r=$[e-2],n=k(t,7)^k(t,18)^t>>>3,o=k(r,17)^k(r,19)^r>>>10;$[e]=o+$[e-7]+n+$[e-16]|0}let{A:r,B:n,C:o,D:i,E:s,F:a,G:c,H:u}=this;for(let e=0;e<64;e++){const t=u+(k(s,6)^k(s,11)^k(s,25))+((h=s)&a^~h&c)+S[e]+$[e]|0,l=(k(r,2)^k(r,13)^k(r,22))+j(r,n,o)|0;u=c,c=a,a=s,s=i+t|0,i=o,o=n,n=r,r=t+l|0}var h;r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,i=i+this.D|0,s=s+this.E|0,a=a+this.F|0,c=c+this.G|0,u=u+this.H|0,this.set(r,n,o,i,s,a,c,u)}roundClean(){$.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const W=/* @__PURE__ */N(()=>new T);var B=/*#__PURE__*/function(){function e(e){var t,r,n,o;if(this.paymentRequest=void 0,this.paymentHash=void 0,this.preimage=void 0,this.verify=void 0,this.satoshi=void 0,this.expiry=void 0,this.timestamp=void 0,this.createdDate=void 0,this.expiryDate=void 0,this.description=void 0,this.successAction=void 0,this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");var i=E(this.paymentRequest);if(!i)throw new Error("Failed to decode payment request");this.paymentHash=i.paymentHash,this.satoshi=i.satoshi,this.timestamp=i.timestamp,this.expiry=i.expiry,this.createdDate=new Date(1e3*this.timestamp),this.expiryDate=this.expiry?new Date(1e3*(this.timestamp+this.expiry)):void 0,this.description=null!=(t=i.description)?t:null,this.verify=null!=(r=e.verify)?r:null,this.preimage=null!=(n=e.preimage)?n:null,this.successAction=null!=(o=e.successAction)?o:null}var t=e.prototype;return t.isPaid=function(){try{var e=this;if(e.preimage)return Promise.resolve(e.validatePreimage(e.preimage));if(e.verify)return Promise.resolve(e.verifyPayment());throw new Error("Could not verify payment")}catch(e){return Promise.reject(e)}},t.validatePreimage=function(e){if(!e||!this.paymentHash)return!1;try{var t=U(W(b(e)));return this.paymentHash===t}catch(e){return!1}},t.verifyPayment=function(){try{var e=this;return Promise.resolve(function(t,r){try{var n=function(){if(!e.verify)throw new Error("LNURL verify not available");return Promise.resolve(fetch(e.verify)).then(function(t){if(!t.ok)throw new Error("Verification request failed: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return t.preimage&&(e.preimage=t.preimage),t.settled})})}()}catch(e){return r(e)}return n&&n.then?n.then(void 0,r):n}(0,function(e){return console.error("Failed to check LNURL-verify",e),!1}))}catch(e){return Promise.reject(e)}},t.hasExpired=function(){var e=this.expiryDate;return!!e&&e.getTime()<Date.now()},e}(),H=function(e,t){var r=e.satoshi,n=e.comment,o=e.p,i=e.e,s=e.relays;void 0===t&&(t={});try{var a=t.nostr||globalThis.nostr;if(!a)throw new Error("nostr option or window.nostr is not available");var c=[["relays"].concat(s),["amount",r.toString()]];return o&&c.push(["p",o]),i&&c.push(["e",i]),Promise.resolve(a.getPublicKey()).then(function(e){var t={pubkey:e,created_at:Math.floor(Date.now()/1e3),kind:9734,tags:c,content:null!=n?n:""};return t.id=F(t),Promise.resolve(a.signEvent(t))})}catch(i){return Promise.reject(i)}},O=function(e){if("keysend"!==e.tag)throw new Error("Invalid keysend params");if("OK"!==e.status)throw new Error("Keysend status not OK");if(!e.pubkey)throw new Error("Pubkey does not exist");var t,r;return e.customData&&e.customData[0]&&(t=e.customData[0].customKey,r=e.customData[0].customValue),{destination:e.pubkey,customKey:t,customValue:r}};function C(e){if("string"!=typeof e.content)return!1;if("number"!=typeof e.created_at)return!1;if(!Array.isArray(e.tags))return!1;for(var t=0;t<e.tags.length;t++){var r=e.tags[t];if(!Array.isArray(r))return!1;for(var n=0;n<r.length;n++)if("object"==typeof r[n])return!1}return!0}function K(e){if(!C(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function F(e){return U(W(K(e)))}function V(e,t){var r,n,o,i;return t&&e&&(n=(r=null==(o=e.names)?void 0:o[t])?null==(i=e.relays)?void 0:i[r]:void 0),[e,r,n]}var q=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,z=function(e){return!!e&&q.test(e)},M=function(e){var t=e.amount;return t>0&&t>=e.min&&t<=e.max},G=function(e){try{if("payRequest"!==e.tag)throw new Error("Invalid pay service params");var t=(e.callback+"").trim();if(!z(t))throw new Error("Callback must be a valid url");var r,n,o=Math.ceil(Number(e.minSendable||0)),i=Math.floor(Number(e.maxSendable));if(!o||!i||o>i)throw new Error("Invalid pay service params");try{r=JSON.parse(e.metadata+""),n=U(W(e.metadata+""))}catch(e){r=[],n=U(W("[]"))}for(var s="",a="",c="",u="",h=0;h<r.length;h++){var l=r[h],f=l[0],d=l[1];switch(f){case"text/plain":c=d;break;case"text/identifier":u=d;break;case"text/email":s=d;break;case"image/png;base64":case"image/jpeg;base64":a="data:"+f+","+d}}var p,m=e.payerData;try{p=new URL(t).hostname}catch(e){}return Promise.resolve({callback:t,fixed:o===i,min:o,max:i,domain:p,metadata:r,metadataHash:n,identifier:u,email:s,description:c,image:a,payerData:m,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1})}catch(e){return Promise.reject(e)}};function J(){return J=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},J.apply(this,arguments)}var Z=function(e,t){try{var r=e.boost;t||(t={});var n=t.webln||globalThis.webln;if(!n)throw new Error("WebLN not available");if(!n.keysend)throw new Error("Keysend not available in current WebLN provider");var o=e.amount||Math.floor(r.value_msat/1e3),i={destination:e.destination,amount:o,customRecords:{7629169:JSON.stringify(r)}};return e.customKey&&e.customValue&&(i.customRecords[e.customKey]=e.customValue),Promise.resolve(n.enable()).then(function(){return Promise.resolve(n.keysend(i))})}catch(e){return Promise.reject(e)}},X=/^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,Q="https://api.getalby.com/lnurl",Y=/*#__PURE__*/function(){function e(e,t){this.address=void 0,this.options=void 0,this.username=void 0,this.domain=void 0,this.pubkey=void 0,this.lnurlpData=void 0,this.keysendData=void 0,this.nostrData=void 0,this.nostrPubkey=void 0,this.nostrRelays=void 0,this.webln=void 0,this.address=e,this.options={proxy:"https://api.getalby.com/lnurl"},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}var t=e.prototype;return t.parse=function(){var e=X.exec(this.address.toLowerCase());e&&(this.username=e[1],this.domain=e[2])},t.getWebLN=function(){return this.webln||globalThis.webln},t.fetch=function(){try{var e=this;return Promise.resolve(e.options.proxy?e.fetchWithProxy():e.fetchWithoutProxy())}catch(e){return Promise.reject(e)}},t.fetchWithProxy=function(){try{var e=this;return Promise.resolve(fetch(e.options.proxy+"/lightning-address-details?"+new URLSearchParams({ln:e.address}).toString())).then(function(t){if(!t.ok)throw new Error("Failed to fetch lnurl info: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t.lnurlp)).then(function(){e.parseKeysendResponse(t.keysend),e.parseNostrResponse(t.nostr)})})})}catch(e){return Promise.reject(e)}},t.fetchWithoutProxy=function(){try{var e=this;return e.domain&&e.username?Promise.resolve(Promise.all([e.fetchLnurlData(),e.fetchKeysendData(),e.fetchNostrData()])).then(function(){}):Promise.resolve()}catch(e){return Promise.reject(e)}},t.fetchLnurlData=function(){try{var e=this;return Promise.resolve(fetch(e.lnurlpUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t)).then(function(){})})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchKeysendData=function(){try{var e=this;return Promise.resolve(fetch(e.keysendUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseKeysendResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchNostrData=function(){try{var e=this;return Promise.resolve(fetch(e.nostrUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseNostrResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.lnurlpUrl=function(){return"https://"+this.domain+"/.well-known/lnurlp/"+this.username},t.keysendUrl=function(){return"https://"+this.domain+"/.well-known/keysend/"+this.username},t.nostrUrl=function(){return"https://"+this.domain+"/.well-known/nostr.json?name="+this.username},t.generateInvoice=function(e){try{var t,r=function(e){var r=t&&t.pr&&t.pr.toString();if(!r)throw new Error("Invalid pay service invoice");var n={pr:r};if(t&&t.verify&&(n.verify=t.verify.toString()),t&&t.successAction&&"object"==typeof t.successAction){var o=t.successAction,i=o.tag,s=o.description,a=o.url;"message"===i?n.successAction={tag:i,message:o.message}:"url"===i&&(n.successAction={tag:i,description:s,url:a})}return new B(n)},n=this,o=function(){if(n.options.proxy)return Promise.resolve(fetch(n.options.proxy+"/generate-invoice?"+new URLSearchParams(J({ln:n.address},e)).toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e.invoice})});if(!n.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!n.lnurlpData.callback||!z(n.lnurlpData.callback))throw new Error("Valid callback does not exist in lnurlpData");var r=new URL(n.lnurlpData.callback);return r.search=new URLSearchParams(e).toString(),Promise.resolve(fetch(r.toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e})})}();return Promise.resolve(o&&o.then?o.then(r):r())}catch(e){return Promise.reject(e)}},t.requestInvoice=function(e){try{var t=this;if(!t.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");var r=1e3*e.satoshi,n=t.lnurlpData,o=n.commentAllowed;if(!M({amount:r,min:n.min,max:n.max}))throw new Error("Invalid amount");if(e.comment&&o&&o>0&&e.comment.length>o)throw new Error("The comment length must be "+o+" characters or fewer");var i={amount:r.toString()};return e.comment&&(i.comment=e.comment),e.payerdata&&(i.payerdata=JSON.stringify(e.payerdata)),Promise.resolve(t.generateInvoice(i))}catch(e){return Promise.reject(e)}},t.boost=function(e,t){void 0===t&&(t=0);try{var r=this;if(!r.keysendData)throw new Error("No keysendData available. Please call fetch() first.");var n=r.keysendData,o=n.destination,i=n.customKey,s=n.customValue,a=r.getWebLN();if(!a)throw new Error("WebLN not available");return Promise.resolve(Z({destination:o,customKey:i,customValue:s,amount:t,boost:e},{webln:a}))}catch(e){return Promise.reject(e)}},t.zapInvoice=function(e,t){var r=e.satoshi,n=e.comment,o=e.relays,i=e.e;void 0===t&&(t={});try{var s=this;if(!s.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!s.nostrPubkey)throw new Error("Nostr Pubkey is missing");var a=s.nostrPubkey,c=1e3*r,u=s.lnurlpData,h=u.allowsNostr;if(!M({amount:c,min:u.min,max:u.max}))throw new Error("Invalid amount");if(!h)throw new Error("Your provider does not support zaps");return Promise.resolve(H({satoshi:c,comment:n,p:a,e:i,relays:o},t)).then(function(e){var t={amount:c.toString(),nostr:JSON.stringify(e)};return Promise.resolve(s.generateInvoice(t))})}catch(i){return Promise.reject(i)}},t.zap=function(e,t){void 0===t&&(t={});try{var r=this.zapInvoice(e,t),n=this.getWebLN();if(!n)throw new Error("WebLN not available");return Promise.resolve(n.enable()).then(function(){var e=n.sendPayment;return Promise.resolve(r).then(function(t){return e.call(n,t.paymentRequest)})})}catch(e){return Promise.reject(e)}},t.parseLnUrlPayResponse=function(e){try{var t=this,r=function(){if(e)return Promise.resolve(G(e)).then(function(e){t.lnurlpData=e})}();return Promise.resolve(r&&r.then?r.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},t.parseKeysendResponse=function(e){e&&(this.keysendData=O(e))},t.parseNostrResponse=function(e){if(e){var t=V(e,this.username);this.nostrData=t[0],this.nostrPubkey=t[1],this.nostrRelays=t[2]}},e}(),ee=/*#__PURE__*/function(){function e(e){this.storage=void 0,this.storage=e||{}}var t=e.prototype;return t.getItem=function(e){return this.storage[e]},t.setItem=function(e,t){this.storage[e]=t},e}(),te=/*#__PURE__*/function(){function e(e){}var t=e.prototype;return t.getItem=function(e){return null},t.setItem=function(e,t){},e}(),re=function(e){for(var t,r=e.replace("L402","").replace("LSAT","").trim(),n={},o=/(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;null!==(t=o.exec(r));)n[t[1]]=t[3]||t[4]||t[5];return n},ne=new ee,oe=function(e,t,r){try{var n,o=function(r){return n?r:(t.headers["Accept-Authenticate"]=i,Promise.resolve(fetch(e,t)).then(function(r){var n=r.headers.get("www-authenticate");if(!n)return r;var o=re(n),c=o.token||o.macaroon,u=o.invoice;return Promise.resolve(s.enable()).then(function(){return Promise.resolve(s.sendPayment(u)).then(function(r){return a.setItem(e,JSON.stringify({token:c,preimage:r.preimage})),t.headers.Authorization=i+" "+c+":"+r.preimage,Promise.resolve(fetch(e,t))})})}))};r||(r={});var i=r.headerKey||"L402",s=r.webln||globalThis.webln;if(!s)throw new Error("WebLN is missing");var a=r.store||ne;t||(t={}),t.cache="no-store",t.mode="cors",t.headers||(t.headers={});var c=a.getItem(e),u=function(){if(c){var r=JSON.parse(c);return t.headers.Authorization=i+" "+r.token+":"+r.preimage,Promise.resolve(fetch(e,t)).then(function(e){return n=1,e})}}();return Promise.resolve(u&&u.then?u.then(o):o(u))}catch(e){return Promise.reject(e)}},ie={__proto__:null,fetchWithL402:oe,MemoryStorage:ee,NoStorage:te,parseL402:re},se=function(e){try{var t="https://getalby.com/api/rates/"+e.toLowerCase()+".json";return Promise.resolve(fetch(t)).then(function(e){if(!e.ok)throw new Error("Failed to fetch rate: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){return e.rate_float/1e8})})}catch(e){return Promise.reject(e)}},ae=function(e){var t=e.satoshi;return Promise.resolve(se(e.currency)).then(function(e){return Number(t)*e})},ce=function(e){var t=e.amount;return Promise.resolve(se(e.currency)).then(function(e){return Math.floor(Number(t)/e)})},ue=function(e){var t=e.currency,r=e.locale;return r||(r="en"),Promise.resolve(ae({satoshi:e.satoshi,currency:t})).then(function(e){return e.toLocaleString(r,{style:"currency",currency:t})})},he={__proto__:null,getFiatBtcRate:se,getFiatValue:ae,getSatoshiValue:ce,getFormattedFiatValue:ue};export{Q as DEFAULT_PROXY,B as Invoice,X as LN_ADDRESS_REGEX,Y as LightningAddress,ee as MemoryStorage,te as NoStorage,E as decodeInvoice,oe as fetchWithL402,he as fiat,b as fromHexString,H as generateZapEvent,F as getEventHash,se as getFiatBtcRate,ae as getFiatValue,ue as getFormattedFiatValue,ce as getSatoshiValue,z as isUrl,M as isValidAmount,ie as l402,O as parseKeysendResponse,re as parseL402,G as parseLnUrlPayResponse,V as parseNostrResponse,Z as sendBoostagram,K as serializeEvent,C as validateEvent};
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e||self).lightningTools={})}(this,function(e){var t=function(e){var t={exports:{}};return function(e,t){function r(e){if(!Number.isSafeInteger(e))throw new Error(`Wrong integer: ${e}`)}function n(...e){const t=(e,t)=>r=>e(t(r));return{encode:Array.from(e).reverse().reduce((e,r)=>e?t(e,r.encode):r.encode,void 0),decode:e.reduce((e,r)=>e?t(e,r.decode):r.decode,void 0)}}function o(e){return{encode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("alphabet.encode input should be an array of numbers");return t.map(t=>{if(r(t),t<0||t>=e.length)throw new Error(`Digit index outside alphabet: ${t} (alphabet: ${e.length})`);return e[t]})},decode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("alphabet.decode input should be array of strings");return t.map(t=>{if("string"!=typeof t)throw new Error(`alphabet.decode: not string element=${t}`);const r=e.indexOf(t);if(-1===r)throw new Error(`Unknown letter: "${t}". Allowed: ${e}`);return r})}}}function i(e=""){if("string"!=typeof e)throw new Error("join separator should be string");return{encode:t=>{if(!Array.isArray(t)||t.length&&"string"!=typeof t[0])throw new Error("join.encode input should be array of strings");for(let e of t)if("string"!=typeof e)throw new Error(`join.encode: non-string input=${e}`);return t.join(e)},decode:t=>{if("string"!=typeof t)throw new Error("join.decode input should be string");return t.split(e)}}}function s(e,t="="){if(r(e),"string"!=typeof t)throw new Error("padding chr should be string");return{encode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.encode: non-string input=${e}`);for(;r.length*e%8;)r.push(t);return r},decode(r){if(!Array.isArray(r)||r.length&&"string"!=typeof r[0])throw new Error("padding.encode input should be array of strings");for(let e of r)if("string"!=typeof e)throw new Error(`padding.decode: non-string input=${e}`);let n=r.length;if(n*e%8)throw new Error("Invalid padding: string should have whole number of bytes");for(;n>0&&r[n-1]===t;n--)if(!((n-1)*e%8))throw new Error("Invalid padding: string has too much padding");return r.slice(0,n)}}}function a(e){if("function"!=typeof e)throw new Error("normalize fn should be function");return{encode:e=>e,decode:t=>e(t)}}function c(e,t,n){if(t<2)throw new Error(`convertRadix: wrong from=${t}, base cannot be less than 2`);if(n<2)throw new Error(`convertRadix: wrong to=${n}, base cannot be less than 2`);if(!Array.isArray(e))throw new Error("convertRadix: data should be array");if(!e.length)return[];let o=0;const i=[],s=Array.from(e);for(s.forEach(e=>{if(r(e),e<0||e>=t)throw new Error(`Wrong integer: ${e}`)});;){let e=0,r=!0;for(let i=o;i<s.length;i++){const a=s[i],c=t*e+a;if(!Number.isSafeInteger(c)||t*e/t!==e||c-a!=t*e)throw new Error("convertRadix: carry overflow");if(e=c%n,s[i]=Math.floor(c/n),!Number.isSafeInteger(s[i])||s[i]*n+e!==c)throw new Error("convertRadix: carry overflow");r&&(s[i]?r=!1:o=i)}if(i.push(e),r)break}for(let t=0;t<e.length-1&&0===e[t];t++)i.push(0);return i.reverse()}Object.defineProperty(t,"__esModule",{value:!0}),t.bytes=t.stringToBytes=t.str=t.bytesToString=t.hex=t.utf8=t.bech32m=t.bech32=t.base58check=t.base58xmr=t.base58xrp=t.base58flickr=t.base58=t.base64url=t.base64=t.base32crockford=t.base32hex=t.base32=t.base16=t.utils=t.assertNumber=void 0,t.assertNumber=r;const u=(e,t)=>t?u(t,e%t):e,h=(e,t)=>e+(t-u(e,t));function l(e,t,n,o){if(!Array.isArray(e))throw new Error("convertRadix2: data should be array");if(t<=0||t>32)throw new Error(`convertRadix2: wrong from=${t}`);if(n<=0||n>32)throw new Error(`convertRadix2: wrong to=${n}`);if(h(t,n)>32)throw new Error(`convertRadix2: carry overflow from=${t} to=${n} carryBits=${h(t,n)}`);let i=0,s=0;const a=2**n-1,c=[];for(const o of e){if(r(o),o>=2**t)throw new Error(`convertRadix2: invalid data word=${o} from=${t}`);if(i=i<<t|o,s+t>32)throw new Error(`convertRadix2: carry overflow pos=${s} from=${t}`);for(s+=t;s>=n;s-=n)c.push((i>>s-n&a)>>>0);i&=2**s-1}if(i=i<<n-s&a,!o&&s>=t)throw new Error("Excess padding");if(!o&&i)throw new Error(`Non-zero padding: ${i}`);return o&&s>0&&c.push(i>>>0),c}function f(e){return r(e),{encode:t=>{if(!(t instanceof Uint8Array))throw new Error("radix.encode input should be Uint8Array");return c(Array.from(t),256,e)},decode:t=>{if(!Array.isArray(t)||t.length&&"number"!=typeof t[0])throw new Error("radix.decode input should be array of strings");return Uint8Array.from(c(t,e,256))}}}function d(e,t=!1){if(r(e),e<=0||e>32)throw new Error("radix2: bits should be in (0..32]");if(h(8,e)>32||h(e,8)>32)throw new Error("radix2: carry overflow");return{encode:r=>{if(!(r instanceof Uint8Array))throw new Error("radix2.encode input should be Uint8Array");return l(Array.from(r),8,e,!t)},decode:r=>{if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("radix2.decode input should be array of strings");return Uint8Array.from(l(r,e,8,t))}}}function p(e){if("function"!=typeof e)throw new Error("unsafeWrapper fn should be function");return function(...t){try{return e.apply(null,t)}catch(e){}}}function m(e,t){if(r(e),"function"!=typeof t)throw new Error("checksum fn should be function");return{encode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.encode: input should be Uint8Array");const n=t(r).slice(0,e),o=new Uint8Array(r.length+e);return o.set(r),o.set(n,r.length),o},decode(r){if(!(r instanceof Uint8Array))throw new Error("checksum.decode: input should be Uint8Array");const n=r.slice(0,-e),o=t(n).slice(0,e),i=r.slice(-e);for(let t=0;t<e;t++)if(o[t]!==i[t])throw new Error("Invalid checksum");return n}}}t.utils={alphabet:o,chain:n,checksum:m,radix:f,radix2:d,join:i,padding:s},t.base16=n(d(4),o("0123456789ABCDEF"),i("")),t.base32=n(d(5),o("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),s(5),i("")),t.base32hex=n(d(5),o("0123456789ABCDEFGHIJKLMNOPQRSTUV"),s(5),i("")),t.base32crockford=n(d(5),o("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),i(""),a(e=>e.toUpperCase().replace(/O/g,"0").replace(/[IL]/g,"1"))),t.base64=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),s(6),i("")),t.base64url=n(d(6),o("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),s(6),i(""));const y=e=>n(f(58),o(e),i(""));t.base58=y("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"),t.base58flickr=y("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"),t.base58xrp=y("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");const w=[0,2,3,5,6,7,9,10,11];t.base58xmr={encode(e){let r="";for(let n=0;n<e.length;n+=8){const o=e.subarray(n,n+8);r+=t.base58.encode(o).padStart(w[o.length],"1")}return r},decode(e){let r=[];for(let n=0;n<e.length;n+=11){const o=e.slice(n,n+11),i=w.indexOf(o.length),s=t.base58.decode(o);for(let e=0;e<s.length-i;e++)if(0!==s[e])throw new Error("base58xmr: wrong padding");r=r.concat(Array.from(s.slice(s.length-i)))}return Uint8Array.from(r)}},t.base58check=e=>n(m(4,t=>e(e(t))),t.base58);const g=n(o("qpzry9x8gf2tvdw0s3jn54khce6mua7l"),i("")),v=[996825010,642813549,513874426,1027748829,705979059];function b(e){const t=e>>25;let r=(33554431&e)<<5;for(let e=0;e<v.length;e++)1==(t>>e&1)&&(r^=v[e]);return r}function E(e,t,r=1){const n=e.length;let o=1;for(let t=0;t<n;t++){const r=e.charCodeAt(t);if(r<33||r>126)throw new Error(`Invalid prefix (${e})`);o=b(o)^r>>5}o=b(o);for(let t=0;t<n;t++)o=b(o)^31&e.charCodeAt(t);for(let e of t)o=b(o)^e;for(let e=0;e<6;e++)o=b(o);return o^=r,g.encode(l([o%2**30],30,5,!1))}function x(e){const t="bech32"===e?1:734539939,r=d(5),n=r.decode,o=r.encode,i=p(n);function s(e,r=90){if("string"!=typeof e)throw new Error("bech32.decode input should be string, not "+typeof e);if(e.length<8||!1!==r&&e.length>r)throw new TypeError(`Wrong string length: ${e.length} (${e}). Expected (8..${r})`);const n=e.toLowerCase();if(e!==n&&e!==e.toUpperCase())throw new Error("String must be lowercase or uppercase");const o=(e=n).lastIndexOf("1");if(0===o||-1===o)throw new Error('Letter "1" must be present between prefix and data only');const i=e.slice(0,o),s=e.slice(o+1);if(s.length<6)throw new Error("Data must be at least 6 characters long");const a=g.decode(s).slice(0,-6),c=E(i,a,t);if(!s.endsWith(c))throw new Error(`Invalid checksum in ${e}: expected "${c}"`);return{prefix:i,words:a}}return{encode:function(e,r,n=90){if("string"!=typeof e)throw new Error("bech32.encode prefix should be string, not "+typeof e);if(!Array.isArray(r)||r.length&&"number"!=typeof r[0])throw new Error("bech32.encode words should be array of numbers, not "+typeof r);const o=e.length+7+r.length;if(!1!==n&&o>n)throw new TypeError(`Length ${o} exceeds limit ${n}`);return`${e=e.toLowerCase()}1${g.encode(r)}${E(e,r,t)}`},decode:s,decodeToBytes:function(e){const{prefix:t,words:r}=s(e,!1);return{prefix:t,words:r,bytes:n(r)}},decodeUnsafe:p(s),fromWords:n,fromWordsUnsafe:i,toWords:o}}t.bech32=x("bech32"),t.bech32m=x("bech32m"),t.utf8={encode:e=>(new TextDecoder).decode(e),decode:e=>(new TextEncoder).encode(e)},t.hex=n(d(4),o("0123456789abcdef"),i(""),a(e=>{if("string"!=typeof e||e.length%2)throw new TypeError(`hex.decode: expected string, got ${typeof e} with length ${e.length}`);return e.toLowerCase()}));const P={utf8:t.utf8,hex:t.hex,base16:t.base16,base32:t.base32,base64:t.base64,base64url:t.base64url,base58:t.base58,base58xmr:t.base58xmr},A=`Invalid encoding type. Available types: ${Object.keys(P).join(", ")}`;t.bytesToString=(e,t)=>{if("string"!=typeof e||!P.hasOwnProperty(e))throw new TypeError(A);if(!(t instanceof Uint8Array))throw new TypeError("bytesToString() expects Uint8Array");return P[e].encode(t)},t.str=t.bytesToString,t.stringToBytes=(e,t)=>{if(!P.hasOwnProperty(e))throw new TypeError(A);if("string"!=typeof t)throw new TypeError("stringToBytes() expects string");return P[e].decode(t)},t.bytes=t.stringToBytes}(0,t.exports),t.exports}();const{bech32:r,hex:n,utf8:o}=t,i={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},s={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},a={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},c={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},u={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},h=["option_data_loss_protect","initial_routing_sync","option_upfront_shutdown_script","gossip_queries","var_onion_optin","gossip_queries_ex","option_static_remotekey","payment_secret","basic_mpp","option_support_large_channel"],l={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},f=BigInt("2100000000000000000"),d=BigInt(1e11),p={payment_hash:1,payment_secret:16,description:13,payee:19,description_hash:23,expiry:6,min_final_cltv_expiry:24,fallback_address:9,route_hint:3,feature_bits:5,metadata:27},m={};for(let e=0,t=Object.keys(p);e<t.length;e++){const r=t[e],n=p[t[e]].toString();m[n]=r}const y={1:e=>n.encode(r.fromWordsUnsafe(e)),16:e=>n.encode(r.fromWordsUnsafe(e)),13:e=>o.encode(r.fromWordsUnsafe(e)),19:e=>n.encode(r.fromWordsUnsafe(e)),23:e=>n.encode(r.fromWordsUnsafe(e)),27:e=>n.encode(r.fromWordsUnsafe(e)),6:g,24:g,3:function(e){const t=[];let o,i,s,a,c,u=r.fromWordsUnsafe(e);for(;u.length>0;)o=n.encode(u.slice(0,33)),i=n.encode(u.slice(33,41)),s=parseInt(n.encode(u.slice(41,45)),16),a=parseInt(n.encode(u.slice(45,49)),16),c=parseInt(n.encode(u.slice(49,51)),16),u=u.slice(51),t.push({pubkey:o,short_channel_id:i,fee_base_msat:s,fee_proportional_millionths:a,cltv_expiry_delta:c});return t},5:function(e){const t=e.slice().reverse().map(e=>[!!(1&e),!!(2&e),!!(4&e),!!(8&e),!!(16&e)]).reduce((e,t)=>e.concat(t),[]);for(;t.length<2*h.length;)t.push(!1);const r={};h.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*h.length);return r.extra_bits={start_bit:2*h.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function w(e){return t=>({tagCode:parseInt(e),words:r.encode("unknown",t,Number.MAX_SAFE_INTEGER)})}function g(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}var v=function(e){return Uint8Array.from(e.match(/.{1,2}/g).map(function(e){return parseInt(e,16)}))},b=function(e){if(!e)return null;try{var t=function(e,t){if("string"!=typeof e)throw new Error("Lightning Payment Request must be string");if("ln"!==e.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const o=[],h=r.decode(e,Number.MAX_SAFE_INTEGER);e=e.toLowerCase();const v=h.prefix;let b=h.words,E=e.slice(v.length+1),x=b.slice(-104);b=b.slice(0,-104);let P=v.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(P&&!P[2]&&(P=v.match(/^ln(\S+)$/)),!P)throw new Error("Not a proper lightning payment request");o.push({name:"lightning_network",letters:"ln"});const A=P[1];let k;switch(A){case i.bech32:k=i;break;case s.bech32:k=s;break;case a.bech32:k=a;break;case c.bech32:k=c;break;case u.bech32:k=u}if(!k||k.bech32!==A)throw new Error("Unknown coin bech32 prefix");o.push({name:"coin_network",letters:A,value:k});const _=P[2];let U;_?(U=function(e,t){let r,n;if(e.slice(-1).match(/^[munp]$/))r=e.slice(-1),n=e.slice(0,-1);else{if(e.slice(-1).match(/^[^munp0-9]$/))throw new Error("Not a valid multiplier for the amount");n=e}if(!n.match(/^\d+$/))throw new Error("Not a valid human readable amount");const o=BigInt(n),i=r?o*d/l[r]:o*d;if("p"===r&&o%BigInt(10)!==BigInt(0)||i>f)throw new Error("Amount is outside of valid range");return i.toString()}(_+P[3]),o.push({name:"amount",letters:P[2]+P[3],value:U})):U=null,o.push({name:"separator",letters:"1"});const L=g(b.slice(0,7));let D,N,I,S;for(b=b.slice(7),o.push({name:"timestamp",letters:E.slice(0,7),value:L}),E=E.slice(7);b.length>0;){const e=b[0].toString();D=m[e]||"unknown_tag",N=y[e]||w(e),b=b.slice(1),I=g(b.slice(0,2)),b=b.slice(2),S=b.slice(0,I),b=b.slice(I),o.push({name:D,tag:E[0],letters:E.slice(0,3+I),value:N(S)}),E=E.slice(3+I)}o.push({name:"signature",letters:E.slice(0,104),value:n.encode(r.fromWordsUnsafe(x))}),E=E.slice(104),o.push({name:"checksum",letters:E});let R={paymentRequest:e,sections:o,get expiry(){let e=o.find(e=>"expiry"===e.name);if(e)return j("timestamp")+e.value},get route_hints(){return o.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in p)"route_hint"!==e&&Object.defineProperty(R,e,{get:()=>j(e)});return R;function j(e){let t=o.find(t=>t.name===e);return t?t.value:void 0}}(e);if(!t||!t.sections)return null;var o=t.sections.find(function(e){return"payment_hash"===e.name});if("payment_hash"!==(null==o?void 0:o.name)||!o.value)return null;var h=o.value,v=0,b=t.sections.find(function(e){return"amount"===e.name});"amount"===(null==b?void 0:b.name)&&b.value&&(v=parseInt(b.value)/1e3);var E=t.sections.find(function(e){return"timestamp"===e.name});if("timestamp"!==(null==E?void 0:E.name)||!E.value)return null;var x,P=E.value,A=t.sections.find(function(e){return"expiry"===e.name});"expiry"===(null==A?void 0:A.name)&&(x=A.value);var k=t.sections.find(function(e){return"description"===e.name});return{paymentHash:h,satoshi:v,timestamp:P,expiry:x,description:"description"===(null==k?void 0:k.name)?null==k?void 0:k.value:void 0}}catch(e){return null}};function E(e,t=!0){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}const x=e=>e instanceof Uint8Array,P=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),A=(e,t)=>e<<32-t|e>>>t;if(68!==new Uint8Array(new Uint32Array([287454020]).buffer)[0])throw new Error("Non little-endian hardware is not supported");const k=/* @__PURE__ */Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function _(e){if(!x(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=k[e[r]];return t}function U(e){if("string"==typeof e&&(e=function(e){if("string"!=typeof e)throw new Error("utf8ToBytes expected string, got "+typeof e);return new Uint8Array((new TextEncoder).encode(e))}(e)),!x(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class L{clone(){return this._cloneInto()}}function D(e){const t=t=>e().update(U(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class N extends L{constructor(e,t,r,n){super(),this.blockLen=e,this.outputLen=t,this.padOffset=r,this.isLE=n,this.finished=!1,this.length=0,this.pos=0,this.destroyed=!1,this.buffer=new Uint8Array(e),this.view=P(this.buffer)}update(e){E(this);const{view:t,buffer:r,blockLen:n}=this,o=(e=U(e)).length;for(let i=0;i<o;){const s=Math.min(n-this.pos,o-i);if(s!==n)r.set(e.subarray(i,i+s),this.pos),this.pos+=s,i+=s,this.pos===n&&(this.process(t,0),this.pos=0);else{const t=P(e);for(;n<=o-i;i+=n)this.process(t,i)}}return this.length+=e.length,this.roundClean(),this}digestInto(e){E(this),function(e,t){!function(e,...t){if(!(e instanceof Uint8Array))throw new Error("Expected Uint8Array");if(t.length>0&&!t.includes(e.length))throw new Error(`Expected Uint8Array of length ${t}, not of length=${e.length}`)}(e);const r=t.outputLen;if(e.length<r)throw new Error(`digestInto() expects output buffer of length at least ${r}`)}(e,this),this.finished=!0;const{buffer:t,view:r,blockLen:n,isLE:o}=this;let{pos:i}=this;t[i++]=128,this.buffer.subarray(i).fill(0),this.padOffset>n-i&&(this.process(r,0),i=0);for(let e=i;e<n;e++)t[e]=0;!function(e,t,r,n){if("function"==typeof e.setBigUint64)return e.setBigUint64(t,r,n);const o=BigInt(32),i=BigInt(4294967295),s=Number(r>>o&i),a=Number(r&i),c=n?0:4;e.setUint32(t+(n?4:0),s,n),e.setUint32(t+c,a,n)}(r,n-8,BigInt(8*this.length),o),this.process(r,0);const s=P(e),a=this.outputLen;if(a%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const c=a/4,u=this.get();if(c>u.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<c;e++)s.setUint32(4*e,u[e],o)}digest(){const{buffer:e,outputLen:t}=this;this.digestInto(e);const r=e.slice(0,t);return this.destroy(),r}_cloneInto(e){e||(e=new this.constructor),e.set(...this.get());const{blockLen:t,buffer:r,length:n,finished:o,destroyed:i,pos:s}=this;return e.length=n,e.pos=s,e.finished=o,e.destroyed=i,n%t&&e.buffer.set(r),e}}const I=(e,t,r)=>e&t^e&r^t&r,S=/* @__PURE__ */new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),R=/* @__PURE__ */new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),j=/* @__PURE__ */new Uint32Array(64);class $ extends N{constructor(){super(64,32,8,!1),this.A=0|R[0],this.B=0|R[1],this.C=0|R[2],this.D=0|R[3],this.E=0|R[4],this.F=0|R[5],this.G=0|R[6],this.H=0|R[7]}get(){const{A:e,B:t,C:r,D:n,E:o,F:i,G:s,H:a}=this;return[e,t,r,n,o,i,s,a]}set(e,t,r,n,o,i,s,a){this.A=0|e,this.B=0|t,this.C=0|r,this.D=0|n,this.E=0|o,this.F=0|i,this.G=0|s,this.H=0|a}process(e,t){for(let r=0;r<16;r++,t+=4)j[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=j[e-15],r=j[e-2],n=A(t,7)^A(t,18)^t>>>3,o=A(r,17)^A(r,19)^r>>>10;j[e]=o+j[e-7]+n+j[e-16]|0}let{A:r,B:n,C:o,D:i,E:s,F:a,G:c,H:u}=this;for(let e=0;e<64;e++){const t=u+(A(s,6)^A(s,11)^A(s,25))+((h=s)&a^~h&c)+S[e]+j[e]|0,l=(A(r,2)^A(r,13)^A(r,22))+I(r,n,o)|0;u=c,c=a,a=s,s=i+t|0,i=o,o=n,n=r,r=t+l|0}var h;r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,i=i+this.D|0,s=s+this.E|0,a=a+this.F|0,c=c+this.G|0,u=u+this.H|0,this.set(r,n,o,i,s,a,c,u)}roundClean(){j.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const T=/* @__PURE__ */D(()=>new $);var W=/*#__PURE__*/function(){function e(e){var t,r,n,o;if(this.paymentRequest=void 0,this.paymentHash=void 0,this.preimage=void 0,this.verify=void 0,this.satoshi=void 0,this.expiry=void 0,this.timestamp=void 0,this.createdDate=void 0,this.expiryDate=void 0,this.description=void 0,this.successAction=void 0,this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");var i=b(this.paymentRequest);if(!i)throw new Error("Failed to decode payment request");this.paymentHash=i.paymentHash,this.satoshi=i.satoshi,this.timestamp=i.timestamp,this.expiry=i.expiry,this.createdDate=new Date(1e3*this.timestamp),this.expiryDate=this.expiry?new Date(1e3*(this.timestamp+this.expiry)):void 0,this.description=null!=(t=i.description)?t:null,this.verify=null!=(r=e.verify)?r:null,this.preimage=null!=(n=e.preimage)?n:null,this.successAction=null!=(o=e.successAction)?o:null}var t=e.prototype;return t.isPaid=function(){try{var e=this;if(e.preimage)return Promise.resolve(e.validatePreimage(e.preimage));if(e.verify)return Promise.resolve(e.verifyPayment());throw new Error("Could not verify payment")}catch(e){return Promise.reject(e)}},t.validatePreimage=function(e){if(!e||!this.paymentHash)return!1;try{var t=_(T(v(e)));return this.paymentHash===t}catch(e){return!1}},t.verifyPayment=function(){try{var e=this;return Promise.resolve(function(t,r){try{var n=function(){if(!e.verify)throw new Error("LNURL verify not available");return Promise.resolve(fetch(e.verify)).then(function(t){if(!t.ok)throw new Error("Verification request failed: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return t.preimage&&(e.preimage=t.preimage),t.settled})})}()}catch(e){return r(e)}return n&&n.then?n.then(void 0,r):n}(0,function(e){return console.error("Failed to check LNURL-verify",e),!1}))}catch(e){return Promise.reject(e)}},t.hasExpired=function(){var e=this.expiryDate;return!!e&&e.getTime()<Date.now()},e}(),B=function(e,t){var r=e.satoshi,n=e.comment,o=e.p,i=e.e,s=e.relays;void 0===t&&(t={});try{var a=t.nostr||globalThis.nostr;if(!a)throw new Error("nostr option or window.nostr is not available");var c=[["relays"].concat(s),["amount",r.toString()]];return o&&c.push(["p",o]),i&&c.push(["e",i]),Promise.resolve(a.getPublicKey()).then(function(e){var t={pubkey:e,created_at:Math.floor(Date.now()/1e3),kind:9734,tags:c,content:null!=n?n:""};return t.id=K(t),Promise.resolve(a.signEvent(t))})}catch(i){return Promise.reject(i)}},H=function(e){if("keysend"!==e.tag)throw new Error("Invalid keysend params");if("OK"!==e.status)throw new Error("Keysend status not OK");if(!e.pubkey)throw new Error("Pubkey does not exist");var t,r;return e.customData&&e.customData[0]&&(t=e.customData[0].customKey,r=e.customData[0].customValue),{destination:e.pubkey,customKey:t,customValue:r}};function O(e){if("string"!=typeof e.content)return!1;if("number"!=typeof e.created_at)return!1;if(!Array.isArray(e.tags))return!1;for(var t=0;t<e.tags.length;t++){var r=e.tags[t];if(!Array.isArray(r))return!1;for(var n=0;n<r.length;n++)if("object"==typeof r[n])return!1}return!0}function F(e){if(!O(e))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,e.pubkey,e.created_at,e.kind,e.tags,e.content])}function K(e){return _(T(F(e)))}function C(e,t){var r,n,o,i;return t&&e&&(n=(r=null==(o=e.names)?void 0:o[t])?null==(i=e.relays)?void 0:i[r]:void 0),[e,r,n]}var V=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,q=function(e){return!!e&&V.test(e)},z=function(e){var t=e.amount;return t>0&&t>=e.min&&t<=e.max},M=function(e){try{if("payRequest"!==e.tag)throw new Error("Invalid pay service params");var t=(e.callback+"").trim();if(!q(t))throw new Error("Callback must be a valid url");var r,n,o=Math.ceil(Number(e.minSendable||0)),i=Math.floor(Number(e.maxSendable));if(!o||!i||o>i)throw new Error("Invalid pay service params");try{r=JSON.parse(e.metadata+""),n=_(T(e.metadata+""))}catch(e){r=[],n=_(T("[]"))}for(var s="",a="",c="",u="",h=0;h<r.length;h++){var l=r[h],f=l[0],d=l[1];switch(f){case"text/plain":c=d;break;case"text/identifier":u=d;break;case"text/email":s=d;break;case"image/png;base64":case"image/jpeg;base64":a="data:"+f+","+d}}var p,m=e.payerData;try{p=new URL(t).hostname}catch(e){}return Promise.resolve({callback:t,fixed:o===i,min:o,max:i,domain:p,metadata:r,metadataHash:n,identifier:u,email:s,description:c,image:a,payerData:m,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1})}catch(e){return Promise.reject(e)}};function G(){return G=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},G.apply(this,arguments)}var J=function(e,t){try{var r=e.boost;t||(t={});var n=t.webln||globalThis.webln;if(!n)throw new Error("WebLN not available");if(!n.keysend)throw new Error("Keysend not available in current WebLN provider");var o=e.amount||Math.floor(r.value_msat/1e3),i={destination:e.destination,amount:o,customRecords:{7629169:JSON.stringify(r)}};return e.customKey&&e.customValue&&(i.customRecords[e.customKey]=e.customValue),Promise.resolve(n.enable()).then(function(){return Promise.resolve(n.keysend(i))})}catch(e){return Promise.reject(e)}},Z=/^((?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)|(?:".+"))@((?:\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,X="https://api.getalby.com/lnurl",Y=/*#__PURE__*/function(){function e(e,t){this.address=void 0,this.options=void 0,this.username=void 0,this.domain=void 0,this.pubkey=void 0,this.lnurlpData=void 0,this.keysendData=void 0,this.nostrData=void 0,this.nostrPubkey=void 0,this.nostrRelays=void 0,this.webln=void 0,this.address=e,this.options={proxy:X},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}var t=e.prototype;return t.parse=function(){var e=Z.exec(this.address.toLowerCase());e&&(this.username=e[1],this.domain=e[2])},t.getWebLN=function(){return this.webln||globalThis.webln},t.fetch=function(){try{var e=this;return Promise.resolve(e.options.proxy?e.fetchWithProxy():e.fetchWithoutProxy())}catch(e){return Promise.reject(e)}},t.fetchWithProxy=function(){try{var e=this;return Promise.resolve(fetch(e.options.proxy+"/lightning-address-details?"+new URLSearchParams({ln:e.address}).toString())).then(function(t){if(!t.ok)throw new Error("Failed to fetch lnurl info: "+t.status+" "+t.statusText);return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t.lnurlp)).then(function(){e.parseKeysendResponse(t.keysend),e.parseNostrResponse(t.nostr)})})})}catch(e){return Promise.reject(e)}},t.fetchWithoutProxy=function(){try{var e=this;return e.domain&&e.username?Promise.resolve(Promise.all([e.fetchLnurlData(),e.fetchKeysendData(),e.fetchNostrData()])).then(function(){}):Promise.resolve()}catch(e){return Promise.reject(e)}},t.fetchLnurlData=function(){try{var e=this;return Promise.resolve(fetch(e.lnurlpUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){return Promise.resolve(e.parseLnUrlPayResponse(t)).then(function(){})})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchKeysendData=function(){try{var e=this;return Promise.resolve(fetch(e.keysendUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseKeysendResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.fetchNostrData=function(){try{var e=this;return Promise.resolve(fetch(e.nostrUrl())).then(function(t){var r=function(){if(t.ok)return Promise.resolve(t.json()).then(function(t){e.parseNostrResponse(t)})}();if(r&&r.then)return r.then(function(){})})}catch(e){return Promise.reject(e)}},t.lnurlpUrl=function(){return"https://"+this.domain+"/.well-known/lnurlp/"+this.username},t.keysendUrl=function(){return"https://"+this.domain+"/.well-known/keysend/"+this.username},t.nostrUrl=function(){return"https://"+this.domain+"/.well-known/nostr.json?name="+this.username},t.generateInvoice=function(e){try{var t,r=function(e){var r=t&&t.pr&&t.pr.toString();if(!r)throw new Error("Invalid pay service invoice");var n={pr:r};if(t&&t.verify&&(n.verify=t.verify.toString()),t&&t.successAction&&"object"==typeof t.successAction){var o=t.successAction,i=o.tag,s=o.description,a=o.url;"message"===i?n.successAction={tag:i,message:o.message}:"url"===i&&(n.successAction={tag:i,description:s,url:a})}return new W(n)},n=this,o=function(){if(n.options.proxy)return Promise.resolve(fetch(n.options.proxy+"/generate-invoice?"+new URLSearchParams(G({ln:n.address},e)).toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e.invoice})});if(!n.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!n.lnurlpData.callback||!q(n.lnurlpData.callback))throw new Error("Valid callback does not exist in lnurlpData");var r=new URL(n.lnurlpData.callback);return r.search=new URLSearchParams(e).toString(),Promise.resolve(fetch(r.toString())).then(function(e){if(!e.ok)throw new Error("Failed to generate invoice: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){t=e})})}();return Promise.resolve(o&&o.then?o.then(r):r())}catch(e){return Promise.reject(e)}},t.requestInvoice=function(e){try{var t=this;if(!t.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");var r=1e3*e.satoshi,n=t.lnurlpData,o=n.commentAllowed;if(!z({amount:r,min:n.min,max:n.max}))throw new Error("Invalid amount");if(e.comment&&o&&o>0&&e.comment.length>o)throw new Error("The comment length must be "+o+" characters or fewer");var i={amount:r.toString()};return e.comment&&(i.comment=e.comment),e.payerdata&&(i.payerdata=JSON.stringify(e.payerdata)),Promise.resolve(t.generateInvoice(i))}catch(e){return Promise.reject(e)}},t.boost=function(e,t){void 0===t&&(t=0);try{var r=this;if(!r.keysendData)throw new Error("No keysendData available. Please call fetch() first.");var n=r.keysendData,o=n.destination,i=n.customKey,s=n.customValue,a=r.getWebLN();if(!a)throw new Error("WebLN not available");return Promise.resolve(J({destination:o,customKey:i,customValue:s,amount:t,boost:e},{webln:a}))}catch(e){return Promise.reject(e)}},t.zapInvoice=function(e,t){var r=e.satoshi,n=e.comment,o=e.relays,i=e.e;void 0===t&&(t={});try{var s=this;if(!s.lnurlpData)throw new Error("No lnurlpData available. Please call fetch() first.");if(!s.nostrPubkey)throw new Error("Nostr Pubkey is missing");var a=s.nostrPubkey,c=1e3*r,u=s.lnurlpData,h=u.allowsNostr;if(!z({amount:c,min:u.min,max:u.max}))throw new Error("Invalid amount");if(!h)throw new Error("Your provider does not support zaps");return Promise.resolve(B({satoshi:c,comment:n,p:a,e:i,relays:o},t)).then(function(e){var t={amount:c.toString(),nostr:JSON.stringify(e)};return Promise.resolve(s.generateInvoice(t))})}catch(i){return Promise.reject(i)}},t.zap=function(e,t){void 0===t&&(t={});try{var r=this.zapInvoice(e,t),n=this.getWebLN();if(!n)throw new Error("WebLN not available");return Promise.resolve(n.enable()).then(function(){var e=n.sendPayment;return Promise.resolve(r).then(function(t){return e.call(n,t.paymentRequest)})})}catch(e){return Promise.reject(e)}},t.parseLnUrlPayResponse=function(e){try{var t=this,r=function(){if(e)return Promise.resolve(M(e)).then(function(e){t.lnurlpData=e})}();return Promise.resolve(r&&r.then?r.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},t.parseKeysendResponse=function(e){e&&(this.keysendData=H(e))},t.parseNostrResponse=function(e){if(e){var t=C(e,this.username);this.nostrData=t[0],this.nostrPubkey=t[1],this.nostrRelays=t[2]}},e}(),Q=/*#__PURE__*/function(){function e(e){this.storage=void 0,this.storage=e||{}}var t=e.prototype;return t.getItem=function(e){return this.storage[e]},t.setItem=function(e,t){this.storage[e]=t},e}(),ee=/*#__PURE__*/function(){function e(e){}var t=e.prototype;return t.getItem=function(e){return null},t.setItem=function(e,t){},e}(),te=function(e){for(var t,r=e.replace("L402","").replace("LSAT","").trim(),n={},o=/(\w+)=("([^"]*)"|'([^']*)'|([^,]*))/g;null!==(t=o.exec(r));)n[t[1]]=t[3]||t[4]||t[5];return n},re=new Q,ne=function(e,t,r){try{var n,o=function(r){return n?r:(t.headers["Accept-Authenticate"]=i,Promise.resolve(fetch(e,t)).then(function(r){var n=r.headers.get("www-authenticate");if(!n)return r;var o=te(n),c=o.token||o.macaroon,u=o.invoice;return Promise.resolve(s.enable()).then(function(){return Promise.resolve(s.sendPayment(u)).then(function(r){return a.setItem(e,JSON.stringify({token:c,preimage:r.preimage})),t.headers.Authorization=i+" "+c+":"+r.preimage,Promise.resolve(fetch(e,t))})})}))};r||(r={});var i=r.headerKey||"L402",s=r.webln||globalThis.webln;if(!s)throw new Error("WebLN is missing");var a=r.store||re;t||(t={}),t.cache="no-store",t.mode="cors",t.headers||(t.headers={});var c=a.getItem(e),u=function(){if(c){var r=JSON.parse(c);return t.headers.Authorization=i+" "+r.token+":"+r.preimage,Promise.resolve(fetch(e,t)).then(function(e){return n=1,e})}}();return Promise.resolve(u&&u.then?u.then(o):o(u))}catch(e){return Promise.reject(e)}},oe={__proto__:null,fetchWithL402:ne,MemoryStorage:Q,NoStorage:ee,parseL402:te},ie=function(e){try{var t="https://getalby.com/api/rates/"+e.toLowerCase()+".json";return Promise.resolve(fetch(t)).then(function(e){if(!e.ok)throw new Error("Failed to fetch rate: "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){return e.rate_float/1e8})})}catch(e){return Promise.reject(e)}},se=function(e){var t=e.satoshi;return Promise.resolve(ie(e.currency)).then(function(e){return Number(t)*e})},ae=function(e){var t=e.amount;return Promise.resolve(ie(e.currency)).then(function(e){return Math.floor(Number(t)/e)})},ce=function(e){var t=e.currency,r=e.locale;return r||(r="en"),Promise.resolve(se({satoshi:e.satoshi,currency:t})).then(function(e){return e.toLocaleString(r,{style:"currency",currency:t})})},ue={__proto__:null,getFiatBtcRate:ie,getFiatValue:se,getSatoshiValue:ae,getFormattedFiatValue:ce};e.DEFAULT_PROXY=X,e.Invoice=W,e.LN_ADDRESS_REGEX=Z,e.LightningAddress=Y,e.MemoryStorage=Q,e.NoStorage=ee,e.decodeInvoice=b,e.fetchWithL402=ne,e.fiat=ue,e.fromHexString=v,e.generateZapEvent=B,e.getEventHash=K,e.getFiatBtcRate=ie,e.getFiatValue=se,e.getFormattedFiatValue=ce,e.getSatoshiValue=ae,e.isUrl=q,e.isValidAmount=z,e.l402=oe,e.parseKeysendResponse=H,e.parseL402=te,e.parseLnUrlPayResponse=M,e.parseNostrResponse=C,e.sendBoostagram=J,e.serializeEvent=F,e.validateEvent=O});
export * from "./l402";
export * from "./utils";
import { WebLNProvider } from "@webbtc/webln-types";
export declare const fetchWithL402: (url: string, fetchArgs: RequestInit, options: {
headerKey?: string;
webln?: WebLNProvider;
store?: Storage;
}) => Promise<Response>;
export declare class MemoryStorage {
storage: any;
constructor(initial?: Record<string, unknown>);
getItem(key: string): any;
setItem(key: string, value: unknown): void;
}
export declare class NoStorage {
constructor(initial?: unknown);
getItem(key: string): null;
setItem(key: string, value: unknown): void;
}
export declare const parseL402: (input: string) => Record<string, string>;
export * from "./types";
export * from "./utils";
export * from "./LightningAddress";
import { SendPaymentResponse, WebLNProvider } from "@webbtc/webln-types";
import { Invoice } from "../bolt11";
import { Boost } from "../podcasting2";
import { KeysendResponse, LnUrlPayResponse, NostrResponse, RequestInvoiceArgs, ZapArgs, ZapOptions } from "./types";
export declare const LN_ADDRESS_REGEX: RegExp;
export declare const DEFAULT_PROXY = "https://api.getalby.com/lnurl";
type LightningAddressOptions = {
proxy?: string | false;
webln?: WebLNProvider;
};
export declare class LightningAddress {
address: string;
options: LightningAddressOptions;
username: string | undefined;
domain: string | undefined;
pubkey: string | undefined;
lnurlpData: LnUrlPayResponse | undefined;
keysendData: KeysendResponse | undefined;
nostrData: NostrResponse | undefined;
nostrPubkey: string | undefined;
nostrRelays: string[] | undefined;
webln: WebLNProvider | undefined;
constructor(address: string, options?: LightningAddressOptions);
parse(): void;
getWebLN(): any;
fetch(): Promise<void>;
fetchWithProxy(): Promise<void>;
fetchWithoutProxy(): Promise<void>;
fetchLnurlData(): Promise<void>;
fetchKeysendData(): Promise<void>;
fetchNostrData(): Promise<void>;
lnurlpUrl(): string;
keysendUrl(): string;
nostrUrl(): string;
generateInvoice(params: Record<string, string>): Promise<Invoice>;
requestInvoice(args: RequestInvoiceArgs): Promise<Invoice>;
boost(boost: Boost, amount?: number): Promise<SendPaymentResponse>;
zapInvoice({ satoshi, comment, relays, e }: ZapArgs, options?: ZapOptions): Promise<Invoice>;
zap(args: ZapArgs, options?: ZapOptions): Promise<SendPaymentResponse>;
private parseLnUrlPayResponse;
private parseKeysendResponse;
private parseNostrResponse;
}
export {};
export type LnUrlRawData = {
tag: string;
callback: string;
minSendable: number;
maxSendable: number;
metadata: string;
payerData?: LUD18ServicePayerData;
commentAllowed?: number;
allowsNostr?: boolean;
};
export type LnUrlPayResponse = {
callback: string;
fixed: boolean;
min: number;
max: number;
domain?: string;
metadata: Array<Array<string>>;
metadataHash: string;
identifier: string;
email: string;
description: string;
image: string;
commentAllowed?: number;
rawData: LnUrlRawData;
allowsNostr: boolean;
payerData?: LUD18ServicePayerData;
};
export type LUD18ServicePayerData = Partial<{
name: {
mandatory: boolean;
};
pubkey: {
mandatory: boolean;
};
identifier: {
mandatory: boolean;
};
email: {
mandatory: boolean;
};
auth: {
mandatory: boolean;
k1: string;
};
}> & Record<string, unknown>;
export type LUD18PayerData = Partial<{
name?: string;
pubkey?: string;
identifier?: string;
email?: string;
auth?: {
key: string;
sig: string;
};
}> & Record<string, unknown>;
export type NostrResponse = {
names: Record<string, string>;
relays: Record<string, string[]>;
};
export type Event = {
id?: string;
kind: number;
pubkey?: string;
content: string;
tags: string[][];
created_at: number;
sig?: string;
};
export type ZapArgs = {
satoshi: number;
comment?: string;
relays: string[];
p?: string;
e?: string;
};
export type NostrProvider = {
getPublicKey(): Promise<string>;
signEvent(event: Event & {
pubkey: string;
id: string;
}): Promise<Event>;
};
export type ZapOptions = {
nostr?: NostrProvider;
};
export type RequestInvoiceArgs = {
satoshi: number;
comment?: string;
payerdata?: LUD18PayerData;
};
export type KeysendResponse = {
customKey: string;
customValue: string;
destination: string;
};
export type KeySendRawData = {
tag: string;
status: string;
customData?: {
customKey?: string;
customValue?: string;
}[];
pubkey: string;
};
import { KeySendRawData, KeysendResponse, Event, NostrResponse, ZapArgs, ZapOptions, LnUrlPayResponse, LnUrlRawData } from "./types";
export declare const parseKeysendResponse: (data: KeySendRawData) => KeysendResponse;
export declare function generateZapEvent({ satoshi, comment, p, e, relays }: ZapArgs, options?: ZapOptions): Promise<Event>;
export declare function validateEvent(event: Event): boolean;
export declare function serializeEvent(evt: Event): string;
export declare function getEventHash(event: Event): string;
export declare function parseNostrResponse(nostrData: NostrResponse, username: string | undefined): readonly [NostrResponse, string | undefined, string[] | undefined];
export declare const isUrl: (url: string | null) => url is string;
export declare const isValidAmount: ({ amount, min, max, }: {
amount: number;
min: number;
max: number;
}) => boolean;
export declare const parseLnUrlPayResponse: (data: LnUrlRawData) => Promise<LnUrlPayResponse>;
import { BoostArguments, BoostOptions } from "./types";
export declare const sendBoostagram: (args: BoostArguments, options?: BoostOptions) => Promise<import("@webbtc/webln-types").SendPaymentResponse>;
export * from "./types";
export * from "./boostagrams";
export type BoostOptions = {
webln?: unknown;
};
export type BoostArguments = {
destination: string;
customKey?: string;
customValue?: string;
amount?: number;
boost: Boost;
};
export type WeblnBoostParams = {
destination: string;
amount: number;
customRecords: Record<string, string>;
};
export type Boost = {
action: string;
value_msat: number;
value_msat_total: number;
app_name: string;
app_version: string;
feedId: string;
podcast: string;
episode: string;
ts: number;
name: string;
sender_name: string;
};