From 1463d75ee2e176804fda43bd03168053bd86fa3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Thu, 13 Nov 2025 15:37:59 +0100 Subject: [PATCH] refactor: move _api_docs.html into vue component (#3520) --- lnbits/core/templates/core/_api_docs.html | 305 ----------------- lnbits/core/templates/core/wallet.html | 2 +- lnbits/static/bundle-components.min.js | 2 +- lnbits/static/js/components.js | 22 -- .../js/components/lnbits-wallet-api-docs.js | 47 +++ .../js/components/lnbits-wallet-list.js | 21 ++ lnbits/static/js/wallet.js | 34 -- lnbits/static/vendor.json | 2 + lnbits/templates/components.vue | 95 +----- .../components/lnbits-wallet-api-docs.vue | 319 ++++++++++++++++++ .../components/lnbits-wallet-list.vue | 90 +++++ package.json | 2 + 12 files changed, 486 insertions(+), 455 deletions(-) delete mode 100644 lnbits/core/templates/core/_api_docs.html create mode 100644 lnbits/static/js/components/lnbits-wallet-api-docs.js create mode 100644 lnbits/static/js/components/lnbits-wallet-list.js create mode 100644 lnbits/templates/components/lnbits-wallet-api-docs.vue create mode 100644 lnbits/templates/components/lnbits-wallet-list.vue diff --git a/lnbits/core/templates/core/_api_docs.html b/lnbits/core/templates/core/_api_docs.html deleted file mode 100644 index a0309b1a..00000000 --- a/lnbits/core/templates/core/_api_docs.html +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - Node URL: - - - - - - - Wallet ID: - - - - - - - - - - Admin key: - - - -
- - - - -
- -
-
-
-
-
-
- - - - Invoice/read key: - - - -
- - - - -
- -
-
-
-
-
-
-
-
- - - - GET /api/v1/wallet -
Headers
- {"X-Api-Key": ""}
-
- Returns 200 OK (application/json) -
- {"id": <string>, "name": <string>, "balance": - <int>} -
Curl example
- curl api/v1/wallet -H "X-Api-Key: - " -
-
-
- - - - - POST /api/v1/payments -
Headers
- {"X-Api-Key": ""}
-
Body (application/json)
- {"out": false, "amount": <int>, "memo": <string>, - "expiry": <int>, "unit": <string>, "webhook": - <url:string>, "internal": <bool>} -
- Returns 201 CREATED (application/json) -
- {"payment_hash": <string>, "payment_request": - <string>} -
Curl example
- curl -X POST api/v1/payments -d - '{"out": false, "amount": <int>, "memo": <string>}' -H - "X-Api-Key: - " -H - "Content-type: application/json" -
-
-
- - - - POST /api/v1/payments (reveal - admin keys - ) -
Headers
- {"X-Api-Key": ""} -
Body (application/json)
- {"out": true, "bolt11": <string>} -
- Returns 201 CREATED (application/json) -
- {"payment_hash": <string>} -
Curl example
- curl -X POST api/v1/payments -d - '{"out": true, "bolt11": <string>}' -H "X-Api-Key: - " -H "Content-type: application/json" -
-
-
- - - - - POST - /api/v1/payments/decode -
Body (application/json)
- {"data": <string>} -
- Returns 200 (application/json) -
-
Curl example
- curl -X POST api/v1/payments/decode -d - '{"data": <bolt11/lnurl, string>}' -H "Content-type: - application/json" -
-
-
- - - - GET - /api/v1/payments/<payment_hash> -
Headers
- {"X-Api-Key": ""} -
- Returns 200 OK (application/json) -
- {"paid": <bool>} -
Curl example
- curl -X GET - api/v1/payments/<payment_hash> -H - "X-Api-Key: - " -H - "Content-type: application/json" -
-
- - - WS - /api/v1/ws/<invoice_key> -
- wscat -c / -
- Returns 200 OK (application/json)/payments -
- {"balance": <int>, "payment": <object>} -
-
-
- - -

- -
-
diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html index e6b0ad6e..b773a8d4 100644 --- a/lnbits/core/templates/core/wallet.html +++ b/lnbits/core/templates/core/wallet.html @@ -532,7 +532,7 @@ - {% include "core/_api_docs.html" %} + diff --git a/lnbits/static/bundle-components.min.js b/lnbits/static/bundle-components.min.js index 160edd07..d9b18019 100644 --- a/lnbits/static/bundle-components.min.js +++ b/lnbits/static/bundle-components.min.js @@ -1 +1 @@ -window.PageHome={template:"#page-home",mixins:[window.windowMixin],data:()=>({lnurl:"",authAction:"login",authMethod:"username-password",usr:"",username:"",reset_key:"",email:"",password:"",passwordRepeat:"",walletName:"",signup:!1}),computed:{showClaimLnurl(){return""!==this.lnurl&&this.allowRegister&&"user-id-only"in this.LNBITS_AUTH_METHODS},formatDescription(){return LNbits.utils.convertMarkdown(this.SITE_DESCRIPTION)},isAccessTokenExpired(){return this.$q.cookies.get("is_access_token_expired")},allowRegister(){return this.LNBITS_NEW_ACCOUNTS_ALLOWED},hasCustomImage(){return this.LNBITS_CUSTOM_IMAGE},showHomepageElements(){return this.HOMEPAGE_ELEMENTS_ENABLED},siteTitle(){return this.SITE_TITLE||""},siteTagline(){return this.SITE_TAGLINE||""},adsEnabled(){return this.AD_SPACE_ENABLED&&this.AD_SPACE&&this.AD_SPACE.length>0},adsTitle(){return this.AD_SPACE_TITLE||""},ads(){return this.AD_SPACE.map((e=>e.split(";")))},lnbitsBannerEnabled(){return"sats"==this.LNBITS_DENOMINATION&&"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}},methods:{showLogin(e){this.authAction="login",this.authMethod=e},showRegister(e){this.user="",this.username=null,this.password=null,this.passwordRepeat=null,this.authAction="register",this.authMethod=e},async register(){try{await LNbits.api.register(this.username,this.email,this.password,this.passwordRepeat),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async reset(){try{await LNbits.api.reset(this.reset_key,this.password,this.passwordRepeat),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async login(){try{await LNbits.api.login(this.username,this.password),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async loginUsr(){try{await LNbits.api.loginUsr(this.usr),this.usr="",window.location.href="/wallet"}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},createWallet(){LNbits.api.createAccount(this.walletName).then((e=>{window.location="/wallet?usr="+e.data.user+"&wal="+e.data.id}))},processing(){Quasar.Notify.create({timeout:0,message:"Processing...",icon:null})}},created(){this.g.isUserAuthorized&&(window.location.href="/wallet");const e=new URLSearchParams(window.location.search);this.reset_key=e.get("reset_key"),this.reset_key&&(this.authAction="reset"),e.has("lightning")&&(this.lnurl=e.get("lightning"))}},window.PageExtensionBuilder={template:"#page-extension-builder",mixins:[windowMixin],data:()=>({step:1,previewStepNames:{2:"settings",3:"owner_data",4:"client_data",5:"public_page"},extensionDataCleanString:"",extensionData:{id:"",name:"",stub_version:"",short_description:"",description:"",public_page:{has_public_page:!0,owner_data_fields:{name:"",description:""},client_data_fields:{public_inputs:[]},action_fields:{generate_action:!0,generate_payment_logic:!1,wallet_id:"",currency:"",amount:"",paid_flag:""}},preview_action:{is_preview_mode:!1,is_settings_preview:!1,is_owner_data_preview:!1,is_client_data_preview:!1,is_public_page_preview:!1},settings_data:{name:"Settings",enabled:!0,type:"user",fields:[]},owner_data:{name:"OwnerData",fields:[]},client_data:{enabled:!0,name:"ClientData",fields:[]}},sampleField:{name:"name",type:"str",label:"Name",hint:"",optional:!0,editable:!0,searchable:!0,sortable:!0},settingsTypes:[{label:"User Settings",value:"user"},{label:"Admin Settings",value:"admin"}],amountSource:[{label:"Client Data",value:"client_data"},{label:"Owner Data",value:"owner_data"}],extensionStubVersions:[]}),watch:{"extensionData.public_page.action_fields.amount_source":function(e,t){t&&e!==t&&(this.extensionData.public_page.action_fields.amount="")}},computed:{paymentActionAmountFields(){const e=this.extensionData.public_page.action_fields.amount_source;return e?"owner_data"===e?[""].concat(this.extensionData.owner_data.fields.filter((e=>"int"===e.type||"float"===e.type)).map((e=>e.name))):"client_data"===e?[""].concat(this.extensionData.client_data.fields.filter((e=>"int"===e.type||"float"===e.type)).map((e=>e.name))):void 0:[""]}},methods:{saveState(){this.$q.localStorage.set("lnbits.extension.builder.data",JSON.stringify(this.extensionData)),this.$q.localStorage.set("lnbits.extension.builder.step",this.step)},nextStep(){this.saveState(),this.$refs.stepper.next(),this.refreshPreview()},previousStep(){this.saveState(),this.$refs.stepper.previous(),this.refreshPreview()},onStepChange(){this.saveState(),this.refreshPreview()},clearAllData(){LNbits.utils.confirmDialog("Are you sure you want to clear all data? This action cannot be undone.").onOk((()=>{this.extensionData=JSON.parse(this.extensionDataCleanString),this.$q.localStorage.remove("lnbits.extension.builder.data"),this.$refs.stepper.set(1)}))},exportJsonData(){!0!==Quasar.exportFile(`${this.extensionData.id||"data-export"}.json`,JSON.stringify(this.extensionData,null,2),"text/json")?Quasar.Notify.create({message:"Browser denied file download...",color:"negative",icon:null}):Quasar.Notify.create({message:"File downloaded!",color:"positive",icon:"file_download"})},onJsonDataInput(e){const t=e.target.files[0],a=new FileReader;a.onload=e=>{this.extensionData={...this.extensionData,...JSON.parse(e.target.result)},this.$refs.extensionDataInput.value=null,Quasar.Notify.create({message:"File loaded!",color:"positive",icon:"file_upload"})},a.readAsText(t)},async buildExtension(){try{const e={responseType:"blob"},t=await LNbits.api.request("POST","/api/v1/extension/builder/zip",null,this.extensionData,e),a=window.URL.createObjectURL(new Blob([t.data])),s=document.createElement("a");s.href=a,s.download=`${this.extensionData.id||"lnbits-extension"}.zip`,document.body.appendChild(s),s.click(),s.remove(),window.URL.revokeObjectURL(a)}catch(e){LNbits.utils.notifyApiError(e)}},async buildExtensionAndDeploy(){try{const{data:e}=await LNbits.api.request("POST","/api/v1/extension/builder/deploy",null,this.extensionData);Quasar.Notify.create({message:e.message||"Extension deployed!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},async cleanCacheData(){LNbits.utils.confirmDialog("Are you sure you want to clean the cache data? This action cannot be undone.","Clean Cache Data").onOk((async()=>{try{const{data:e}=await LNbits.api.request("DELETE","/api/v1/extension/builder",null,{});Quasar.Notify.create({message:e.message||"Cache data cleaned!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}}))},async previewExtension(e){this.saveState();try{await LNbits.api.request("POST","/api/v1/extension/builder/preview",null,{...this.extensionData,preview_action:{is_preview_mode:!!e,is_settings_preview:"settings"===e,is_owner_data_preview:"owner_data"===e,is_client_data_preview:"client_data"===e,is_public_page_preview:"public_page"===e}}),this.refreshIframe(e)}catch(e){LNbits.utils.notifyApiError(e)}},async refreshPreview(){setTimeout((()=>{const e=this.previewStepNames[`${this.step}`]||"";e&&this.previewExtension(e)}),100)},async getStubExtensionReleases(){try{const e="extension_builder_stub",{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e}/releases`);this.extensionStubVersions=t.sort(((e,t)=>e.version{const e=t.contentDocument||t.contentWindow.document;e.body.style.transform="scale(0.8)",e.body.style.transformOrigin="center top"},t.src=`/extensions/builder/preview/${this.extensionData.id}?page_name=${e}`):console.warn("Extension Builder Preview iframe not loaded yet.")},initBasicData(){this.extensionData.owner_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.client_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.settings_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionDataCleanString=JSON.stringify(this.extensionData)}},created(){this.initBasicData();const e=this.$q.localStorage.getItem("lnbits.extension.builder.data");e&&(this.extensionData={...this.extensionData,...JSON.parse(e)});const t=+this.$q.localStorage.getItem("lnbits.extension.builder.step");t&&(this.step=t),this.g.user.admin&&this.getStubExtensionReleases(),setTimeout((()=>{this.refreshIframe()}),1e3)}},window.PageExtensions={template:"#page-extensions",mixins:[windowMixin],data:()=>({extbuilderEnabled:!1,slide:0,fullscreen:!1,autoplay:!0,searchTerm:"",tab:"all",manageExtensionTab:"releases",filteredExtensions:null,updatableExtensions:[],showUninstallDialog:!1,showManageExtensionDialog:!1,showExtensionDetailsDialog:!1,showDropDbDialog:!1,showPayToEnableDialog:!1,showUpdateAllDialog:!1,dropDbExtensionId:"",selectedExtension:null,selectedImage:null,selectedExtensionDetails:null,selectedExtensionRepos:null,selectedRelease:null,uninstallAndDropDb:!1,maxStars:5,paylinkWebsocket:null,user:null}),watch:{searchTerm(e){this.filterExtensions(e,this.tab)}},methods:{handleTabChanged(e){this.filterExtensions(this.searchTerm,e)},filterExtensions(e,t){var a;this.filteredExtensions=this.extensions.filter((e=>"all"!==t||!e.isInstalled)).filter((e=>"installed"!==t||e.isInstalled)).filter((e=>"installed"!==t||(!!e.isActive||!!this.g.user.admin))).filter((e=>"featured"!==t||e.isFeatured)).filter((a=e,function(e){return e.name.toLowerCase().includes(a.toLowerCase())||e.shortDescription?.toLowerCase().includes(a.toLowerCase())})).map((e=>({...e,details_link:e.installedRelease?.details_link||e.latestRelease?.details_link}))),this.tab=t},async installExtension(e){this.unsubscribeFromPaylinkWs();const t=this.selectedExtension;t.inProgress=!0,this.showManageExtensionDialog=!1,e.payment_hash=e.payment_hash||this.getPaylinkHash(e.pay_link),LNbits.api.request("POST","/api/v1/extension",this.g.user.wallets[0].adminkey,{ext_id:t.id,archive:e.archive,source_repo:e.source_repo,payment_hash:e.payment_hash,version:e.version}).then((a=>{t.isAvailable=!0,t.isInstalled=!0,t.installedRelease=e,this.toggleExtension(t),t.inProgress=!1,this.filteredExtensions=this.extensions.concat([]),this.handleTabChanged("installed"),this.tab="installed",this.refreshRoute()})).catch((e=>{console.warn(e),t.inProgress=!1,LNbits.utils.notifyApiError(e)}))},async uninstallExtension(){const e=this.selectedExtension;this.showManageExtensionDialog=!1,this.showUninstallDialog=!1,e.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${e.id}`,this.g.user.wallets[0].adminkey).then((t=>{e.isAvailable=!1,e.isInstalled=!1,e.inProgress=!1,e.installedRelease=null,this.filteredExtensions=this.extensions.concat([]),this.handleTabChanged("installed"),this.tab="installed",Quasar.Notify.create({type:"positive",message:"Extension uninstalled!"}),this.uninstallAndDropDb?this.showDropDb():setTimeout((()=>{this.refreshRoute()}),300)})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},async dropExtensionDb(){const e=this.selectedExtension;this.showManageExtensionDialog=!1,this.showDropDbDialog=!1,this.dropDbExtensionId="",e.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${e.id}/db`,this.g.user.wallets[0].adminkey).then((t=>{e.installedRelease=null,e.inProgress=!1,e.hasDatabaseTables=!1,Quasar.Notify.create({type:"positive",message:"Extension DB deleted!"}),setTimeout((()=>{this.refreshRoute()}),300)})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},toggleExtension(e){const t=e.isActive?"activate":"deactivate";LNbits.api.request("PUT",`/api/v1/extension/${e.id}/${t}`,this.g.user.wallets[0].adminkey).then((a=>{Quasar.Notify.create({timeout:2e3,type:"positive",message:`Extension '${e.id}' ${t}d!`})})).catch((t=>{LNbits.utils.notifyApiError(t),e.isActive=!1,e.inProgress=!1}))},async enableExtensionForUser(e){e.isPaymentRequired?this.showPayToEnable(e):this.enableExtension(e)},async enableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/enable`,this.g.user.wallets[0].adminkey).then((t=>{this.g.user.extensions=this.g.user.extensions.concat([e.id]),Quasar.Notify.create({type:"positive",message:"Extension enabled!"})})).catch((e=>{console.warn(e),LNbits.utils.notifyApiError(e)}))},disableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/disable`,this.g.user.wallets[0].adminkey).then((t=>{this.g.user.extensions=this.g.user.extensions.filter((t=>t!==e.id)),Quasar.Notify.create({type:"positive",message:"Extension disabled!"})})).catch((e=>{console.warn(error),LNbits.utils.notifyApiError(e)}))},showPayToEnable(e){this.selectedExtension=e,this.selectedExtension.payToEnable.paidAmount=e.payToEnable.amount,this.selectedExtension.payToEnable.showQRCode=!1,this.showPayToEnableDialog=!0},updatePayToInstallData(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/sell`,this.g.user.wallets[0].adminkey,{required:e.payToEnable.required,amount:e.payToEnable.amount,wallet:e.payToEnable.wallet}).then((e=>{Quasar.Notify.create({type:"positive",message:"Payment info updated!"}),this.showManageExtensionDialog=!1})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},showUninstall(){this.showManageExtensionDialog=!1,this.showUninstallDialog=!0,this.uninstallAndDropDb=!1},showDropDb(){this.showDropDbDialog=!0},async showManageExtension(e){this.selectedExtension=e,this.selectedRelease=null,this.selectedExtensionRepos=null,this.manageExtensionTab="releases",this.showManageExtensionDialog=!0;try{const{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e.id}/releases`,this.g.user.wallets[0].adminkey);this.selectedExtensionRepos=t.reduce(((e,t)=>(e[t.source_repo]=e[t.source_repo]||{releases:[],isInstalled:!1,repo:t.repo},t.inProgress=!1,t.error=null,t.loaded=!1,t.isInstalled=this.isInstalledVersion(this.selectedExtension,t),t.isInstalled&&(e[t.source_repo].isInstalled=!0),t.pay_link&&(t.requiresPayment=!0,t.paidAmount=t.cost_sats,t.payment_hash=this.getPaylinkHash(t.pay_link)),e[t.source_repo].releases.push(t),e)),{})}catch(t){LNbits.utils.notifyApiError(t),e.inProgress=!1}},async showExtensionDetails(e,t){if(t){this.selectedExtensionDetails=null,this.showExtensionDetailsDialog=!0,this.slide=0,this.fullscreen=!1;try{const{data:a}=await LNbits.api.request("GET",`/api/v1/extension/${e}/details?details_link=${t}`,this.g.user.wallets[0].inkey);this.selectedExtensionDetails=a,this.selectedExtensionDetails.description_md=LNbits.utils.convertMarkdown(a.description_md)}catch(e){console.warn(e)}}},async payAndInstall(e){try{this.selectedExtension.inProgress=!0,this.showManageExtensionDialog=!1;const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.rememberPaylinkHash(e.pay_link,t.payment_hash);const a=this.g.user.wallets.find((t=>t.id===e.wallet)),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);e.payment_hash=s.payment_hash,await this.installExtension(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.selectedExtension.inProgress=!1}},async payAndEnable(e){try{const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount),a=this.g.user.wallets.find((t=>t.id===e.payToEnable.paymentWallet)),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);this.enableExtension(e),this.showPayToEnableDialog=!1}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showInstallQRCode(e){this.selectedRelease=e;try{const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.selectedRelease.paymentRequest=t.payment_request,this.selectedRelease.payment_hash=t.payment_hash,this.selectedRelease=_.clone(this.selectedRelease),this.rememberPaylinkHash(this.selectedRelease.pay_link,this.selectedRelease.payment_hash),this.subscribeToPaylinkWs(this.selectedRelease.pay_link,t.payment_hash)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showEnableQRCode(e){try{e.payToEnable.showQRCode=!0,this.selectedExtension=_.clone(e);const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount);e.payToEnable.paymentRequest=t.payment_request,this.selectedExtension=_.clone(e);const a=new URL(window.location);a.protocol="https:"===a.protocol?"wss":"ws",a.pathname=`/api/v1/ws/${t.payment_hash}`;const s=new WebSocket(a);s.addEventListener("message",(async({data:t})=>{!1===JSON.parse(t).pending&&(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.enableExtension(e),s.close())}))}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async requestPaymentForInstall(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/install`,this.g.user.wallets[0].adminkey,{ext_id:e,archive:t.archive,source_repo:t.source_repo,cost_sats:t.paidAmount,version:t.version});return a},async requestPaymentForEnable(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/enable`,this.g.user.wallets[0].adminkey,{amount:t});return a},clearHangingInvoice(e){this.forgetPaylinkHash(e.pay_link),e.payment_hash=null},rememberPaylinkHash(e,t){this.$q.localStorage.set(`lnbits.extensions.paylink.${e}`,t)},getPaylinkHash(e){return this.$q.localStorage.getItem(`lnbits.extensions.paylink.${e}`)},forgetPaylinkHash(e){this.$q.localStorage.remove(`lnbits.extensions.paylink.${e}`)},subscribeToPaylinkWs(e,t){const a=new URL(`${e}/${t}`);a.protocol="https:"===a.protocol?"wss":"ws",this.paylinkWebsocket=new WebSocket(a),this.paylinkWebsocket.addEventListener("message",(async({data:e})=>{JSON.parse(e).paid?(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.installExtension(this.selectedRelease)):Quasar.Notify.create({type:"warning",message:"Invoice tracking lost!"})}))},unsubscribeFromPaylinkWs(){try{this.paylinkWebsocket&&this.paylinkWebsocket.close()}catch(e){console.warn(e)}},hasNewVersion(e){if(e.installedRelease&&e.latestRelease)return e.installedRelease.version!==e.latestRelease.version},isInstalledVersion(e,t){if(e.installedRelease)return e.installedRelease.source_repo===t.source_repo&&e.installedRelease.version===t.version},getReleaseIcon:e=>e.is_version_compatible?e.isInstalled?"download_done":"download":"block",getReleaseIconColor:e=>e.is_version_compatible?e.isInstalled?"text-green":"":"text-red",async getGitHubReleaseDetails(e){if(!e.is_github_release||e.loaded)return;const[t,a]=e.source_repo.split("/");e.inProgress=!0;try{const{data:s}=await LNbits.api.request("GET",`/api/v1/extension/release/${t}/${a}/${e.version}`,this.g.user.wallets[0].adminkey);e.loaded=!0,e.is_version_compatible=s.is_version_compatible,e.min_lnbits_version=s.min_lnbits_version,e.warning=s.warning}catch(t){console.warn(t),e.error=t,LNbits.utils.notifyApiError(t)}finally{e.inProgress=!1}},async selectAllUpdatableExtensionss(){this.updatableExtensions.forEach((e=>e.selectedForUpdate=!0))},async updateSelectedExtensions(){let e=0;for(const t of this.updatableExtensions)try{if(!t.selectedForUpdate)continue;t.inProgress=!0,await LNbits.api.request("POST","/api/v1/extension",this.g.user.wallets[0].adminkey,{ext_id:t.id,archive:t.latestRelease.archive,source_repo:t.latestRelease.source_repo,payment_hash:t.latestRelease.payment_hash,version:t.latestRelease.version}),e++,t.isAvailable=!0,t.isInstalled=!0,t.isUpgraded=!0,t.inProgress=!1,t.installedRelease=t.latestRelease,t.isActive=!0,this.toggleExtension(t)}catch(e){console.warn(e),Quasar.Notify.create({type:"negative",message:`Failed to update ${t.id}!`})}finally{t.inProgress=!1}Quasar.Notify.create({type:e?"positive":"warning",message:`${e||"No"} extensions updated!`}),this.showUpdateAllDialog=!1,setTimeout((()=>{this.refreshRoute()}),2e3)},async fetchAllExtensions(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension/all");return e}catch(e){return console.warn(e),LNbits.utils.notifyApiError(e),[]}}},async created(){this.extensions=await this.fetchAllExtensions(),this.extbuilderEnabled=user.admin||this.LNBITS_EXT_BUILDER,this.filteredExtensions=this.extensions.concat([]);const e=window.location.hash.replace("#",""),t=this.filteredExtensions.find((t=>t.id===e));if(t)this.searchTerm=t.id,this.handleTabChanged(t.isInstalled?"installed":"all"),this.tab=t.isInstalled?"installed":"all";else{const e=this.filteredExtensions.some((e=>e.isInstalled));this.handleTabChanged(e?"installed":"all"),this.tab=e?"installed":"all"}this.updatableExtensions=this.extensions.filter((e=>this.hasNewVersion(e)))}},window.PageFirstInstall={template:"#page-first-install",mixins:[window.windowMixin],data:()=>({loginData:{isPwd:!0,isPwdRepeat:!0,username:"",password:"",passwordRepeat:""}}),computed:{checkPasswordsMatch(){return this.loginData.password!==this.loginData.passwordRepeat}},methods:{async setPassword(){try{await LNbits.api.request("PUT","/api/v1/auth/first_install",null,{username:this.loginData.username,password:this.loginData.password,password_repeat:this.loginData.passwordRepeat}),window.location.href="/admin"}catch(e){LNbits.utils.notifyApiError(e)}}},created(){document.title="First Install - LNbits"}},window.PagePayments={template:"#page-payments",mixins:[window.windowMixin],data:()=>({payments:[],dailyChartData:[],searchDate:{from:null,to:null},searchData:{wallet_id:null,payment_hash:null,memo:null,internal_memo:null},statusFilters:{success:!0,pending:!0,failed:!0,incoming:!0,outgoing:!0},chartData:{showPaymentStatus:!0,showPaymentTags:!0,showBalance:!0,showWalletsSize:!1,showBalanceInOut:!1,showPaymentCountInOut:!1},searchOptions:{status:[]},paymentsTable:{columns:[{name:"status",align:"left",label:"Status",field:"status",sortable:!1},{name:"created_at",align:"left",label:"Created At",field:"created_at",sortable:!0},{name:"amount",align:"right",label:"Amount",field:"amount",sortable:!0},{name:"amountFiat",align:"right",label:"Fiat",field:"amountFiat",sortable:!1},{name:"fee_sats",align:"left",label:"Fee",field:"fee_sats",sortable:!0},{name:"tag",align:"left",label:"Tag",field:"tag",sortable:!1},{name:"memo",align:"left",label:"Memo",field:"memo",sortable:!1,max_length:20},{name:"internal_memo",align:"left",label:"Internal Memo",field:"internal_memo",sortable:!1,max_length:20},{name:"wallet_id",align:"left",label:"Wallet (ID)",field:"wallet_id",sortable:!1},{name:"payment_hash",align:"left",label:"Payment Hash",field:"payment_hash",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:25,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},chartsReady:!1,showDetails:!1,paymentDetails:null,lnbitsBalance:0}),async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchPayments()},computed:{},methods:{async fetchPayments(e){const t=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{});delete t["time[ge]"],delete t["time[le]"],this.searchDate.from&&(t["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(t["time[le]"]=this.searchDate.to+"T23:59:59"),this.paymentsTable.filter=t;try{const t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/payments/all/paginated?${t}`);this.paymentsTable.pagination.rowsNumber=a.total,this.payments=a.data.map((e=>(e.extra&&e.extra.tag&&(e.tag=e.extra.tag),e.timeFrom=moment.utc(e.created_at).local().fromNow(),e.outgoing=e.amount<0,e.amount=new Intl.NumberFormat(this.g.locale).format(e.amount/1e3)+" sats",e.extra?.wallet_fiat_amount&&(e.amountFiat=this.formatCurrency(e.extra.wallet_fiat_amount,e.extra.wallet_fiat_currency)),e.extra?.internal_memo&&(e.internal_memo=e.extra.internal_memo),e.fee_sats=new Intl.NumberFormat(this.g.locale).format(e.fee/1e3)+" sats",e)))}catch(e){console.error(e),LNbits.utils.notifyApiError(e)}finally{this.updateCharts(e)}},async searchPaymentsBy(e,t){e&&(this.searchData[e]=t),await this.fetchPayments()},clearDateSeach(){this.searchDate={from:null,to:null},delete this.paymentsTable.filter["time[ge]"],delete this.paymentsTable.filter["time[le]"],this.fetchPayments()},searchByDate(){"string"==typeof this.searchDate&&(this.searchDate={from:this.searchDate,to:this.searchDate}),this.searchDate.from&&(this.paymentsTable.filter["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(this.paymentsTable.filter["time[le]"]=this.searchDate.to+"T23:59:59"),this.fetchPayments()},handleFilterChanged(){const{success:e,pending:t,failed:a,incoming:s,outgoing:i}=this.statusFilters;delete this.searchData["status[ne]"],delete this.searchData["status[eq]"],e&&t&&a||(e&&t?this.searchData["status[ne]"]="failed":e&&a?this.searchData["status[ne]"]="pending":a&&t?this.searchData["status[ne]"]="success":e?this.searchData["status[eq]"]="success":t?this.searchData["status[eq]"]="pending":a&&(this.searchData["status[eq]"]="failed")),delete this.searchData["amount[ge]"],delete this.searchData["amount[le]"],s&&i||(s?this.searchData["amount[ge]"]="0":i&&(this.searchData["amount[le]"]="0")),this.fetchPayments()},showDetailsToggle(e){return this.paymentDetails=e,this.showDetails=!this.showDetails},formatDate:e=>LNbits.utils.formatDateString(e),formatCurrency(e,t){try{return LNbits.utils.formatCurrency(e,t)}catch(t){return console.error(t),`${e} ???`}},shortify:(e,t=10)=>(valueLength=(e||"").length,valueLength<=t?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async updateCharts(e){let t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e);try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=status`);e.sort(((e,t)=>e.field-t.field)).reverse(),this.searchOptions.status=e.map((e=>e.field)),this.paymentsStatusChart.data.datasets[0].data=e.map((e=>e.total)),this.paymentsStatusChart.data.labels=[...this.searchOptions.status],this.paymentsStatusChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/wallets?${t}`),a=e.map((e=>e.balance/e.payments_count)),s=Math.min(...a),i=Math.max(...a),n=e=>Math.floor(3+22*(e-s)/(i-s)),l=this.randomColors(20),o=e.map(((e,t)=>({data:[{x:e.payments_count,y:e.balance,r:n(Math.max(e.balance/e.payments_count,5))}],label:e.wallet_name,wallet_id:e.wallet_id,backgroundColor:l[t%100],hoverOffset:4})));this.paymentsWalletsChart.data.datasets=o,this.paymentsWalletsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=tag`);this.searchOptions.tag=e.map((e=>e.field)),this.searchOptions.status.sort(),this.paymentsTagsChart.data.datasets[0].data=e.map((e=>e.total)),this.paymentsTagsChart.data.labels=e.map((e=>e.field||"core")),this.paymentsTagsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const t=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{}),a={...this.paymentsTable,filter:t},s=LNbits.utils.prepareFilterQuery(a,e);let{data:i}=await LNbits.api.request("GET",`/api/v1/payments/stats/daily?${s}`);const n=this.searchDate.from+"T00:00:00",l=this.searchDate.to+"T23:59:59";this.lnbitsBalance=i.length?i[i.length-1].balance:0,i=i.filter((e=>this.searchDate.from&&this.searchDate.to?e.date>=n&&e.date<=l:this.searchDate.from?e.date>=n:!this.searchDate.to||e.date<=l)),this.paymentsDailyChart.data.datasets=[{label:"Balance",data:i.map((e=>e.balance)),pointStyle:!1,borderWidth:2,tension:.7,fill:1},{label:"Fees",data:i.map((e=>e.fee)),pointStyle:!1,borderWidth:1,tension:.4,fill:1}],this.paymentsDailyChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsDailyChart.update(),this.paymentsBalanceInOutChart.data.datasets=[{label:"Incoming Payments Balance",data:i.map((e=>e.balance_in))},{label:"Outgoing Payments Balance",data:i.map((e=>e.balance_out))}],this.paymentsBalanceInOutChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsBalanceInOutChart.update(),this.paymentsCountInOutChart.data.datasets=[{label:"Incoming Payments Count",data:i.map((e=>e.count_in))},{label:"Outgoing Payments Count",data:i.map((e=>-e.count_out))}],this.paymentsCountInOutChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsCountInOutChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async initCharts(){const e=this.$q.localStorage.getItem("lnbits.payments.chartData")||{};this.chartData={...this.chartData,...e},this.chartsReady?(this.paymentsStatusChart=new Chart(this.$refs.paymentsStatusChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("status",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(0, 205, 86)","rgb(64, 72, 78)","rgb(255, 99, 132)"],hoverOffset:4}]}}),this.paymentsWalletsChart=new Chart(this.$refs.paymentsWalletsChart.getContext("2d"),{type:"bubble",options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!1},title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].datasetIndex;this.searchPaymentsBy("wallet_id",a.data.datasets[e].wallet_id)}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(20),hoverOffset:4}]}}),this.paymentsTagsChart=new Chart(this.$refs.paymentsTagsChart.getContext("2d"),{type:"pie",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!1,title:{display:!1,text:"Tags"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("tag",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsDailyChart=new Chart(this.$refs.paymentsDailyChart.getContext("2d"),{type:"line",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsBalanceInOutChart=new Chart(this.$refs.paymentsBalanceInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(50),hoverOffset:4}]}}),this.paymentsCountInOutChart=new Chart(this.$refs.paymentsCountInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:""}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(80),hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")},saveChartsPreferences(){this.$q.localStorage.set("lnbits.payments.chartData",this.chartData)},randomColors(e=1){const t=[];for(let a=1;a<=10;a++)for(let s=1;s<=10;s++)t.push(`rgb(${s*e*33%200}, ${71*(a+s+e)%255}, ${(a+30*e)%255})`);return t}}},window.PageNode={mixins:[window.windowMixin],template:"#page-node",config:{globalProperties:{LNbits:LNbits,msg:"hello"}},data(){return{isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:{data:[],filter:""},activeBalance:{},ranks:{},peers:{data:[],filter:""},connectPeerDialog:{show:!1,data:{}},setFeeDialog:{show:!1,data:{fee_ppm:0,fee_base_msat:0}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},transactionDetailsDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}],stateFilters:[{label:"Active",value:"active"},{label:"Pending",value:"pending"}],paymentsTable:{data:[],columns:[{name:"pending",label:""},{name:"date",align:"left",label:this.$t("date"),field:"date",sortable:!0},{name:"sat",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:e=>this.formatMsat(e.amount),sortable:!0},{name:"fee",align:"right",label:this.$t("fee")+" (m"+LNBITS_DENOMINATION+")",field:"fee"},{name:"destination",align:"right",label:"Destination",field:"destination"},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null},invoiceTable:{data:[],columns:[{name:"pending",label:""},{name:"paid_at",field:"paid_at",align:"left",label:"Paid at",sortable:!0},{name:"expiry",label:this.$t("expiry"),field:"expiry",align:"left",sortable:!0},{name:"amount",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:e=>this.formatMsat(e.amount),sortable:!0},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null}}},created(){this.getInfo(),this.get1MLStats()},watch:{tab(e){"transactions"!==e||this.paymentsTable.data.length?"channels"!==e||this.channels.data.length||(this.getChannels(),this.getPeers()):(this.getPayments(),this.getInvoices())}},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)},filteredChannels(){return this.stateFilters?this.channels.data.filter((e=>this.stateFilters.find((({value:t})=>t==e.state)))):this.channels.data},totalBalance(){return this.filteredChannels.reduce(((e,t)=>(e.local_msat+=t.balance.local_msat,e.remote_msat+=t.balance.remote_msat,e.total_msat+=t.balance.total_msat,e)),{local_msat:0,remote_msat:0,total_msat:0})}},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),api(e,t,a){const s=new URLSearchParams(a?.query);return LNbits.api.request(e,`/node/api/v1${t}?${s}`,{},a?.data).catch((e=>{LNbits.utils.notifyApiError(e)}))},getChannel(e){return this.api("GET",`/channels/${e}`).then((e=>{this.setFeeDialog.data.fee_ppm=e.data.fee_ppm,this.setFeeDialog.data.fee_base_msat=e.data.fee_base_msat}))},getChannels(){return this.api("GET","/channels").then((e=>{this.channels.data=e.data}))},getInfo(){return this.api("GET","/info").then((e=>{this.info=e.data,this.channel_stats=e.data.channel_stats})).catch((()=>{this.info={},this.channel_stats={}}))},get1MLStats(){return this.api("GET","/rank").then((e=>{this.ranks=e.data})).catch((()=>{this.ranks={}}))},getPayments(e){e&&(this.paymentsTable.pagination=e.pagination);let t=this.paymentsTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.api("GET","/payments",{query:a}).then((e=>{this.paymentsTable.data=e.data.data,this.paymentsTable.pagination.rowsNumber=e.data.total}))},getInvoices(e){e&&(this.invoiceTable.pagination=e.pagination);let t=this.invoiceTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.api("GET","/invoices",{query:a}).then((e=>{this.invoiceTable.data=e.data.data,this.invoiceTable.pagination.rowsNumber=e.data.total}))},getPeers(){return this.api("GET","/peers").then((e=>{this.peers.data=e.data}))},connectPeer(){this.api("POST","/peers",{data:this.connectPeerDialog.data}).then((()=>{this.connectPeerDialog.show=!1,this.getPeers()}))},disconnectPeer(e){LNbits.utils.confirmDialog("Do you really wanna disconnect this peer?").onOk((()=>{this.api("DELETE",`/peers/${e}`).then((e=>{Quasar.Notify.create({message:"Disconnected",icon:null}),this.needsRestart=!0,this.getPeers()}))}))},setChannelFee(e){this.api("PUT",`/channels/${e}`,{data:this.setFeeDialog.data}).then((e=>{this.setFeeDialog.show=!1,this.getChannels()})).catch(LNbits.utils.notifyApiError)},openChannel(){this.api("POST","/channels",{data:this.openChannelDialog.data}).then((e=>{this.openChannelDialog.show=!1,this.getChannels()})).catch((e=>{console.log(e)}))},showCloseChannelDialog(e){this.closeChannelDialog.show=!0,this.closeChannelDialog.data={force:!1,short_id:e.short_id,...e.point}},closeChannel(){this.api("DELETE","/channels",{query:this.closeChannelDialog.data}).then((e=>{this.closeChannelDialog.show=!1,this.getChannels()}))},showSetFeeDialog(e){this.setFeeDialog.show=!0,this.setFeeDialog.channel_id=e,this.getChannel(e)},showOpenChannelDialog(e){this.openChannelDialog.show=!0,this.openChannelDialog.data={peer_id:e,funding_amount:0}},showNodeInfoDialog(e){this.nodeInfoDialog.show=!0,this.nodeInfoDialog.data=e},showTransactionDetailsDialog(e){this.transactionDetailsDialog.show=!0,this.transactionDetailsDialog.data=e},shortenNodeId:e=>e?e.substring(0,5)+"..."+e.substring(e.length-5):"..."}},window.PageNodePublic={template:"#page-node-public",mixins:[window.windowMixin],data:()=>({enabled:!1,isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:[],activeBalance:{},ranks:{},peers:[],connectPeerDialog:{show:!1,data:{}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}]}),created(){this.getInfo(),this.get1MLStats()},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),api:(e,t,a)=>LNbits.api.request(e,"/node/public/api/v1"+t,{},a),getInfo(){this.api("GET","/info",{}).then((e=>{this.info=e.data,this.channel_stats=e.data.channel_stats,this.enabled=!0})).catch((()=>{this.info={},this.channel_stats={}}))},get1MLStats(){this.api("GET","/rank",{}).then((e=>{this.ranks=e.data})).catch((()=>{this.ranks={}}))}}},window.PageAudit={template:"#page-audit",mixins:[window.windowMixin],data:()=>({chartsReady:!1,auditEntries:[],searchData:{user_id:"",ip_address:"",request_type:"",component:"",request_method:"",response_code:"",path:""},searchOptions:{component:[],request_method:[],response_code:[]},auditTable:{columns:[{name:"created_at",align:"center",label:"Date",field:"created_at",sortable:!0},{name:"duration",align:"left",label:"Duration (sec)",field:"duration",sortable:!0},{name:"component",align:"left",label:"Component",field:"component",sortable:!1},{name:"request_method",align:"left",label:"Method",field:"request_method",sortable:!1},{name:"response_code",align:"left",label:"Code",field:"response_code",sortable:!1},{name:"user_id",align:"left",label:"User Id",field:"user_id",sortable:!1},{name:"ip_address",align:"left",label:"IP Address",field:"ip_address",sortable:!1},{name:"path",align:"left",label:"Path",field:"path",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},auditDetailsDialog:{data:null,show:!1}}),async created(){},async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchAudit()},methods:{formatDate:e=>LNbits.utils.formatDateString(e),async fetchAudit(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1?${t}`);this.auditTable.pagination.rowsNumber=a.total,this.auditEntries=a.data,await this.fetchAuditStats(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.auditTable.loading=!1}},async fetchAuditStats(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1/stats?${t}`),s=a.request_method.map((e=>e.field));this.searchOptions.request_method=[...new Set(this.searchOptions.request_method.concat(s))],this.requestMethodChart.data.labels=s,this.requestMethodChart.data.datasets[0].data=a.request_method.map((e=>e.total)),this.requestMethodChart.update();const i=a.response_code.map((e=>e.field));this.searchOptions.response_code=[...new Set(this.searchOptions.response_code.concat(i))],this.responseCodeChart.data.labels=i,this.responseCodeChart.data.datasets[0].data=a.response_code.map((e=>e.total)),this.responseCodeChart.update();const n=a.component.map((e=>e.field));this.searchOptions.component=[...new Set(this.searchOptions.component.concat(n))],this.componentUseChart.data.labels=n,this.componentUseChart.data.datasets[0].data=a.component.map((e=>e.total)),this.componentUseChart.update(),this.longDurationChart.data.labels=a.long_duration.map((e=>e.field)),this.longDurationChart.data.datasets[0].data=a.long_duration.map((e=>e.total)),this.longDurationChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async searchAuditBy(e,t){e&&(this.searchData[e]=t),this.auditTable.filter=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{}),await this.fetchAudit()},showDetailsDialog(e){const t=JSON.parse(e?.request_details||"");try{t.body&&(t.body=JSON.parse(t.body))}catch(e){}this.auditDetailsDialog.data=JSON.stringify(t,null,4),this.auditDetailsDialog.show=!0},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async initCharts(){this.chartsReady?(this.responseCodeChart=new Chart(this.$refs.responseCodeChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,plugins:{legend:{position:"bottom"},title:{display:!1,text:"HTTP Response Codes"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("response_code",a.data.labels[e])}}},data:{datasets:[{label:"",data:[20,10],backgroundColor:["rgb(100, 99, 200)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"]}],labels:[]}}),this.requestMethodChart=new Chart(this.$refs.requestMethodChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("request_method",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"],hoverOffset:4}]}}),this.componentUseChart=new Chart(this.$refs.componentUseChart.getContext("2d"),{type:"pie",options:{responsive:!0,plugins:{legend:{position:"xxx"},title:{display:!1,text:"Components"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("component",a.data.labels[e])}}},data:{datasets:[{data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}}),this.longDurationChart=new Chart(this.$refs.longDurationChart.getContext("2d"),{type:"bar",options:{responsive:!0,indexAxis:"y",maintainAspectRatio:!1,plugins:{legend:{title:{display:!1,text:"Long Duration"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("path",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")}}},window.PageWallets={template:"#page-wallets",mixins:[window.windowMixin],data:()=>({user:null,tab:"wallets",wallets:[],addWalletDialog:{show:!1},walletsTable:{columns:[{name:"name",align:"left",label:"Name",field:"name",sortable:!0},{name:"currency",align:"center",label:"Currency",field:"currency",sortable:!0},{name:"updated_at",align:"right",label:"Last Updated",field:"updated_at",sortable:!0}],pagination:{sortBy:"updated_at",rowsPerPage:12,page:1,descending:!0,rowsNumber:10},search:"",hideEmpty:!0,loading:!1}}),watch:{"walletsTable.search":{handler(){const e={};this.walletsTable.search&&(e.search=this.walletsTable.search),this.getUserWallets()}}},methods:{async getUserWallets(e){try{this.walletsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.walletsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/wallet/paginated?${t}`,null);this.wallets=a.data,this.walletsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.walletsTable.loading=!1}},showNewWalletDialog(){this.addWalletDialog={show:!0,walletType:"lightning"},this.showAddNewWalletDialog()},goToWallet(e){window.location=`/wallet?wal=${e}`},formattedFiatAmount:(e,t)=>LNbits.utils.formatCurrency(Number(e).toFixed(2),t),formattedSatAmount:e=>LNbits.utils.formatMsat(e)+" sat"},async created(){await this.getUserWallets()}},window.PageUsers={template:"#page-users",mixins:[window.windowMixin],data:()=>({paymentsWallet:{},cancel:{},users:[],wallets:[],searchData:{user:"",username:"",email:"",pubkey:""},paymentPage:{show:!1},activeWallet:{userId:null,show:!1},activeUser:{data:null,showUserId:!1,show:!1},createWalletDialog:{data:{},show:!1},walletTable:{columns:[{name:"name",align:"left",label:"Name",field:"name"},{name:"id",align:"left",label:"Wallet Id",field:"id"},{name:"currency",align:"left",label:"Currency",field:"currency"},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat"}],pagination:{sortBy:"name",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},usersTable:{columns:[{name:"admin",align:"left",label:"Admin",field:"admin",sortable:!1},{name:"wallet_id",align:"left",label:"Wallets",field:"wallet_id",sortable:!1},{name:"user",align:"left",label:"User Id",field:"user",sortable:!1},{name:"username",align:"left",label:"Username",field:"username",sortable:!1},{name:"email",align:"left",label:"Email",field:"email",sortable:!1},{name:"pubkey",align:"left",label:"Public Key",field:"pubkey",sortable:!1},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat",sortable:!0},{name:"transaction_count",align:"left",label:"Payments",field:"transaction_count",sortable:!0},{name:"last_payment",align:"left",label:"Last Payment",field:"last_payment",sortable:!0}],pagination:{sortBy:"balance_msat",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1}}),watch:{"usersTable.hideEmpty":function(e,t){this.usersTable.filter=e?{"transaction_count[gt]":0}:{},this.fetchUsers()}},created(){this.fetchUsers()},methods:{formatDate:e=>LNbits.utils.formatDateString(e),formatSat:e=>LNbits.utils.formatSat(Math.floor(e/1e3)),backToUsersPage(){this.activeUser.show=!1,this.paymentPage.show=!1,this.activeWallet.show=!1,this.fetchUsers()},handleBalanceUpdate(){this.fetchWallets(this.activeWallet.userId)},resetPassword(e){return LNbits.api.request("PUT",`/users/api/v1/user/${e}/reset_password`).then((e=>{LNbits.utils.confirmDialog(this.$t("reset_key_generated")+" "+this.$t("reset_key_copy")).onOk((()=>{const t=window.location.origin+"?reset_key="+e.data;this.copyText(t)}))})).catch(LNbits.utils.notifyApiError)},createUser(){LNbits.api.request("POST","/users/api/v1/user",null,this.activeUser.data).then((e=>{Quasar.Notify.create({type:"positive",message:"User created!",icon:null}),this.activeUser.setPassword=!0,this.activeUser.data=e.data,this.fetchUsers()})).catch(LNbits.utils.notifyApiError)},updateUser(){LNbits.api.request("PUT",`/users/api/v1/user/${this.activeUser.data.id}`,null,this.activeUser.data).then((()=>{Quasar.Notify.create({type:"positive",message:"User updated!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1,this.fetchUsers()})).catch(LNbits.utils.notifyApiError)},createWallet(){const e=this.activeWallet.userId;e?LNbits.api.request("POST",`/users/api/v1/user/${e}/wallet`,null,this.createWalletDialog.data).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Wallet created!"})})).catch(LNbits.utils.notifyApiError):Quasar.Notify.create({type:"warning",message:"No user selected!",icon:null})},deleteUser(e){LNbits.utils.confirmDialog("Are you sure you want to delete this user?").onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}`).then((()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"User deleted!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1})).catch(LNbits.utils.notifyApiError)}))},undeleteUserWallet(e,t){LNbits.api.request("PUT",`/users/api/v1/user/${e}/wallet/${t}/undelete`).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Undeleted user wallet!",icon:null})})).catch(LNbits.utils.notifyApiError)},deleteUserWallet(e,t,a){const s=a?"Wallet is already deleted, are you sure you want to permanently delete this user wallet?":"Are you sure you want to delete this user wallet?";LNbits.utils.confirmDialog(s).onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallet/${t}`).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"User wallet deleted!",icon:null})})).catch(LNbits.utils.notifyApiError)}))},deleteAllUserWallets(e){LNbits.utils.confirmDialog(this.$t("confirm_delete_all_wallets")).onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallets`).then((t=>{Quasar.Notify.create({type:"positive",message:t.data.message,icon:null}),this.fetchWallets(e)})).catch(LNbits.utils.notifyApiError)}))},copyWalletLink(e){const t=`${window.location.origin}/wallet?usr=${this.activeWallet.userId}&wal=${e}`;this.copyText(t)},fetchUsers(e){this.relaxFilterForFields(["username","email"]);const t=LNbits.utils.prepareFilterQuery(this.usersTable,e);LNbits.api.request("GET",`/users/api/v1/user?${t}`).then((e=>{this.usersTable.loading=!1,this.usersTable.pagination.rowsNumber=e.data.total,this.users=e.data.data})).catch(LNbits.utils.notifyApiError)},fetchWallets(e){return LNbits.api.request("GET",`/users/api/v1/user/${e}/wallet`).then((t=>{this.wallets=t.data,this.activeWallet.userId=e,this.activeWallet.show=!0})).catch(LNbits.utils.notifyApiError)},relaxFilterForFields(e=[]){e.forEach((e=>{const t=this.usersTable?.filter?.[e];t&&this.usersTable.filter[e]&&(this.usersTable.filter[`${e}[like]`]=t,delete this.usersTable.filter[e])}))},updateWallet(e){LNbits.api.request("PATCH","/api/v1/wallet",e.adminkey,{name:e.name}).then((()=>{e.editable=!1,Quasar.Notify.create({message:"Wallet name updated.",type:"positive",timeout:3500})})).catch((e=>{LNbits.utils.notifyApiError(e)}))},toggleAdmin(e){LNbits.api.request("GET",`/users/api/v1/user/${e}/admin`).then((()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"Toggled admin!",icon:null})})).catch(LNbits.utils.notifyApiError)},async showAccountPage(e){if(this.activeUser.showPassword=!1,this.activeUser.showUserId=!1,this.activeUser.setPassword=!1,!e)return this.activeUser.data={extra:{}},void(this.activeUser.show=!0);try{const{data:t}=await LNbits.api.request("GET",`/users/api/v1/user/${e}`);this.activeUser.data=t,this.activeUser.show=!0}catch(e){console.warn(e),Quasar.Notify.create({type:"warning",message:"Failed to get user!"}),this.activeUser.show=!1}},async showWalletPayments(e){this.activeUser.show=!1,await this.fetchWallets(this.users[0].id),await this.showPayments(e)},showPayments(e){this.paymentsWallet=this.wallets.find((t=>t.id===e)),this.paymentPage.show=!0},searchUserBy(e){const t=this.searchData[e];this.usersTable.filter={},t&&(this.usersTable.filter[e]=t),this.fetchUsers()},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`)}},window.PageAccount={template:"#page-account",mixins:[window.windowMixin],data(){return{user:null,hasUsername:!1,showUserId:!1,themeOptions:[{name:"bitcoin",color:"deep-orange"},{name:"mint",color:"green"},{name:"autumn",color:"brown"},{name:"monochrome",color:"grey"},{name:"salvador",color:"blue-10"},{name:"freedom",color:"pink-13"},{name:"cyber",color:"light-green-9"},{name:"flamingo",color:"pink-3"}],reactionOptions:["None","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],borderOptions:["retro-border","hard-border","neon-border","no-border"],tab:"user",credentialsData:{show:!1,oldPassword:null,newPassword:null,newPasswordRepeat:null,username:null,pubkey:null},apiAcl:{showNewAclDialog:!1,showPasswordDialog:!1,showNewTokenDialog:!1,data:[],passwordGuardedFunction:null,newAclName:"",newTokenName:"",password:"",apiToken:null,selectedTokenId:null,columns:[{name:"Name",align:"left",label:this.$t("Name"),field:"Name",sortable:!1},{name:"path",align:"left",label:this.$t("path"),field:"path",sortable:!1},{name:"read",align:"left",label:this.$t("read"),field:"read",sortable:!1},{name:"write",align:"left",label:this.$t("write"),field:"write",sortable:!1}],pagination:{rowsPerPage:100,page:1}},selectedApiAcl:{id:null,name:null,endpoints:[],token_id_list:[],allRead:!1,allWrite:!1},assets:[],assetsTable:{loading:!1,columns:[{name:"name",align:"left",label:this.$t("Name"),field:"name",sortable:!0},{name:"created_at",align:"left",label:this.$t("created_at"),field:"created_at",sortable:!0}],pagination:{rowsPerPage:6,page:1}},assetsUploadToPublic:!1,notifications:{nostr:{identifier:""}}}},watch:{"assetsTable.search":{handler(){const e={};this.assetsTable.search&&(e.search=this.assetsTable.search),this.getUserAssets()}}},methods:{activeLanguage:e=>window.i18n.global.locale===e,changeLanguage(e){window.i18n.global.locale=e,this.$q.localStorage.set("lnbits.lang",e)},async updateAccount(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/update",null,{user_id:this.user.id,username:this.user.username,email:this.user.email,extra:this.user.extra});this.user=e,this.hasUsername=!!e.username,Quasar.Notify.create({type:"positive",message:"Account updated."})}catch(e){LNbits.utils.notifyApiError(e)}},disableUpdatePassword(){return!this.credentialsData.newPassword||!this.credentialsData.newPasswordRepeat||this.credentialsData.newPassword!==this.credentialsData.newPasswordRepeat},async updatePassword(){if(this.credentialsData.username)try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/password",null,{user_id:this.user.id,username:this.credentialsData.username,password_old:this.credentialsData.oldPassword,password:this.credentialsData.newPassword,password_repeat:this.credentialsData.newPasswordRepeat});this.user=e,this.hasUsername=!!e.username,this.credentialsData.show=!1,Quasar.Notify.create({type:"positive",message:"Password updated."})}catch(e){LNbits.utils.notifyApiError(e)}else Quasar.Notify.create({type:"warning",message:"Please set a username."})},async updatePubkey(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/pubkey",null,{user_id:this.user.id,pubkey:this.credentialsData.pubkey});this.user=e,this.hasUsername=!!e.username,this.credentialsData.show=!1,this.$q.notify({type:"positive",message:"Public key updated."})}catch(e){LNbits.utils.notifyApiError(e)}},showUpdateCredentials(){this.credentialsData={show:!0,oldPassword:null,username:this.user.username,pubkey:this.user.pubkey,newPassword:null,newPasswordRepeat:null}},newApiAclDialog(){this.apiAcl.newAclName=null,this.apiAcl.showNewAclDialog=!0},newTokenAclDialog(){this.apiAcl.newTokenName=null,this.apiAcl.newTokenExpiry=null,this.apiAcl.showNewTokenDialog=!0},handleApiACLSelected(e){this.selectedApiAcl={id:null,name:null,endpoints:[],token_id_list:[]},this.apiAcl.selectedTokenId=null,e&&setTimeout((()=>{const t=this.apiAcl.data.find((t=>t.id===e));this.selectedApiAcl&&(this.selectedApiAcl={...t},this.selectedApiAcl.allRead=this.selectedApiAcl.endpoints.every((e=>e.read)),this.selectedApiAcl.allWrite=this.selectedApiAcl.endpoints.every((e=>e.write)))}))},handleAllEndpointsReadAccess(){this.selectedApiAcl.endpoints.forEach((e=>e.read=this.selectedApiAcl.allRead))},handleAllEndpointsWriteAccess(){this.selectedApiAcl.endpoints.forEach((e=>e.write=this.selectedApiAcl.allWrite))},async getApiACLs(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/auth/acl",null);this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}},askPasswordAndRunFunction(e){this.apiAcl.passwordGuardedFunction=e,this.apiAcl.showPasswordDialog=!0},runPasswordGuardedFunction(){this.apiAcl.showPasswordDialog=!1;const e=this.apiAcl.passwordGuardedFunction;e&&this[e]()},async addApiACL(){if(this.apiAcl.newAclName){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.apiAcl.newAclName,name:this.apiAcl.newAclName,password:this.apiAcl.password});this.apiAcl.data=e.access_control_list;const t=this.apiAcl.data.find((e=>e.name===this.apiAcl.newAclName));this.handleApiACLSelected(t.id),this.apiAcl.showNewAclDialog=!1,this.$q.notify({type:"positive",message:"Access Control List created."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.name="",this.apiAcl.password=""}this.apiAcl.showNewAclDialog=!1}else this.$q.notify({type:"warning",message:"Name is required."})},async updateApiACLs(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.user.id,password:this.apiAcl.password,...this.selectedApiAcl});this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteApiACL(){if(this.selectedApiAcl.id){try{await LNbits.api.request("DELETE","/api/v1/auth/acl",null,{id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Access Control List deleted."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}this.apiAcl.data=this.apiAcl.data.filter((e=>e.id!==this.selectedApiAcl.id)),this.handleApiACLSelected(this.apiAcl.data[0]?.id)}},async generateApiToken(){if(!this.selectedApiAcl.id)return;const e=new Date(this.apiAcl.newTokenExpiry)-new Date;try{const{data:t}=await LNbits.api.request("POST","/api/v1/auth/acl/token",null,{acl_id:this.selectedApiAcl.id,token_name:this.apiAcl.newTokenName,password:this.apiAcl.password,expiration_time_minutes:Math.trunc(e/6e4)});this.apiAcl.apiToken=t.api_token,this.apiAcl.selectedTokenId=t.id,Quasar.Notify.create({type:"positive",message:"Token Generated."}),await this.getApiACLs(),this.handleApiACLSelected(this.selectedApiAcl.id),this.apiAcl.showNewTokenDialog=!1}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteToken(){if(this.apiAcl.selectedTokenId)try{await LNbits.api.request("DELETE","/api/v1/auth/acl/token",null,{id:this.apiAcl.selectedTokenId,acl_id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Token deleted."}),this.selectedApiAcl.token_id_list=this.selectedApiAcl.token_id_list.filter((e=>e.id!==this.apiAcl.selectedTokenId)),this.apiAcl.selectedTokenId=null}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async getUserAssets(e){try{this.assetsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.assetsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/assets/paginated?${t}`,null);this.assets=a.data,this.assetsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.assetsTable.loading=!1}},onImageInput(e){const t=e.target.files[0];t&&this.uploadAsset(t)},async uploadAsset(e){const t=new FormData;t.append("file",e);try{await LNbits.api.request("POST",`/api/v1/assets?public_asset=${this.assetsUploadToPublic}`,null,t,{headers:{"Content-Type":"multipart/form-data"}}),this.$q.notify({type:"positive",message:"Upload successful!",icon:null}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async deleteAsset(e){LNbits.utils.confirmDialog("Are you sure you want to delete this asset?").onOk((async()=>{try{await LNbits.api.request("DELETE",`/api/v1/assets/${e.id}`,null),this.$q.notify({type:"positive",message:"Asset deleted."}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}}))},async toggleAssetPublicAccess(e){try{await LNbits.api.request("PUT",`/api/v1/assets/${e.id}`,null,{is_public:!e.is_public}),this.$q.notify({type:"positive",message:"Update successful!",icon:null}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},copyAssetLinkToClipboard(e){const t=`${window.location.origin}/api/v1/assets/${e.id}/binary`;this.copyText(t)}},async created(){try{const{data:e}=await LNbits.api.getAuthenticatedUser();this.user=e,this.hasUsername=!!e.username,this.user.extra||(this.user.extra={})}catch(e){LNbits.utils.notifyApiError(e)}const e=window.location.hash.replace("#","");e&&(this.tab=e),await this.getApiACLs(),await this.getUserAssets(),this.themeOptions=this.themeOptions.filter((e=>this.allowedThemes.includes(e.name)))}},window.PageAdmin={template:"#page-admin",mixins:[windowMixin],data:()=>({tab:"funding",settings:{},formData:{lnbits_exchange_rate_providers:[],lnbits_audit_exclude_paths:[],lnbits_audit_include_paths:[],lnbits_audit_http_response_codes:[]},isSuperUser:!1,needsRestart:!1}),async created(){await this.getSettings();const e=window.location.hash.replace("#","");e&&(this.tab=e)},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)}},methods:{getDefaultSetting(e){LNbits.api.request("GET",`/admin/api/v1/settings/default?field_name=${e}`).then((t=>{this.formData[e]=t.data.default_value})).catch((function(e){LNbits.utils.notifyApiError(e)}))},restartServer(){LNbits.api.request("GET","/admin/api/v1/restart/").then((e=>{this.$q.notify({type:"positive",message:"Success! Restarted Server",icon:null}),this.needsRestart=!1})).catch(LNbits.utils.notifyApiError)},async getSettings(){await LNbits.api.request("GET","/admin/api/v1/settings",this.g.user.wallets[0].adminkey).then((e=>{this.isSuperUser=e.data.is_super_user||!1,this.settings=e.data,this.formData={...this.settings}})).catch(LNbits.utils.notifyApiError)},updateSettings(){const e=_.omit(this.formData,["is_super_user","lnbits_allowed_funding_sources","touch"]);LNbits.api.request("PUT","/admin/api/v1/settings",this.g.user.wallets[0].adminkey,e).then((e=>{this.needsRestart=this.settings.lnbits_backend_wallet_class!==this.formData.lnbits_backend_wallet_class,this.settings=this.formData,this.formData=_.clone(this.settings),Quasar.Notify.create({type:"positive",message:"Success! Settings changed! "+(this.needsRestart?"Restart required!":""),icon:null})})).catch(LNbits.utils.notifyApiError)},deleteSettings(){LNbits.utils.confirmDialog("Are you sure you want to restore settings to default?").onOk((()=>{LNbits.api.request("DELETE","/admin/api/v1/settings").then((e=>{Quasar.Notify.create({type:"positive",message:"Success! Restored settings to defaults. Restarting...",icon:null}),this.$q.localStorage.clear()})).catch(LNbits.utils.notifyApiError)}))},downloadBackup(){window.open("/admin/api/v1/backup","_blank")}}},window.app.component("lnbits-admin-funding",{props:["is-super-user","form-data","settings"],template:"#lnbits-admin-funding",mixins:[window.windowMixin],data:()=>({auditData:[]}),created(){this.getAudit()},methods:{getAudit(){LNbits.api.request("GET","/admin/api/v1/audit",this.g.user.wallets[0].adminkey).then((e=>{this.auditData=e.data})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("lnbits-admin-funding-sources",{template:"#lnbits-admin-funding-sources",mixins:[window.windowMixin],props:["form-data","allowed-funding-sources"],methods:{getFundingSourceLabel(e){const t=this.rawFundingSources.find((t=>t[0]===e));return t?t[1]:e},showQRValue(e){this.qrValue=e,this.showQRDialog=!0}},computed:{fundingSources(){let e=[];for(const[t,a,s]of this.rawFundingSources){const a={};if(null!==s)for(let[e,t]of Object.entries(s))a[e]="string"==typeof t?{label:t,value:null}:t||{};e.push([t,a])}return new Map(e)},sortedAllowedFundingSources(){return this.allowedFundingSources.sort()}},data:()=>({hideInput:!0,showQRDialog:!1,qrValue:"",rawFundingSources:[["VoidWallet","Void Wallet",null],["FakeWallet","Fake Wallet",{fake_wallet_secret:"Secret",lnbits_denomination:'"sats" or 3 Letter Custom Denomination'}],["CLNRestWallet","Core Lightning Rest (plugin)",{clnrest_url:"Endpoint",clnrest_ca:"ca.pem",clnrest_cert:"server.pem",clnrest_readonly_rune:"Rune used for readonly requests",clnrest_invoice_rune:"Rune used for creating invoices",clnrest_pay_rune:"Rune used for paying invoices using pay",clnrest_renepay_rune:"Rune used for paying invoices using renepay",clnrest_last_pay_index:"Ignores any invoices paid prior to or including this index. 0 is equivalent to not specifying and negative value is invalid.",clnrest_nodeid:"Node id"}],["CoreLightningWallet","Core Lightning",{corelightning_rpc:"Endpoint",corelightning_pay_command:"Custom Pay Command"}],["CoreLightningRestWallet","Core Lightning Rest (legacy)",{corelightning_rest_url:"Endpoint",corelightning_rest_cert:"Certificate",corelightning_rest_macaroon:"Macaroon"}],["LndRestWallet","Lightning Network Daemon (LND Rest)",{lnd_rest_endpoint:"Endpoint",lnd_rest_cert:"Certificate",lnd_rest_macaroon:"Macaroon",lnd_rest_macaroon_encrypted:"Encrypted Macaroon",lnd_rest_route_hints:"Enable Route Hints",lnd_rest_allow_self_payment:"Allow Self Payment"}],["LndWallet","Lightning Network Daemon (LND)",{lnd_grpc_endpoint:"Endpoint",lnd_grpc_cert:"Certificate",lnd_grpc_port:"Port",lnd_grpc_macaroon:"GRPC Macaroon",lnd_grpc_invoice_macaroon:"GRPC Invoice Macaroon",lnd_grpc_admin_macaroon:"GRPC Admin Macaroon",lnd_grpc_macaroon_encrypted:"Encrypted Macaroon"}],["LnTipsWallet","LN.Tips",{lntips_api_endpoint:"Endpoint",lntips_api_key:"API Key"}],["LNPayWallet","LN Pay",{lnpay_api_endpoint:"Endpoint",lnpay_api_key:"API Key",lnpay_wallet_key:"Wallet Key"}],["EclairWallet","Eclair (ACINQ)",{eclair_url:"URL",eclair_pass:"Password"}],["LNbitsWallet","LNbits",{lnbits_endpoint:"Endpoint",lnbits_key:"Admin Key"}],["BlinkWallet","Blink",{blink_api_endpoint:"Endpoint",blink_ws_endpoint:"WebSocket",blink_token:"Key"}],["AlbyWallet","Alby",{alby_api_endpoint:"Endpoint",alby_access_token:"Key"}],["BoltzWallet","Boltz",{boltz_client_endpoint:"Endpoint",boltz_client_macaroon:"Admin Macaroon path or hex",boltz_client_cert:"Certificate path or hex",boltz_client_wallet:"Wallet Name",boltz_client_password:"Wallet Password (can be empty)",boltz_mnemonic:{label:"Liquid mnemonic (copy into greenwallet)",readonly:!0,copy:!0,qrcode:!0}}],["ZBDWallet","ZBD",{zbd_api_endpoint:"Endpoint",zbd_api_key:"Key"}],["PhoenixdWallet","Phoenixd",{phoenixd_api_endpoint:"Endpoint",phoenixd_api_password:"Key"}],["OpenNodeWallet","OpenNode",{opennode_api_endpoint:"Endpoint",opennode_key:"Key"}],["ClicheWallet","Cliche (NBD)",{cliche_endpoint:"Endpoint"}],["SparkWallet","Spark",{spark_url:"Endpoint",spark_token:"Token"}],["NWCWallet","Nostr Wallet Connect",{nwc_pairing_url:"Pairing URL"}],["BreezSdkWallet","Breez SDK",{breez_api_key:"Breez API Key",breez_greenlight_seed:"Greenlight Seed",breez_greenlight_device_key:"Greenlight Device Key",breez_greenlight_device_cert:"Greenlight Device Cert",breez_greenlight_invite_code:"Greenlight Invite Code"}],["StrikeWallet","Strike (alpha)",{strike_api_endpoint:"API Endpoint",strike_api_key:"API Key"}],["BreezLiquidSdkWallet","Breez Liquid SDK",{breez_liquid_api_key:"Breez API Key (can be empty)",breez_liquid_seed:"Liquid seed phrase",breez_liquid_fee_offset_sat:"Offset amount in sats to increase fee limit"}]]})}),window.app.component("lnbits-admin-fiat-providers",{props:["form-data"],template:"#lnbits-admin-fiat-providers",mixins:[window.windowMixin],data:()=>({formAddStripeUser:"",hideInputToggle:!0}),methods:{addStripeAllowedUser(){const e=this.formAddStripeUser||"";e.length&&!this.formData.stripe_limits.allowed_users.includes(e)&&(this.formData.stripe_limits.allowed_users=[...this.formData.stripe_limits.allowed_users,e],this.formAddStripeUser="")},removeStripeAllowedUser(e){this.formData.stripe_limits.allowed_users=this.formData.stripe_limits.allowed_users.filter((t=>t!==e))},checkFiatProvider(e){LNbits.api.request("PUT",`/api/v1/fiat/check/${e}`).then((e=>{const t=e.data;Quasar.Notify.create({type:t.success?"positive":"warning",message:t.message,icon:null})})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("lnbits-admin-exchange-providers",{props:["form-data"],template:"#lnbits-admin-exchange-providers",mixins:[window.windowMixin],data:()=>({exchangeData:{selectedProvider:null,showTickerConversion:!1,convertFromTicker:null,convertToTicker:null},exchangesTable:{columns:[{name:"name",align:"left",label:"Exchange Name",field:"name",sortable:!0},{name:"api_url",align:"left",label:"URL",field:"api_url",sortable:!1},{name:"path",align:"left",label:"JSON Path",field:"path",sortable:!1},{name:"exclude_to",align:"left",label:"Exclude Currencies",field:"exclude_to",sortable:!1},{name:"ticker_conversion",align:"left",label:"Ticker Conversion",field:"ticker_conversion",sortable:!1}],pagination:{sortBy:"name",rowsPerPage:100,page:1,rowsNumber:100},search:null,hideEmpty:!0}}),mounted(){this.getExchangeRateHistory()},created(){const e=window.location.hash.replace("#","");"exchange_providers"===e&&this.showExchangeProvidersTab(e)},methods:{getExchangeRateHistory(){LNbits.api.request("GET","/api/v1/rate/history",this.g.user.wallets[0].inkey).then((e=>{this.initExchangeChart(e.data)})).catch((function(e){LNbits.utils.notifyApiError(e)}))},showExchangeProvidersTab(e){"exchange_providers"===e&&this.getExchangeRateHistory()},addExchangeProvider(){this.formData.lnbits_exchange_rate_providers=[{name:"",api_url:"",path:"",exclude_to:[]},...this.formData.lnbits_exchange_rate_providers]},removeExchangeProvider(e){this.formData.lnbits_exchange_rate_providers=this.formData.lnbits_exchange_rate_providers.filter((t=>t!==e))},removeExchangeTickerConversion(e,t){e.ticker_conversion=e.ticker_conversion.filter((e=>e!==t)),this.formData.touch=null},addExchangeTickerConversion(){this.exchangeData.selectedProvider&&(this.exchangeData.selectedProvider.ticker_conversion.push(`${this.exchangeData.convertFromTicker}:${this.exchangeData.convertToTicker}`),this.formData.touch=null,this.exchangeData.showTickerConversion=!1)},showTickerConversionDialog(e){this.exchangeData.convertFromTicker=null,this.exchangeData.convertToTicker=null,this.exchangeData.selectedProvider=e,this.exchangeData.showTickerConversion=!0},initExchangeChart(e){const t=e.map((e=>Quasar.date.formatDate(new Date(1e3*e.timestamp),"HH:mm"))),a=[...this.formData.lnbits_exchange_rate_providers,{name:"LNbits"}].map((t=>({label:t.name,data:e.map((e=>e.rates[t.name])),pointStyle:!0,borderWidth:"LNbits"===t.name?4:1,tension:.4})));this.exchangeRatesChart=new Chart(this.$refs.exchangeRatesChart.getContext("2d"),{type:"line",options:{plugins:{legend:{display:!1}}},data:{labels:t,datasets:a}})}}}),window.app.component("lnbits-admin-security",{props:["form-data"],template:"#lnbits-admin-security",mixins:[window.windowMixin],data:()=>({logs:[],formBlockedIPs:"",serverlogEnabled:!1,nostrAcceptedUrl:"",formAllowedIPs:"",formCallbackUrlRule:""}),created(){},methods:{addAllowedIPs(){const e=this.formAllowedIPs.trim(),t=this.formData.lnbits_allowed_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_ips=[...t,e],this.formAllowedIPs="")},removeAllowedIPs(e){const t=this.formData.lnbits_allowed_ips;this.formData.lnbits_allowed_ips=t.filter((t=>t!==e))},addBlockedIPs(){const e=this.formBlockedIPs.trim(),t=this.formData.lnbits_blocked_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_blocked_ips=[...t,e],this.formBlockedIPs="")},removeBlockedIPs(e){const t=this.formData.lnbits_blocked_ips;this.formData.lnbits_blocked_ips=t.filter((t=>t!==e))},addCallbackUrlRule(){const e=this.formCallbackUrlRule.trim(),t=this.formData.lnbits_callback_url_rules;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_callback_url_rules=[...t,e],this.formCallbackUrlRule="")},removeCallbackUrlRule(e){const t=this.formData.lnbits_callback_url_rules;this.formData.lnbits_callback_url_rules=t.filter((t=>t!==e))},addNostrUrl(){const e=this.nostrAcceptedUrl.trim();this.removeNostrUrl(e),this.formData.nostr_absolute_request_urls.push(e),this.nostrAcceptedUrl=""},removeNostrUrl(e){this.formData.nostr_absolute_request_urls=this.formData.nostr_absolute_request_urls.filter((t=>t!==e))},async toggleServerLog(){if(this.serverlogEnabled=!this.serverlogEnabled,this.serverlogEnabled){const e="http:"!==location.protocol?"wss://":"ws://",t=await LNbits.utils.digestMessage(this.g.user.id),a=e+document.domain+":"+location.port+"/api/v1/ws/"+t;this.ws=new WebSocket(a),this.ws.addEventListener("message",(async({data:e})=>{this.logs.push(e.toString());const t=this.$refs.logScroll;if(t){const e=t.getScrollTarget(),a=0;t.setScrollPosition(e.scrollHeight,a)}}))}else this.ws.close()}}}),window.app.component("lnbits-admin-users",{props:["form-data"],template:"#lnbits-admin-users",mixins:[window.windowMixin],data:()=>({formAddUser:"",formAddAdmin:""}),methods:{addAllowedUser(){let e=this.formAddUser,t=this.formData.lnbits_allowed_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_users=[...t,e],this.formAddUser="")},removeAllowedUser(e){let t=this.formData.lnbits_allowed_users;this.formData.lnbits_allowed_users=t.filter((t=>t!==e))},addAdminUser(){let e=this.formAddAdmin,t=this.formData.lnbits_admin_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_admin_users=[...t,e],this.formAddAdmin="")},removeAdminUser(e){let t=this.formData.lnbits_admin_users;this.formData.lnbits_admin_users=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-server",{props:["form-data"],template:"#lnbits-admin-server",mixins:[window.windowMixin],data:()=>({currencies:[]}),async created(){this.currencies=await LNbits.api.getCurrencies()}}),window.app.component("lnbits-admin-extensions",{props:["form-data"],template:"#lnbits-admin-extensions",mixins:[window.windowMixin],data:()=>({formAddExtensionsManifest:""}),methods:{addExtensionsManifest(){const e=this.formAddExtensionsManifest.trim(),t=this.formData.lnbits_extensions_manifests;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_extensions_manifests=[...t,e],this.formAddExtensionsManifest="")},removeExtensionsManifest(e){const t=this.formData.lnbits_extensions_manifests;this.formData.lnbits_extensions_manifests=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-notifications",{props:["form-data"],template:"#lnbits-admin-notifications",mixins:[window.windowMixin],data:()=>({nostrNotificationIdentifier:"",emailNotificationAddress:""}),methods:{sendTestEmail(){LNbits.api.request("GET","/admin/api/v1/testemail",this.g.user.wallets[0].adminkey).then((e=>{if("error"===e.data.status)throw new Error(e.data.message);this.$q.notify({message:"Test email sent!",color:"positive"})})).catch((e=>{this.$q.notify({message:e.message,color:"negative"})}))},addNostrNotificationIdentifier(){const e=this.nostrNotificationIdentifier.trim(),t=this.formData.lnbits_nostr_notifications_identifiers;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_nostr_notifications_identifiers=[...t,e],this.nostrNotificationIdentifier="")},removeNostrNotificationIdentifier(e){const t=this.formData.lnbits_nostr_notifications_identifiers;this.formData.lnbits_nostr_notifications_identifiers=t.filter((t=>t!==e))},addEmailNotificationAddress(){const e=this.emailNotificationAddress.trim(),t=this.formData.lnbits_email_notifications_to_emails;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_email_notifications_to_emails=[...t,e],this.emailNotificationAddress="")},removeEmailNotificationAddress(e){const t=this.formData.lnbits_email_notifications_to_emails;this.formData.lnbits_email_notifications_to_emails=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-site-customisation",{props:["form-data"],template:"#lnbits-admin-site-customisation",mixins:[window.windowMixin],data:()=>({lnbits_theme_options:["classic","bitcoin","flamingo","cyber","freedom","mint","autumn","monochrome","salvador"],colors:["primary","secondary","accent","positive","negative","info","warning","red","yellow","orange"],reactionOptions:["none","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],globalBorderOptions:["retro-border","hard-border","neon-border","no-border"]}),methods:{}}),window.app.component("lnbits-admin-assets-config",{props:["form-data"],template:"#lnbits-admin-assets-config",mixins:[window.windowMixin],data:()=>({newAllowedAssetMimeType:"",newNoLimitUser:""}),async created(){},methods:{addAllowedAssetMimeType(){this.newAllowedAssetMimeType&&(this.removeAllowedAssetMimeType(this.newAllowedAssetMimeType),this.formData.lnbits_assets_allowed_mime_types.push(this.newAllowedAssetMimeType),this.newAllowedAssetMimeType="")},removeAllowedAssetMimeType(e){const t=this.formData.lnbits_assets_allowed_mime_types.indexOf(e);-1!==t&&this.formData.lnbits_assets_allowed_mime_types.splice(t,1)},addNewNoLimitUser(){this.newNoLimitUser&&(this.removeNoLimitUser(this.newNoLimitUser),this.formData.lnbits_assets_no_limit_users.push(this.newNoLimitUser),this.newNoLimitUser="")},removeNoLimitUser(e){e&&(this.formData.lnbits_assets_no_limit_users=this.formData.lnbits_assets_no_limit_users.filter((t=>t!==e)))}}}),window.app.component("lnbits-admin-audit",{props:["form-data"],template:"#lnbits-admin-audit",mixins:[window.windowMixin],data:()=>({formAddIncludePath:"",formAddExcludePath:"",formAddIncludeResponseCode:""}),methods:{addIncludePath(){if(""===this.formAddIncludePath)return;const e=this.formData.lnbits_audit_include_paths;e.includes(this.formAddIncludePath)||(this.formData.lnbits_audit_include_paths=[...e,this.formAddIncludePath]),this.formAddIncludePath=""},removeIncludePath(e){this.formData.lnbits_audit_include_paths=this.formData.lnbits_audit_include_paths.filter((t=>t!==e))},addExcludePath(){if(""===this.formAddExcludePath)return;const e=this.formData.lnbits_audit_exclude_paths;e.includes(this.formAddExcludePath)||(this.formData.lnbits_audit_exclude_paths=[...e,this.formAddExcludePath]),this.formAddExcludePath=""},removeExcludePath(e){this.formData.lnbits_audit_exclude_paths=this.formData.lnbits_audit_exclude_paths.filter((t=>t!==e))},addIncludeResponseCode(){if(""===this.formAddIncludeResponseCode)return;const e=this.formData.lnbits_audit_http_response_codes;e.includes(this.formAddIncludeResponseCode)||(this.formData.lnbits_audit_http_response_codes=[...e,this.formAddIncludeResponseCode]),this.formAddIncludeResponseCode=""},removeIncludeResponseCode(e){this.formData.lnbits_audit_http_response_codes=this.formData.lnbits_audit_http_response_codes.filter((t=>t!==e))}}}),window.app.component("lnbits-home-logos",{template:"#lnbits-home-logos",mixins:[window.windowMixin],data:()=>({logos:[{href:"https://github.com/ElementsProject/lightning",lightSrc:"/static/images/clnl.png",darkSrc:"/static/images/cln.png"},{href:"https://github.com/lightningnetwork/lnd",lightSrc:"/static/images/lnd.png",darkSrc:"/static/images/lnd.png"},{href:"https://opennode.com",lightSrc:"/static/images/opennodel.png",darkSrc:"/static/images/opennode.png"},{href:"https://lnpay.co/",lightSrc:"/static/images/lnpayl.png",darkSrc:"/static/images/lnpay.png"},{href:"https://github.com/rootzoll/raspiblitz",lightSrc:"/static/images/blitzl.png",darkSrc:"/static/images/blitz.png"},{href:"https://start9.com/",lightSrc:"/static/images/start9l.png",darkSrc:"/static/images/start9.png"},{href:"https://getumbrel.com/",lightSrc:"/static/images/umbrell.png",darkSrc:"/static/images/umbrel.png"},{href:"https://mynodebtc.com",lightSrc:"/static/images/mynodel.png",darkSrc:"/static/images/mynode.png"},{href:"https://github.com/shesek/spark-wallet",lightSrc:"/static/images/sparkl.png",darkSrc:"/static/images/spark.png"},{href:"https://voltage.cloud",lightSrc:"/static/images/voltagel.png",darkSrc:"/static/images/voltage.png"},{href:"https://breez.technology/sdk/",lightSrc:"/static/images/breezl.png",darkSrc:"/static/images/breez.png"},{href:"https://blockstream.com/lightning/greenlight/",lightSrc:"/static/images/greenlightl.png",darkSrc:"/static/images/greenlight.png"},{href:"https://getalby.com",lightSrc:"/static/images/albyl.png",darkSrc:"/static/images/alby.png"},{href:"https://zbd.gg",lightSrc:"/static/images/zbdl.png",darkSrc:"/static/images/zbd.png"},{href:"https://phoenix.acinq.co/server",lightSrc:"/static/images/phoenixdl.png",darkSrc:"/static/images/phoenixd.png"},{href:"https://boltz.exchange/",lightSrc:"/static/images/boltzl.svg",darkSrc:"/static/images/boltz.svg"},{href:"https://www.blink.sv/",lightSrc:"/static/images/blink_logol.png",darkSrc:"/static/images/blink_logo.png"}]}),computed:{showLogos(){return"sats"==this.LNBITS_DENOMINATION&&"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}}}),window.app.component("lnbits-new-user-wallet",{props:["form-data"],template:"#lnbits-new-user-wallet",mixins:[window.windowMixin],data:()=>({walletTypes:[{label:"Lightning Wallet",value:"lightning"}],newWallet:{walletType:"lightning",name:"",sharedWalletId:""}}),methods:{async submitRejectWalletInvitation(){try{const e=this.g.user.extra.wallet_invite_requests||[],t=e.find((e=>e.to_wallet_id===this.newWallet.sharedWalletId));if(!t)return void Quasar.Notify.create({message:"Cannot find invitation for the selected wallet.",type:"warning"});await LNbits.api.request("DELETE",`/api/v1/wallet/share/invite/${t.request_id}`,this.g.wallet.adminkey),Quasar.Notify.create({message:"Invitation rejected.",type:"positive"}),this.g.user.extra.wallet_invite_requests=e.filter((e=>e.request_id!==t.request_id))}catch(e){LNbits.utils.notifyApiError(e)}},async submitAddWallet(){console.log("### submitAddWallet",this.newWallet);const e=this.newWallet;if("lightning"!==e.walletType||e.name)if("lightning-shared"!==e.walletType||e.sharedWalletId)try{await LNbits.api.createWallet(this.g.user.wallets[0],e.name,e.walletType,{shared_wallet_id:e.sharedWalletId})}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}else this.$q.notify({message:"Missing a shared wallet ID",color:"warning"});else this.$q.notify({message:"Please enter a name for the wallet",color:"warning"})}},created(){this.g.user?.extra?.wallet_invite_requests?.length&&this.walletTypes.push({label:`Lightning Wallet (Share Invite: ${this.g.user.extra.wallet_invite_requests.length})`,value:"lightning-shared"})}}),window.app.component("lnbits-qrcode",{mixins:[window.windowMixin],template:"#lnbits-qrcode",components:{QrcodeVue:QrcodeVue},props:{value:{type:String,required:!0},nfc:{type:Boolean,default:!1},showButtons:{type:Boolean,default:!0},href:{type:String,default:""},margin:{type:Number,default:3},maxWidth:{type:Number,default:450},logo:{type:String,default:LNBITS_QR_LOGO}},data:()=>({nfcTagWriting:!1,nfcSupported:"undefined"!=typeof NDEFReader}),methods:{clickQrCode(e){if(""===this.href)return this.copyText(this.value),e.preventDefault(),e.stopPropagation(),!1},async writeNfcTag(){try{if(!this.nfcSupported)throw{toString:function(){return"NFC not supported on this device or browser."}};const e=new NDEFReader;this.nfcTagWriting=!0,this.$q.notify({message:"Tap your NFC tag to write the LNURL-withdraw link to it."}),await e.write({records:[{recordType:"url",data:this.value,lang:"en"}]}),this.nfcTagWriting=!1,this.$q.notify({type:"positive",message:"NFC tag written successfully."})}catch(e){this.nfcTagWriting=!1,this.$q.notify({type:"negative",message:e?e.toString():"An unexpected error has occurred."})}},downloadSVG(){const e=this.$refs.qrCode.$el;if(!e)return void console.error("SVG element not found");let t=(new XMLSerializer).serializeToString(e);t.match(/^]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/)||(t=t.replace(/^({tab:"bech32",lnurl:""}),methods:{setLnurl(){if("bech32"==this.tab){const e=(new TextEncoder).encode(this.url),t=NostrTools.nip19.encodeBytes("lnurl",e);this.lnurl=`lightning:${t.toUpperCase()}`}else"lud17"==this.tab&&(this.url.startsWith("http://")?this.lnurl=this.url.replace("http://",this.prefix+"://"):this.lnurl=this.url.replace("https://",this.prefix+"://"));this.$emit("update:lnurl",this.lnurl)}},watch:{url(){this.setLnurl()},tab(){this.setLnurl()}},created(){this.setLnurl()}}),window.app.component("lnbits-footer",{template:"#lnbits-footer",mixins:[window.windowMixin],computed:{version(){return this.LNBITS_VERSION||"unknown version"},title(){return`${this.SITE_TITLE}, ${this.SITE_TAGLINE}`},showFooter(){return"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}}}),window.app.component("lnbits-header",{template:"#lnbits-header",mixins:[window.windowMixin],computed:{denomination(){return this.LNBITS_DENOMINATION||"sat"},hasServiceFeeMax(){return this.g.user&&this.LNBITS_SERVICE_FEE_MAX&&this.LNBITS_SERVICE_FEE_MAX>0},serviceFeeMax(){return this.LNBITS_SERVICE_FEE_MAX||0},hasServiceFee(){return this.g.user&&this.LNBITS_SERVICE_FEE&&this.LNBITS_SERVICE_FEE>0},serviceFee(){return this.LNBITS_SERVICE_FEE||0},hasCustomBadge(){return this.LNBITS_CUSTOM_BADGE&&""!=this.LNBITS_CUSTOM_BADGE},customBadge(){return this.LNBITS_CUSTOM_BADGE||""},customBadgeColor(){return this.LNBITS_CUSTOM_BADGE_COLOR||""},title(){return this.SITE_TITLE},titleIsLnbits(){return"LNbits"==this.SITE_TITLE},customLogoUrl(){return this.USE_CUSTOM_LOGO||null},userPictureUrl(){return this.g.user.config.picture},hasUserPicture(){return this.g.user&&this.g.user.config&&this.g.user.config.picture},showAdmin(){return this.g.user&&(this.g.user.super_user||this.g.user.admin)},showVoidwallet(){return this.g.user&&1==this.VOIDWALLET}}}),window.app.component("lnbits-header-wallets",{template:"#lnbits-header-wallets",mixins:[window.windowMixin]}),window.app.component("lnbits-drawer",{template:"#lnbits-drawer",mixins:[window.windowMixin]}),window.app.component("lnbits-theme",{mixins:[window.windowMixin],watch:{"g.reactionChoice"(e){this.$q.localStorage.set("lnbits.reactions",e)},"g.themeChoice"(e){document.body.setAttribute("data-theme",e),this.$q.localStorage.set("lnbits.theme",e)},"g.darkChoice"(e){this.$q.dark.set(e),this.$q.localStorage.set("lnbits.darkMode",e)},"g.borderChoice"(e){document.body.classList.forEach((e=>{e.endsWith("-border")&&document.body.classList.remove(e)})),this.$q.localStorage.setItem("lnbits.border",e),document.body.classList.add(e)},"g.gradientChoice"(e){this.$q.localStorage.set("lnbits.gradientBg",e),!0===e?document.body.classList.add("gradient-bg"):document.body.classList.remove("gradient-bg")},"g.mobileSimple"(e){this.$q.localStorage.set("lnbits.mobileSimple",e),!0===e?document.body.classList.add("mobile-simple"):document.body.classList.remove("mobile-simple")},"g.bgimageChoice"(e){this.$q.localStorage.set("lnbits.backgroundImage",e),""===e?document.body.classList.remove("bg-image"):(document.body.classList.add("bg-image"),document.body.style.setProperty("--background",`url(${e})`))}},methods:{async checkUrlParams(){const e=new URLSearchParams(window.location.search);if(0===e.length)return;if(e.has("theme")){const t=e.get("theme").trim().toLowerCase();this.g.themeChoice=t,e.delete("theme")}if(e.has("border")){const t=e.get("border").trim().toLowerCase();this.g.borderChoice=t,e.delete("border")}if(e.has("gradient")){const t=e.get("gradient").toLowerCase();this.g.gradientChoice="1"===t||"true"===t,e.delete("gradient")}if(e.has("dark")){const t=e.get("dark").trim().toLowerCase();this.g.darkChoice="1"===t||"true"===t,e.delete("dark")}if(e.has("usr")){try{await LNbits.api.loginUsr(e.get("usr")),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}e.delete("usr")}const t=e.size?`?${e.toString()}`:"",a=window.location.pathname+t;window.history.replaceState(null,null,a)}},created(){Chart.defaults.color=this.$q.dark.isActive?"#fff":"#000",this.$q.dark.set(this.g.darkChoice),document.body.setAttribute("data-theme",this.g.themeChoice),document.body.classList.add(this.g.borderChoice),!0===this.g.gradientChoice&&document.body.classList.add("gradient-bg"),""!==this.g.bgimageChoice&&(document.body.classList.add("bg-image"),document.body.style.setProperty("--background",`url(${this.g.bgimageChoice})`)),!0===this.g.mobileSimple&&document.body.classList.add("mobile-simple"),this.checkUrlParams()}}),window.app.component("lnbits-manage-extension-list",{mixins:[window.windowMixin],template:"#lnbits-manage-extension-list",data:()=>({extensions:[],userExtensions:[],searchTerm:""}),watch:{"g.user.extensions":{async handler(){await this.loadExtensions()}},searchTerm(){this.filterUserExtensionsByTerm()}},methods:{map(e){const t={...e};return t.url=["/",t.code,"/"].join(""),t},async loadExtensions(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension");this.extensions=e.map((e=>this.map(e))).sort(((e,t)=>e.name.localeCompare(t.name))),this.filterUserExtensionsByTerm()}catch(e){LNbits.utils.notifyApiError(e)}},filterUserExtensionsByTerm(){const e=this.g.user.extensions;this.userExtensions=this.extensions.filter((t=>e.includes(t.code))).filter((e=>""===this.searchTerm||`${e.code} ${e.name} ${e.short_description} ${e.url}`.toLocaleLowerCase().includes(this.searchTerm.toLocaleLowerCase()))).map((e=>(e.isActive=window.location.pathname.startsWith(e.url),e)))}},async created(){await this.loadExtensions()}}),window.app.component("lnbits-language-dropdown",{template:"#lnbits-language-dropdown",mixins:[window.windowMixin],methods:{activeLanguage:e=>window.i18n.global.locale===e,changeLanguage(e){this.g.locale=e,window.i18n.global.locale=e,this.$q.localStorage.set("lnbits.lang",e)}},data:()=>({langs:[{value:"en",label:"English",display:"🇬🇧 EN"},{value:"de",label:"Deutsch",display:"🇩🇪 DE"},{value:"es",label:"Español",display:"🇪🇸 ES"},{value:"jp",label:"日本語",display:"🇯🇵 JP"},{value:"cn",label:"中文",display:"🇨🇳 CN"},{value:"fr",label:"Français",display:"🇫🇷 FR"},{value:"it",label:"Italiano",display:"🇮🇹 IT"},{value:"pi",label:"Pirate",display:"🏴‍☠️ PI"},{value:"nl",label:"Nederlands",display:"🇳🇱 NL"},{value:"we",label:"Cymraeg",display:"🏴󠁧󠁢󠁷󠁬󠁳󠁿 CY"},{value:"pl",label:"Polski",display:"🇵🇱 PL"},{value:"pt",label:"Português",display:"🇵🇹 PT"},{value:"br",label:"Português do Brasil",display:"🇧🇷 BR"},{value:"cs",label:"Česky",display:"🇨🇿 CS"},{value:"sk",label:"Slovensky",display:"🇸🇰 SK"},{value:"kr",label:"한국어",display:"🇰🇷 KR"},{value:"fi",label:"Suomi",display:"🇫🇮 FI"}]})}),window.app.component("lnbits-payment-list",{template:"#lnbits-payment-list",props:["update","lazy","wallet"],mixins:[window.windowMixin],data(){return{denomination:LNBITS_DENOMINATION,payments:[],paymentsTable:{columns:[{name:"time",align:"left",label:this.$t("memo")+"/"+this.$t("date"),field:"date",sortable:!0},{name:"amount",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:"sat",sortable:!0}],pagination:{rowsPerPage:10,page:1,sortBy:"time",descending:!0,rowsNumber:10},search:"",filter:{"status[ne]":"failed"},loading:!1},searchDate:{from:null,to:null},searchStatus:{success:!0,pending:!0,failed:!1,incoming:!0,outgoing:!0},exportTagName:"",exportPaymentTagList:[],paymentsCSV:{columns:[{name:"pending",align:"left",label:"Pending",field:"pending"},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"},{name:"time",align:"left",label:this.$t("date"),field:"date",sortable:!0},{name:"amount",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:"sat",sortable:!0},{name:"fee",align:"right",label:this.$t("fee")+" (m"+LNBITS_DENOMINATION+")",field:"fee"},{name:"tag",align:"right",label:this.$t("tag"),field:"tag"},{name:"payment_hash",align:"right",label:this.$t("payment_hash"),field:"payment_hash"},{name:"payment_proof",align:"right",label:this.$t("payment_proof"),field:"payment_proof"},{name:"webhook",align:"right",label:this.$t("webhook"),field:"webhook"},{name:"fiat_currency",align:"right",label:"Fiat Currency",field:e=>e.extra.wallet_fiat_currency},{name:"fiat_amount",align:"right",label:"Fiat Amount",field:e=>e.extra.wallet_fiat_amount}],preimage:null,loading:!1},hodlInvoice:{show:!1,payment:null,preimage:null}}},computed:{currentWallet(){return this.wallet||this.g.wallet},filteredPayments(){const e=this.paymentsTable.search;return e&&""!==e?LNbits.utils.search(this.payments,e):this.payments},paymentsOmitter(){return this.$q.screen.lt.md&&this.g.mobileSimple?this.payments.length>0?[this.payments[0]]:[]:this.payments},pendingPaymentsExist(){return-1!==this.payments.findIndex((e=>e.pending))}},methods:{searchByDate(){"string"==typeof this.searchDate&&(this.searchDate={from:this.searchDate,to:this.searchDate}),this.searchDate.from&&(this.paymentsTable.filter["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(this.paymentsTable.filter["time[le]"]=this.searchDate.to+"T23:59:59"),this.fetchPayments()},clearDateSeach(){this.searchDate={from:null,to:null},delete this.paymentsTable.filter["time[ge]"],delete this.paymentsTable.filter["time[le]"],this.fetchPayments()},fetchPayments(e){this.$emit("filter-changed",{...this.paymentsTable.filter});const t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e);return LNbits.api.getPayments(this.currentWallet,t).then((e=>{this.paymentsTable.loading=!1,this.paymentsTable.pagination.rowsNumber=e.data.total,this.payments=e.data.data.map((e=>LNbits.map.payment(e)))})).catch((e=>{this.paymentsTable.loading=!1,g.user.admin?this.fetchPaymentsAsAdmin(this.currentWallet.id,t):LNbits.utils.notifyApiError(e)}))},fetchPaymentsAsAdmin(e,t){return t=(t||"")+"&wallet_id="+e,LNbits.api.request("GET","/api/v1/payments/all/paginated?"+t).then((e=>{this.paymentsTable.loading=!1,this.paymentsTable.pagination.rowsNumber=e.data.total,this.payments=e.data.data.map((e=>LNbits.map.payment(e)))})).catch((e=>{this.paymentsTable.loading=!1,LNbits.utils.notifyApiError(e)}))},checkPayment(e){LNbits.api.getPayment(this.g.wallet,e).then((e=>{this.update=!this.update,"success"==e.data.status&&Quasar.Notify.create({type:"positive",message:this.$t("payment_successful")}),"pending"==e.data.status&&Quasar.Notify.create({type:"info",message:this.$t("payment_pending")})})).catch(LNbits.utils.notifyApiError)},showHoldInvoiceDialog(e){this.hodlInvoice.show=!0,this.hodlInvoice.preimage="",this.hodlInvoice.payment=e},cancelHoldInvoice(e){LNbits.api.cancelInvoice(this.g.wallet,e).then((()=>{this.update=!this.update,Quasar.Notify.create({type:"positive",message:this.$t("invoice_cancelled")})})).catch(LNbits.utils.notifyApiError)},settleHoldInvoice(e){LNbits.api.settleInvoice(this.g.wallet,e).then((()=>{this.update=!this.update,Quasar.Notify.create({type:"positive",message:this.$t("invoice_settled")})})).catch(LNbits.utils.notifyApiError)},paymentTableRowKey:e=>e.payment_hash+e.amount,exportCSV(e=!1){const t=this.paymentsTable.pagination,a={sortby:t.sortBy??"time",direction:t.descending?"desc":"asc"},s=new URLSearchParams(a);LNbits.api.getPayments(this.g.wallet,s).then((t=>{let a=t.data.data.map(LNbits.map.payment),s=this.paymentsCSV.columns;if(e){this.exportPaymentTagList.length&&(a=a.filter((e=>this.exportPaymentTagList.includes(e.tag))));const e=Object.keys(a.reduce(((e,t)=>({...e,...t.details})),{})).map((e=>({name:e,align:"right",label:e.charAt(0).toUpperCase()+e.slice(1).replace(/([A-Z])/g," $1"),field:t=>t.details[e],format:e=>"object"==typeof e?JSON.stringify(e):e})));s=this.paymentsCSV.columns.concat(e)}LNbits.utils.exportCSV(s,a,this.g.wallet.name+"-payments")}))},addFilterTag(){if(!this.exportTagName)return;const e=this.exportTagName.trim();this.exportPaymentTagList=this.exportPaymentTagList.filter((t=>t!==e)),this.exportPaymentTagList.push(e),this.exportTagName=""},removeExportTag(e){this.exportPaymentTagList=this.exportPaymentTagList.filter((t=>t!==e))},formatCurrency(e,t){try{return LNbits.utils.formatCurrency(e,t)}catch(t){return console.error(t),`${e} ???`}},handleFilterChanged(){const{success:e,pending:t,failed:a,incoming:s,outgoing:i}=this.searchStatus;delete this.paymentsTable.filter["status[ne]"],delete this.paymentsTable.filter["status[eq]"],e&&t&&a||(e&&t?this.paymentsTable.filter["status[ne]"]="failed":e&&a?this.paymentsTable.filter["status[ne]"]="pending":a&&t?this.paymentsTable.filter["status[ne]"]="success":e?this.paymentsTable.filter["status[eq]"]="success":t?this.paymentsTable.filter["status[eq]"]="pending":a&&(this.paymentsTable.filter["status[eq]"]="failed")),delete this.paymentsTable.filter["amount[ge]"],delete this.paymentsTable.filter["amount[le]"],s&&i||(s?this.paymentsTable.filter["amount[ge]"]=0:i&&(this.paymentsTable.filter["amount[le]"]=0))}},watch:{"paymentsTable.search":{handler(){const e={};this.paymentsTable.search&&(e.search=this.paymentsTable.search),this.fetchPayments()}},lazy(e){!0===e&&this.fetchPayments()},update(){this.fetchPayments()},"g.updatePayments"(){this.fetchPayments()},"g.wallet":{handler(e){this.fetchPayments()},deep:!0}},created(){void 0===this.lazy&&this.fetchPayments()}}),window.app.component("lnbits-extension-settings-form",{name:"lnbits-extension-settings-form",template:"#lnbits-extension-settings-form",props:["options","adminkey","endpoint"],methods:{async updateSettings(){if(!this.settings)return Quasar.Notify.create({message:"No settings to update",type:"negative"});try{const{data:e}=await LNbits.api.request("PUT",this.endpoint,this.adminkey,this.settings);this.settings=e}catch(e){LNbits.utils.notifyApiError(e)}},async getSettings(){try{const{data:e}=await LNbits.api.request("GET",this.endpoint,this.adminkey);this.settings=e}catch(e){LNbits.utils.notifyApiError(e)}},async resetSettings(){LNbits.utils.confirmDialog("Are you sure you want to reset the settings?").onOk((async()=>{try{await LNbits.api.request("DELETE",this.endpoint,this.adminkey),await this.getSettings()}catch(e){LNbits.utils.notifyApiError(e)}}))}},async created(){await this.getSettings()},data:()=>({settings:void 0})}),window.app.component("lnbits-extension-settings-btn-dialog",{template:"#lnbits-extension-settings-btn-dialog",name:"lnbits-extension-settings-btn-dialog",props:["options","adminkey","endpoint"],data:()=>({show:!1})}),window.app.component("lnbits-data-fields",{name:"lnbits-data-fields",template:"#lnbits-data-fields",props:["fields","hide-advanced"],data:()=>({fieldTypes:[{label:"Text",value:"str"},{label:"Integer",value:"int"},{label:"Float",value:"float"},{label:"Boolean",value:"bool"},{label:"Date Time",value:"datetime"},{label:"JSON",value:"json"},{label:"Wallet Select",value:"wallet"},{label:"Currency Select",value:"currency"}],fieldsTable:{columns:[{name:"name",align:"left",label:"Field Name",field:"name",sortable:!0},{name:"type",align:"left",label:"Type",field:"type",sortable:!1},{name:"label",align:"left",label:"UI Label",field:"label",sortable:!0},{name:"hint",align:"left",label:"UI Hint",field:"hint",sortable:!1},{name:"optional",align:"left",label:"Optional",field:"optional",sortable:!1}],pagination:{sortBy:"name",rowsPerPage:100,page:1,rowsNumber:100},search:null,hideEmpty:!0}}),methods:{addField:function(){this.fields.push({name:"field_name_"+(this.fields.length+1),type:"text",label:"",hint:"",optional:!0,sortable:!0,searchable:!0,editable:!0,fields:[]})},removeField:function(e){const t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},async created(){this.hideAdvanced||this.fieldsTable.columns.push({name:"editable",align:"left",label:"UI Editable",field:"editable",sortable:!1},{name:"sortable",align:"left",label:"Sortable",field:"sortable",sortable:!1},{name:"searchable",align:"left",label:"Searchable",field:"searchable",sortable:!1})}}),window.app.component(QrcodeVue),window.app.component("lnbits-extension-rating",{template:"#lnbits-extension-rating",name:"lnbits-extension-rating",props:["rating"]}),window.app.component("lnbits-fsat",{template:"{{ fsat }}",props:{amount:{type:Number,default:0}},computed:{fsat(){return LNbits.utils.formatSat(this.amount)}}}),window.app.component("lnbits-wallet-list",{mixins:[window.windowMixin],template:"#lnbits-wallet-list",props:["balance"],data:()=>({activeWallet:null,balance:0,walletName:"",LNBITS_DENOMINATION:LNBITS_DENOMINATION}),methods:{createWallet(){this.$emit("wallet-action",{action:"create-wallet"})}},created(){document.addEventListener("updateWalletBalance",this.updateWalletBalance)}}),window.app.component("lnbits-manage",{mixins:[window.windowMixin],template:"#lnbits-manage",computed:{showAdmin(){return this.LNBITS_ADMIN_UI},showUsers(){return this.LNBITS_ADMIN_UI},showNode(){return this.LNBITS_NODE_UI},showAudit(){return this.LNBITS_AUDIT_ENABLED},showExtensions(){return!1===this.LNBITS_EXTENSIONS_DEACTIVATE_ALL}},methods:{isActive:e=>window.location.pathname===e},data:()=>({extensions:[]})}),window.app.component("lnbits-payment-details",{mixins:[window.windowMixin],template:"#lnbits-payment-details",props:["payment"],mixins:[window.windowMixin],data:()=>({LNBITS_DENOMINATION:LNBITS_DENOMINATION}),computed:{hasPreimage(){return this.payment.preimage&&"0000000000000000000000000000000000000000000000000000000000000000"!==this.payment.preimage},hasExpiry(){return!!this.payment.expiry},hasSuccessAction(){return this.hasPreimage&&this.payment.extra&&this.payment.extra.success_action},webhookStatusColor(){return this.payment.webhook_status>=300||this.payment.webhook_status<0?"red-10":this.payment.webhook_status?"green-10":"cyan-7"},webhookStatusText(){return this.payment.webhook_status?this.payment.webhook_status:"not sent yet"},hasTag(){return this.payment.extra&&!!this.payment.extra.tag},extras(){if(!this.payment.extra)return[];let e=_.omit(this.payment.extra,["tag","success_action"]);return Object.keys(e).map((t=>({key:t,value:e[t]})))}}}),window.app.component("lnbits-lnurlpay-success-action",{mixins:[window.windowMixin],template:"#lnbits-lnurlpay-success-action",props:["payment","success_action"],data(){return{decryptedValue:this.success_action.ciphertext}},mounted(){if("aes"!==this.success_action.tag)return null;decryptLnurlPayAES(this.success_action,this.payment.preimage).then((e=>{this.decryptedValue=e}))}}),window.app.component("lnbits-notifications-btn",{template:"#lnbits-notifications-btn",mixins:[window.windowMixin],props:["pubkey"],data:()=>({isSupported:!1,isSubscribed:!1,isPermissionGranted:!1,isPermissionDenied:!1}),methods:{urlB64ToUint8Array(e){const t=(e+"=".repeat((4-e.length%4)%4)).replace(/\-/g,"+").replace(/_/g,"/"),a=atob(t),s=new Uint8Array(a.length);for(let e=0;et!==e)),this.$q.localStorage.set("lnbits.webpush.subscribedUsers",JSON.stringify(t))},isUserSubscribed(e){return(JSON.parse(this.$q.localStorage.getItem("lnbits.webpush.subscribedUsers"))||[]).includes(e)},subscribe(){this.isSupported&&!this.isPermissionDenied&&(Notification.requestPermission().then((e=>{this.isPermissionGranted="granted"===e,this.isPermissionDenied="denied"===e})).catch(console.log),navigator.serviceWorker.ready.then((e=>{navigator.serviceWorker.getRegistration().then((e=>{e.pushManager.getSubscription().then((t=>{if(null===t||!this.isUserSubscribed(this.g.user.id)){const t={applicationServerKey:this.urlB64ToUint8Array(this.pubkey),userVisibleOnly:!0};e.pushManager.subscribe(t).then((e=>{LNbits.api.request("POST","/api/v1/webpush",null,{subscription:JSON.stringify(e)}).then((e=>{this.saveUserSubscribed(e.data.user),this.isSubscribed=!0})).catch(LNbits.utils.notifyApiError)}))}})).catch(console.log)}))})))},unsubscribe(){navigator.serviceWorker.ready.then((e=>{e.pushManager.getSubscription().then((e=>{e&&LNbits.api.request("DELETE","/api/v1/webpush?endpoint="+btoa(e.endpoint),null).then((()=>{this.removeUserSubscribed(this.g.user.id),this.isSubscribed=!1})).catch(LNbits.utils.notifyApiError)}))})).catch(console.log)},checkSupported(){let e="https:"===window.location.protocol,t="serviceWorker"in navigator,a="Notification"in window,s="PushManager"in window;return this.isSupported=e&&t&&a&&s,this.isSupported||console.log("Notifications disabled because requirements are not met:",{HTTPS:e,"Service Worker API":t,"Notification API":a,"Push API":s}),this.isSupported},async updateSubscriptionStatus(){await navigator.serviceWorker.ready.then((e=>{e.pushManager.getSubscription().then((e=>{this.isSubscribed=!!e&&this.isUserSubscribed(this.g.user.id)}))})).catch(console.log)}},created(){this.isPermissionDenied="denied"===Notification.permission,this.checkSupported()&&this.updateSubscriptionStatus()}}),window.app.component("lnbits-dynamic-fields",{template:"#lnbits-dynamic-fields",mixins:[window.windowMixin],props:["options","modelValue"],data:()=>({formData:null,rules:[e=>!!e||"Field is required"]}),methods:{applyRules(e){return e?this.rules:[]},buildData(e,t={}){return e.reduce(((e,a)=>(a.options?.length?e[a.name]=this.buildData(a.options,t[a.name]):e[a.name]=t[a.name]??a.default,e)),{})},handleValueChanged(){this.$emit("update:model-value",this.formData)}},created(){this.formData=this.buildData(this.options,this.modelValue)}}),window.app.component("lnbits-dynamic-chips",{template:"#lnbits-dynamic-chips",mixins:[window.windowMixin],props:["modelValue"],data:()=>({chip:"",chips:[]}),methods:{addChip(){this.chip&&(this.chips.push(this.chip),this.chip="",this.$emit("update:model-value",this.chips.join(",")))},removeChip(e){this.chips.splice(e,1),this.$emit("update:model-value",this.chips.join(","))}},created(){"string"==typeof this.modelValue?this.chips=this.modelValue.split(","):this.chips=[...this.modelValue]}}),window.app.component("lnbits-update-balance",{template:"#lnbits-update-balance",mixins:[window.windowMixin],props:["wallet_id","small_btn"],computed:{denomination:()=>LNBITS_DENOMINATION,admin:()=>user.super_user},data:()=>({credit:0}),methods:{updateBalance(e){LNbits.api.updateBalance(e.value,this.wallet_id).then((t=>{if(!0!==t.data.success)throw new Error(t.data);credit=parseInt(e.value),Quasar.Notify.create({type:"positive",message:this.$t("credit_ok",{amount:credit}),icon:null}),this.credit=0,e.value=0,e.set()})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("user-id-only",{template:"#user-id-only",mixins:[window.windowMixin],props:{allowed_new_users:Boolean,authAction:String,authMethod:String,usr:String,wallet:String},data(){return{user:this.usr,walletName:this.wallet}},methods:{showLogin(e){this.$emit("show-login",e)},showRegister(e){this.$emit("show-register",e)},loginUsr(){this.$emit("update:usr",this.user),this.$emit("login-usr")},createWallet(){this.$emit("update:wallet",this.walletName),this.$emit("create-wallet")}},computed:{showInstantLogin(){return"username-password"!==this.authMethod||"register"!==this.authAction}},created(){}}),window.app.component("username-password",{template:"#username-password",mixins:[window.windowMixin],props:{allowed_new_users:Boolean,authMethods:Array,authAction:String,username:String,password_1:String,password_2:String,resetKey:String},data(){return{oauth:["nostr-auth-nip98","google-auth","github-auth","keycloak-auth"],username:this.userName,password:this.password_1,passwordRepeat:this.password_2,reset_key:this.resetKey,keycloakOrg:LNBITS_AUTH_KEYCLOAK_ORG||"Keycloak",keycloakIcon:LNBITS_AUTH_KEYCLOAK_ICON}},methods:{login(){this.$emit("update:userName",this.username),this.$emit("update:password_1",this.password),this.$emit("login")},register(){this.$emit("update:userName",this.username),this.$emit("update:password_1",this.password),this.$emit("update:password_2",this.passwordRepeat),this.$emit("register")},reset(){this.$emit("update:resetKey",this.reset_key),this.$emit("update:password_1",this.password),this.$emit("update:password_2",this.passwordRepeat),this.$emit("reset")},validateUsername:e=>new RegExp("^(?=[a-zA-Z0-9._]{2,20}$)(?!.*[_.]{2})[^_.].*[^_.]$").test(e),async signInWithNostr(){try{const e=await this.createNostrToken();if(!e)return;resp=await LNbits.api.loginByProvider("nostr",{Authorization:e},{}),window.location.href="/wallet"}catch(e){console.warn(e);const t=e?.response?.data?.detail||`${e}`;Quasar.Notify.create({type:"negative",message:"Failed to sign in with Nostr.",caption:t})}},async createNostrToken(){try{if(!window.nostr?.signEvent)return void Quasar.Notify.create({type:"negative",message:"No Nostr signing app detected.",caption:'Is "window.nostr" present?'});const e=`${window.location}nostr`,t="POST",a=await NostrTools.nip98.getToken(e,t,(e=>async function(e){try{const{data:t}=await LNbits.api.getServerHealth();return e.created_at=t.server_time,await window.nostr.signEvent(e)}catch(e){console.error(e),Quasar.Notify.create({type:"negative",message:"Failed to sign nostr event.",caption:`${e}`})}}(e)),!0);if(!await NostrTools.nip98.validateToken(a,e,t))throw new Error("Invalid signed token!");return a}catch(e){console.warn(e),Quasar.Notify.create({type:"negative",message:"Failed create Nostr event.",caption:`${e}`})}}},computed:{showOauth(){return this.oauth.some((e=>this.authMethods.includes(e)))}},created(){}}),window.app.component("separator-text",{template:"#separator-text",props:{text:String,uppercase:{type:Boolean,default:!1},color:{type:String,default:"grey"}}}),window.app.component("lnbits-node-ranks",{props:["ranks"],data:()=>({stats:[{label:"Capacity",key:"capacity"},{label:"Channels",key:"channelcount"},{label:"Age",key:"age"},{label:"Growth",key:"growth"},{label:"Availability",key:"availability"}]}),template:"\n \n
\n
1ml Node Rank
\n
\n
\n
{{ stat.label }}
\n
\n {{ (ranks && ranks[stat.key]) ?? '-' }}\n
\n
\n
\n
\n
\n "}),window.app.component("lnbits-channel-stats",{props:["stats"],data:()=>({states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}]}),template:"\n \n
\n
Channels
\n
\n
\n
\n {{ state.label }}\n
\n
\n {{ (stats?.counts && stats.counts[state.value]) ?? \"-\" }}\n
\n
\n
\n
\n
\n "}),window.app.component("lnbits-stat",{props:["title","amount","msat","btc"],computed:{value(){return this.amount??(this.btc?LNbits.utils.formatSat(this.btc):LNbits.utils.formatMsat(this.msat))}},template:"\n \n \n
\n {{ title }}\n
\n
\n {{ value }}\n sats\n BTC\n
\n
\n
\n "}),window.app.component("lnbits-node-qrcode",{props:["info"],mixins:[window.windowMixin],template:'\n \n \n
\n
\n \n
\n No addresses available\n
\n
\n
\n
\n \n Public Key Click to copy \n \n \n
\n '}),window.app.component("lnbits-channel-balance",{props:["balance","color"],methods:{formatMsat:e=>LNbits.utils.formatMsat(e)},template:'\n
\n
\n \n Local: {{ formatMsat(balance.local_msat) }}\n sats\n \n \n Remote: {{ formatMsat(balance.remote_msat) }}\n sats\n \n
\n\n \n
\n \n {{ balance.alias }}\n \n
\n \n
\n '}),window.app.component("lnbits-date",{props:["ts"],computed:{date(){return LNbits.utils.formatDate(this.ts)},dateFrom(){return moment.utc(this.date).local().fromNow()}},template:"\n
\n {{ this.date }}\n {{ this.dateFrom }}\n
\n "}),window.app.component("lnbits-node-info",{props:["info"],data:()=>({showDialog:!1}),mixins:[window.windowMixin],methods:{shortenNodeId:e=>e?e.substring(0,5)+"..."+e.substring(e.length-5):"..."},template:"\n
\n
{{ this.info.alias }}
\n
\n
{{ this.info.backend_name }}
\n \n #{{ this.info.color }}\n \n
{{ shortenNodeId(this.info.id) }}
\n \n \n
\n \n \n \n
\n "}),window.app.component("lnbits-stat",{props:["title","amount","msat","btc"],computed:{value(){return this.amount??(this.btc?LNbits.utils.formatSat(this.btc):LNbits.utils.formatMsat(this.msat))}},template:"\n \n \n
\n {{ title }}\n
\n
\n {{ value }}\n sats\n BTC\n
\n
\n
\n "});const DynamicComponent={props:{fetchUrl:{type:String,required:!0},scripts:{type:Array,default:()=>[]}},data:()=>({keys:[]}),async mounted(){await this.loadDynamicContent()},methods:{loadScript:async e=>new Promise(((t,a)=>{const s=document.querySelector(`script[src="${e}"]`);s&&s.remove();const i=document.createElement("script");i.src=e,i.async=!0,i.onload=t,i.onerror=()=>a(new Error(`Failed to load script: ${e}`)),document.head.appendChild(i)})),async loadDynamicContent(){this.$q.loading.show();try{const e=this.fetchUrl.split("#")[0],t=await fetch(e,{credentials:"include",headers:{Accept:"text/html","X-Requested-With":"XMLHttpRequest"}}),a=await t.text(),s=new DOMParser,i=s.parseFromString(a,"text/html").querySelector("#window-vars-script");i&&new Function(i.innerHTML)(),await this.loadScript("/static/js/base.js");for(const e of this.scripts)await this.loadScript(e);const n=this.$router.currentRoute.value.meta.previousRouteName;n&&window.app._context.components[n]&&delete window.app._context.components[n];const l=`${this.$route.name}PageLogic`,o=window[l];if(!o)throw new Error(`Component logic '${l}' not found. Ensure it is defined in the script.`);o.mixins=o.mixins||[],window.windowMixin&&o.mixins.push(window.windowMixin),window.app.component(this.$route.name,{...o,template:a}),delete window[l],this.$forceUpdate()}catch(e){console.error("Error loading dynamic content:",e)}finally{this.$q.loading.hide()}}},watch:{$route(e,t){routes.map((e=>e.name)).includes(e.name)?(this.$router.currentRoute.value.meta.previousRouteName=t.name,this.loadDynamicContent()):console.log(`Route '${e.name}' is not valid. Leave this one to Fastapi.`)}},template:'\n \n '},routes=[{path:"/wallet",name:"Wallet",component:DynamicComponent,props:e=>{let t="/wallet";if(Object.keys(e.query).length>0){t+="?";for(const[a,s]of Object.entries(e.query))t+=`${a}=${s}&`;t=t.slice(0,-1)}return{fetchUrl:t,scripts:["/static/js/wallet.js"]}}},{path:"/node",name:"Node",component:PageNode},{path:"/node/public",name:"NodePublic",component:PageNodePublic},{path:"/payments",name:"Payments",component:PagePayments},{path:"/audit",name:"Audit",component:PageAudit},{path:"/wallets",name:"Wallets",component:PageWallets},{path:"/users",name:"Users",component:PageUsers},{path:"/admin",name:"Admin",component:PageAdmin},{path:"/account",name:"Account",component:PageAccount},{path:"/extensions/builder",name:"ExtensionsBuilder",component:PageExtensionBuilder},{path:"/extensions",name:"Extensions",component:PageExtensions},{path:"/first_install",name:"FirstInstall",component:PageFirstInstall},{path:"/",name:"PageHome",component:PageHome}];window.router=VueRouter.createRouter({history:VueRouter.createWebHistory(),routes:routes}),window.app.mixin({computed:{isVueRoute(){const e=window.location.pathname,t=window.router.resolve(e);return t?.matched?.length>0}}}),window.app.use(VueQrcodeReader),window.app.use(Quasar,{config:{loading:{spinner:Quasar.QSpinnerBars}}}),window.i18n=new VueI18n.createI18n({locale:window.g.locale,fallbackLocale:"en",messages:window.localisation}),window.app.use(window.i18n),window.app.provide("g",g),window.app.use(window.router),window.app.component("DynamicComponent",DynamicComponent),window.app.mount("#vue"); +window.PageHome={template:"#page-home",mixins:[window.windowMixin],data:()=>({lnurl:"",authAction:"login",authMethod:"username-password",usr:"",username:"",reset_key:"",email:"",password:"",passwordRepeat:"",walletName:"",signup:!1}),computed:{showClaimLnurl(){return""!==this.lnurl&&this.allowRegister&&"user-id-only"in this.LNBITS_AUTH_METHODS},formatDescription(){return LNbits.utils.convertMarkdown(this.SITE_DESCRIPTION)},isAccessTokenExpired(){return this.$q.cookies.get("is_access_token_expired")},allowRegister(){return this.LNBITS_NEW_ACCOUNTS_ALLOWED},hasCustomImage(){return this.LNBITS_CUSTOM_IMAGE},showHomepageElements(){return this.HOMEPAGE_ELEMENTS_ENABLED},siteTitle(){return this.SITE_TITLE||""},siteTagline(){return this.SITE_TAGLINE||""},adsEnabled(){return this.AD_SPACE_ENABLED&&this.AD_SPACE&&this.AD_SPACE.length>0},adsTitle(){return this.AD_SPACE_TITLE||""},ads(){return this.AD_SPACE.map((e=>e.split(";")))},lnbitsBannerEnabled(){return"sats"==this.LNBITS_DENOMINATION&&"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}},methods:{showLogin(e){this.authAction="login",this.authMethod=e},showRegister(e){this.user="",this.username=null,this.password=null,this.passwordRepeat=null,this.authAction="register",this.authMethod=e},async register(){try{await LNbits.api.register(this.username,this.email,this.password,this.passwordRepeat),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async reset(){try{await LNbits.api.reset(this.reset_key,this.password,this.passwordRepeat),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async login(){try{await LNbits.api.login(this.username,this.password),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}},async loginUsr(){try{await LNbits.api.loginUsr(this.usr),this.usr="",window.location.href="/wallet"}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},createWallet(){LNbits.api.createAccount(this.walletName).then((e=>{window.location="/wallet?usr="+e.data.user+"&wal="+e.data.id}))},processing(){Quasar.Notify.create({timeout:0,message:"Processing...",icon:null})}},created(){this.g.isUserAuthorized&&(window.location.href="/wallet");const e=new URLSearchParams(window.location.search);this.reset_key=e.get("reset_key"),this.reset_key&&(this.authAction="reset"),e.has("lightning")&&(this.lnurl=e.get("lightning"))}},window.PageExtensionBuilder={template:"#page-extension-builder",mixins:[windowMixin],data:()=>({step:1,previewStepNames:{2:"settings",3:"owner_data",4:"client_data",5:"public_page"},extensionDataCleanString:"",extensionData:{id:"",name:"",stub_version:"",short_description:"",description:"",public_page:{has_public_page:!0,owner_data_fields:{name:"",description:""},client_data_fields:{public_inputs:[]},action_fields:{generate_action:!0,generate_payment_logic:!1,wallet_id:"",currency:"",amount:"",paid_flag:""}},preview_action:{is_preview_mode:!1,is_settings_preview:!1,is_owner_data_preview:!1,is_client_data_preview:!1,is_public_page_preview:!1},settings_data:{name:"Settings",enabled:!0,type:"user",fields:[]},owner_data:{name:"OwnerData",fields:[]},client_data:{enabled:!0,name:"ClientData",fields:[]}},sampleField:{name:"name",type:"str",label:"Name",hint:"",optional:!0,editable:!0,searchable:!0,sortable:!0},settingsTypes:[{label:"User Settings",value:"user"},{label:"Admin Settings",value:"admin"}],amountSource:[{label:"Client Data",value:"client_data"},{label:"Owner Data",value:"owner_data"}],extensionStubVersions:[]}),watch:{"extensionData.public_page.action_fields.amount_source":function(e,t){t&&e!==t&&(this.extensionData.public_page.action_fields.amount="")}},computed:{paymentActionAmountFields(){const e=this.extensionData.public_page.action_fields.amount_source;return e?"owner_data"===e?[""].concat(this.extensionData.owner_data.fields.filter((e=>"int"===e.type||"float"===e.type)).map((e=>e.name))):"client_data"===e?[""].concat(this.extensionData.client_data.fields.filter((e=>"int"===e.type||"float"===e.type)).map((e=>e.name))):void 0:[""]}},methods:{saveState(){this.$q.localStorage.set("lnbits.extension.builder.data",JSON.stringify(this.extensionData)),this.$q.localStorage.set("lnbits.extension.builder.step",this.step)},nextStep(){this.saveState(),this.$refs.stepper.next(),this.refreshPreview()},previousStep(){this.saveState(),this.$refs.stepper.previous(),this.refreshPreview()},onStepChange(){this.saveState(),this.refreshPreview()},clearAllData(){LNbits.utils.confirmDialog("Are you sure you want to clear all data? This action cannot be undone.").onOk((()=>{this.extensionData=JSON.parse(this.extensionDataCleanString),this.$q.localStorage.remove("lnbits.extension.builder.data"),this.$refs.stepper.set(1)}))},exportJsonData(){!0!==Quasar.exportFile(`${this.extensionData.id||"data-export"}.json`,JSON.stringify(this.extensionData,null,2),"text/json")?Quasar.Notify.create({message:"Browser denied file download...",color:"negative",icon:null}):Quasar.Notify.create({message:"File downloaded!",color:"positive",icon:"file_download"})},onJsonDataInput(e){const t=e.target.files[0],a=new FileReader;a.onload=e=>{this.extensionData={...this.extensionData,...JSON.parse(e.target.result)},this.$refs.extensionDataInput.value=null,Quasar.Notify.create({message:"File loaded!",color:"positive",icon:"file_upload"})},a.readAsText(t)},async buildExtension(){try{const e={responseType:"blob"},t=await LNbits.api.request("POST","/api/v1/extension/builder/zip",null,this.extensionData,e),a=window.URL.createObjectURL(new Blob([t.data])),s=document.createElement("a");s.href=a,s.download=`${this.extensionData.id||"lnbits-extension"}.zip`,document.body.appendChild(s),s.click(),s.remove(),window.URL.revokeObjectURL(a)}catch(e){LNbits.utils.notifyApiError(e)}},async buildExtensionAndDeploy(){try{const{data:e}=await LNbits.api.request("POST","/api/v1/extension/builder/deploy",null,this.extensionData);Quasar.Notify.create({message:e.message||"Extension deployed!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}},async cleanCacheData(){LNbits.utils.confirmDialog("Are you sure you want to clean the cache data? This action cannot be undone.","Clean Cache Data").onOk((async()=>{try{const{data:e}=await LNbits.api.request("DELETE","/api/v1/extension/builder",null,{});Quasar.Notify.create({message:e.message||"Cache data cleaned!",color:"positive"})}catch(e){LNbits.utils.notifyApiError(e)}}))},async previewExtension(e){this.saveState();try{await LNbits.api.request("POST","/api/v1/extension/builder/preview",null,{...this.extensionData,preview_action:{is_preview_mode:!!e,is_settings_preview:"settings"===e,is_owner_data_preview:"owner_data"===e,is_client_data_preview:"client_data"===e,is_public_page_preview:"public_page"===e}}),this.refreshIframe(e)}catch(e){LNbits.utils.notifyApiError(e)}},async refreshPreview(){setTimeout((()=>{const e=this.previewStepNames[`${this.step}`]||"";e&&this.previewExtension(e)}),100)},async getStubExtensionReleases(){try{const e="extension_builder_stub",{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e}/releases`);this.extensionStubVersions=t.sort(((e,t)=>e.version{const e=t.contentDocument||t.contentWindow.document;e.body.style.transform="scale(0.8)",e.body.style.transformOrigin="center top"},t.src=`/extensions/builder/preview/${this.extensionData.id}?page_name=${e}`):console.warn("Extension Builder Preview iframe not loaded yet.")},initBasicData(){this.extensionData.owner_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.client_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionData.settings_data.fields=[JSON.parse(JSON.stringify(this.sampleField))],this.extensionDataCleanString=JSON.stringify(this.extensionData)}},created(){this.initBasicData();const e=this.$q.localStorage.getItem("lnbits.extension.builder.data");e&&(this.extensionData={...this.extensionData,...JSON.parse(e)});const t=+this.$q.localStorage.getItem("lnbits.extension.builder.step");t&&(this.step=t),this.g.user.admin&&this.getStubExtensionReleases(),setTimeout((()=>{this.refreshIframe()}),1e3)}},window.PageExtensions={template:"#page-extensions",mixins:[windowMixin],data:()=>({extbuilderEnabled:!1,slide:0,fullscreen:!1,autoplay:!0,searchTerm:"",tab:"all",manageExtensionTab:"releases",filteredExtensions:null,updatableExtensions:[],showUninstallDialog:!1,showManageExtensionDialog:!1,showExtensionDetailsDialog:!1,showDropDbDialog:!1,showPayToEnableDialog:!1,showUpdateAllDialog:!1,dropDbExtensionId:"",selectedExtension:null,selectedImage:null,selectedExtensionDetails:null,selectedExtensionRepos:null,selectedRelease:null,uninstallAndDropDb:!1,maxStars:5,paylinkWebsocket:null,user:null}),watch:{searchTerm(e){this.filterExtensions(e,this.tab)}},methods:{handleTabChanged(e){this.filterExtensions(this.searchTerm,e)},filterExtensions(e,t){var a;this.filteredExtensions=this.extensions.filter((e=>"all"!==t||!e.isInstalled)).filter((e=>"installed"!==t||e.isInstalled)).filter((e=>"installed"!==t||(!!e.isActive||!!this.g.user.admin))).filter((e=>"featured"!==t||e.isFeatured)).filter((a=e,function(e){return e.name.toLowerCase().includes(a.toLowerCase())||e.shortDescription?.toLowerCase().includes(a.toLowerCase())})).map((e=>({...e,details_link:e.installedRelease?.details_link||e.latestRelease?.details_link}))),this.tab=t},async installExtension(e){this.unsubscribeFromPaylinkWs();const t=this.selectedExtension;t.inProgress=!0,this.showManageExtensionDialog=!1,e.payment_hash=e.payment_hash||this.getPaylinkHash(e.pay_link),LNbits.api.request("POST","/api/v1/extension",this.g.user.wallets[0].adminkey,{ext_id:t.id,archive:e.archive,source_repo:e.source_repo,payment_hash:e.payment_hash,version:e.version}).then((a=>{t.isAvailable=!0,t.isInstalled=!0,t.installedRelease=e,this.toggleExtension(t),t.inProgress=!1,this.filteredExtensions=this.extensions.concat([]),this.handleTabChanged("installed"),this.tab="installed",this.refreshRoute()})).catch((e=>{console.warn(e),t.inProgress=!1,LNbits.utils.notifyApiError(e)}))},async uninstallExtension(){const e=this.selectedExtension;this.showManageExtensionDialog=!1,this.showUninstallDialog=!1,e.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${e.id}`,this.g.user.wallets[0].adminkey).then((t=>{e.isAvailable=!1,e.isInstalled=!1,e.inProgress=!1,e.installedRelease=null,this.filteredExtensions=this.extensions.concat([]),this.handleTabChanged("installed"),this.tab="installed",Quasar.Notify.create({type:"positive",message:"Extension uninstalled!"}),this.uninstallAndDropDb?this.showDropDb():setTimeout((()=>{this.refreshRoute()}),300)})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},async dropExtensionDb(){const e=this.selectedExtension;this.showManageExtensionDialog=!1,this.showDropDbDialog=!1,this.dropDbExtensionId="",e.inProgress=!0,LNbits.api.request("DELETE",`/api/v1/extension/${e.id}/db`,this.g.user.wallets[0].adminkey).then((t=>{e.installedRelease=null,e.inProgress=!1,e.hasDatabaseTables=!1,Quasar.Notify.create({type:"positive",message:"Extension DB deleted!"}),setTimeout((()=>{this.refreshRoute()}),300)})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},toggleExtension(e){const t=e.isActive?"activate":"deactivate";LNbits.api.request("PUT",`/api/v1/extension/${e.id}/${t}`,this.g.user.wallets[0].adminkey).then((a=>{Quasar.Notify.create({timeout:2e3,type:"positive",message:`Extension '${e.id}' ${t}d!`})})).catch((t=>{LNbits.utils.notifyApiError(t),e.isActive=!1,e.inProgress=!1}))},async enableExtensionForUser(e){e.isPaymentRequired?this.showPayToEnable(e):this.enableExtension(e)},async enableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/enable`,this.g.user.wallets[0].adminkey).then((t=>{this.g.user.extensions=this.g.user.extensions.concat([e.id]),Quasar.Notify.create({type:"positive",message:"Extension enabled!"})})).catch((e=>{console.warn(e),LNbits.utils.notifyApiError(e)}))},disableExtension(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/disable`,this.g.user.wallets[0].adminkey).then((t=>{this.g.user.extensions=this.g.user.extensions.filter((t=>t!==e.id)),Quasar.Notify.create({type:"positive",message:"Extension disabled!"})})).catch((e=>{console.warn(error),LNbits.utils.notifyApiError(e)}))},showPayToEnable(e){this.selectedExtension=e,this.selectedExtension.payToEnable.paidAmount=e.payToEnable.amount,this.selectedExtension.payToEnable.showQRCode=!1,this.showPayToEnableDialog=!0},updatePayToInstallData(e){LNbits.api.request("PUT",`/api/v1/extension/${e.id}/sell`,this.g.user.wallets[0].adminkey,{required:e.payToEnable.required,amount:e.payToEnable.amount,wallet:e.payToEnable.wallet}).then((e=>{Quasar.Notify.create({type:"positive",message:"Payment info updated!"}),this.showManageExtensionDialog=!1})).catch((t=>{LNbits.utils.notifyApiError(t),e.inProgress=!1}))},showUninstall(){this.showManageExtensionDialog=!1,this.showUninstallDialog=!0,this.uninstallAndDropDb=!1},showDropDb(){this.showDropDbDialog=!0},async showManageExtension(e){this.selectedExtension=e,this.selectedRelease=null,this.selectedExtensionRepos=null,this.manageExtensionTab="releases",this.showManageExtensionDialog=!0;try{const{data:t}=await LNbits.api.request("GET",`/api/v1/extension/${e.id}/releases`,this.g.user.wallets[0].adminkey);this.selectedExtensionRepos=t.reduce(((e,t)=>(e[t.source_repo]=e[t.source_repo]||{releases:[],isInstalled:!1,repo:t.repo},t.inProgress=!1,t.error=null,t.loaded=!1,t.isInstalled=this.isInstalledVersion(this.selectedExtension,t),t.isInstalled&&(e[t.source_repo].isInstalled=!0),t.pay_link&&(t.requiresPayment=!0,t.paidAmount=t.cost_sats,t.payment_hash=this.getPaylinkHash(t.pay_link)),e[t.source_repo].releases.push(t),e)),{})}catch(t){LNbits.utils.notifyApiError(t),e.inProgress=!1}},async showExtensionDetails(e,t){if(t){this.selectedExtensionDetails=null,this.showExtensionDetailsDialog=!0,this.slide=0,this.fullscreen=!1;try{const{data:a}=await LNbits.api.request("GET",`/api/v1/extension/${e}/details?details_link=${t}`,this.g.user.wallets[0].inkey);this.selectedExtensionDetails=a,this.selectedExtensionDetails.description_md=LNbits.utils.convertMarkdown(a.description_md)}catch(e){console.warn(e)}}},async payAndInstall(e){try{this.selectedExtension.inProgress=!0,this.showManageExtensionDialog=!1;const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.rememberPaylinkHash(e.pay_link,t.payment_hash);const a=this.g.user.wallets.find((t=>t.id===e.wallet)),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);e.payment_hash=s.payment_hash,await this.installExtension(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.selectedExtension.inProgress=!1}},async payAndEnable(e){try{const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount),a=this.g.user.wallets.find((t=>t.id===e.payToEnable.paymentWallet)),{data:s}=await LNbits.api.payInvoice(a,t.payment_request);this.enableExtension(e),this.showPayToEnableDialog=!1}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showInstallQRCode(e){this.selectedRelease=e;try{const t=await this.requestPaymentForInstall(this.selectedExtension.id,e);this.selectedRelease.paymentRequest=t.payment_request,this.selectedRelease.payment_hash=t.payment_hash,this.selectedRelease=_.clone(this.selectedRelease),this.rememberPaylinkHash(this.selectedRelease.pay_link,this.selectedRelease.payment_hash),this.subscribeToPaylinkWs(this.selectedRelease.pay_link,t.payment_hash)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async showEnableQRCode(e){try{e.payToEnable.showQRCode=!0,this.selectedExtension=_.clone(e);const t=await this.requestPaymentForEnable(e.id,e.payToEnable.paidAmount);e.payToEnable.paymentRequest=t.payment_request,this.selectedExtension=_.clone(e);const a=new URL(window.location);a.protocol="https:"===a.protocol?"wss":"ws",a.pathname=`/api/v1/ws/${t.payment_hash}`;const s=new WebSocket(a);s.addEventListener("message",(async({data:t})=>{!1===JSON.parse(t).pending&&(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.enableExtension(e),s.close())}))}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async requestPaymentForInstall(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/install`,this.g.user.wallets[0].adminkey,{ext_id:e,archive:t.archive,source_repo:t.source_repo,cost_sats:t.paidAmount,version:t.version});return a},async requestPaymentForEnable(e,t){const{data:a}=await LNbits.api.request("PUT",`/api/v1/extension/${e}/invoice/enable`,this.g.user.wallets[0].adminkey,{amount:t});return a},clearHangingInvoice(e){this.forgetPaylinkHash(e.pay_link),e.payment_hash=null},rememberPaylinkHash(e,t){this.$q.localStorage.set(`lnbits.extensions.paylink.${e}`,t)},getPaylinkHash(e){return this.$q.localStorage.getItem(`lnbits.extensions.paylink.${e}`)},forgetPaylinkHash(e){this.$q.localStorage.remove(`lnbits.extensions.paylink.${e}`)},subscribeToPaylinkWs(e,t){const a=new URL(`${e}/${t}`);a.protocol="https:"===a.protocol?"wss":"ws",this.paylinkWebsocket=new WebSocket(a),this.paylinkWebsocket.addEventListener("message",(async({data:e})=>{JSON.parse(e).paid?(Quasar.Notify.create({type:"positive",message:"Invoice Paid!"}),this.installExtension(this.selectedRelease)):Quasar.Notify.create({type:"warning",message:"Invoice tracking lost!"})}))},unsubscribeFromPaylinkWs(){try{this.paylinkWebsocket&&this.paylinkWebsocket.close()}catch(e){console.warn(e)}},hasNewVersion(e){if(e.installedRelease&&e.latestRelease)return e.installedRelease.version!==e.latestRelease.version},isInstalledVersion(e,t){if(e.installedRelease)return e.installedRelease.source_repo===t.source_repo&&e.installedRelease.version===t.version},getReleaseIcon:e=>e.is_version_compatible?e.isInstalled?"download_done":"download":"block",getReleaseIconColor:e=>e.is_version_compatible?e.isInstalled?"text-green":"":"text-red",async getGitHubReleaseDetails(e){if(!e.is_github_release||e.loaded)return;const[t,a]=e.source_repo.split("/");e.inProgress=!0;try{const{data:s}=await LNbits.api.request("GET",`/api/v1/extension/release/${t}/${a}/${e.version}`,this.g.user.wallets[0].adminkey);e.loaded=!0,e.is_version_compatible=s.is_version_compatible,e.min_lnbits_version=s.min_lnbits_version,e.warning=s.warning}catch(t){console.warn(t),e.error=t,LNbits.utils.notifyApiError(t)}finally{e.inProgress=!1}},async selectAllUpdatableExtensionss(){this.updatableExtensions.forEach((e=>e.selectedForUpdate=!0))},async updateSelectedExtensions(){let e=0;for(const t of this.updatableExtensions)try{if(!t.selectedForUpdate)continue;t.inProgress=!0,await LNbits.api.request("POST","/api/v1/extension",this.g.user.wallets[0].adminkey,{ext_id:t.id,archive:t.latestRelease.archive,source_repo:t.latestRelease.source_repo,payment_hash:t.latestRelease.payment_hash,version:t.latestRelease.version}),e++,t.isAvailable=!0,t.isInstalled=!0,t.isUpgraded=!0,t.inProgress=!1,t.installedRelease=t.latestRelease,t.isActive=!0,this.toggleExtension(t)}catch(e){console.warn(e),Quasar.Notify.create({type:"negative",message:`Failed to update ${t.id}!`})}finally{t.inProgress=!1}Quasar.Notify.create({type:e?"positive":"warning",message:`${e||"No"} extensions updated!`}),this.showUpdateAllDialog=!1,setTimeout((()=>{this.refreshRoute()}),2e3)},async fetchAllExtensions(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension/all");return e}catch(e){return console.warn(e),LNbits.utils.notifyApiError(e),[]}}},async created(){this.extensions=await this.fetchAllExtensions(),this.extbuilderEnabled=user.admin||this.LNBITS_EXT_BUILDER,this.filteredExtensions=this.extensions.concat([]);const e=window.location.hash.replace("#",""),t=this.filteredExtensions.find((t=>t.id===e));if(t)this.searchTerm=t.id,this.handleTabChanged(t.isInstalled?"installed":"all"),this.tab=t.isInstalled?"installed":"all";else{const e=this.filteredExtensions.some((e=>e.isInstalled));this.handleTabChanged(e?"installed":"all"),this.tab=e?"installed":"all"}this.updatableExtensions=this.extensions.filter((e=>this.hasNewVersion(e)))}},window.PageFirstInstall={template:"#page-first-install",mixins:[window.windowMixin],data:()=>({loginData:{isPwd:!0,isPwdRepeat:!0,username:"",password:"",passwordRepeat:""}}),computed:{checkPasswordsMatch(){return this.loginData.password!==this.loginData.passwordRepeat}},methods:{async setPassword(){try{await LNbits.api.request("PUT","/api/v1/auth/first_install",null,{username:this.loginData.username,password:this.loginData.password,password_repeat:this.loginData.passwordRepeat}),window.location.href="/admin"}catch(e){LNbits.utils.notifyApiError(e)}}},created(){document.title="First Install - LNbits"}},window.PagePayments={template:"#page-payments",mixins:[window.windowMixin],data:()=>({payments:[],dailyChartData:[],searchDate:{from:null,to:null},searchData:{wallet_id:null,payment_hash:null,memo:null,internal_memo:null},statusFilters:{success:!0,pending:!0,failed:!0,incoming:!0,outgoing:!0},chartData:{showPaymentStatus:!0,showPaymentTags:!0,showBalance:!0,showWalletsSize:!1,showBalanceInOut:!1,showPaymentCountInOut:!1},searchOptions:{status:[]},paymentsTable:{columns:[{name:"status",align:"left",label:"Status",field:"status",sortable:!1},{name:"created_at",align:"left",label:"Created At",field:"created_at",sortable:!0},{name:"amount",align:"right",label:"Amount",field:"amount",sortable:!0},{name:"amountFiat",align:"right",label:"Fiat",field:"amountFiat",sortable:!1},{name:"fee_sats",align:"left",label:"Fee",field:"fee_sats",sortable:!0},{name:"tag",align:"left",label:"Tag",field:"tag",sortable:!1},{name:"memo",align:"left",label:"Memo",field:"memo",sortable:!1,max_length:20},{name:"internal_memo",align:"left",label:"Internal Memo",field:"internal_memo",sortable:!1,max_length:20},{name:"wallet_id",align:"left",label:"Wallet (ID)",field:"wallet_id",sortable:!1},{name:"payment_hash",align:"left",label:"Payment Hash",field:"payment_hash",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:25,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},chartsReady:!1,showDetails:!1,paymentDetails:null,lnbitsBalance:0}),async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchPayments()},computed:{},methods:{async fetchPayments(e){const t=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{});delete t["time[ge]"],delete t["time[le]"],this.searchDate.from&&(t["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(t["time[le]"]=this.searchDate.to+"T23:59:59"),this.paymentsTable.filter=t;try{const t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/payments/all/paginated?${t}`);this.paymentsTable.pagination.rowsNumber=a.total,this.payments=a.data.map((e=>(e.extra&&e.extra.tag&&(e.tag=e.extra.tag),e.timeFrom=moment.utc(e.created_at).local().fromNow(),e.outgoing=e.amount<0,e.amount=new Intl.NumberFormat(this.g.locale).format(e.amount/1e3)+" sats",e.extra?.wallet_fiat_amount&&(e.amountFiat=this.formatCurrency(e.extra.wallet_fiat_amount,e.extra.wallet_fiat_currency)),e.extra?.internal_memo&&(e.internal_memo=e.extra.internal_memo),e.fee_sats=new Intl.NumberFormat(this.g.locale).format(e.fee/1e3)+" sats",e)))}catch(e){console.error(e),LNbits.utils.notifyApiError(e)}finally{this.updateCharts(e)}},async searchPaymentsBy(e,t){e&&(this.searchData[e]=t),await this.fetchPayments()},clearDateSeach(){this.searchDate={from:null,to:null},delete this.paymentsTable.filter["time[ge]"],delete this.paymentsTable.filter["time[le]"],this.fetchPayments()},searchByDate(){"string"==typeof this.searchDate&&(this.searchDate={from:this.searchDate,to:this.searchDate}),this.searchDate.from&&(this.paymentsTable.filter["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(this.paymentsTable.filter["time[le]"]=this.searchDate.to+"T23:59:59"),this.fetchPayments()},handleFilterChanged(){const{success:e,pending:t,failed:a,incoming:s,outgoing:i}=this.statusFilters;delete this.searchData["status[ne]"],delete this.searchData["status[eq]"],e&&t&&a||(e&&t?this.searchData["status[ne]"]="failed":e&&a?this.searchData["status[ne]"]="pending":a&&t?this.searchData["status[ne]"]="success":e?this.searchData["status[eq]"]="success":t?this.searchData["status[eq]"]="pending":a&&(this.searchData["status[eq]"]="failed")),delete this.searchData["amount[ge]"],delete this.searchData["amount[le]"],s&&i||(s?this.searchData["amount[ge]"]="0":i&&(this.searchData["amount[le]"]="0")),this.fetchPayments()},showDetailsToggle(e){return this.paymentDetails=e,this.showDetails=!this.showDetails},formatDate:e=>LNbits.utils.formatDateString(e),formatCurrency(e,t){try{return LNbits.utils.formatCurrency(e,t)}catch(t){return console.error(t),`${e} ???`}},shortify:(e,t=10)=>(valueLength=(e||"").length,valueLength<=t?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async updateCharts(e){let t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e);try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=status`);e.sort(((e,t)=>e.field-t.field)).reverse(),this.searchOptions.status=e.map((e=>e.field)),this.paymentsStatusChart.data.datasets[0].data=e.map((e=>e.total)),this.paymentsStatusChart.data.labels=[...this.searchOptions.status],this.paymentsStatusChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/wallets?${t}`),a=e.map((e=>e.balance/e.payments_count)),s=Math.min(...a),i=Math.max(...a),n=e=>Math.floor(3+22*(e-s)/(i-s)),l=this.randomColors(20),o=e.map(((e,t)=>({data:[{x:e.payments_count,y:e.balance,r:n(Math.max(e.balance/e.payments_count,5))}],label:e.wallet_name,wallet_id:e.wallet_id,backgroundColor:l[t%100],hoverOffset:4})));this.paymentsWalletsChart.data.datasets=o,this.paymentsWalletsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const{data:e}=await LNbits.api.request("GET",`/api/v1/payments/stats/count?${t}&count_by=tag`);this.searchOptions.tag=e.map((e=>e.field)),this.searchOptions.status.sort(),this.paymentsTagsChart.data.datasets[0].data=e.map((e=>e.total)),this.paymentsTagsChart.data.labels=e.map((e=>e.field||"core")),this.paymentsTagsChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}try{const t=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{}),a={...this.paymentsTable,filter:t},s=LNbits.utils.prepareFilterQuery(a,e);let{data:i}=await LNbits.api.request("GET",`/api/v1/payments/stats/daily?${s}`);const n=this.searchDate.from+"T00:00:00",l=this.searchDate.to+"T23:59:59";this.lnbitsBalance=i.length?i[i.length-1].balance:0,i=i.filter((e=>this.searchDate.from&&this.searchDate.to?e.date>=n&&e.date<=l:this.searchDate.from?e.date>=n:!this.searchDate.to||e.date<=l)),this.paymentsDailyChart.data.datasets=[{label:"Balance",data:i.map((e=>e.balance)),pointStyle:!1,borderWidth:2,tension:.7,fill:1},{label:"Fees",data:i.map((e=>e.fee)),pointStyle:!1,borderWidth:1,tension:.4,fill:1}],this.paymentsDailyChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsDailyChart.update(),this.paymentsBalanceInOutChart.data.datasets=[{label:"Incoming Payments Balance",data:i.map((e=>e.balance_in))},{label:"Outgoing Payments Balance",data:i.map((e=>e.balance_out))}],this.paymentsBalanceInOutChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsBalanceInOutChart.update(),this.paymentsCountInOutChart.data.datasets=[{label:"Incoming Payments Count",data:i.map((e=>e.count_in))},{label:"Outgoing Payments Count",data:i.map((e=>-e.count_out))}],this.paymentsCountInOutChart.data.labels=i.map((e=>e.date.substring(0,10))),this.paymentsCountInOutChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async initCharts(){const e=this.$q.localStorage.getItem("lnbits.payments.chartData")||{};this.chartData={...this.chartData,...e},this.chartsReady?(this.paymentsStatusChart=new Chart(this.$refs.paymentsStatusChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("status",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(0, 205, 86)","rgb(64, 72, 78)","rgb(255, 99, 132)"],hoverOffset:4}]}}),this.paymentsWalletsChart=new Chart(this.$refs.paymentsWalletsChart.getContext("2d"),{type:"bubble",options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!1},title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].datasetIndex;this.searchPaymentsBy("wallet_id",a.data.datasets[e].wallet_id)}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(20),hoverOffset:4}]}}),this.paymentsTagsChart=new Chart(this.$refs.paymentsTagsChart.getContext("2d"),{type:"pie",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!1,title:{display:!1,text:"Tags"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchPaymentsBy("tag",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsDailyChart=new Chart(this.$refs.paymentsDailyChart.getContext("2d"),{type:"line",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(10),hoverOffset:4}]}}),this.paymentsBalanceInOutChart=new Chart(this.$refs.paymentsBalanceInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:"Tags"}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(50),hoverOffset:4}]}}),this.paymentsCountInOutChart=new Chart(this.$refs.paymentsCountInOutChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1},legend:{display:!0,title:{display:!1,text:""}}},scales:{x:{stacked:!0},y:{stacked:!0}}},data:{datasets:[{label:"",data:[],backgroundColor:this.randomColors(80),hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")},saveChartsPreferences(){this.$q.localStorage.set("lnbits.payments.chartData",this.chartData)},randomColors(e=1){const t=[];for(let a=1;a<=10;a++)for(let s=1;s<=10;s++)t.push(`rgb(${s*e*33%200}, ${71*(a+s+e)%255}, ${(a+30*e)%255})`);return t}}},window.PageNode={mixins:[window.windowMixin],template:"#page-node",config:{globalProperties:{LNbits:LNbits,msg:"hello"}},data(){return{isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:{data:[],filter:""},activeBalance:{},ranks:{},peers:{data:[],filter:""},connectPeerDialog:{show:!1,data:{}},setFeeDialog:{show:!1,data:{fee_ppm:0,fee_base_msat:0}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},transactionDetailsDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}],stateFilters:[{label:"Active",value:"active"},{label:"Pending",value:"pending"}],paymentsTable:{data:[],columns:[{name:"pending",label:""},{name:"date",align:"left",label:this.$t("date"),field:"date",sortable:!0},{name:"sat",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:e=>this.formatMsat(e.amount),sortable:!0},{name:"fee",align:"right",label:this.$t("fee")+" (m"+LNBITS_DENOMINATION+")",field:"fee"},{name:"destination",align:"right",label:"Destination",field:"destination"},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null},invoiceTable:{data:[],columns:[{name:"pending",label:""},{name:"paid_at",field:"paid_at",align:"left",label:"Paid at",sortable:!0},{name:"expiry",label:this.$t("expiry"),field:"expiry",align:"left",sortable:!0},{name:"amount",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:e=>this.formatMsat(e.amount),sortable:!0},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"}],pagination:{rowsPerPage:10,page:1,rowsNumber:10},filter:null}}},created(){this.getInfo(),this.get1MLStats()},watch:{tab(e){"transactions"!==e||this.paymentsTable.data.length?"channels"!==e||this.channels.data.length||(this.getChannels(),this.getPeers()):(this.getPayments(),this.getInvoices())}},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)},filteredChannels(){return this.stateFilters?this.channels.data.filter((e=>this.stateFilters.find((({value:t})=>t==e.state)))):this.channels.data},totalBalance(){return this.filteredChannels.reduce(((e,t)=>(e.local_msat+=t.balance.local_msat,e.remote_msat+=t.balance.remote_msat,e.total_msat+=t.balance.total_msat,e)),{local_msat:0,remote_msat:0,total_msat:0})}},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),api(e,t,a){const s=new URLSearchParams(a?.query);return LNbits.api.request(e,`/node/api/v1${t}?${s}`,{},a?.data).catch((e=>{LNbits.utils.notifyApiError(e)}))},getChannel(e){return this.api("GET",`/channels/${e}`).then((e=>{this.setFeeDialog.data.fee_ppm=e.data.fee_ppm,this.setFeeDialog.data.fee_base_msat=e.data.fee_base_msat}))},getChannels(){return this.api("GET","/channels").then((e=>{this.channels.data=e.data}))},getInfo(){return this.api("GET","/info").then((e=>{this.info=e.data,this.channel_stats=e.data.channel_stats})).catch((()=>{this.info={},this.channel_stats={}}))},get1MLStats(){return this.api("GET","/rank").then((e=>{this.ranks=e.data})).catch((()=>{this.ranks={}}))},getPayments(e){e&&(this.paymentsTable.pagination=e.pagination);let t=this.paymentsTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.api("GET","/payments",{query:a}).then((e=>{this.paymentsTable.data=e.data.data,this.paymentsTable.pagination.rowsNumber=e.data.total}))},getInvoices(e){e&&(this.invoiceTable.pagination=e.pagination);let t=this.invoiceTable.pagination;const a={limit:t.rowsPerPage,offset:(t.page-1)*t.rowsPerPage??0};return this.api("GET","/invoices",{query:a}).then((e=>{this.invoiceTable.data=e.data.data,this.invoiceTable.pagination.rowsNumber=e.data.total}))},getPeers(){return this.api("GET","/peers").then((e=>{this.peers.data=e.data}))},connectPeer(){this.api("POST","/peers",{data:this.connectPeerDialog.data}).then((()=>{this.connectPeerDialog.show=!1,this.getPeers()}))},disconnectPeer(e){LNbits.utils.confirmDialog("Do you really wanna disconnect this peer?").onOk((()=>{this.api("DELETE",`/peers/${e}`).then((e=>{Quasar.Notify.create({message:"Disconnected",icon:null}),this.needsRestart=!0,this.getPeers()}))}))},setChannelFee(e){this.api("PUT",`/channels/${e}`,{data:this.setFeeDialog.data}).then((e=>{this.setFeeDialog.show=!1,this.getChannels()})).catch(LNbits.utils.notifyApiError)},openChannel(){this.api("POST","/channels",{data:this.openChannelDialog.data}).then((e=>{this.openChannelDialog.show=!1,this.getChannels()})).catch((e=>{console.log(e)}))},showCloseChannelDialog(e){this.closeChannelDialog.show=!0,this.closeChannelDialog.data={force:!1,short_id:e.short_id,...e.point}},closeChannel(){this.api("DELETE","/channels",{query:this.closeChannelDialog.data}).then((e=>{this.closeChannelDialog.show=!1,this.getChannels()}))},showSetFeeDialog(e){this.setFeeDialog.show=!0,this.setFeeDialog.channel_id=e,this.getChannel(e)},showOpenChannelDialog(e){this.openChannelDialog.show=!0,this.openChannelDialog.data={peer_id:e,funding_amount:0}},showNodeInfoDialog(e){this.nodeInfoDialog.show=!0,this.nodeInfoDialog.data=e},showTransactionDetailsDialog(e){this.transactionDetailsDialog.show=!0,this.transactionDetailsDialog.data=e},shortenNodeId:e=>e?e.substring(0,5)+"..."+e.substring(e.length-5):"..."}},window.PageNodePublic={template:"#page-node-public",mixins:[window.windowMixin],data:()=>({enabled:!1,isSuperUser:!1,wallet:{},tab:"dashboard",payments:1e3,info:{},channel_stats:{},channels:[],activeBalance:{},ranks:{},peers:[],connectPeerDialog:{show:!1,data:{}},openChannelDialog:{show:!1,data:{}},closeChannelDialog:{show:!1,data:{}},nodeInfoDialog:{show:!1,data:{}},states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}]}),created(){this.getInfo(),this.get1MLStats()},methods:{formatMsat:e=>LNbits.utils.formatMsat(e),api:(e,t,a)=>LNbits.api.request(e,"/node/public/api/v1"+t,{},a),getInfo(){this.api("GET","/info",{}).then((e=>{this.info=e.data,this.channel_stats=e.data.channel_stats,this.enabled=!0})).catch((()=>{this.info={},this.channel_stats={}}))},get1MLStats(){this.api("GET","/rank",{}).then((e=>{this.ranks=e.data})).catch((()=>{this.ranks={}}))}}},window.PageAudit={template:"#page-audit",mixins:[window.windowMixin],data:()=>({chartsReady:!1,auditEntries:[],searchData:{user_id:"",ip_address:"",request_type:"",component:"",request_method:"",response_code:"",path:""},searchOptions:{component:[],request_method:[],response_code:[]},auditTable:{columns:[{name:"created_at",align:"center",label:"Date",field:"created_at",sortable:!0},{name:"duration",align:"left",label:"Duration (sec)",field:"duration",sortable:!0},{name:"component",align:"left",label:"Component",field:"component",sortable:!1},{name:"request_method",align:"left",label:"Method",field:"request_method",sortable:!1},{name:"response_code",align:"left",label:"Code",field:"response_code",sortable:!1},{name:"user_id",align:"left",label:"User Id",field:"user_id",sortable:!1},{name:"ip_address",align:"left",label:"IP Address",field:"ip_address",sortable:!1},{name:"path",align:"left",label:"Path",field:"path",sortable:!1}],pagination:{sortBy:"created_at",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},auditDetailsDialog:{data:null,show:!1}}),async created(){},async mounted(){this.chartsReady=!0,await this.$nextTick(),this.initCharts(),await this.fetchAudit()},methods:{formatDate:e=>LNbits.utils.formatDateString(e),async fetchAudit(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1?${t}`);this.auditTable.pagination.rowsNumber=a.total,this.auditEntries=a.data,await this.fetchAuditStats(e)}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}finally{this.auditTable.loading=!1}},async fetchAuditStats(e){try{const t=LNbits.utils.prepareFilterQuery(this.auditTable,e),{data:a}=await LNbits.api.request("GET",`/audit/api/v1/stats?${t}`),s=a.request_method.map((e=>e.field));this.searchOptions.request_method=[...new Set(this.searchOptions.request_method.concat(s))],this.requestMethodChart.data.labels=s,this.requestMethodChart.data.datasets[0].data=a.request_method.map((e=>e.total)),this.requestMethodChart.update();const i=a.response_code.map((e=>e.field));this.searchOptions.response_code=[...new Set(this.searchOptions.response_code.concat(i))],this.responseCodeChart.data.labels=i,this.responseCodeChart.data.datasets[0].data=a.response_code.map((e=>e.total)),this.responseCodeChart.update();const n=a.component.map((e=>e.field));this.searchOptions.component=[...new Set(this.searchOptions.component.concat(n))],this.componentUseChart.data.labels=n,this.componentUseChart.data.datasets[0].data=a.component.map((e=>e.total)),this.componentUseChart.update(),this.longDurationChart.data.labels=a.long_duration.map((e=>e.field)),this.longDurationChart.data.datasets[0].data=a.long_duration.map((e=>e.total)),this.longDurationChart.update()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async searchAuditBy(e,t){e&&(this.searchData[e]=t),this.auditTable.filter=Object.entries(this.searchData).reduce(((e,[t,a])=>a?(e[t]=a,e):e),{}),await this.fetchAudit()},showDetailsDialog(e){const t=JSON.parse(e?.request_details||"");try{t.body&&(t.body=JSON.parse(t.body))}catch(e){}this.auditDetailsDialog.data=JSON.stringify(t,null,4),this.auditDetailsDialog.show=!0},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`),async initCharts(){this.chartsReady?(this.responseCodeChart=new Chart(this.$refs.responseCodeChart.getContext("2d"),{type:"doughnut",options:{responsive:!0,plugins:{legend:{position:"bottom"},title:{display:!1,text:"HTTP Response Codes"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("response_code",a.data.labels[e])}}},data:{datasets:[{label:"",data:[20,10],backgroundColor:["rgb(100, 99, 200)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"]}],labels:[]}}),this.requestMethodChart=new Chart(this.$refs.requestMethodChart.getContext("2d"),{type:"bar",options:{responsive:!0,maintainAspectRatio:!1,plugins:{title:{display:!1}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("request_method",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)"],hoverOffset:4}]}}),this.componentUseChart=new Chart(this.$refs.componentUseChart.getContext("2d"),{type:"pie",options:{responsive:!0,plugins:{legend:{position:"xxx"},title:{display:!1,text:"Components"}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("component",a.data.labels[e])}}},data:{datasets:[{data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}}),this.longDurationChart=new Chart(this.$refs.longDurationChart.getContext("2d"),{type:"bar",options:{responsive:!0,indexAxis:"y",maintainAspectRatio:!1,plugins:{legend:{title:{display:!1,text:"Long Duration"}}},onClick:(e,t,a)=>{if(t[0]){const e=t[0].index;this.searchAuditBy("path",a.data.labels[e])}}},data:{datasets:[{label:"",data:[],backgroundColor:["rgb(255, 99, 132)","rgb(54, 162, 235)","rgb(255, 205, 86)","rgb(255, 5, 86)","rgb(25, 205, 86)","rgb(255, 205, 250)","rgb(100, 205, 250)","rgb(120, 205, 250)","rgb(140, 205, 250)","rgb(160, 205, 250)"],hoverOffset:4}]}})):console.warn("Charts are not ready yet. Initialization delayed.")}}},window.PageWallets={template:"#page-wallets",mixins:[window.windowMixin],data:()=>({user:null,tab:"wallets",wallets:[],addWalletDialog:{show:!1},walletsTable:{columns:[{name:"name",align:"left",label:"Name",field:"name",sortable:!0},{name:"currency",align:"center",label:"Currency",field:"currency",sortable:!0},{name:"updated_at",align:"right",label:"Last Updated",field:"updated_at",sortable:!0}],pagination:{sortBy:"updated_at",rowsPerPage:12,page:1,descending:!0,rowsNumber:10},search:"",hideEmpty:!0,loading:!1}}),watch:{"walletsTable.search":{handler(){const e={};this.walletsTable.search&&(e.search=this.walletsTable.search),this.getUserWallets()}}},methods:{async getUserWallets(e){try{this.walletsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.walletsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/wallet/paginated?${t}`,null);this.wallets=a.data,this.walletsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.walletsTable.loading=!1}},showNewWalletDialog(){this.addWalletDialog={show:!0,walletType:"lightning"},this.showAddNewWalletDialog()},goToWallet(e){window.location=`/wallet?wal=${e}`},formattedFiatAmount:(e,t)=>LNbits.utils.formatCurrency(Number(e).toFixed(2),t),formattedSatAmount:e=>LNbits.utils.formatMsat(e)+" sat"},async created(){await this.getUserWallets()}},window.PageUsers={template:"#page-users",mixins:[window.windowMixin],data:()=>({paymentsWallet:{},cancel:{},users:[],wallets:[],searchData:{user:"",username:"",email:"",pubkey:""},paymentPage:{show:!1},activeWallet:{userId:null,show:!1},activeUser:{data:null,showUserId:!1,show:!1},createWalletDialog:{data:{},show:!1},walletTable:{columns:[{name:"name",align:"left",label:"Name",field:"name"},{name:"id",align:"left",label:"Wallet Id",field:"id"},{name:"currency",align:"left",label:"Currency",field:"currency"},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat"}],pagination:{sortBy:"name",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1},usersTable:{columns:[{name:"admin",align:"left",label:"Admin",field:"admin",sortable:!1},{name:"wallet_id",align:"left",label:"Wallets",field:"wallet_id",sortable:!1},{name:"user",align:"left",label:"User Id",field:"user",sortable:!1},{name:"username",align:"left",label:"Username",field:"username",sortable:!1},{name:"email",align:"left",label:"Email",field:"email",sortable:!1},{name:"pubkey",align:"left",label:"Public Key",field:"pubkey",sortable:!1},{name:"balance_msat",align:"left",label:"Balance",field:"balance_msat",sortable:!0},{name:"transaction_count",align:"left",label:"Payments",field:"transaction_count",sortable:!0},{name:"last_payment",align:"left",label:"Last Payment",field:"last_payment",sortable:!0}],pagination:{sortBy:"balance_msat",rowsPerPage:10,page:1,descending:!0,rowsNumber:10},search:null,hideEmpty:!0,loading:!1}}),watch:{"usersTable.hideEmpty":function(e,t){this.usersTable.filter=e?{"transaction_count[gt]":0}:{},this.fetchUsers()}},created(){this.fetchUsers()},methods:{formatDate:e=>LNbits.utils.formatDateString(e),formatSat:e=>LNbits.utils.formatSat(Math.floor(e/1e3)),backToUsersPage(){this.activeUser.show=!1,this.paymentPage.show=!1,this.activeWallet.show=!1,this.fetchUsers()},handleBalanceUpdate(){this.fetchWallets(this.activeWallet.userId)},resetPassword(e){return LNbits.api.request("PUT",`/users/api/v1/user/${e}/reset_password`).then((e=>{LNbits.utils.confirmDialog(this.$t("reset_key_generated")+" "+this.$t("reset_key_copy")).onOk((()=>{const t=window.location.origin+"?reset_key="+e.data;this.copyText(t)}))})).catch(LNbits.utils.notifyApiError)},createUser(){LNbits.api.request("POST","/users/api/v1/user",null,this.activeUser.data).then((e=>{Quasar.Notify.create({type:"positive",message:"User created!",icon:null}),this.activeUser.setPassword=!0,this.activeUser.data=e.data,this.fetchUsers()})).catch(LNbits.utils.notifyApiError)},updateUser(){LNbits.api.request("PUT",`/users/api/v1/user/${this.activeUser.data.id}`,null,this.activeUser.data).then((()=>{Quasar.Notify.create({type:"positive",message:"User updated!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1,this.fetchUsers()})).catch(LNbits.utils.notifyApiError)},createWallet(){const e=this.activeWallet.userId;e?LNbits.api.request("POST",`/users/api/v1/user/${e}/wallet`,null,this.createWalletDialog.data).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Wallet created!"})})).catch(LNbits.utils.notifyApiError):Quasar.Notify.create({type:"warning",message:"No user selected!",icon:null})},deleteUser(e){LNbits.utils.confirmDialog("Are you sure you want to delete this user?").onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}`).then((()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"User deleted!",icon:null}),this.activeUser.data=null,this.activeUser.show=!1})).catch(LNbits.utils.notifyApiError)}))},undeleteUserWallet(e,t){LNbits.api.request("PUT",`/users/api/v1/user/${e}/wallet/${t}/undelete`).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"Undeleted user wallet!",icon:null})})).catch(LNbits.utils.notifyApiError)},deleteUserWallet(e,t,a){const s=a?"Wallet is already deleted, are you sure you want to permanently delete this user wallet?":"Are you sure you want to delete this user wallet?";LNbits.utils.confirmDialog(s).onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallet/${t}`).then((()=>{this.fetchWallets(e),Quasar.Notify.create({type:"positive",message:"User wallet deleted!",icon:null})})).catch(LNbits.utils.notifyApiError)}))},deleteAllUserWallets(e){LNbits.utils.confirmDialog(this.$t("confirm_delete_all_wallets")).onOk((()=>{LNbits.api.request("DELETE",`/users/api/v1/user/${e}/wallets`).then((t=>{Quasar.Notify.create({type:"positive",message:t.data.message,icon:null}),this.fetchWallets(e)})).catch(LNbits.utils.notifyApiError)}))},copyWalletLink(e){const t=`${window.location.origin}/wallet?usr=${this.activeWallet.userId}&wal=${e}`;this.copyText(t)},fetchUsers(e){this.relaxFilterForFields(["username","email"]);const t=LNbits.utils.prepareFilterQuery(this.usersTable,e);LNbits.api.request("GET",`/users/api/v1/user?${t}`).then((e=>{this.usersTable.loading=!1,this.usersTable.pagination.rowsNumber=e.data.total,this.users=e.data.data})).catch(LNbits.utils.notifyApiError)},fetchWallets(e){return LNbits.api.request("GET",`/users/api/v1/user/${e}/wallet`).then((t=>{this.wallets=t.data,this.activeWallet.userId=e,this.activeWallet.show=!0})).catch(LNbits.utils.notifyApiError)},relaxFilterForFields(e=[]){e.forEach((e=>{const t=this.usersTable?.filter?.[e];t&&this.usersTable.filter[e]&&(this.usersTable.filter[`${e}[like]`]=t,delete this.usersTable.filter[e])}))},updateWallet(e){LNbits.api.request("PATCH","/api/v1/wallet",e.adminkey,{name:e.name}).then((()=>{e.editable=!1,Quasar.Notify.create({message:"Wallet name updated.",type:"positive",timeout:3500})})).catch((e=>{LNbits.utils.notifyApiError(e)}))},toggleAdmin(e){LNbits.api.request("GET",`/users/api/v1/user/${e}/admin`).then((()=>{this.fetchUsers(),Quasar.Notify.create({type:"positive",message:"Toggled admin!",icon:null})})).catch(LNbits.utils.notifyApiError)},async showAccountPage(e){if(this.activeUser.showPassword=!1,this.activeUser.showUserId=!1,this.activeUser.setPassword=!1,!e)return this.activeUser.data={extra:{}},void(this.activeUser.show=!0);try{const{data:t}=await LNbits.api.request("GET",`/users/api/v1/user/${e}`);this.activeUser.data=t,this.activeUser.show=!0}catch(e){console.warn(e),Quasar.Notify.create({type:"warning",message:"Failed to get user!"}),this.activeUser.show=!1}},async showWalletPayments(e){this.activeUser.show=!1,await this.fetchWallets(this.users[0].id),await this.showPayments(e)},showPayments(e){this.paymentsWallet=this.wallets.find((t=>t.id===e)),this.paymentPage.show=!0},searchUserBy(e){const t=this.searchData[e];this.usersTable.filter={},t&&(this.usersTable.filter[e]=t),this.fetchUsers()},shortify:e=>(valueLength=(e||"").length,valueLength<=10?e:`${e.substring(0,5)}...${e.substring(valueLength-5,valueLength)}`)}},window.PageAccount={template:"#page-account",mixins:[window.windowMixin],data(){return{user:null,hasUsername:!1,showUserId:!1,themeOptions:[{name:"bitcoin",color:"deep-orange"},{name:"mint",color:"green"},{name:"autumn",color:"brown"},{name:"monochrome",color:"grey"},{name:"salvador",color:"blue-10"},{name:"freedom",color:"pink-13"},{name:"cyber",color:"light-green-9"},{name:"flamingo",color:"pink-3"}],reactionOptions:["None","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],borderOptions:["retro-border","hard-border","neon-border","no-border"],tab:"user",credentialsData:{show:!1,oldPassword:null,newPassword:null,newPasswordRepeat:null,username:null,pubkey:null},apiAcl:{showNewAclDialog:!1,showPasswordDialog:!1,showNewTokenDialog:!1,data:[],passwordGuardedFunction:null,newAclName:"",newTokenName:"",password:"",apiToken:null,selectedTokenId:null,columns:[{name:"Name",align:"left",label:this.$t("Name"),field:"Name",sortable:!1},{name:"path",align:"left",label:this.$t("path"),field:"path",sortable:!1},{name:"read",align:"left",label:this.$t("read"),field:"read",sortable:!1},{name:"write",align:"left",label:this.$t("write"),field:"write",sortable:!1}],pagination:{rowsPerPage:100,page:1}},selectedApiAcl:{id:null,name:null,endpoints:[],token_id_list:[],allRead:!1,allWrite:!1},assets:[],assetsTable:{loading:!1,columns:[{name:"name",align:"left",label:this.$t("Name"),field:"name",sortable:!0},{name:"created_at",align:"left",label:this.$t("created_at"),field:"created_at",sortable:!0}],pagination:{rowsPerPage:6,page:1}},assetsUploadToPublic:!1,notifications:{nostr:{identifier:""}}}},watch:{"assetsTable.search":{handler(){const e={};this.assetsTable.search&&(e.search=this.assetsTable.search),this.getUserAssets()}}},methods:{activeLanguage:e=>window.i18n.global.locale===e,changeLanguage(e){window.i18n.global.locale=e,this.$q.localStorage.set("lnbits.lang",e)},async updateAccount(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/update",null,{user_id:this.user.id,username:this.user.username,email:this.user.email,extra:this.user.extra});this.user=e,this.hasUsername=!!e.username,Quasar.Notify.create({type:"positive",message:"Account updated."})}catch(e){LNbits.utils.notifyApiError(e)}},disableUpdatePassword(){return!this.credentialsData.newPassword||!this.credentialsData.newPasswordRepeat||this.credentialsData.newPassword!==this.credentialsData.newPasswordRepeat},async updatePassword(){if(this.credentialsData.username)try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/password",null,{user_id:this.user.id,username:this.credentialsData.username,password_old:this.credentialsData.oldPassword,password:this.credentialsData.newPassword,password_repeat:this.credentialsData.newPasswordRepeat});this.user=e,this.hasUsername=!!e.username,this.credentialsData.show=!1,Quasar.Notify.create({type:"positive",message:"Password updated."})}catch(e){LNbits.utils.notifyApiError(e)}else Quasar.Notify.create({type:"warning",message:"Please set a username."})},async updatePubkey(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/pubkey",null,{user_id:this.user.id,pubkey:this.credentialsData.pubkey});this.user=e,this.hasUsername=!!e.username,this.credentialsData.show=!1,this.$q.notify({type:"positive",message:"Public key updated."})}catch(e){LNbits.utils.notifyApiError(e)}},showUpdateCredentials(){this.credentialsData={show:!0,oldPassword:null,username:this.user.username,pubkey:this.user.pubkey,newPassword:null,newPasswordRepeat:null}},newApiAclDialog(){this.apiAcl.newAclName=null,this.apiAcl.showNewAclDialog=!0},newTokenAclDialog(){this.apiAcl.newTokenName=null,this.apiAcl.newTokenExpiry=null,this.apiAcl.showNewTokenDialog=!0},handleApiACLSelected(e){this.selectedApiAcl={id:null,name:null,endpoints:[],token_id_list:[]},this.apiAcl.selectedTokenId=null,e&&setTimeout((()=>{const t=this.apiAcl.data.find((t=>t.id===e));this.selectedApiAcl&&(this.selectedApiAcl={...t},this.selectedApiAcl.allRead=this.selectedApiAcl.endpoints.every((e=>e.read)),this.selectedApiAcl.allWrite=this.selectedApiAcl.endpoints.every((e=>e.write)))}))},handleAllEndpointsReadAccess(){this.selectedApiAcl.endpoints.forEach((e=>e.read=this.selectedApiAcl.allRead))},handleAllEndpointsWriteAccess(){this.selectedApiAcl.endpoints.forEach((e=>e.write=this.selectedApiAcl.allWrite))},async getApiACLs(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/auth/acl",null);this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}},askPasswordAndRunFunction(e){this.apiAcl.passwordGuardedFunction=e,this.apiAcl.showPasswordDialog=!0},runPasswordGuardedFunction(){this.apiAcl.showPasswordDialog=!1;const e=this.apiAcl.passwordGuardedFunction;e&&this[e]()},async addApiACL(){if(this.apiAcl.newAclName){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.apiAcl.newAclName,name:this.apiAcl.newAclName,password:this.apiAcl.password});this.apiAcl.data=e.access_control_list;const t=this.apiAcl.data.find((e=>e.name===this.apiAcl.newAclName));this.handleApiACLSelected(t.id),this.apiAcl.showNewAclDialog=!1,this.$q.notify({type:"positive",message:"Access Control List created."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.name="",this.apiAcl.password=""}this.apiAcl.showNewAclDialog=!1}else this.$q.notify({type:"warning",message:"Name is required."})},async updateApiACLs(){try{const{data:e}=await LNbits.api.request("PUT","/api/v1/auth/acl",null,{id:this.user.id,password:this.apiAcl.password,...this.selectedApiAcl});this.apiAcl.data=e.access_control_list}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteApiACL(){if(this.selectedApiAcl.id){try{await LNbits.api.request("DELETE","/api/v1/auth/acl",null,{id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Access Control List deleted."})}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}this.apiAcl.data=this.apiAcl.data.filter((e=>e.id!==this.selectedApiAcl.id)),this.handleApiACLSelected(this.apiAcl.data[0]?.id)}},async generateApiToken(){if(!this.selectedApiAcl.id)return;const e=new Date(this.apiAcl.newTokenExpiry)-new Date;try{const{data:t}=await LNbits.api.request("POST","/api/v1/auth/acl/token",null,{acl_id:this.selectedApiAcl.id,token_name:this.apiAcl.newTokenName,password:this.apiAcl.password,expiration_time_minutes:Math.trunc(e/6e4)});this.apiAcl.apiToken=t.api_token,this.apiAcl.selectedTokenId=t.id,Quasar.Notify.create({type:"positive",message:"Token Generated."}),await this.getApiACLs(),this.handleApiACLSelected(this.selectedApiAcl.id),this.apiAcl.showNewTokenDialog=!1}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async deleteToken(){if(this.apiAcl.selectedTokenId)try{await LNbits.api.request("DELETE","/api/v1/auth/acl/token",null,{id:this.apiAcl.selectedTokenId,acl_id:this.selectedApiAcl.id,password:this.apiAcl.password}),this.$q.notify({type:"positive",message:"Token deleted."}),this.selectedApiAcl.token_id_list=this.selectedApiAcl.token_id_list.filter((e=>e.id!==this.apiAcl.selectedTokenId)),this.apiAcl.selectedTokenId=null}catch(e){LNbits.utils.notifyApiError(e)}finally{this.apiAcl.password=""}},async getUserAssets(e){try{this.assetsTable.loading=!0;const t=LNbits.utils.prepareFilterQuery(this.assetsTable,e),{data:a}=await LNbits.api.request("GET",`/api/v1/assets/paginated?${t}`,null);this.assets=a.data,this.assetsTable.pagination.rowsNumber=a.total}catch(e){LNbits.utils.notifyApiError(e)}finally{this.assetsTable.loading=!1}},onImageInput(e){const t=e.target.files[0];t&&this.uploadAsset(t)},async uploadAsset(e){const t=new FormData;t.append("file",e);try{await LNbits.api.request("POST",`/api/v1/assets?public_asset=${this.assetsUploadToPublic}`,null,t,{headers:{"Content-Type":"multipart/form-data"}}),this.$q.notify({type:"positive",message:"Upload successful!",icon:null}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},async deleteAsset(e){LNbits.utils.confirmDialog("Are you sure you want to delete this asset?").onOk((async()=>{try{await LNbits.api.request("DELETE",`/api/v1/assets/${e.id}`,null),this.$q.notify({type:"positive",message:"Asset deleted."}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}}))},async toggleAssetPublicAccess(e){try{await LNbits.api.request("PUT",`/api/v1/assets/${e.id}`,null,{is_public:!e.is_public}),this.$q.notify({type:"positive",message:"Update successful!",icon:null}),await this.getUserAssets()}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}},copyAssetLinkToClipboard(e){const t=`${window.location.origin}/api/v1/assets/${e.id}/binary`;this.copyText(t)}},async created(){try{const{data:e}=await LNbits.api.getAuthenticatedUser();this.user=e,this.hasUsername=!!e.username,this.user.extra||(this.user.extra={})}catch(e){LNbits.utils.notifyApiError(e)}const e=window.location.hash.replace("#","");e&&(this.tab=e),await this.getApiACLs(),await this.getUserAssets(),this.themeOptions=this.themeOptions.filter((e=>this.allowedThemes.includes(e.name)))}},window.PageAdmin={template:"#page-admin",mixins:[windowMixin],data:()=>({tab:"funding",settings:{},formData:{lnbits_exchange_rate_providers:[],lnbits_audit_exclude_paths:[],lnbits_audit_include_paths:[],lnbits_audit_http_response_codes:[]},isSuperUser:!1,needsRestart:!1}),async created(){await this.getSettings();const e=window.location.hash.replace("#","");e&&(this.tab=e)},computed:{checkChanges(){return!_.isEqual(this.settings,this.formData)}},methods:{getDefaultSetting(e){LNbits.api.request("GET",`/admin/api/v1/settings/default?field_name=${e}`).then((t=>{this.formData[e]=t.data.default_value})).catch((function(e){LNbits.utils.notifyApiError(e)}))},restartServer(){LNbits.api.request("GET","/admin/api/v1/restart/").then((e=>{this.$q.notify({type:"positive",message:"Success! Restarted Server",icon:null}),this.needsRestart=!1})).catch(LNbits.utils.notifyApiError)},async getSettings(){await LNbits.api.request("GET","/admin/api/v1/settings",this.g.user.wallets[0].adminkey).then((e=>{this.isSuperUser=e.data.is_super_user||!1,this.settings=e.data,this.formData={...this.settings}})).catch(LNbits.utils.notifyApiError)},updateSettings(){const e=_.omit(this.formData,["is_super_user","lnbits_allowed_funding_sources","touch"]);LNbits.api.request("PUT","/admin/api/v1/settings",this.g.user.wallets[0].adminkey,e).then((e=>{this.needsRestart=this.settings.lnbits_backend_wallet_class!==this.formData.lnbits_backend_wallet_class,this.settings=this.formData,this.formData=_.clone(this.settings),Quasar.Notify.create({type:"positive",message:"Success! Settings changed! "+(this.needsRestart?"Restart required!":""),icon:null})})).catch(LNbits.utils.notifyApiError)},deleteSettings(){LNbits.utils.confirmDialog("Are you sure you want to restore settings to default?").onOk((()=>{LNbits.api.request("DELETE","/admin/api/v1/settings").then((e=>{Quasar.Notify.create({type:"positive",message:"Success! Restored settings to defaults. Restarting...",icon:null}),this.$q.localStorage.clear()})).catch(LNbits.utils.notifyApiError)}))},downloadBackup(){window.open("/admin/api/v1/backup","_blank")}}},window.app.component("lnbits-admin-funding",{props:["is-super-user","form-data","settings"],template:"#lnbits-admin-funding",mixins:[window.windowMixin],data:()=>({auditData:[]}),created(){this.getAudit()},methods:{getAudit(){LNbits.api.request("GET","/admin/api/v1/audit",this.g.user.wallets[0].adminkey).then((e=>{this.auditData=e.data})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("lnbits-admin-funding-sources",{template:"#lnbits-admin-funding-sources",mixins:[window.windowMixin],props:["form-data","allowed-funding-sources"],methods:{getFundingSourceLabel(e){const t=this.rawFundingSources.find((t=>t[0]===e));return t?t[1]:e},showQRValue(e){this.qrValue=e,this.showQRDialog=!0}},computed:{fundingSources(){let e=[];for(const[t,a,s]of this.rawFundingSources){const a={};if(null!==s)for(let[e,t]of Object.entries(s))a[e]="string"==typeof t?{label:t,value:null}:t||{};e.push([t,a])}return new Map(e)},sortedAllowedFundingSources(){return this.allowedFundingSources.sort()}},data:()=>({hideInput:!0,showQRDialog:!1,qrValue:"",rawFundingSources:[["VoidWallet","Void Wallet",null],["FakeWallet","Fake Wallet",{fake_wallet_secret:"Secret",lnbits_denomination:'"sats" or 3 Letter Custom Denomination'}],["CLNRestWallet","Core Lightning Rest (plugin)",{clnrest_url:"Endpoint",clnrest_ca:"ca.pem",clnrest_cert:"server.pem",clnrest_readonly_rune:"Rune used for readonly requests",clnrest_invoice_rune:"Rune used for creating invoices",clnrest_pay_rune:"Rune used for paying invoices using pay",clnrest_renepay_rune:"Rune used for paying invoices using renepay",clnrest_last_pay_index:"Ignores any invoices paid prior to or including this index. 0 is equivalent to not specifying and negative value is invalid.",clnrest_nodeid:"Node id"}],["CoreLightningWallet","Core Lightning",{corelightning_rpc:"Endpoint",corelightning_pay_command:"Custom Pay Command"}],["CoreLightningRestWallet","Core Lightning Rest (legacy)",{corelightning_rest_url:"Endpoint",corelightning_rest_cert:"Certificate",corelightning_rest_macaroon:"Macaroon"}],["LndRestWallet","Lightning Network Daemon (LND Rest)",{lnd_rest_endpoint:"Endpoint",lnd_rest_cert:"Certificate",lnd_rest_macaroon:"Macaroon",lnd_rest_macaroon_encrypted:"Encrypted Macaroon",lnd_rest_route_hints:"Enable Route Hints",lnd_rest_allow_self_payment:"Allow Self Payment"}],["LndWallet","Lightning Network Daemon (LND)",{lnd_grpc_endpoint:"Endpoint",lnd_grpc_cert:"Certificate",lnd_grpc_port:"Port",lnd_grpc_macaroon:"GRPC Macaroon",lnd_grpc_invoice_macaroon:"GRPC Invoice Macaroon",lnd_grpc_admin_macaroon:"GRPC Admin Macaroon",lnd_grpc_macaroon_encrypted:"Encrypted Macaroon"}],["LnTipsWallet","LN.Tips",{lntips_api_endpoint:"Endpoint",lntips_api_key:"API Key"}],["LNPayWallet","LN Pay",{lnpay_api_endpoint:"Endpoint",lnpay_api_key:"API Key",lnpay_wallet_key:"Wallet Key"}],["EclairWallet","Eclair (ACINQ)",{eclair_url:"URL",eclair_pass:"Password"}],["LNbitsWallet","LNbits",{lnbits_endpoint:"Endpoint",lnbits_key:"Admin Key"}],["BlinkWallet","Blink",{blink_api_endpoint:"Endpoint",blink_ws_endpoint:"WebSocket",blink_token:"Key"}],["AlbyWallet","Alby",{alby_api_endpoint:"Endpoint",alby_access_token:"Key"}],["BoltzWallet","Boltz",{boltz_client_endpoint:"Endpoint",boltz_client_macaroon:"Admin Macaroon path or hex",boltz_client_cert:"Certificate path or hex",boltz_client_wallet:"Wallet Name",boltz_client_password:"Wallet Password (can be empty)",boltz_mnemonic:{label:"Liquid mnemonic (copy into greenwallet)",readonly:!0,copy:!0,qrcode:!0}}],["ZBDWallet","ZBD",{zbd_api_endpoint:"Endpoint",zbd_api_key:"Key"}],["PhoenixdWallet","Phoenixd",{phoenixd_api_endpoint:"Endpoint",phoenixd_api_password:"Key"}],["OpenNodeWallet","OpenNode",{opennode_api_endpoint:"Endpoint",opennode_key:"Key"}],["ClicheWallet","Cliche (NBD)",{cliche_endpoint:"Endpoint"}],["SparkWallet","Spark",{spark_url:"Endpoint",spark_token:"Token"}],["NWCWallet","Nostr Wallet Connect",{nwc_pairing_url:"Pairing URL"}],["BreezSdkWallet","Breez SDK",{breez_api_key:"Breez API Key",breez_greenlight_seed:"Greenlight Seed",breez_greenlight_device_key:"Greenlight Device Key",breez_greenlight_device_cert:"Greenlight Device Cert",breez_greenlight_invite_code:"Greenlight Invite Code"}],["StrikeWallet","Strike (alpha)",{strike_api_endpoint:"API Endpoint",strike_api_key:"API Key"}],["BreezLiquidSdkWallet","Breez Liquid SDK",{breez_liquid_api_key:"Breez API Key (can be empty)",breez_liquid_seed:"Liquid seed phrase",breez_liquid_fee_offset_sat:"Offset amount in sats to increase fee limit"}]]})}),window.app.component("lnbits-admin-fiat-providers",{props:["form-data"],template:"#lnbits-admin-fiat-providers",mixins:[window.windowMixin],data:()=>({formAddStripeUser:"",hideInputToggle:!0}),methods:{addStripeAllowedUser(){const e=this.formAddStripeUser||"";e.length&&!this.formData.stripe_limits.allowed_users.includes(e)&&(this.formData.stripe_limits.allowed_users=[...this.formData.stripe_limits.allowed_users,e],this.formAddStripeUser="")},removeStripeAllowedUser(e){this.formData.stripe_limits.allowed_users=this.formData.stripe_limits.allowed_users.filter((t=>t!==e))},checkFiatProvider(e){LNbits.api.request("PUT",`/api/v1/fiat/check/${e}`).then((e=>{const t=e.data;Quasar.Notify.create({type:t.success?"positive":"warning",message:t.message,icon:null})})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("lnbits-admin-exchange-providers",{props:["form-data"],template:"#lnbits-admin-exchange-providers",mixins:[window.windowMixin],data:()=>({exchangeData:{selectedProvider:null,showTickerConversion:!1,convertFromTicker:null,convertToTicker:null},exchangesTable:{columns:[{name:"name",align:"left",label:"Exchange Name",field:"name",sortable:!0},{name:"api_url",align:"left",label:"URL",field:"api_url",sortable:!1},{name:"path",align:"left",label:"JSON Path",field:"path",sortable:!1},{name:"exclude_to",align:"left",label:"Exclude Currencies",field:"exclude_to",sortable:!1},{name:"ticker_conversion",align:"left",label:"Ticker Conversion",field:"ticker_conversion",sortable:!1}],pagination:{sortBy:"name",rowsPerPage:100,page:1,rowsNumber:100},search:null,hideEmpty:!0}}),mounted(){this.getExchangeRateHistory()},created(){const e=window.location.hash.replace("#","");"exchange_providers"===e&&this.showExchangeProvidersTab(e)},methods:{getExchangeRateHistory(){LNbits.api.request("GET","/api/v1/rate/history",this.g.user.wallets[0].inkey).then((e=>{this.initExchangeChart(e.data)})).catch((function(e){LNbits.utils.notifyApiError(e)}))},showExchangeProvidersTab(e){"exchange_providers"===e&&this.getExchangeRateHistory()},addExchangeProvider(){this.formData.lnbits_exchange_rate_providers=[{name:"",api_url:"",path:"",exclude_to:[]},...this.formData.lnbits_exchange_rate_providers]},removeExchangeProvider(e){this.formData.lnbits_exchange_rate_providers=this.formData.lnbits_exchange_rate_providers.filter((t=>t!==e))},removeExchangeTickerConversion(e,t){e.ticker_conversion=e.ticker_conversion.filter((e=>e!==t)),this.formData.touch=null},addExchangeTickerConversion(){this.exchangeData.selectedProvider&&(this.exchangeData.selectedProvider.ticker_conversion.push(`${this.exchangeData.convertFromTicker}:${this.exchangeData.convertToTicker}`),this.formData.touch=null,this.exchangeData.showTickerConversion=!1)},showTickerConversionDialog(e){this.exchangeData.convertFromTicker=null,this.exchangeData.convertToTicker=null,this.exchangeData.selectedProvider=e,this.exchangeData.showTickerConversion=!0},initExchangeChart(e){const t=e.map((e=>Quasar.date.formatDate(new Date(1e3*e.timestamp),"HH:mm"))),a=[...this.formData.lnbits_exchange_rate_providers,{name:"LNbits"}].map((t=>({label:t.name,data:e.map((e=>e.rates[t.name])),pointStyle:!0,borderWidth:"LNbits"===t.name?4:1,tension:.4})));this.exchangeRatesChart=new Chart(this.$refs.exchangeRatesChart.getContext("2d"),{type:"line",options:{plugins:{legend:{display:!1}}},data:{labels:t,datasets:a}})}}}),window.app.component("lnbits-admin-security",{props:["form-data"],template:"#lnbits-admin-security",mixins:[window.windowMixin],data:()=>({logs:[],formBlockedIPs:"",serverlogEnabled:!1,nostrAcceptedUrl:"",formAllowedIPs:"",formCallbackUrlRule:""}),created(){},methods:{addAllowedIPs(){const e=this.formAllowedIPs.trim(),t=this.formData.lnbits_allowed_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_ips=[...t,e],this.formAllowedIPs="")},removeAllowedIPs(e){const t=this.formData.lnbits_allowed_ips;this.formData.lnbits_allowed_ips=t.filter((t=>t!==e))},addBlockedIPs(){const e=this.formBlockedIPs.trim(),t=this.formData.lnbits_blocked_ips;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_blocked_ips=[...t,e],this.formBlockedIPs="")},removeBlockedIPs(e){const t=this.formData.lnbits_blocked_ips;this.formData.lnbits_blocked_ips=t.filter((t=>t!==e))},addCallbackUrlRule(){const e=this.formCallbackUrlRule.trim(),t=this.formData.lnbits_callback_url_rules;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_callback_url_rules=[...t,e],this.formCallbackUrlRule="")},removeCallbackUrlRule(e){const t=this.formData.lnbits_callback_url_rules;this.formData.lnbits_callback_url_rules=t.filter((t=>t!==e))},addNostrUrl(){const e=this.nostrAcceptedUrl.trim();this.removeNostrUrl(e),this.formData.nostr_absolute_request_urls.push(e),this.nostrAcceptedUrl=""},removeNostrUrl(e){this.formData.nostr_absolute_request_urls=this.formData.nostr_absolute_request_urls.filter((t=>t!==e))},async toggleServerLog(){if(this.serverlogEnabled=!this.serverlogEnabled,this.serverlogEnabled){const e="http:"!==location.protocol?"wss://":"ws://",t=await LNbits.utils.digestMessage(this.g.user.id),a=e+document.domain+":"+location.port+"/api/v1/ws/"+t;this.ws=new WebSocket(a),this.ws.addEventListener("message",(async({data:e})=>{this.logs.push(e.toString());const t=this.$refs.logScroll;if(t){const e=t.getScrollTarget(),a=0;t.setScrollPosition(e.scrollHeight,a)}}))}else this.ws.close()}}}),window.app.component("lnbits-admin-users",{props:["form-data"],template:"#lnbits-admin-users",mixins:[window.windowMixin],data:()=>({formAddUser:"",formAddAdmin:""}),methods:{addAllowedUser(){let e=this.formAddUser,t=this.formData.lnbits_allowed_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_allowed_users=[...t,e],this.formAddUser="")},removeAllowedUser(e){let t=this.formData.lnbits_allowed_users;this.formData.lnbits_allowed_users=t.filter((t=>t!==e))},addAdminUser(){let e=this.formAddAdmin,t=this.formData.lnbits_admin_users;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_admin_users=[...t,e],this.formAddAdmin="")},removeAdminUser(e){let t=this.formData.lnbits_admin_users;this.formData.lnbits_admin_users=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-server",{props:["form-data"],template:"#lnbits-admin-server",mixins:[window.windowMixin],data:()=>({currencies:[]}),async created(){this.currencies=await LNbits.api.getCurrencies()}}),window.app.component("lnbits-admin-extensions",{props:["form-data"],template:"#lnbits-admin-extensions",mixins:[window.windowMixin],data:()=>({formAddExtensionsManifest:""}),methods:{addExtensionsManifest(){const e=this.formAddExtensionsManifest.trim(),t=this.formData.lnbits_extensions_manifests;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_extensions_manifests=[...t,e],this.formAddExtensionsManifest="")},removeExtensionsManifest(e){const t=this.formData.lnbits_extensions_manifests;this.formData.lnbits_extensions_manifests=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-notifications",{props:["form-data"],template:"#lnbits-admin-notifications",mixins:[window.windowMixin],data:()=>({nostrNotificationIdentifier:"",emailNotificationAddress:""}),methods:{sendTestEmail(){LNbits.api.request("GET","/admin/api/v1/testemail",this.g.user.wallets[0].adminkey).then((e=>{if("error"===e.data.status)throw new Error(e.data.message);this.$q.notify({message:"Test email sent!",color:"positive"})})).catch((e=>{this.$q.notify({message:e.message,color:"negative"})}))},addNostrNotificationIdentifier(){const e=this.nostrNotificationIdentifier.trim(),t=this.formData.lnbits_nostr_notifications_identifiers;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_nostr_notifications_identifiers=[...t,e],this.nostrNotificationIdentifier="")},removeNostrNotificationIdentifier(e){const t=this.formData.lnbits_nostr_notifications_identifiers;this.formData.lnbits_nostr_notifications_identifiers=t.filter((t=>t!==e))},addEmailNotificationAddress(){const e=this.emailNotificationAddress.trim(),t=this.formData.lnbits_email_notifications_to_emails;e&&e.length&&!t.includes(e)&&(this.formData.lnbits_email_notifications_to_emails=[...t,e],this.emailNotificationAddress="")},removeEmailNotificationAddress(e){const t=this.formData.lnbits_email_notifications_to_emails;this.formData.lnbits_email_notifications_to_emails=t.filter((t=>t!==e))}}}),window.app.component("lnbits-admin-site-customisation",{props:["form-data"],template:"#lnbits-admin-site-customisation",mixins:[window.windowMixin],data:()=>({lnbits_theme_options:["classic","bitcoin","flamingo","cyber","freedom","mint","autumn","monochrome","salvador"],colors:["primary","secondary","accent","positive","negative","info","warning","red","yellow","orange"],reactionOptions:["none","confettiBothSides","confettiFireworks","confettiStars","confettiTop"],globalBorderOptions:["retro-border","hard-border","neon-border","no-border"]}),methods:{}}),window.app.component("lnbits-admin-assets-config",{props:["form-data"],template:"#lnbits-admin-assets-config",mixins:[window.windowMixin],data:()=>({newAllowedAssetMimeType:"",newNoLimitUser:""}),async created(){},methods:{addAllowedAssetMimeType(){this.newAllowedAssetMimeType&&(this.removeAllowedAssetMimeType(this.newAllowedAssetMimeType),this.formData.lnbits_assets_allowed_mime_types.push(this.newAllowedAssetMimeType),this.newAllowedAssetMimeType="")},removeAllowedAssetMimeType(e){const t=this.formData.lnbits_assets_allowed_mime_types.indexOf(e);-1!==t&&this.formData.lnbits_assets_allowed_mime_types.splice(t,1)},addNewNoLimitUser(){this.newNoLimitUser&&(this.removeNoLimitUser(this.newNoLimitUser),this.formData.lnbits_assets_no_limit_users.push(this.newNoLimitUser),this.newNoLimitUser="")},removeNoLimitUser(e){e&&(this.formData.lnbits_assets_no_limit_users=this.formData.lnbits_assets_no_limit_users.filter((t=>t!==e)))}}}),window.app.component("lnbits-admin-audit",{props:["form-data"],template:"#lnbits-admin-audit",mixins:[window.windowMixin],data:()=>({formAddIncludePath:"",formAddExcludePath:"",formAddIncludeResponseCode:""}),methods:{addIncludePath(){if(""===this.formAddIncludePath)return;const e=this.formData.lnbits_audit_include_paths;e.includes(this.formAddIncludePath)||(this.formData.lnbits_audit_include_paths=[...e,this.formAddIncludePath]),this.formAddIncludePath=""},removeIncludePath(e){this.formData.lnbits_audit_include_paths=this.formData.lnbits_audit_include_paths.filter((t=>t!==e))},addExcludePath(){if(""===this.formAddExcludePath)return;const e=this.formData.lnbits_audit_exclude_paths;e.includes(this.formAddExcludePath)||(this.formData.lnbits_audit_exclude_paths=[...e,this.formAddExcludePath]),this.formAddExcludePath=""},removeExcludePath(e){this.formData.lnbits_audit_exclude_paths=this.formData.lnbits_audit_exclude_paths.filter((t=>t!==e))},addIncludeResponseCode(){if(""===this.formAddIncludeResponseCode)return;const e=this.formData.lnbits_audit_http_response_codes;e.includes(this.formAddIncludeResponseCode)||(this.formData.lnbits_audit_http_response_codes=[...e,this.formAddIncludeResponseCode]),this.formAddIncludeResponseCode=""},removeIncludeResponseCode(e){this.formData.lnbits_audit_http_response_codes=this.formData.lnbits_audit_http_response_codes.filter((t=>t!==e))}}}),window.app.component("lnbits-wallet-list",{template:"#lnbits-wallet-list",mixins:[window.windowMixin],props:["balance"],data:()=>({activeWallet:null,balance:0,walletName:"",LNBITS_DENOMINATION:LNBITS_DENOMINATION}),methods:{createWallet(){this.$emit("wallet-action",{action:"create-wallet"})}},created(){document.addEventListener("updateWalletBalance",this.updateWalletBalance)}}),window.app.component("lnbits-wallet-api-docs",{template:"#lnbits-wallet-api-docs",mixins:[window.windowMixin],methods:{resetKeys(){LNbits.utils.confirmDialog("Are you sure you want to reset your API keys?").onOk((()=>{LNbits.api.resetWalletKeys(this.g.wallet).then((e=>{const{id:t,adminkey:a,inkey:s}=e;this.g.wallet={...this.g.wallet,inkey:s,adminkey:a};const i=this.g.user.wallets.findIndex((e=>e.id===t));-1!==i&&(this.g.user.wallets[i]={...this.g.user.wallets[i],inkey:s,adminkey:a}),Quasar.Notify.create({timeout:3500,type:"positive",message:"API keys reset!"})})).catch((e=>{LNbits.utils.notifyApiError(e)}))}))}},data:()=>({inkeyHidden:!0,adminkeyHidden:!0,walletIdHidden:!0})}),window.app.component("lnbits-home-logos",{template:"#lnbits-home-logos",mixins:[window.windowMixin],data:()=>({logos:[{href:"https://github.com/ElementsProject/lightning",lightSrc:"/static/images/clnl.png",darkSrc:"/static/images/cln.png"},{href:"https://github.com/lightningnetwork/lnd",lightSrc:"/static/images/lnd.png",darkSrc:"/static/images/lnd.png"},{href:"https://opennode.com",lightSrc:"/static/images/opennodel.png",darkSrc:"/static/images/opennode.png"},{href:"https://lnpay.co/",lightSrc:"/static/images/lnpayl.png",darkSrc:"/static/images/lnpay.png"},{href:"https://github.com/rootzoll/raspiblitz",lightSrc:"/static/images/blitzl.png",darkSrc:"/static/images/blitz.png"},{href:"https://start9.com/",lightSrc:"/static/images/start9l.png",darkSrc:"/static/images/start9.png"},{href:"https://getumbrel.com/",lightSrc:"/static/images/umbrell.png",darkSrc:"/static/images/umbrel.png"},{href:"https://mynodebtc.com",lightSrc:"/static/images/mynodel.png",darkSrc:"/static/images/mynode.png"},{href:"https://github.com/shesek/spark-wallet",lightSrc:"/static/images/sparkl.png",darkSrc:"/static/images/spark.png"},{href:"https://voltage.cloud",lightSrc:"/static/images/voltagel.png",darkSrc:"/static/images/voltage.png"},{href:"https://breez.technology/sdk/",lightSrc:"/static/images/breezl.png",darkSrc:"/static/images/breez.png"},{href:"https://blockstream.com/lightning/greenlight/",lightSrc:"/static/images/greenlightl.png",darkSrc:"/static/images/greenlight.png"},{href:"https://getalby.com",lightSrc:"/static/images/albyl.png",darkSrc:"/static/images/alby.png"},{href:"https://zbd.gg",lightSrc:"/static/images/zbdl.png",darkSrc:"/static/images/zbd.png"},{href:"https://phoenix.acinq.co/server",lightSrc:"/static/images/phoenixdl.png",darkSrc:"/static/images/phoenixd.png"},{href:"https://boltz.exchange/",lightSrc:"/static/images/boltzl.svg",darkSrc:"/static/images/boltz.svg"},{href:"https://www.blink.sv/",lightSrc:"/static/images/blink_logol.png",darkSrc:"/static/images/blink_logo.png"}]}),computed:{showLogos(){return"sats"==this.LNBITS_DENOMINATION&&"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}}}),window.app.component("lnbits-new-user-wallet",{props:["form-data"],template:"#lnbits-new-user-wallet",mixins:[window.windowMixin],data:()=>({walletTypes:[{label:"Lightning Wallet",value:"lightning"}],newWallet:{walletType:"lightning",name:"",sharedWalletId:""}}),methods:{async submitRejectWalletInvitation(){try{const e=this.g.user.extra.wallet_invite_requests||[],t=e.find((e=>e.to_wallet_id===this.newWallet.sharedWalletId));if(!t)return void Quasar.Notify.create({message:"Cannot find invitation for the selected wallet.",type:"warning"});await LNbits.api.request("DELETE",`/api/v1/wallet/share/invite/${t.request_id}`,this.g.wallet.adminkey),Quasar.Notify.create({message:"Invitation rejected.",type:"positive"}),this.g.user.extra.wallet_invite_requests=e.filter((e=>e.request_id!==t.request_id))}catch(e){LNbits.utils.notifyApiError(e)}},async submitAddWallet(){console.log("### submitAddWallet",this.newWallet);const e=this.newWallet;if("lightning"!==e.walletType||e.name)if("lightning-shared"!==e.walletType||e.sharedWalletId)try{await LNbits.api.createWallet(this.g.user.wallets[0],e.name,e.walletType,{shared_wallet_id:e.sharedWalletId})}catch(e){console.warn(e),LNbits.utils.notifyApiError(e)}else this.$q.notify({message:"Missing a shared wallet ID",color:"warning"});else this.$q.notify({message:"Please enter a name for the wallet",color:"warning"})}},created(){this.g.user?.extra?.wallet_invite_requests?.length&&this.walletTypes.push({label:`Lightning Wallet (Share Invite: ${this.g.user.extra.wallet_invite_requests.length})`,value:"lightning-shared"})}}),window.app.component("lnbits-qrcode",{mixins:[window.windowMixin],template:"#lnbits-qrcode",components:{QrcodeVue:QrcodeVue},props:{value:{type:String,required:!0},nfc:{type:Boolean,default:!1},showButtons:{type:Boolean,default:!0},href:{type:String,default:""},margin:{type:Number,default:3},maxWidth:{type:Number,default:450},logo:{type:String,default:LNBITS_QR_LOGO}},data:()=>({nfcTagWriting:!1,nfcSupported:"undefined"!=typeof NDEFReader}),methods:{clickQrCode(e){if(""===this.href)return this.copyText(this.value),e.preventDefault(),e.stopPropagation(),!1},async writeNfcTag(){try{if(!this.nfcSupported)throw{toString:function(){return"NFC not supported on this device or browser."}};const e=new NDEFReader;this.nfcTagWriting=!0,this.$q.notify({message:"Tap your NFC tag to write the LNURL-withdraw link to it."}),await e.write({records:[{recordType:"url",data:this.value,lang:"en"}]}),this.nfcTagWriting=!1,this.$q.notify({type:"positive",message:"NFC tag written successfully."})}catch(e){this.nfcTagWriting=!1,this.$q.notify({type:"negative",message:e?e.toString():"An unexpected error has occurred."})}},downloadSVG(){const e=this.$refs.qrCode.$el;if(!e)return void console.error("SVG element not found");let t=(new XMLSerializer).serializeToString(e);t.match(/^]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/)||(t=t.replace(/^({tab:"bech32",lnurl:""}),methods:{setLnurl(){if("bech32"==this.tab){const e=(new TextEncoder).encode(this.url),t=NostrTools.nip19.encodeBytes("lnurl",e);this.lnurl=`lightning:${t.toUpperCase()}`}else"lud17"==this.tab&&(this.url.startsWith("http://")?this.lnurl=this.url.replace("http://",this.prefix+"://"):this.lnurl=this.url.replace("https://",this.prefix+"://"));this.$emit("update:lnurl",this.lnurl)}},watch:{url(){this.setLnurl()},tab(){this.setLnurl()}},created(){this.setLnurl()}}),window.app.component("lnbits-footer",{template:"#lnbits-footer",mixins:[window.windowMixin],computed:{version(){return this.LNBITS_VERSION||"unknown version"},title(){return`${this.SITE_TITLE}, ${this.SITE_TAGLINE}`},showFooter(){return"LNbits"==this.SITE_TITLE&&1==this.LNBITS_SHOW_HOME_PAGE_ELEMENTS}}}),window.app.component("lnbits-header",{template:"#lnbits-header",mixins:[window.windowMixin],computed:{denomination(){return this.LNBITS_DENOMINATION||"sat"},hasServiceFeeMax(){return this.g.user&&this.LNBITS_SERVICE_FEE_MAX&&this.LNBITS_SERVICE_FEE_MAX>0},serviceFeeMax(){return this.LNBITS_SERVICE_FEE_MAX||0},hasServiceFee(){return this.g.user&&this.LNBITS_SERVICE_FEE&&this.LNBITS_SERVICE_FEE>0},serviceFee(){return this.LNBITS_SERVICE_FEE||0},hasCustomBadge(){return this.LNBITS_CUSTOM_BADGE&&""!=this.LNBITS_CUSTOM_BADGE},customBadge(){return this.LNBITS_CUSTOM_BADGE||""},customBadgeColor(){return this.LNBITS_CUSTOM_BADGE_COLOR||""},title(){return this.SITE_TITLE},titleIsLnbits(){return"LNbits"==this.SITE_TITLE},customLogoUrl(){return this.USE_CUSTOM_LOGO||null},userPictureUrl(){return this.g.user.config.picture},hasUserPicture(){return this.g.user&&this.g.user.config&&this.g.user.config.picture},showAdmin(){return this.g.user&&(this.g.user.super_user||this.g.user.admin)},showVoidwallet(){return this.g.user&&1==this.VOIDWALLET}}}),window.app.component("lnbits-header-wallets",{template:"#lnbits-header-wallets",mixins:[window.windowMixin]}),window.app.component("lnbits-drawer",{template:"#lnbits-drawer",mixins:[window.windowMixin]}),window.app.component("lnbits-theme",{mixins:[window.windowMixin],watch:{"g.reactionChoice"(e){this.$q.localStorage.set("lnbits.reactions",e)},"g.themeChoice"(e){document.body.setAttribute("data-theme",e),this.$q.localStorage.set("lnbits.theme",e)},"g.darkChoice"(e){this.$q.dark.set(e),this.$q.localStorage.set("lnbits.darkMode",e)},"g.borderChoice"(e){document.body.classList.forEach((e=>{e.endsWith("-border")&&document.body.classList.remove(e)})),this.$q.localStorage.setItem("lnbits.border",e),document.body.classList.add(e)},"g.gradientChoice"(e){this.$q.localStorage.set("lnbits.gradientBg",e),!0===e?document.body.classList.add("gradient-bg"):document.body.classList.remove("gradient-bg")},"g.mobileSimple"(e){this.$q.localStorage.set("lnbits.mobileSimple",e),!0===e?document.body.classList.add("mobile-simple"):document.body.classList.remove("mobile-simple")},"g.bgimageChoice"(e){this.$q.localStorage.set("lnbits.backgroundImage",e),""===e?document.body.classList.remove("bg-image"):(document.body.classList.add("bg-image"),document.body.style.setProperty("--background",`url(${e})`))}},methods:{async checkUrlParams(){const e=new URLSearchParams(window.location.search);if(0===e.length)return;if(e.has("theme")){const t=e.get("theme").trim().toLowerCase();this.g.themeChoice=t,e.delete("theme")}if(e.has("border")){const t=e.get("border").trim().toLowerCase();this.g.borderChoice=t,e.delete("border")}if(e.has("gradient")){const t=e.get("gradient").toLowerCase();this.g.gradientChoice="1"===t||"true"===t,e.delete("gradient")}if(e.has("dark")){const t=e.get("dark").trim().toLowerCase();this.g.darkChoice="1"===t||"true"===t,e.delete("dark")}if(e.has("usr")){try{await LNbits.api.loginUsr(e.get("usr")),window.location.href="/wallet"}catch(e){LNbits.utils.notifyApiError(e)}e.delete("usr")}const t=e.size?`?${e.toString()}`:"",a=window.location.pathname+t;window.history.replaceState(null,null,a)}},created(){Chart.defaults.color=this.$q.dark.isActive?"#fff":"#000",this.$q.dark.set(this.g.darkChoice),document.body.setAttribute("data-theme",this.g.themeChoice),document.body.classList.add(this.g.borderChoice),!0===this.g.gradientChoice&&document.body.classList.add("gradient-bg"),""!==this.g.bgimageChoice&&(document.body.classList.add("bg-image"),document.body.style.setProperty("--background",`url(${this.g.bgimageChoice})`)),!0===this.g.mobileSimple&&document.body.classList.add("mobile-simple"),this.checkUrlParams()}}),window.app.component("lnbits-manage-extension-list",{mixins:[window.windowMixin],template:"#lnbits-manage-extension-list",data:()=>({extensions:[],userExtensions:[],searchTerm:""}),watch:{"g.user.extensions":{async handler(){await this.loadExtensions()}},searchTerm(){this.filterUserExtensionsByTerm()}},methods:{map(e){const t={...e};return t.url=["/",t.code,"/"].join(""),t},async loadExtensions(){try{const{data:e}=await LNbits.api.request("GET","/api/v1/extension");this.extensions=e.map((e=>this.map(e))).sort(((e,t)=>e.name.localeCompare(t.name))),this.filterUserExtensionsByTerm()}catch(e){LNbits.utils.notifyApiError(e)}},filterUserExtensionsByTerm(){const e=this.g.user.extensions;this.userExtensions=this.extensions.filter((t=>e.includes(t.code))).filter((e=>""===this.searchTerm||`${e.code} ${e.name} ${e.short_description} ${e.url}`.toLocaleLowerCase().includes(this.searchTerm.toLocaleLowerCase()))).map((e=>(e.isActive=window.location.pathname.startsWith(e.url),e)))}},async created(){await this.loadExtensions()}}),window.app.component("lnbits-language-dropdown",{template:"#lnbits-language-dropdown",mixins:[window.windowMixin],methods:{activeLanguage:e=>window.i18n.global.locale===e,changeLanguage(e){this.g.locale=e,window.i18n.global.locale=e,this.$q.localStorage.set("lnbits.lang",e)}},data:()=>({langs:[{value:"en",label:"English",display:"🇬🇧 EN"},{value:"de",label:"Deutsch",display:"🇩🇪 DE"},{value:"es",label:"Español",display:"🇪🇸 ES"},{value:"jp",label:"日本語",display:"🇯🇵 JP"},{value:"cn",label:"中文",display:"🇨🇳 CN"},{value:"fr",label:"Français",display:"🇫🇷 FR"},{value:"it",label:"Italiano",display:"🇮🇹 IT"},{value:"pi",label:"Pirate",display:"🏴‍☠️ PI"},{value:"nl",label:"Nederlands",display:"🇳🇱 NL"},{value:"we",label:"Cymraeg",display:"🏴󠁧󠁢󠁷󠁬󠁳󠁿 CY"},{value:"pl",label:"Polski",display:"🇵🇱 PL"},{value:"pt",label:"Português",display:"🇵🇹 PT"},{value:"br",label:"Português do Brasil",display:"🇧🇷 BR"},{value:"cs",label:"Česky",display:"🇨🇿 CS"},{value:"sk",label:"Slovensky",display:"🇸🇰 SK"},{value:"kr",label:"한국어",display:"🇰🇷 KR"},{value:"fi",label:"Suomi",display:"🇫🇮 FI"}]})}),window.app.component("lnbits-payment-list",{template:"#lnbits-payment-list",props:["update","lazy","wallet"],mixins:[window.windowMixin],data(){return{denomination:LNBITS_DENOMINATION,payments:[],paymentsTable:{columns:[{name:"time",align:"left",label:this.$t("memo")+"/"+this.$t("date"),field:"date",sortable:!0},{name:"amount",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:"sat",sortable:!0}],pagination:{rowsPerPage:10,page:1,sortBy:"time",descending:!0,rowsNumber:10},search:"",filter:{"status[ne]":"failed"},loading:!1},searchDate:{from:null,to:null},searchStatus:{success:!0,pending:!0,failed:!1,incoming:!0,outgoing:!0},exportTagName:"",exportPaymentTagList:[],paymentsCSV:{columns:[{name:"pending",align:"left",label:"Pending",field:"pending"},{name:"memo",align:"left",label:this.$t("memo"),field:"memo"},{name:"time",align:"left",label:this.$t("date"),field:"date",sortable:!0},{name:"amount",align:"right",label:this.$t("amount")+" ("+LNBITS_DENOMINATION+")",field:"sat",sortable:!0},{name:"fee",align:"right",label:this.$t("fee")+" (m"+LNBITS_DENOMINATION+")",field:"fee"},{name:"tag",align:"right",label:this.$t("tag"),field:"tag"},{name:"payment_hash",align:"right",label:this.$t("payment_hash"),field:"payment_hash"},{name:"payment_proof",align:"right",label:this.$t("payment_proof"),field:"payment_proof"},{name:"webhook",align:"right",label:this.$t("webhook"),field:"webhook"},{name:"fiat_currency",align:"right",label:"Fiat Currency",field:e=>e.extra.wallet_fiat_currency},{name:"fiat_amount",align:"right",label:"Fiat Amount",field:e=>e.extra.wallet_fiat_amount}],preimage:null,loading:!1},hodlInvoice:{show:!1,payment:null,preimage:null}}},computed:{currentWallet(){return this.wallet||this.g.wallet},filteredPayments(){const e=this.paymentsTable.search;return e&&""!==e?LNbits.utils.search(this.payments,e):this.payments},paymentsOmitter(){return this.$q.screen.lt.md&&this.g.mobileSimple?this.payments.length>0?[this.payments[0]]:[]:this.payments},pendingPaymentsExist(){return-1!==this.payments.findIndex((e=>e.pending))}},methods:{searchByDate(){"string"==typeof this.searchDate&&(this.searchDate={from:this.searchDate,to:this.searchDate}),this.searchDate.from&&(this.paymentsTable.filter["time[ge]"]=this.searchDate.from+"T00:00:00"),this.searchDate.to&&(this.paymentsTable.filter["time[le]"]=this.searchDate.to+"T23:59:59"),this.fetchPayments()},clearDateSeach(){this.searchDate={from:null,to:null},delete this.paymentsTable.filter["time[ge]"],delete this.paymentsTable.filter["time[le]"],this.fetchPayments()},fetchPayments(e){this.$emit("filter-changed",{...this.paymentsTable.filter});const t=LNbits.utils.prepareFilterQuery(this.paymentsTable,e);return LNbits.api.getPayments(this.currentWallet,t).then((e=>{this.paymentsTable.loading=!1,this.paymentsTable.pagination.rowsNumber=e.data.total,this.payments=e.data.data.map((e=>LNbits.map.payment(e)))})).catch((e=>{this.paymentsTable.loading=!1,g.user.admin?this.fetchPaymentsAsAdmin(this.currentWallet.id,t):LNbits.utils.notifyApiError(e)}))},fetchPaymentsAsAdmin(e,t){return t=(t||"")+"&wallet_id="+e,LNbits.api.request("GET","/api/v1/payments/all/paginated?"+t).then((e=>{this.paymentsTable.loading=!1,this.paymentsTable.pagination.rowsNumber=e.data.total,this.payments=e.data.data.map((e=>LNbits.map.payment(e)))})).catch((e=>{this.paymentsTable.loading=!1,LNbits.utils.notifyApiError(e)}))},checkPayment(e){LNbits.api.getPayment(this.g.wallet,e).then((e=>{this.update=!this.update,"success"==e.data.status&&Quasar.Notify.create({type:"positive",message:this.$t("payment_successful")}),"pending"==e.data.status&&Quasar.Notify.create({type:"info",message:this.$t("payment_pending")})})).catch(LNbits.utils.notifyApiError)},showHoldInvoiceDialog(e){this.hodlInvoice.show=!0,this.hodlInvoice.preimage="",this.hodlInvoice.payment=e},cancelHoldInvoice(e){LNbits.api.cancelInvoice(this.g.wallet,e).then((()=>{this.update=!this.update,Quasar.Notify.create({type:"positive",message:this.$t("invoice_cancelled")})})).catch(LNbits.utils.notifyApiError)},settleHoldInvoice(e){LNbits.api.settleInvoice(this.g.wallet,e).then((()=>{this.update=!this.update,Quasar.Notify.create({type:"positive",message:this.$t("invoice_settled")})})).catch(LNbits.utils.notifyApiError)},paymentTableRowKey:e=>e.payment_hash+e.amount,exportCSV(e=!1){const t=this.paymentsTable.pagination,a={sortby:t.sortBy??"time",direction:t.descending?"desc":"asc"},s=new URLSearchParams(a);LNbits.api.getPayments(this.g.wallet,s).then((t=>{let a=t.data.data.map(LNbits.map.payment),s=this.paymentsCSV.columns;if(e){this.exportPaymentTagList.length&&(a=a.filter((e=>this.exportPaymentTagList.includes(e.tag))));const e=Object.keys(a.reduce(((e,t)=>({...e,...t.details})),{})).map((e=>({name:e,align:"right",label:e.charAt(0).toUpperCase()+e.slice(1).replace(/([A-Z])/g," $1"),field:t=>t.details[e],format:e=>"object"==typeof e?JSON.stringify(e):e})));s=this.paymentsCSV.columns.concat(e)}LNbits.utils.exportCSV(s,a,this.g.wallet.name+"-payments")}))},addFilterTag(){if(!this.exportTagName)return;const e=this.exportTagName.trim();this.exportPaymentTagList=this.exportPaymentTagList.filter((t=>t!==e)),this.exportPaymentTagList.push(e),this.exportTagName=""},removeExportTag(e){this.exportPaymentTagList=this.exportPaymentTagList.filter((t=>t!==e))},formatCurrency(e,t){try{return LNbits.utils.formatCurrency(e,t)}catch(t){return console.error(t),`${e} ???`}},handleFilterChanged(){const{success:e,pending:t,failed:a,incoming:s,outgoing:i}=this.searchStatus;delete this.paymentsTable.filter["status[ne]"],delete this.paymentsTable.filter["status[eq]"],e&&t&&a||(e&&t?this.paymentsTable.filter["status[ne]"]="failed":e&&a?this.paymentsTable.filter["status[ne]"]="pending":a&&t?this.paymentsTable.filter["status[ne]"]="success":e?this.paymentsTable.filter["status[eq]"]="success":t?this.paymentsTable.filter["status[eq]"]="pending":a&&(this.paymentsTable.filter["status[eq]"]="failed")),delete this.paymentsTable.filter["amount[ge]"],delete this.paymentsTable.filter["amount[le]"],s&&i||(s?this.paymentsTable.filter["amount[ge]"]=0:i&&(this.paymentsTable.filter["amount[le]"]=0))}},watch:{"paymentsTable.search":{handler(){const e={};this.paymentsTable.search&&(e.search=this.paymentsTable.search),this.fetchPayments()}},lazy(e){!0===e&&this.fetchPayments()},update(){this.fetchPayments()},"g.updatePayments"(){this.fetchPayments()},"g.wallet":{handler(e){this.fetchPayments()},deep:!0}},created(){void 0===this.lazy&&this.fetchPayments()}}),window.app.component("lnbits-extension-settings-form",{name:"lnbits-extension-settings-form",template:"#lnbits-extension-settings-form",props:["options","adminkey","endpoint"],methods:{async updateSettings(){if(!this.settings)return Quasar.Notify.create({message:"No settings to update",type:"negative"});try{const{data:e}=await LNbits.api.request("PUT",this.endpoint,this.adminkey,this.settings);this.settings=e}catch(e){LNbits.utils.notifyApiError(e)}},async getSettings(){try{const{data:e}=await LNbits.api.request("GET",this.endpoint,this.adminkey);this.settings=e}catch(e){LNbits.utils.notifyApiError(e)}},async resetSettings(){LNbits.utils.confirmDialog("Are you sure you want to reset the settings?").onOk((async()=>{try{await LNbits.api.request("DELETE",this.endpoint,this.adminkey),await this.getSettings()}catch(e){LNbits.utils.notifyApiError(e)}}))}},async created(){await this.getSettings()},data:()=>({settings:void 0})}),window.app.component("lnbits-extension-settings-btn-dialog",{template:"#lnbits-extension-settings-btn-dialog",name:"lnbits-extension-settings-btn-dialog",props:["options","adminkey","endpoint"],data:()=>({show:!1})}),window.app.component("lnbits-data-fields",{name:"lnbits-data-fields",template:"#lnbits-data-fields",props:["fields","hide-advanced"],data:()=>({fieldTypes:[{label:"Text",value:"str"},{label:"Integer",value:"int"},{label:"Float",value:"float"},{label:"Boolean",value:"bool"},{label:"Date Time",value:"datetime"},{label:"JSON",value:"json"},{label:"Wallet Select",value:"wallet"},{label:"Currency Select",value:"currency"}],fieldsTable:{columns:[{name:"name",align:"left",label:"Field Name",field:"name",sortable:!0},{name:"type",align:"left",label:"Type",field:"type",sortable:!1},{name:"label",align:"left",label:"UI Label",field:"label",sortable:!0},{name:"hint",align:"left",label:"UI Hint",field:"hint",sortable:!1},{name:"optional",align:"left",label:"Optional",field:"optional",sortable:!1}],pagination:{sortBy:"name",rowsPerPage:100,page:1,rowsNumber:100},search:null,hideEmpty:!0}}),methods:{addField:function(){this.fields.push({name:"field_name_"+(this.fields.length+1),type:"text",label:"",hint:"",optional:!0,sortable:!0,searchable:!0,editable:!0,fields:[]})},removeField:function(e){const t=this.fields.indexOf(e);t>-1&&this.fields.splice(t,1)}},async created(){this.hideAdvanced||this.fieldsTable.columns.push({name:"editable",align:"left",label:"UI Editable",field:"editable",sortable:!1},{name:"sortable",align:"left",label:"Sortable",field:"sortable",sortable:!1},{name:"searchable",align:"left",label:"Searchable",field:"searchable",sortable:!1})}}),window.app.component(QrcodeVue),window.app.component("lnbits-extension-rating",{template:"#lnbits-extension-rating",name:"lnbits-extension-rating",props:["rating"]}),window.app.component("lnbits-fsat",{template:"{{ fsat }}",props:{amount:{type:Number,default:0}},computed:{fsat(){return LNbits.utils.formatSat(this.amount)}}}),window.app.component("lnbits-manage",{mixins:[window.windowMixin],template:"#lnbits-manage",computed:{showAdmin(){return this.LNBITS_ADMIN_UI},showUsers(){return this.LNBITS_ADMIN_UI},showNode(){return this.LNBITS_NODE_UI},showAudit(){return this.LNBITS_AUDIT_ENABLED},showExtensions(){return!1===this.LNBITS_EXTENSIONS_DEACTIVATE_ALL}},methods:{isActive:e=>window.location.pathname===e},data:()=>({extensions:[]})}),window.app.component("lnbits-payment-details",{mixins:[window.windowMixin],template:"#lnbits-payment-details",props:["payment"],mixins:[window.windowMixin],data:()=>({LNBITS_DENOMINATION:LNBITS_DENOMINATION}),computed:{hasPreimage(){return this.payment.preimage&&"0000000000000000000000000000000000000000000000000000000000000000"!==this.payment.preimage},hasExpiry(){return!!this.payment.expiry},hasSuccessAction(){return this.hasPreimage&&this.payment.extra&&this.payment.extra.success_action},webhookStatusColor(){return this.payment.webhook_status>=300||this.payment.webhook_status<0?"red-10":this.payment.webhook_status?"green-10":"cyan-7"},webhookStatusText(){return this.payment.webhook_status?this.payment.webhook_status:"not sent yet"},hasTag(){return this.payment.extra&&!!this.payment.extra.tag},extras(){if(!this.payment.extra)return[];let e=_.omit(this.payment.extra,["tag","success_action"]);return Object.keys(e).map((t=>({key:t,value:e[t]})))}}}),window.app.component("lnbits-lnurlpay-success-action",{mixins:[window.windowMixin],template:"#lnbits-lnurlpay-success-action",props:["payment","success_action"],data(){return{decryptedValue:this.success_action.ciphertext}},mounted(){if("aes"!==this.success_action.tag)return null;decryptLnurlPayAES(this.success_action,this.payment.preimage).then((e=>{this.decryptedValue=e}))}}),window.app.component("lnbits-notifications-btn",{template:"#lnbits-notifications-btn",mixins:[window.windowMixin],props:["pubkey"],data:()=>({isSupported:!1,isSubscribed:!1,isPermissionGranted:!1,isPermissionDenied:!1}),methods:{urlB64ToUint8Array(e){const t=(e+"=".repeat((4-e.length%4)%4)).replace(/\-/g,"+").replace(/_/g,"/"),a=atob(t),s=new Uint8Array(a.length);for(let e=0;et!==e)),this.$q.localStorage.set("lnbits.webpush.subscribedUsers",JSON.stringify(t))},isUserSubscribed(e){return(JSON.parse(this.$q.localStorage.getItem("lnbits.webpush.subscribedUsers"))||[]).includes(e)},subscribe(){this.isSupported&&!this.isPermissionDenied&&(Notification.requestPermission().then((e=>{this.isPermissionGranted="granted"===e,this.isPermissionDenied="denied"===e})).catch(console.log),navigator.serviceWorker.ready.then((e=>{navigator.serviceWorker.getRegistration().then((e=>{e.pushManager.getSubscription().then((t=>{if(null===t||!this.isUserSubscribed(this.g.user.id)){const t={applicationServerKey:this.urlB64ToUint8Array(this.pubkey),userVisibleOnly:!0};e.pushManager.subscribe(t).then((e=>{LNbits.api.request("POST","/api/v1/webpush",null,{subscription:JSON.stringify(e)}).then((e=>{this.saveUserSubscribed(e.data.user),this.isSubscribed=!0})).catch(LNbits.utils.notifyApiError)}))}})).catch(console.log)}))})))},unsubscribe(){navigator.serviceWorker.ready.then((e=>{e.pushManager.getSubscription().then((e=>{e&&LNbits.api.request("DELETE","/api/v1/webpush?endpoint="+btoa(e.endpoint),null).then((()=>{this.removeUserSubscribed(this.g.user.id),this.isSubscribed=!1})).catch(LNbits.utils.notifyApiError)}))})).catch(console.log)},checkSupported(){let e="https:"===window.location.protocol,t="serviceWorker"in navigator,a="Notification"in window,s="PushManager"in window;return this.isSupported=e&&t&&a&&s,this.isSupported||console.log("Notifications disabled because requirements are not met:",{HTTPS:e,"Service Worker API":t,"Notification API":a,"Push API":s}),this.isSupported},async updateSubscriptionStatus(){await navigator.serviceWorker.ready.then((e=>{e.pushManager.getSubscription().then((e=>{this.isSubscribed=!!e&&this.isUserSubscribed(this.g.user.id)}))})).catch(console.log)}},created(){this.isPermissionDenied="denied"===Notification.permission,this.checkSupported()&&this.updateSubscriptionStatus()}}),window.app.component("lnbits-dynamic-fields",{template:"#lnbits-dynamic-fields",mixins:[window.windowMixin],props:["options","modelValue"],data:()=>({formData:null,rules:[e=>!!e||"Field is required"]}),methods:{applyRules(e){return e?this.rules:[]},buildData(e,t={}){return e.reduce(((e,a)=>(a.options?.length?e[a.name]=this.buildData(a.options,t[a.name]):e[a.name]=t[a.name]??a.default,e)),{})},handleValueChanged(){this.$emit("update:model-value",this.formData)}},created(){this.formData=this.buildData(this.options,this.modelValue)}}),window.app.component("lnbits-dynamic-chips",{template:"#lnbits-dynamic-chips",mixins:[window.windowMixin],props:["modelValue"],data:()=>({chip:"",chips:[]}),methods:{addChip(){this.chip&&(this.chips.push(this.chip),this.chip="",this.$emit("update:model-value",this.chips.join(",")))},removeChip(e){this.chips.splice(e,1),this.$emit("update:model-value",this.chips.join(","))}},created(){"string"==typeof this.modelValue?this.chips=this.modelValue.split(","):this.chips=[...this.modelValue]}}),window.app.component("lnbits-update-balance",{template:"#lnbits-update-balance",mixins:[window.windowMixin],props:["wallet_id","small_btn"],computed:{denomination:()=>LNBITS_DENOMINATION,admin:()=>user.super_user},data:()=>({credit:0}),methods:{updateBalance(e){LNbits.api.updateBalance(e.value,this.wallet_id).then((t=>{if(!0!==t.data.success)throw new Error(t.data);credit=parseInt(e.value),Quasar.Notify.create({type:"positive",message:this.$t("credit_ok",{amount:credit}),icon:null}),this.credit=0,e.value=0,e.set()})).catch(LNbits.utils.notifyApiError)}}}),window.app.component("user-id-only",{template:"#user-id-only",mixins:[window.windowMixin],props:{allowed_new_users:Boolean,authAction:String,authMethod:String,usr:String,wallet:String},data(){return{user:this.usr,walletName:this.wallet}},methods:{showLogin(e){this.$emit("show-login",e)},showRegister(e){this.$emit("show-register",e)},loginUsr(){this.$emit("update:usr",this.user),this.$emit("login-usr")},createWallet(){this.$emit("update:wallet",this.walletName),this.$emit("create-wallet")}},computed:{showInstantLogin(){return"username-password"!==this.authMethod||"register"!==this.authAction}},created(){}}),window.app.component("username-password",{template:"#username-password",mixins:[window.windowMixin],props:{allowed_new_users:Boolean,authMethods:Array,authAction:String,username:String,password_1:String,password_2:String,resetKey:String},data(){return{oauth:["nostr-auth-nip98","google-auth","github-auth","keycloak-auth"],username:this.userName,password:this.password_1,passwordRepeat:this.password_2,reset_key:this.resetKey,keycloakOrg:LNBITS_AUTH_KEYCLOAK_ORG||"Keycloak",keycloakIcon:LNBITS_AUTH_KEYCLOAK_ICON}},methods:{login(){this.$emit("update:userName",this.username),this.$emit("update:password_1",this.password),this.$emit("login")},register(){this.$emit("update:userName",this.username),this.$emit("update:password_1",this.password),this.$emit("update:password_2",this.passwordRepeat),this.$emit("register")},reset(){this.$emit("update:resetKey",this.reset_key),this.$emit("update:password_1",this.password),this.$emit("update:password_2",this.passwordRepeat),this.$emit("reset")},validateUsername:e=>new RegExp("^(?=[a-zA-Z0-9._]{2,20}$)(?!.*[_.]{2})[^_.].*[^_.]$").test(e),async signInWithNostr(){try{const e=await this.createNostrToken();if(!e)return;resp=await LNbits.api.loginByProvider("nostr",{Authorization:e},{}),window.location.href="/wallet"}catch(e){console.warn(e);const t=e?.response?.data?.detail||`${e}`;Quasar.Notify.create({type:"negative",message:"Failed to sign in with Nostr.",caption:t})}},async createNostrToken(){try{if(!window.nostr?.signEvent)return void Quasar.Notify.create({type:"negative",message:"No Nostr signing app detected.",caption:'Is "window.nostr" present?'});const e=`${window.location}nostr`,t="POST",a=await NostrTools.nip98.getToken(e,t,(e=>async function(e){try{const{data:t}=await LNbits.api.getServerHealth();return e.created_at=t.server_time,await window.nostr.signEvent(e)}catch(e){console.error(e),Quasar.Notify.create({type:"negative",message:"Failed to sign nostr event.",caption:`${e}`})}}(e)),!0);if(!await NostrTools.nip98.validateToken(a,e,t))throw new Error("Invalid signed token!");return a}catch(e){console.warn(e),Quasar.Notify.create({type:"negative",message:"Failed create Nostr event.",caption:`${e}`})}}},computed:{showOauth(){return this.oauth.some((e=>this.authMethods.includes(e)))}},created(){}}),window.app.component("separator-text",{template:"#separator-text",props:{text:String,uppercase:{type:Boolean,default:!1},color:{type:String,default:"grey"}}}),window.app.component("lnbits-node-ranks",{props:["ranks"],data:()=>({stats:[{label:"Capacity",key:"capacity"},{label:"Channels",key:"channelcount"},{label:"Age",key:"age"},{label:"Growth",key:"growth"},{label:"Availability",key:"availability"}]}),template:"\n \n
\n
1ml Node Rank
\n
\n
\n
{{ stat.label }}
\n
\n {{ (ranks && ranks[stat.key]) ?? '-' }}\n
\n
\n
\n
\n
\n "}),window.app.component("lnbits-channel-stats",{props:["stats"],data:()=>({states:[{label:"Active",value:"active",color:"green"},{label:"Pending",value:"pending",color:"orange"},{label:"Inactive",value:"inactive",color:"grey"},{label:"Closed",value:"closed",color:"red"}]}),template:"\n \n
\n
Channels
\n
\n
\n
\n {{ state.label }}\n
\n
\n {{ (stats?.counts && stats.counts[state.value]) ?? \"-\" }}\n
\n
\n
\n
\n
\n "}),window.app.component("lnbits-stat",{props:["title","amount","msat","btc"],computed:{value(){return this.amount??(this.btc?LNbits.utils.formatSat(this.btc):LNbits.utils.formatMsat(this.msat))}},template:"\n \n \n
\n {{ title }}\n
\n
\n {{ value }}\n sats\n BTC\n
\n
\n
\n "}),window.app.component("lnbits-node-qrcode",{props:["info"],mixins:[window.windowMixin],template:'\n \n \n
\n
\n \n
\n No addresses available\n
\n
\n
\n
\n \n Public Key Click to copy \n \n \n
\n '}),window.app.component("lnbits-channel-balance",{props:["balance","color"],methods:{formatMsat:e=>LNbits.utils.formatMsat(e)},template:'\n
\n
\n \n Local: {{ formatMsat(balance.local_msat) }}\n sats\n \n \n Remote: {{ formatMsat(balance.remote_msat) }}\n sats\n \n
\n\n \n
\n \n {{ balance.alias }}\n \n
\n \n
\n '}),window.app.component("lnbits-date",{props:["ts"],computed:{date(){return LNbits.utils.formatDate(this.ts)},dateFrom(){return moment.utc(this.date).local().fromNow()}},template:"\n
\n {{ this.date }}\n {{ this.dateFrom }}\n
\n "}),window.app.component("lnbits-node-info",{props:["info"],data:()=>({showDialog:!1}),mixins:[window.windowMixin],methods:{shortenNodeId:e=>e?e.substring(0,5)+"..."+e.substring(e.length-5):"..."},template:"\n
\n
{{ this.info.alias }}
\n
\n
{{ this.info.backend_name }}
\n \n #{{ this.info.color }}\n \n
{{ shortenNodeId(this.info.id) }}
\n \n \n
\n \n \n \n
\n "}),window.app.component("lnbits-stat",{props:["title","amount","msat","btc"],computed:{value(){return this.amount??(this.btc?LNbits.utils.formatSat(this.btc):LNbits.utils.formatMsat(this.msat))}},template:"\n \n \n
\n {{ title }}\n
\n
\n {{ value }}\n sats\n BTC\n
\n
\n
\n "});const DynamicComponent={props:{fetchUrl:{type:String,required:!0},scripts:{type:Array,default:()=>[]}},data:()=>({keys:[]}),async mounted(){await this.loadDynamicContent()},methods:{loadScript:async e=>new Promise(((t,a)=>{const s=document.querySelector(`script[src="${e}"]`);s&&s.remove();const i=document.createElement("script");i.src=e,i.async=!0,i.onload=t,i.onerror=()=>a(new Error(`Failed to load script: ${e}`)),document.head.appendChild(i)})),async loadDynamicContent(){this.$q.loading.show();try{const e=this.fetchUrl.split("#")[0],t=await fetch(e,{credentials:"include",headers:{Accept:"text/html","X-Requested-With":"XMLHttpRequest"}}),a=await t.text(),s=new DOMParser,i=s.parseFromString(a,"text/html").querySelector("#window-vars-script");i&&new Function(i.innerHTML)(),await this.loadScript("/static/js/base.js");for(const e of this.scripts)await this.loadScript(e);const n=this.$router.currentRoute.value.meta.previousRouteName;n&&window.app._context.components[n]&&delete window.app._context.components[n];const l=`${this.$route.name}PageLogic`,o=window[l];if(!o)throw new Error(`Component logic '${l}' not found. Ensure it is defined in the script.`);o.mixins=o.mixins||[],window.windowMixin&&o.mixins.push(window.windowMixin),window.app.component(this.$route.name,{...o,template:a}),delete window[l],this.$forceUpdate()}catch(e){console.error("Error loading dynamic content:",e)}finally{this.$q.loading.hide()}}},watch:{$route(e,t){routes.map((e=>e.name)).includes(e.name)?(this.$router.currentRoute.value.meta.previousRouteName=t.name,this.loadDynamicContent()):console.log(`Route '${e.name}' is not valid. Leave this one to Fastapi.`)}},template:'\n \n '},routes=[{path:"/wallet",name:"Wallet",component:DynamicComponent,props:e=>{let t="/wallet";if(Object.keys(e.query).length>0){t+="?";for(const[a,s]of Object.entries(e.query))t+=`${a}=${s}&`;t=t.slice(0,-1)}return{fetchUrl:t,scripts:["/static/js/wallet.js"]}}},{path:"/node",name:"Node",component:PageNode},{path:"/node/public",name:"NodePublic",component:PageNodePublic},{path:"/payments",name:"Payments",component:PagePayments},{path:"/audit",name:"Audit",component:PageAudit},{path:"/wallets",name:"Wallets",component:PageWallets},{path:"/users",name:"Users",component:PageUsers},{path:"/admin",name:"Admin",component:PageAdmin},{path:"/account",name:"Account",component:PageAccount},{path:"/extensions/builder",name:"ExtensionsBuilder",component:PageExtensionBuilder},{path:"/extensions",name:"Extensions",component:PageExtensions},{path:"/first_install",name:"FirstInstall",component:PageFirstInstall},{path:"/",name:"PageHome",component:PageHome}];window.router=VueRouter.createRouter({history:VueRouter.createWebHistory(),routes:routes}),window.app.mixin({computed:{isVueRoute(){const e=window.location.pathname,t=window.router.resolve(e);return t?.matched?.length>0}}}),window.app.use(VueQrcodeReader),window.app.use(Quasar,{config:{loading:{spinner:Quasar.QSpinnerBars}}}),window.i18n=new VueI18n.createI18n({locale:window.g.locale,fallbackLocale:"en",messages:window.localisation}),window.app.use(window.i18n),window.app.provide("g",g),window.app.use(window.router),window.app.component("DynamicComponent",DynamicComponent),window.app.mount("#vue"); diff --git a/lnbits/static/js/components.js b/lnbits/static/js/components.js index 2321c71c..bf7abb1d 100644 --- a/lnbits/static/js/components.js +++ b/lnbits/static/js/components.js @@ -21,28 +21,6 @@ window.app.component('lnbits-fsat', { } }) -window.app.component('lnbits-wallet-list', { - mixins: [window.windowMixin], - template: '#lnbits-wallet-list', - props: ['balance'], - data() { - return { - activeWallet: null, - balance: 0, - walletName: '', - LNBITS_DENOMINATION: LNBITS_DENOMINATION - } - }, - methods: { - createWallet() { - this.$emit('wallet-action', {action: 'create-wallet'}) - } - }, - created() { - document.addEventListener('updateWalletBalance', this.updateWalletBalance) - } -}) - window.app.component('lnbits-manage', { mixins: [window.windowMixin], template: '#lnbits-manage', diff --git a/lnbits/static/js/components/lnbits-wallet-api-docs.js b/lnbits/static/js/components/lnbits-wallet-api-docs.js new file mode 100644 index 00000000..3c293f51 --- /dev/null +++ b/lnbits/static/js/components/lnbits-wallet-api-docs.js @@ -0,0 +1,47 @@ +window.app.component('lnbits-wallet-api-docs', { + template: '#lnbits-wallet-api-docs', + mixins: [window.windowMixin], + methods: { + resetKeys() { + LNbits.utils + .confirmDialog('Are you sure you want to reset your API keys?') + .onOk(() => { + LNbits.api + .resetWalletKeys(this.g.wallet) + .then(response => { + const {id, adminkey, inkey} = response + this.g.wallet = { + ...this.g.wallet, + inkey, + adminkey + } + const walletIndex = this.g.user.wallets.findIndex( + wallet => wallet.id === id + ) + if (walletIndex !== -1) { + this.g.user.wallets[walletIndex] = { + ...this.g.user.wallets[walletIndex], + inkey, + adminkey + } + } + Quasar.Notify.create({ + timeout: 3500, + type: 'positive', + message: 'API keys reset!' + }) + }) + .catch(err => { + LNbits.utils.notifyApiError(err) + }) + }) + } + }, + data() { + return { + inkeyHidden: true, + adminkeyHidden: true, + walletIdHidden: true + } + } +}) diff --git a/lnbits/static/js/components/lnbits-wallet-list.js b/lnbits/static/js/components/lnbits-wallet-list.js new file mode 100644 index 00000000..fdafbc11 --- /dev/null +++ b/lnbits/static/js/components/lnbits-wallet-list.js @@ -0,0 +1,21 @@ +window.app.component('lnbits-wallet-list', { + template: '#lnbits-wallet-list', + mixins: [window.windowMixin], + props: ['balance'], + data() { + return { + activeWallet: null, + balance: 0, + walletName: '', + LNBITS_DENOMINATION: LNBITS_DENOMINATION + } + }, + methods: { + createWallet() { + this.$emit('wallet-action', {action: 'create-wallet'}) + } + }, + created() { + document.addEventListener('updateWalletBalance', this.updateWalletBalance) + } +}) diff --git a/lnbits/static/js/wallet.js b/lnbits/static/js/wallet.js index df2e3d0b..b8a71a12 100644 --- a/lnbits/static/js/wallet.js +++ b/lnbits/static/js/wallet.js @@ -641,40 +641,6 @@ window.WalletPageLogic = { } }) }, - resetKeys() { - LNbits.utils - .confirmDialog('Are you sure you want to reset your API keys?') - .onOk(() => { - LNbits.api - .resetWalletKeys(this.g.wallet) - .then(response => { - const {id, adminkey, inkey} = response - this.g.wallet = { - ...this.g.wallet, - inkey, - adminkey - } - const walletIndex = this.g.user.wallets.findIndex( - wallet => wallet.id === id - ) - if (walletIndex !== -1) { - this.g.user.wallets[walletIndex] = { - ...this.g.user.wallets[walletIndex], - inkey, - adminkey - } - } - Quasar.Notify.create({ - timeout: 3500, - type: 'positive', - message: 'API keys reset!' - }) - }) - .catch(err => { - LNbits.utils.notifyApiError(err) - }) - }) - }, updateWallet(data) { LNbits.api .request('PATCH', '/api/v1/wallet', this.g.wallet.adminkey, data) diff --git a/lnbits/static/vendor.json b/lnbits/static/vendor.json index a10200bc..99e46d45 100644 --- a/lnbits/static/vendor.json +++ b/lnbits/static/vendor.json @@ -67,6 +67,8 @@ "js/components/admin/lnbits-admin-site-customisation.js", "js/components/admin/lnbits-admin-assets-config.js", "js/components/admin/lnbits-admin-audit.js", + "js/components/lnbits-wallet-list.js", + "js/components/lnbits-wallet-api-docs.js", "js/components/lnbits-home-logos.js", "js/components/lnbits-new-user-wallet.js", "js/components/lnbits-qrcode.js", diff --git a/lnbits/templates/components.vue b/lnbits/templates/components.vue index 0c91c801..376561a2 100644 --- a/lnbits/templates/components.vue +++ b/lnbits/templates/components.vue @@ -18,98 +18,9 @@ include('components/lnbits-drawer.vue') %} {% include('components/lnbits-home-logos.vue') %} {% include('components/lnbits-manage-extension-list.vue') %} {% include('components/lnbits-language-dropdown.vue') %} {% -include('components/lnbits-payment-list.vue') %} - - +include('components/lnbits-payment-list.vue') %} {% +include('components/lnbits-wallet-api-docs.vue') %} {% +include('components/lnbits-wallet-list.vue') %}