@getalby/lightning-tools
Version:
Collection of helpful building blocks and tools to develop Bitcoin Lightning web apps
6 lines (5 loc) • 37.4 kB
JavaScript
!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";function t(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 r(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 n=e=>e instanceof Uint8Array,o=e=>new DataView(e.buffer,e.byteOffset,e.byteLength),s=(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 i=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function a(e){if(!n(e))throw new Error("Uint8Array expected");let t="";for(let r=0;r<e.length;r++)t+=i[e[r]];return t}function c(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)),!n(e))throw new Error("expected Uint8Array, got "+typeof e);return e}class h{clone(){return this._cloneInto()}}function l(e){const t=t=>e().update(c(t)).digest(),r=e();return t.outputLen=r.outputLen,t.blockLen=r.blockLen,t.create=()=>e(),t}class u extends h{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=o(this.buffer)}update(e){t(this);const{view:r,buffer:n,blockLen:s}=this,i=(e=c(e)).length;for(let t=0;t<i;){const a=Math.min(s-this.pos,i-t);if(a===s){const r=o(e);for(;s<=i-t;t+=s)this.process(r,t);continue}n.set(e.subarray(t,t+a),this.pos),this.pos+=a,t+=a,this.pos===s&&(this.process(r,0),this.pos=0)}return this.length+=e.length,this.roundClean(),this}digestInto(e){t(this),r(e,this),this.finished=!0;const{buffer:n,view:s,blockLen:i,isLE:a}=this;let{pos:c}=this;n[c++]=128,this.buffer.subarray(c).fill(0),this.padOffset>i-c&&(this.process(s,0),c=0);for(let e=c;e<i;e++)n[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)}(s,i-8,BigInt(8*this.length),a),this.process(s,0);const h=o(e),l=this.outputLen;if(l%4)throw new Error("_sha2: outputLen should be aligned to 32bit");const u=l/4,f=this.get();if(u>f.length)throw new Error("_sha2: outputLen bigger than state");for(let e=0;e<u;e++)h.setUint32(4*e,f[e],a)}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 f=(e,t,r)=>e&t^~e&r,d=(e,t,r)=>e&t^e&r^t&r,p=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]),w=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),m=new Uint32Array(64);class y extends u{constructor(){super(64,32,8,!1),this.A=0|w[0],this.B=0|w[1],this.C=0|w[2],this.D=0|w[3],this.E=0|w[4],this.F=0|w[5],this.G=0|w[6],this.H=0|w[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)m[r]=e.getUint32(t,!1);for(let e=16;e<64;e++){const t=m[e-15],r=m[e-2],n=s(t,7)^s(t,18)^t>>>3,o=s(r,17)^s(r,19)^r>>>10;m[e]=o+m[e-7]+n+m[e-16]|0}let{A:r,B:n,C:o,D:i,E:a,F:c,G:h,H:l}=this;for(let e=0;e<64;e++){const t=l+(s(a,6)^s(a,11)^s(a,25))+f(a,c,h)+p[e]+m[e]|0,u=(s(r,2)^s(r,13)^s(r,22))+d(r,n,o)|0;l=h,h=c,c=a,a=i+t|0,i=o,o=n,n=r,r=t+u|0}r=r+this.A|0,n=n+this.B|0,o=o+this.C|0,i=i+this.D|0,a=a+this.E|0,c=c+this.F|0,h=h+this.G|0,l=l+this.H|0,this.set(r,n,o,i,a,c,h,l)}roundClean(){m.fill(0)}destroy(){this.set(0,0,0,0,0,0,0,0),this.buffer.fill(0)}}const g=l(()=>new y);var b,v,E,x={};var A=function(){if(E)return v;E=1;const{bech32:e,hex:t,utf8:r}=(b||(b=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 m=[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(m[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=m.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 y=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 v(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,y.encode(l([o%2**30],30,5,!1))}function E(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=y.decode(i).slice(0,-6),c=v(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${y.encode(r)}${v(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=E("bech32"),e.bech32m=E("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}(x)),x),n={bech32:"bc",pubKeyHash:0,scriptHash:5,validWitnessVersions:[0]},o={bech32:"tb",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},s={bech32:"tbs",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},i={bech32:"bcrt",pubKeyHash:111,scriptHash:196,validWitnessVersions:[0]},a={bech32:"sb",pubKeyHash:63,scriptHash:123,validWitnessVersions:[0]},c=["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"],h={m:BigInt(1e3),u:BigInt(1e6),n:BigInt(1e9),p:BigInt(1e12)},l=BigInt("2100000000000000000"),u=BigInt(1e11),f={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},d={};for(let e=0,t=Object.keys(f);e<t.length;e++){const r=t[e],n=f[t[e]].toString();d[n]=r}const p={1:r=>t.encode(e.fromWordsUnsafe(r)),16:r=>t.encode(e.fromWordsUnsafe(r)),13:t=>r.encode(e.fromWordsUnsafe(t)),19:r=>t.encode(e.fromWordsUnsafe(r)),23:r=>t.encode(e.fromWordsUnsafe(r)),27:r=>t.encode(e.fromWordsUnsafe(r)),6:m,24:m,3:function(r){const n=[];let o,s,i,a,c,h=e.fromWordsUnsafe(r);for(;h.length>0;)o=t.encode(h.slice(0,33)),s=t.encode(h.slice(33,41)),i=parseInt(t.encode(h.slice(41,45)),16),a=parseInt(t.encode(h.slice(45,49)),16),c=parseInt(t.encode(h.slice(49,51)),16),h=h.slice(51),n.push({pubkey:o,short_channel_id:s,fee_base_msat:i,fee_proportional_millionths:a,cltv_expiry_delta:c});return n},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*c.length;)t.push(!1);const r={};c.forEach((e,n)=>{let o;o=t[2*n]?"required":t[2*n+1]?"supported":"unsupported",r[e]=o});const n=t.slice(2*c.length);return r.extra_bits={start_bit:2*c.length,bits:n,has_required:n.reduce((e,t,r)=>r%2!=0?e||!1:e||t,!1)},r}};function w(t){return r=>({tagCode:parseInt(t),words:e.encode("unknown",r,Number.MAX_SAFE_INTEGER)})}function m(e){return e.reverse().reduce((e,t,r)=>e+t*Math.pow(32,r),0)}function y(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*u/h[r]:o*u;if("p"===r&&o%BigInt(10)!==BigInt(0)||s>l)throw new Error("Amount is outside of valid range");return t?s.toString():s}return v={decode:function(r,c){if("string"!=typeof r)throw new Error("Lightning Payment Request must be string");if("ln"!==r.slice(0,2).toLowerCase())throw new Error("Not a proper lightning payment request");const h=[],l=e.decode(r,Number.MAX_SAFE_INTEGER);r=r.toLowerCase();const u=l.prefix;let g=l.words,b=r.slice(u.length+1),v=g.slice(-104);g=g.slice(0,-104);let E=u.match(/^ln(\S+?)(\d*)([a-zA-Z]?)$/);if(E&&!E[2]&&(E=u.match(/^ln(\S+)$/)),!E)throw new Error("Not a proper lightning payment request");h.push({name:"lightning_network",letters:"ln"});const x=E[1];let A;if(c){if(void 0===c.bech32||void 0===c.pubKeyHash||void 0===c.scriptHash||!Array.isArray(c.validWitnessVersions))throw new Error("Invalid network");A=c}else switch(x){case n.bech32:A=n;break;case o.bech32:A=o;break;case s.bech32:A=s;break;case i.bech32:A=i;break;case a.bech32:A=a}if(!A||A.bech32!==x)throw new Error("Unknown coin bech32 prefix");h.push({name:"coin_network",letters:x,value:A});const k=E[2];let U;if(k){U=y(k+E[3],!0),h.push({name:"amount",letters:E[2]+E[3],value:U})}else U=null;h.push({name:"separator",letters:"1"});const $=m(g.slice(0,7));let L,I,N,R;for(g=g.slice(7),h.push({name:"timestamp",letters:b.slice(0,7),value:$}),b=b.slice(7);g.length>0;){const e=g[0].toString();L=d[e]||"unknown_tag",I=p[e]||w(e),g=g.slice(1),N=m(g.slice(0,2)),g=g.slice(2),R=g.slice(0,N),g=g.slice(N),h.push({name:L,tag:b[0],letters:b.slice(0,3+N),value:I(R)}),b=b.slice(3+N)}h.push({name:"signature",letters:b.slice(0,104),value:t.encode(e.fromWordsUnsafe(v))}),b=b.slice(104),h.push({name:"checksum",letters:b});let _={paymentRequest:r,sections:h,get expiry(){let e=h.find(e=>"expiry"===e.name);if(e)return S("timestamp")+e.value},get route_hints(){return h.filter(e=>"route_hint"===e.name).map(e=>e.value)}};for(let e in f)"route_hint"!==e&&Object.defineProperty(_,e,{get:()=>S(e)});return _;function S(e){let t=h.find(t=>t.name===e);return t?t.value:void 0}},hrpToMillisat:y}}();const k=e=>Uint8Array.from(e.match(/.{1,2}/g).map(e=>parseInt(e,16))),U=e=>{if(!e)return null;try{const t=A.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,s=0,i="0";const a=t.sections.find(e=>"amount"===e.name);"amount"===a?.name&&a.value&&(i=a.value,s=parseInt(a.value),o=parseInt(a.value)/1e3);const c=t.sections.find(e=>"timestamp"===e.name);if("timestamp"!==c?.name||!c.value)return null;const h=c.value;let l;const u=t.sections.find(e=>"expiry"===e.name);"expiry"===u?.name&&(l=u.value);const f=t.sections.find(e=>"description"===e.name);return{paymentHash:n,satoshi:o,millisatoshi:s,amountRaw:i,timestamp:h,expiry:l,description:"description"===f?.name?f?.value:void 0}}catch{return null}};function $(e,t){try{if(!/^[0-9a-fA-F]{64}$/.test(e))return!1;if(!/^[0-9a-fA-F]{64}$/.test(t))return!1;return t===a(g(k(e)))}catch{return!1}}class L{constructor(e){if(this.paymentRequest=e.pr,!this.paymentRequest)throw new Error("Invalid payment request");const t=U(this.paymentRequest);if(!t)throw new Error("Failed to decode payment request");this.paymentHash=t.paymentHash,this.satoshi=t.satoshi,this.millisatoshi=t.millisatoshi,this.amountRaw=t.amountRaw,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){return!(!e||!this.paymentHash)&&$(e,this.paymentHash)}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 I=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 N({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=S(c),await i.signEvent(c)}function R(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 _(e){if(!R(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 S(e){return a(g(_(e)))}function D(e,t){let r,n;return t&&e&&(r=e.names?.[t],n=r?e.relays?.[r]:void 0),[e,r,n]}const W=/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/,T=e=>!!e&&W.test(e),P=({amount:e,min:t,max:r})=>e>0&&e>=t&&e<=r,H=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=a(g(e.metadata+""))}catch{o=[],s=a(g("[]"))}let i="",c="",h="",l="";for(let e=0;e<o.length;e++){const[t,r]=o[e];switch(t){case"text/plain":h=r;break;case"text/identifier":l=r;break;case"text/email":i=r;break;case"image/png;base64":case"image/jpeg;base64":c="data:"+t+","+r}}const u=e.payerData;let f;try{f=new URL(t).hostname}catch{}return{callback:t,fixed:r===n,min:r,max:n,domain:f,metadata:o,metadataHash:s,identifier:l,email:i,description:h,image:c,payerData:u,commentAllowed:Number(e.commentAllowed)||0,rawData:e,allowsNostr:e.allowsNostr||!1}},C=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)},B=/^((?:[^<>()[\]\\.,;:\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,}))$/,O="https://api.getalby.com/lnurl";function j(e,t){return{payInvoice:async r=>{const n=new L({pr:r.invoice});if(n.satoshi>t)throw new Error(`Invoice amount (${n.satoshi} sats) exceeds maxAmount (${t} sats)`);return e.payInvoice(r)}}}const q=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];if(!r.token&&r.macaroon&&(r.token=r.macaroon,delete r.macaroon),!("token"in r)||"string"!=typeof r.token)throw new Error("No macaroon or token found in www-authenticate header");if(!("invoice"in r)||"string"!=typeof r.invoice)throw new Error("No invoice found in www-authenticate header");return r},F=async(e,t,r,n,o)=>{const s=q(e),i=s.token||s.macaroon,a=s.invoice;if(!i)throw new Error("L402: missing token/macaroon in WWW-Authenticate header");if(!a)throw new Error("L402: missing invoice in WWW-Authenticate header");const c=await o.payInvoice({invoice:a});return n.set("Authorization",`L402 ${i}:${c.preimage}`),fetch(t,r)},K=e=>{let t;try{t=JSON.parse(decodeURIComponent(escape(atob(e))))}catch(e){throw new Error("x402: invalid PAYMENT-REQUIRED header (not valid base64-encoded JSON)")}if(!Array.isArray(t.accepts)||0===t.accepts.length)throw new Error("x402: PAYMENT-REQUIRED header contains no payment options");return{accepts:t.accepts}},M=e=>{let t;try{({accepts:t}=K(e))}catch(e){return null}const r=t.find(e=>"lightning"===e?.extra?.paymentMethod);return r?.extra?.invoice?r:null},V=async(e,t,r,n,o)=>{const{accepts:s}=K(e),i=s.find(e=>"lightning"===e?.extra?.paymentMethod);if(!i)throw new Error("x402: unsupported x402 network, only Bitcoin lightning network is supported.");if(!i.extra?.invoice)throw new Error("x402: payment requirements missing lightning invoice");const a=new L({pr:i.extra.invoice});if(a.amountRaw!=i.amount)throw new Error(`Invalid invoice amount: ${a.amountRaw}. expected ${i.amount}`);return await o.payInvoice({invoice:a.paymentRequest}),n.set("payment-signature",((e,t,r,n)=>{const o=JSON.stringify({x402Version:2,scheme:e,network:t,payload:{invoice:r},accepted:n});return btoa(unescape(encodeURIComponent(o)))})(i.scheme,i.network,a.paymentRequest,i)),fetch(t,r)},z=e=>{if(!e.trimStart().toLowerCase().startsWith("payment"))return null;const t=e.slice(e.toLowerCase().indexOf("payment")+7).trim(),r={},n=/(\w+)=("([^"]*)"|'([^']*)'|([^,\s]*))/g;let o;for(;null!==(o=n.exec(t));)r[o[1]]=o[3]??o[4]??o[5]??"";return"lightning"===r.method&&"charge"===r.intent&&r.id&&r.realm&&r.request?{id:r.id,realm:r.realm,method:r.method,intent:r.intent,request:r.request,...r.expires?{expires:r.expires}:{}}:null},J=e=>{if(null===e||"object"!=typeof e)return JSON.stringify(e);if(Array.isArray(e))return"["+e.map(J).join(",")+"]";return"{"+Object.keys(e).sort().map(t=>JSON.stringify(t)+":"+J(e[t])).join(",")+"}"},G=(e,t,r)=>{const n={id:e.id,intent:e.intent,method:e.method,realm:e.realm,request:e.request};e.expires&&(n.expires=e.expires);return(e=>{const t=(new TextEncoder).encode(e);let r="";for(let e=0;e<t.length;e++)r+=String.fromCharCode(t[e]);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")})(J({challenge:n,payload:{preimage:t}}))},Z=async(e,t,r,n,o)=>{const s=z(e);if(!s)throw new Error("mpp: invalid or unsupported WWW-Authenticate challenge (expected Payment method=lightning intent=charge)");let i;try{i=JSON.parse((e=>{const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=atob(t),n=new Uint8Array(r.length);for(let e=0;e<r.length;e++)n[e]=r.charCodeAt(e);return new TextDecoder("utf-8").decode(n)})(s.request))}catch(e){throw new Error("mpp: invalid request auth-param (not valid base64url-encoded JSON)")}const a=i.methodDetails?.invoice;if(!a)throw new Error("mpp: missing invoice in charge request");const c=await o.payInvoice({invoice:a}),h=G(s,c.preimage);return n.set("Authorization",`Payment ${h}`),fetch(t,r)};async function X(e,t){const{createHmac:r}=await import("crypto");return r("sha256",e).update(t).digest("hex")}const Y=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},Q=async({satoshi:e,currency:t})=>{const r=await Y(t);return Number(e)*r};e.DEFAULT_PROXY=O,e.Invoice=L,e.LN_ADDRESS_REGEX=B,e.LightningAddress=class{constructor(e,t){this.address=e,this.options={proxy:O},this.options=Object.assign(this.options,t),this.parse(),this.webln=this.options.webln}parse(){const e=B.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 L(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 C({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 N({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 H(e))}parseKeysendResponse(e){e&&(this.keysendData=I(e))}parseNostrResponse(e){e&&([this.nostrData,this.nostrPubkey,this.nostrRelays]=D(e,this.username))}},e.createGuardedWallet=j,e.decodeInvoice=U,e.fetch402=async(e,t,r)=>{const n=r.maxAmount?j(r.wallet,r.maxAmount):r.wallet;t||(t={}),t.cache="no-store",t.mode="cors";const o=new Headers(t.headers??void 0);t.headers=o;const s=await fetch(e,t),i=s.headers.get("www-authenticate");if(i){const r=i.trimStart().toLowerCase();if(r.startsWith("l402")||r.startsWith("lsat"))return F(i,e,t,o,n)}if(i&&z(i))return Z(i,e,t,o,n);const a=s.headers.get("PAYMENT-REQUIRED");return a&&M(a)?V(a,e,t,o,n):s},e.fetchWithL402=async(e,t,r)=>{const n=r.wallet;if(!n)throw new Error("wallet is missing");t||(t={}),t.cache="no-store",t.mode="cors";const o=new Headers(t.headers??void 0);t.headers=o;const s=await fetch(e,t),i=s.headers.get("www-authenticate");return i?F(i,e,t,o,n):s},e.fetchWithMpp=async(e,t,r)=>{const n=r.wallet;if(!n)throw new Error("wallet is missing");t||(t={}),t.cache="no-store",t.mode="cors";const o=new Headers(t.headers??void 0);t.headers=o;const s=await fetch(e,t),i=s.headers.get("www-authenticate");return i&&i.trimStart().toLowerCase().startsWith("payment")?Z(i,e,t,o,n):s},e.fetchWithX402=async(e,t,r)=>{const n=r.wallet;t||(t={}),t.cache="no-store",t.mode="cors";const o=new Headers(t.headers??void 0);t.headers=o;const s=await fetch(e,t),i=s.headers.get("PAYMENT-REQUIRED");return i?V(i,e,t,o,n):s},e.findX402LightningRequirements=M,e.fromHexString=k,e.generateZapEvent=N,e.getEventHash=S,e.getFiatBtcRate=Y,e.getFiatCurrencies=async()=>{const e=await fetch("https://getalby.com/api/rates");if(!e.ok)throw new Error(`Failed to fetch currencies: ${e.status} ${e.statusText}`);const t=await e.json();return Object.entries(t).filter(([e])=>"BTC"!==e.toUpperCase()).map(([e,t])=>({code:e.toUpperCase(),name:t.name,priority:t.priority,symbol:t.symbol})).sort((e,t)=>e.name.localeCompare(t.name)).sort((e,t)=>e.priority-t.priority)},e.getFiatValue=Q,e.getFormattedFiatValue=async({satoshi:e,currency:t,locale:r})=>{r||(r="en");return(await Q({satoshi:e,currency:t})).toLocaleString(r,{style:"currency",currency:t})},e.getSatoshiValue=async({amount:e,currency:t})=>{const r=await Y(t);return Math.floor(Number(e)/r)},e.isUrl=T,e.isValidAmount=P,e.issueL402Macaroon=async function(e,t,r){if(void 0!==r&&Object.prototype.hasOwnProperty.call(r,"paymentHash"))throw new Error("paymentHash is reserved");const n={...r,paymentHash:t},o=Buffer.from(JSON.stringify(n)).toString("base64url");return`${o}.${await X(e,o)}`},e.makeL402AuthenticateHeader=e=>{if(!e.token)throw new Error("token must be provided");return`L402 version="0" token="${e.token}", invoice="${e.invoice}"`},e.parseKeysendResponse=I,e.parseL402=q,e.parseL402Authorization=function(e){const t=e.replace(/^LSAT /,"L402 "),r="L402 ";if(!t.startsWith(r))return null;const n=t.slice(5),o=n.indexOf(":");if(-1===o)throw new Error("Invalid authorization header value");return{token:n.slice(0,o),preimage:n.slice(o+1)}},e.parseLnUrlPayResponse=H,e.parseNostrResponse=D,e.sendBoostagram=C,e.serializeEvent=_,e.validateEvent=R,e.validatePreimage=$,e.verifyL402Macaroon=async function(e,t){const{timingSafeEqual:r}=await import("crypto"),n=t.lastIndexOf(".");if(-1===n)throw new Error("Invalid macaroon token");const o=t.slice(0,n),s=t.slice(n+1),i=await X(e,o);try{if(!r(Buffer.from(s,"hex"),Buffer.from(i,"hex")))throw new Error("Invalid macaroon token")}catch(e){throw new Error("Invalid macaroon token")}try{const e=JSON.parse(Buffer.from(o,"base64url").toString("utf8"));if(null===e||"object"!=typeof e||Array.isArray(e)||"string"!=typeof e.paymentHash)throw new Error("Invalid macaroon payload");return e}catch{throw new Error("Invalid macaroon token")}}});
//# sourceMappingURL=lightning-tools.umd.js.map