@getalby/lightning-tools
Advanced tools
+1250
| '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;;;;;;;"} |
+1674
| '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;;;;"} |
+1246
| 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;;;;"} |
+1661
| 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; | ||
| }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1266896
699.66%35
45.83%10035
1149.69%2
-60%26
30%328
-0.61%65
27.45%