diff --git a/lib/lightning-address.js b/lib/lightning-address.js index 1350318..91b834e 100644 --- a/lib/lightning-address.js +++ b/lib/lightning-address.js @@ -2,8 +2,8 @@ const addressRegExp = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/ export class LightningAddress { - addressView = document.getElementById('lightning-address-output'); - addressInput = document.getElementById('lightning-address-input'); + addressView = window.document.getElementById('lightning-address-output'); + addressInput = window.document.getElementById('lightning-address-input'); #domain = ''; #userName = ''; @@ -25,11 +25,11 @@ export class LightningAddress { return; } + // Document: https://github.com/lnurl/luds/blob/luds/16.md this.data = await fetch(`https://${this.#domain}/.well-known/lnurlp/${this.#userName}`).then(async (res) => { return res.json(); }) - console.info(this.data); // Debug; return this.data; } @@ -40,13 +40,17 @@ export class LightningAddress { */ async getInvoice(amount) { if(!this.data || this.data.tag !== 'payRequest' || !this.data.callback) { - return; + throw new Error('支払い可能なライトニングアドレスではないようです') } if(this.data.status === 'ERROR') { - // TODO: 仕様上this.data.reasonが存在するはずなのでエラー理由をスローする - - return; + // 仕様上this.data.reasonが存在するはずなのでエラー理由をスローする + // https://github.com/lnurl/luds/blob/luds/06.md + if(this.data.reason) { + throw new Error(this.data.reason) + } else { + throw new Error(`Invalid lnurlp response: ${JSON.stringify(this.data)}`) + } } // 数量のバリデーション diff --git a/lib/pos.js b/lib/pos.js index 37c1683..88193e2 100644 --- a/lib/pos.js +++ b/lib/pos.js @@ -1,7 +1,11 @@ import { LightningAddress } from './lightning-address.js'; +/** + * POS機能 + * ライトニングアドレスを保管して入力された金額のインボイスのQRコードの表示を行う。 + * またインプットの値とインボイスの値が乖離することを避けるため入力値を監視し変更された場合は直ちに破棄する。 + */ export class Pos { - // 定数 localStorageKey = 'POS:LnAddress'; #getQrCodeConfig(data) { return { @@ -27,29 +31,24 @@ export class Pos { // LightningAddressクラスのインスタンス #lnAddress; - #qrCode; #qrWrapper = window.document.getElementById('lightning-pos-qr-box'); #satsInput = window.document.getElementById('sats'); #messageArea = window.document.getElementById('pos-message'); #otherUnits = ['btc', 'jpy', 'usd', 'eur'] - // 制御用フラグ + // 連打による連続的なリクエストを制限するためのフラグ #isRequesting = false; initialize() { - console.info('Pos: initialize POS') - // ローカルストレージからアドレスを取得 this.#lnAddress = new LightningAddress(window.localStorage.getItem(this.localStorageKey) ?? ''); - // 値が変更されたら請求書は削除する + // 値が変更されたら請求書QRコードは削除しなければいけないため入力値を監視する this.#handleInputChange(); } setLnAddress(form) { - console.info('Pos: setting lnAddress'); - const formData = new FormData(form); this.#lnAddress = new LightningAddress(formData.get('lightning-address') ?? ''); @@ -61,7 +60,6 @@ export class Pos { } window.localStorage.setItem(this.localStorageKey, this.#lnAddress.toString()); - console.info(`Pos: set lnAddress: ${this.#lnAddress}`); } getCurrntSatsAmount() { @@ -92,7 +90,7 @@ export class Pos { try { await this.#lnAddress.fetchAddressData(); const invoice = await this.#lnAddress.getInvoice(amount * 1000); - this.#updateQrCode(invoice.pr); + this.#showQrCode(invoice.pr); } catch (error) { this.#setMessage(error.message ?? JSON.stringify(error)); } finally { @@ -101,7 +99,6 @@ export class Pos { } clearLnAddress() { - console.info(`Pos: clear lnAddress`); this.#lnAddress = new LightningAddress(''); window.localStorage.clear(this.localStorageKey); this.#clearQrCode(); @@ -112,19 +109,15 @@ export class Pos { } #showQrCode(data) { - this.#qrCode = new QRCodeStyling(this.#getQrCodeConfig(data)) - this.#qrCode.append(this.#qrWrapper); - } - - #updateQrCode(data) { - this.#qrCode.update(this.#getQrCodeConfig(data)); + const qrCode = new QRCodeStyling(this.#getQrCodeConfig(data)) + qrCode.append(this.#qrWrapper); } + // どの通貨が変更された場合もQRコードをクリアする #handleInputChange() { let inputs = this.#otherUnits.map(u => window.document.getElementById(u)) inputs = [ ...inputs, this.#satsInput ]; - // どの通貨が変更された場合もQRコードをクリアする inputs.forEach(input => { input.addEventListener('input', () => { this.#clearQrCode(); @@ -135,7 +128,7 @@ export class Pos { // エラーメッセージなどを表示する #setMessage(message) { this.#messageArea.innerHTML = ''; - const p = document.createElement('p') + const p = window.document.createElement('p') p.innerText = message; this.#messageArea.appendChild(p) diff --git a/main.js b/main.js index fd313c0..9b31906 100644 --- a/main.js +++ b/main.js @@ -804,7 +804,9 @@ posPayButton.addEventListener('click', () => { pos.generateInvoice(); }); -// ライトニングアドレスの変更ダイアログの制御 +/** + * ライトニングアドレスの変更ダイアログの制御 + */ const showButton = document.getElementById('show-lightning-address-dialog'); const lnDialog = document.getElementById('update-lightning-address-dialog'); const lnDialogSubmitButton = document.getElementById('lightning-address-submit-button'); @@ -841,7 +843,6 @@ lnDialogSubmitButton.addEventListener('click', (event) => { lnDialog.close(); }); - // index.htmlで使用する関数をグローバルスコープで使用できるようにwindowに追加する window.satsRate = { calculateValues,