From f70cd837c5b10c26bc682181c0d3b6aeee5eb83c Mon Sep 17 00:00:00 2001 From: Arc Date: Wed, 16 Jul 2025 16:06:33 +0100 Subject: [PATCH 01/10] Just changing names --- lnpos/100_config.ino | 46 +++++++++++++++++++-------------------- lnpos/CHANGELOG.md | 2 +- lnpos/lnpos.ino | 52 +++++++++++++++++++++++++------------------- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/lnpos/100_config.ino b/lnpos/100_config.ino index 7f9c59e..9b3bc1f 100644 --- a/lnpos/100_config.ino +++ b/lnpos/100_config.ino @@ -125,27 +125,27 @@ void readFiles() return; } - lnurlPoS = getJsonValue(doc, "config_lnurlpos"); - lnurlATM = getJsonValue(doc, "config_lnurlatm"); + offlinePoS = getJsonValue(doc, "config_lnurlpos"); + offlineATM = getJsonValue(doc, "config_lnurlatm"); masterKey = getJsonValue(doc, "config_masterkey"); lnbitsServer = getJsonValue(doc, "config_server"); invoice = getJsonValue(doc, "config_invoice"); - lncurrency = getJsonValue(doc, "config_lncurrency"); - lnurlATMMS = getJsonValue(doc, "config_lnurlatmms"); - lnurlATMPin = getJsonValue(doc, "config_lnurlatmpin"); + lnCurrency = getJsonValue(doc, "config_lncurrency"); + mempool = getJsonValue(doc, "config_lnurlatmms"); + securityPin = getJsonValue(doc, "config_lnurlatmpin"); decimalplaces = getJsonValue(doc, "config_decimalplaces"); ssid = getJsonValue(doc, "config_wifi_ssid"); password = getJsonValue(doc, "config_wifi_password"); } ////////LNURL PoS string///////// - if (lnurlPoS != "null" || lnurlPoS != "") + if (offlinePoS != "null" || offlinePoS != "") { - baseURLPoS = getValue(lnurlPoS, ',', 0); - secretPoS = getValue(lnurlPoS, ',', 1); - currencyPoS = getValue(lnurlPoS, ',', 2); + baseURLPoS = getValue(offlinePoS, ',', 0); + secretPoS = getValue(offlinePoS, ',', 1); + currencyPoS = getValue(offlinePoS, ',', 2); Serial.println(""); - Serial.println("lnurlPoS: " + lnurlPoS); + Serial.println("offlinePoS: " + offlinePoS); Serial.println("baseURLPoS: " + baseURLPoS); Serial.println("secretPoS: " + secretPoS); Serial.println("currencyPoS: " + currencyPoS); @@ -156,21 +156,21 @@ void readFiles() } else { - Serial.println("lnurlPoS not set"); + Serial.println("offlinePoS not set"); } ////////LNURL ATM string///////// - if (lnurlATM != "null" || lnurlATM != "") + if (offlineATM != "null" || offlineATM != "") { Serial.println(""); - Serial.println("lnurlATM: " + lnurlATM); - baseURLATM = getValue(lnurlATM, ',', 0); + Serial.println("offlineATM: " + offlineATM); + baseURLATM = getValue(offlineATM, ',', 0); // remove /api/v1.... and add /atm?lightning= int apiPos = baseURLATM.indexOf("api"); baseUrlAtmPage = baseURLATM.substring(0, apiPos); baseUrlAtmPage += "atm?lightning="; - secretATM = getValue(lnurlATM, ',', 1); - currencyATM = getValue(lnurlATM, ',', 2); + secretATM = getValue(offlineATM, ',', 1); + currencyATM = getValue(offlineATM, ',', 2); Serial.println("baseUrlAtmPage: " + baseUrlAtmPage); Serial.println("baseURLATM: " + baseURLATM); Serial.println("secretATM: " + secretATM); @@ -230,11 +230,11 @@ void readFiles() } /////////PoS Currency/////// - if (lncurrency != "null" || lncurrency != "") + if (lnCurrency != "null" || lnCurrency != "") { Serial.println(""); Serial.println("PoS currency used from memory"); - Serial.println("PoS currency: " + lncurrency); + Serial.println("PoS currency: " + lnCurrency); } else { @@ -242,11 +242,11 @@ void readFiles() } /////////mempool.space server/////// - if (lnurlATMMS != "null" || lnurlATMMS != "") + if (mempool != "null" || mempool != "") { Serial.println(""); Serial.println("mempool.space server used from memory"); - Serial.println("mempool.space server: " + lnurlATMMS); + Serial.println("mempool.space server: " + mempool); } else { @@ -254,15 +254,15 @@ void readFiles() } /////////mATM/Settings pin/////// - if (lnurlATMPin != "null" || lnurlATMPin != "") + if (securityPin != "null" || securityPin != "") { Serial.println(""); Serial.println("ATM/settings security pin used from memory"); - Serial.println("ATM/settings security pin: " + lnurlATMPin); + Serial.println("ATM/settings security pin: " + securityPin); } else { - lnurlATMPin = "878787"; + securityPin = "878787"; Serial.println("ATM/Settings security pin not set using default"); } diff --git a/lnpos/CHANGELOG.md b/lnpos/CHANGELOG.md index c00f84e..117b617 100644 --- a/lnpos/CHANGELOG.md +++ b/lnpos/CHANGELOG.md @@ -1,6 +1,6 @@ 0.1.4 ====== -- Fix typo with logging 'lnurlATM' configuration to serial +- Fix typo with logging 'offlineATM' configuration to serial - Remove unused WebServer to reduce build time, file size and installation time - Show a little "arrow" in front of the selected menu item to avoid ambiguity when only 2 menu items are present (or when the user is color blind) - Make "USB" indicator blue so it looks better and is easier to distinguish diff --git a/lnpos/lnpos.ino b/lnpos/lnpos.ino index f15320f..b721dad 100644 --- a/lnpos/lnpos.ino +++ b/lnpos/lnpos.ino @@ -28,25 +28,33 @@ fs::SPIFFSFS &FlashFS = SPIFFS; bool format = false; //////////////////////////////////////////////////////// -////////////LNPOS WILL LOOK FOR DETAILS SET///////////// -////////OVER THE WEBINSTALLER CONFIG, HOWEVER/////////// ///////////OPTIONALLY SET HARDCODED DETAILS///////////// //////////////////////////////////////////////////////// +///////// OPTIONALLY SET HARDCODED SETTINGS //////////// bool hardcoded = false; /// Set to true to hardcode -String lnurlPoS = "https://demo.lnbits.com/lnpos/api/v1/lnurl/WTmei,BzzoY5wbgpym3eMdb9ueXr,USD"; -String lnurlATM = "https://demo.lnbits.com/fossa/api/v1/lnurl/W5xu4,XGg4BJ3xCh36JdMKm2kgDw,USD"; +/// FOR OFFLINE POS +String offlinePoS = "https://demo.lnbits.com/lnpos/api/v1/lnurl/WTmei,BzzoY5wbgpym3eMdb9ueXr,USD"; + +/// FOR OFFLINE ATM +String offlineATM = "https://demo.lnbits.com/fossa/api/v1/lnurl/W5xu4,XGg4BJ3xCh36JdMKm2kgDw,USD"; + +/// FOR GENERATING ONCHAIN ADDRESSES String masterKey = "xpub6CJFgwcim8tPBJo2A6dS13kZxqbgtWKD3LKj1tyurWADbXbPyWo11exyotTSUY3cvhQy5Mfj8FSURgpXhc4L2UvQyaTMC36S49JnNJMmcWU"; +String mempool = "https://mempool.space"; + +/// FOR ONLINE POS String lnbitsServer = "https://demo.lnbits.com"; String invoice = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; -String lncurrency = "GBP"; -String lnurlATMMS = "https://mempool.space"; -String lnurlATMPin = "878787"; -String decimalplaces = "2"; +String lnCurrency = "GBP"; String ssid = "AlansBits"; String password = "ithurtswhenip"; +/// ADDITIONAL SETTINGS +String securityPin = "878787"; // FOR SETTINGS AND ATM +String fiatDecimalPlaces = "2"; // FOR OUR JAPANESE FREINDS + ////////////////////////////////////////////////// // variables @@ -297,14 +305,14 @@ void checkHardcoded() { if (!hardcoded) { - lnurlPoS = ""; - lnurlATM = ""; + offlinePoS = ""; + offlineATM = ""; masterKey = ""; lnbitsServer = ""; invoice = ""; - lncurrency = ""; - lnurlATMMS = ""; - lnurlATMPin = ""; + lnCurrency = ""; + mempool = ""; + securityPin = ""; decimalplaces = ""; ssid = ""; password = ""; @@ -332,7 +340,7 @@ void accessPoint() isATMMoneyPin(true); } - if (pinToShow.length() == lnurlATMPin.length() && pinToShow != lnurlATMPin) + if (pinToShow.length() == securityPin.length() && pinToShow != securityPin) { error(" WRONG PIN"); delay(1500); @@ -341,7 +349,7 @@ void accessPoint() dataIn = ""; isATMMoneyPin(true); } - else if (pinToShow == lnurlATMPin) + else if (pinToShow == securityPin) { error(" SETTINGS", "HOLD 1 FOR USB", ""); // start portal (any key pressed on startup) @@ -424,7 +432,7 @@ void onchainMain() { while (unConfirmed) { - qrData = "https://" + lnurlATMMS + "/address/" + qrData; + qrData = "https://" + mempool + "/address/" + qrData; qrShowCodeOnchain(false, " *MENU"); while (unConfirmed) @@ -454,7 +462,7 @@ void lnMain() return; } - if (lncurrency == "" || lncurrency == "default") + if (lnCurrency == "" || lnCurrency == "default") { currencyLoop(); } @@ -652,7 +660,7 @@ void lnurlATMMain() isATMMoneyPin(true); } - if (pinToShow.length() == lnurlATMPin.length() && pinToShow != lnurlATMPin) + if (pinToShow.length() == securityPin.length() && pinToShow != securityPin) { error(" WRONG PIN"); delay(1500); @@ -661,7 +669,7 @@ void lnurlATMMain() dataIn = ""; isATMMoneyPin(true); } - else if (pinToShow == lnurlATMPin) + else if (pinToShow == securityPin) { isATMMoneyNumber(true); inputs = ""; @@ -784,7 +792,7 @@ void isLNMoneyNumber(bool cleared) tft.print(" - ENTER AMOUNT -"); tft.setTextSize(3); tft.setCursor(0, 50); - tft.println(String(lncurrency) + ": "); + tft.println(String(lnCurrency) + ": "); tft.println("SAT: "); tft.setCursor(0, 120); tft.setTextSize(2); @@ -1218,7 +1226,7 @@ void currencyLoop() if (currencyItems[i] == currencyItems[currencyItemNo]) { tft.setTextColor(TFT_GREEN, TFT_BLACK); - lncurrency = currencyItems[i]; + lnCurrency = currencyItems[i]; } else { @@ -1419,7 +1427,7 @@ bool getSats() } const char *lnbitsServerChar = lnbitsServer.c_str(); const char *invoiceChar = invoice.c_str(); - const char *lncurrencyChar = lncurrency.c_str(); + const char *lncurrencyChar = lnCurrency.c_str(); Serial.println("connecting to LNbits server " + lnbitsServer); if (!client.connect(lnbitsServerChar, 443)) From f9dd92c5396303c3441fdec900965740517e9481 Mon Sep 17 00:00:00 2001 From: arcbtc Date: Wed, 16 Jul 2025 21:15:57 +0100 Subject: [PATCH 02/10] added menus and fixed names --- config.js | 56 +++++++++++++++++++++++++++----------------- lnpos/100_config.ino | 10 ++++---- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/config.js b/config.js index 3e079ca..25ddf3d 100644 --- a/config.js +++ b/config.js @@ -20,29 +20,45 @@ export const addressesAndFiles = [ export const configPath = "elements.json"; export const elements = [ { - name: "config_lnurlpos", - value: "", - label: "LNURLPoS string from LNURLDevices extension", - type: "text", + type: "heading", + label: "Offline PoS", }, { - name: "config_lnurlatm", + name: "config_offlinepos", value: "", - label: "LNURL ATM", + label: "LNURL string from the LNPoS extension", type: "text", }, { - name: "config_password", + type: "heading", + label: "Offline ATM", + }, + { + name: "config_offlineatm", value: "", - label: "Device Password", + label: "LNURL string from the FOSSA extension", type: "text", }, + { + type: "heading", + label: "Onchain addresses", + }, { name: "config_masterkey", value: "", label: "Onchain Master Public Key", type: "text", }, + { + name: "config_mempool", + value: "", + label: "Mempool.space Server, for creating a checking link", + type: "text", + }, + { + type: "heading", + label: "Online PoS", + }, { name: "config_server", value: "", @@ -62,33 +78,31 @@ export const elements = [ type: "text", }, { - name: "config_lnurlatmms", + name: "config_wifi_ssid", value: "", - label: "Mempool.space Server", + label: "WiFi SSID", type: "text", }, { - name: "config_lnurlatmpin", + name: "config_wifi_password", value: "", - label: "LNURLATM pin String", + label: "WiFi Password", type: "text", }, { - name: "config_decimalplaces", - value: 2, - label: "FIAT Decimal Places", - type: "text", + type: "heading", + label: "Additional settings", }, { - name: "config_wifi_ssid", + name: "config_securitypin", value: "", - label: "WiFi SSID", + label: "LNURLATM pin String", type: "text", }, { - name: "config_wifi_password", - value: "", - label: "WiFi Password", + name: "config_fiatdecimalplaces", + value: 2, + label: "FIAT Decimal Places ie 2 for USD, 0 for YEN", type: "text", }, ]; diff --git a/lnpos/100_config.ino b/lnpos/100_config.ino index 9b3bc1f..e20e5be 100644 --- a/lnpos/100_config.ino +++ b/lnpos/100_config.ino @@ -125,15 +125,15 @@ void readFiles() return; } - offlinePoS = getJsonValue(doc, "config_lnurlpos"); - offlineATM = getJsonValue(doc, "config_lnurlatm"); + offlinePoS = getJsonValue(doc, "config_offlinepos"); + offlineATM = getJsonValue(doc, "config_offlineatm"); masterKey = getJsonValue(doc, "config_masterkey"); lnbitsServer = getJsonValue(doc, "config_server"); invoice = getJsonValue(doc, "config_invoice"); lnCurrency = getJsonValue(doc, "config_lncurrency"); - mempool = getJsonValue(doc, "config_lnurlatmms"); - securityPin = getJsonValue(doc, "config_lnurlatmpin"); - decimalplaces = getJsonValue(doc, "config_decimalplaces"); + mempool = getJsonValue(doc, "config_mempool"); + securityPin = getJsonValue(doc, "config_securitypin"); + decimalplaces = getJsonValue(doc, "config_fiatdecimalplaces"); ssid = getJsonValue(doc, "config_wifi_ssid"); password = getJsonValue(doc, "config_wifi_password"); } From d27eb51d2f31e560e53644e5b89c8f80aa1d61e3 Mon Sep 17 00:00:00 2001 From: arcbtc Date: Wed, 16 Jul 2025 21:38:35 +0100 Subject: [PATCH 03/10] might as well add some data you never know --- build.sh | 0 config.js | 26 +++++++++++++------------- debug.sh | 0 lnpos/100_config.ino | 6 +++--- lnpos/lnpos.ino | 38 +++++++++++++++++++------------------- 5 files changed, 35 insertions(+), 35 deletions(-) mode change 100644 => 100755 build.sh mode change 100644 => 100755 debug.sh diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/config.js b/config.js index 25ddf3d..b3cae3d 100644 --- a/config.js +++ b/config.js @@ -45,13 +45,13 @@ export const elements = [ }, { name: "config_masterkey", - value: "", - label: "Onchain Master Public Key", + value: "xpub6CGXUdDautexBBybgGaFnhVwSzjVozfiGefFgHfaTjjKk1DVkNKzYM1akU8fJHafGBhaVY7tP5zkMorFi2vKPFmBjv8s6KwcPYkFG4C6khn", + label: "Onchain Extended Public Key", type: "text", }, { name: "config_mempool", - value: "", + value: "https://mempool.space", label: "Mempool.space Server, for creating a checking link", type: "text", }, @@ -59,33 +59,33 @@ export const elements = [ type: "heading", label: "Online PoS", }, + { + name: "config_lncurrency", + value: "GBP", + label: "PoS Currency. ie: EUR", + type: "text", + }, { name: "config_server", - value: "", + value: "https://v1.lnbits.com", label: "LNbits Server", type: "text", }, { name: "config_invoice", - value: "", + value: "517400f477ec44d7a9187b3bce88c721", label: "Wallet Invoice Key", type: "text", }, - { - name: "config_lncurrency", - value: "", - label: "PoS Currency. ie: EUR", - type: "text", - }, { name: "config_wifi_ssid", - value: "", + value: "ithurtswhenip", label: "WiFi SSID", type: "text", }, { name: "config_wifi_password", - value: "", + value: "qwertyu", label: "WiFi Password", type: "text", }, diff --git a/debug.sh b/debug.sh old mode 100644 new mode 100755 diff --git a/lnpos/100_config.ino b/lnpos/100_config.ino index e20e5be..c6c9d12 100644 --- a/lnpos/100_config.ino +++ b/lnpos/100_config.ino @@ -133,7 +133,7 @@ void readFiles() lnCurrency = getJsonValue(doc, "config_lncurrency"); mempool = getJsonValue(doc, "config_mempool"); securityPin = getJsonValue(doc, "config_securitypin"); - decimalplaces = getJsonValue(doc, "config_fiatdecimalplaces"); + fiatDecimalPlaces = getJsonValue(doc, "config_fiatdecimalplaces"); ssid = getJsonValue(doc, "config_wifi_ssid"); password = getJsonValue(doc, "config_wifi_password"); } @@ -267,11 +267,11 @@ void readFiles() } /////////no. FIAT decimal places/////// - if (decimalplaces != "null" || decimalplaces != "") + if (fiatDecimalPlaces != "null" || fiatDecimalPlaces != "") { Serial.println(""); Serial.println("no. fiat decimal places used from memory"); - Serial.println("no. fiat decimal places: " + decimalplaces); + Serial.println("no. fiat decimal places: " + fiatDecimalPlaces); } else { diff --git a/lnpos/lnpos.ino b/lnpos/lnpos.ino index b721dad..d232f04 100644 --- a/lnpos/lnpos.ino +++ b/lnpos/lnpos.ino @@ -159,11 +159,11 @@ bool isInteger(const char *str) return true; } -void formatNumber(float number, int decimalplaces, char *output) +void formatNumber(float number, int fiatDecimalPlaces, char *output) { - // Create a format string based on the decimalplaces + // Create a format string based on the fiatDecimalPlaces char formatString[10]; - sprintf(formatString, "%%.%df", decimalplaces); + sprintf(formatString, "%%.%df", fiatDecimalPlaces); // Use the format string to write the number to the output buffer sprintf(output, formatString, number); @@ -226,7 +226,7 @@ void loop() { noSats = "0"; dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; unConfirmed = true; key_val = ""; @@ -313,7 +313,7 @@ void checkHardcoded() lnCurrency = ""; mempool = ""; securityPin = ""; - decimalplaces = ""; + fiatDecimalPlaces = ""; ssid = ""; password = ""; } @@ -432,7 +432,7 @@ void onchainMain() { while (unConfirmed) { - qrData = "https://" + mempool + "/address/" + qrData; + qrData = mempool + "/address/" + qrData; qrShowCodeOnchain(false, " *MENU"); while (unConfirmed) @@ -545,7 +545,7 @@ void lnMain() { noSats = "0"; dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; unConfirmed = false; timer = 5000; @@ -565,7 +565,7 @@ void lnMain() noSats = "0"; dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; } else @@ -800,8 +800,8 @@ void isLNMoneyNumber(bool cleared) if (!cleared) { - amountToShowNumber = dataIn.toFloat() / pow(10, decimalplaces.toInt()); - formatNumber(amountToShowNumber, decimalplaces.toInt(), decimalplacesOutput); + amountToShowNumber = dataIn.toFloat() / pow(10, fiatDecimalPlaces.toInt()); + formatNumber(amountToShowNumber, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = String(decimalplacesOutput); noSats = String(converted * amountToShowNumber); } @@ -809,7 +809,7 @@ void isLNMoneyNumber(bool cleared) { noSats = "0"; dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; } @@ -839,14 +839,14 @@ void isLNURLMoneyNumber(bool cleared) if (!cleared) { - amountToShowNumber = dataIn.toFloat() / pow(10, decimalplaces.toInt()); - formatNumber(amountToShowNumber, decimalplaces.toInt(), decimalplacesOutput); + amountToShowNumber = dataIn.toFloat() / pow(10, fiatDecimalPlaces.toInt()); + formatNumber(amountToShowNumber, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = String(decimalplacesOutput); } else { dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; } @@ -872,14 +872,14 @@ void isATMMoneyNumber(bool cleared) if (!cleared) { - amountToShowNumber = dataIn.toFloat() / pow(10, decimalplaces.toInt()); - formatNumber(amountToShowNumber, decimalplaces.toInt(), decimalplacesOutput); + amountToShowNumber = dataIn.toFloat() / pow(10, fiatDecimalPlaces.toInt()); + formatNumber(amountToShowNumber, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = String(decimalplacesOutput); } else { dataIn = "0"; - formatNumber(0, decimalplaces.toInt(), decimalplacesOutput); + formatNumber(0, fiatDecimalPlaces.toInt(), decimalplacesOutput); amountToShow = decimalplacesOutput; } @@ -1360,7 +1360,7 @@ bool checkOnlineParams() return false; } - const char *decimal = decimalplaces.c_str(); + const char *decimal = fiatDecimalPlaces.c_str(); if (!isInteger(decimal)) { error("WRONG DECIMAL"); @@ -1403,7 +1403,7 @@ bool checkOfflineParams() return false; } - if (!isInteger(decimalplaces.c_str())) + if (!isInteger(fiatDecimalPlaces.c_str())) { error("WRONG DECIMAL"); delay(3000); From a96a1e50be0467404bb2910feb94f1fd118ed5ff Mon Sep 17 00:00:00 2001 From: arcbtc Date: Wed, 16 Jul 2025 22:11:46 +0100 Subject: [PATCH 04/10] temp add --- .gitignore | 2 ++ build-webinstaller.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) mode change 100644 => 100755 build-webinstaller.sh diff --git a/.gitignore b/.gitignore index 32f3e79..68d38d7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ tmp .vscode build .cache + +hardware-installer/ diff --git a/build-webinstaller.sh b/build-webinstaller.sh old mode 100644 new mode 100755 index f47ca6f..4b5a734 --- a/build-webinstaller.sh +++ b/build-webinstaller.sh @@ -4,7 +4,7 @@ REPO=https://github.com/lnbits/lnpos/releases/download INSTALLER_PATH=./hardware-installer/public/firmware git clone https://github.com/lnbits/hardware-installer - +git checkout headings cp INSTALLER.md ./hardware-installer/public/INSTALLER.md cp versions.json ./hardware-installer/src/versions.json cp config.js ./hardware-installer/src/config.js From e23c48a009367faac627f473143333cdfdee2099 Mon Sep 17 00:00:00 2001 From: arcbtc Date: Thu, 17 Jul 2025 00:11:03 +0100 Subject: [PATCH 05/10] temp pulling branch for testing --- INSTALLER.md | 13 ++++++------- build-webinstaller.sh | 4 ++-- config.js | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/INSTALLER.md b/INSTALLER.md index bcaff40..45658e1 100644 --- a/INSTALLER.md +++ b/INSTALLER.md @@ -4,17 +4,16 @@ LNPoS ## Free and open-source bitcoin point-of-sale - LNPoS includes: -- LNPoS (for online LN payments, original project) -- LNURLPoS (for offline LN payments, original project ) -- OnChain (for onchain payments) -- LNURLATM (for making offline LN withdraw links). +- Online PoS (for online LN payments, just connects to LNbits wallet over wifi) +- Offline PoS (for offline LN payments, original project) +- Onchain (for onchain payments, uses an bip39 xpub and also creates a mempool.space link for checking) +- Offline ATM (for making offline LN withdraw links, original project)

-Original demo +Video tutorial tutorial -Video tutorial https://twitter.com/arcbtc/status/1585605023337168896 +Born here Join our telegram group MakerBits diff --git a/build-webinstaller.sh b/build-webinstaller.sh index 4b5a734..2e9dd3c 100755 --- a/build-webinstaller.sh +++ b/build-webinstaller.sh @@ -3,8 +3,8 @@ PROJECT_NAME=lnpos REPO=https://github.com/lnbits/lnpos/releases/download INSTALLER_PATH=./hardware-installer/public/firmware -git clone https://github.com/lnbits/hardware-installer -git checkout headings +git clone --branch headings --single-branch https://github.com/lnbits/hardware-installer.git + cp INSTALLER.md ./hardware-installer/public/INSTALLER.md cp versions.json ./hardware-installer/src/versions.json cp config.js ./hardware-installer/src/config.js diff --git a/config.js b/config.js index b3cae3d..8c8357d 100644 --- a/config.js +++ b/config.js @@ -26,7 +26,7 @@ export const elements = [ { name: "config_offlinepos", value: "", - label: "LNURL string from the LNPoS extension", + label: "String from the LNPoS extension", type: "text", }, { @@ -36,7 +36,7 @@ export const elements = [ { name: "config_offlineatm", value: "", - label: "LNURL string from the FOSSA extension", + label: "String from the FOSSA extension", type: "text", }, { From 99236ded8caa0e1cf01019aa51532a716312fdd9 Mon Sep 17 00:00:00 2001 From: arcbtc Date: Thu, 17 Jul 2025 00:24:05 +0100 Subject: [PATCH 06/10] wrong label --- config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.js b/config.js index 8c8357d..0be8e75 100644 --- a/config.js +++ b/config.js @@ -95,8 +95,8 @@ export const elements = [ }, { name: "config_securitypin", - value: "", - label: "LNURLATM pin String", + value: "878787", + label: "Security pin for settings and ATM mode", type: "text", }, { From e7e5a60d48c37d88c9c9065841643329095c190e Mon Sep 17 00:00:00 2001 From: arcbtc Date: Mon, 28 Jul 2025 11:08:37 +0100 Subject: [PATCH 07/10] naming --- lnpos/lnpos.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lnpos/lnpos.ino b/lnpos/lnpos.ino index d232f04..3c4f4e8 100644 --- a/lnpos/lnpos.ino +++ b/lnpos/lnpos.ino @@ -85,7 +85,7 @@ String amountToShow = "0"; String key_val; String selection; -const char menuItems[5][13] = {"LNPoS", "Offline PoS", "OnChain", "ATM", "Settings"}; +const char menuItems[5][13] = {"Online PoS", "Offline PoS", "OnChain", "ATM", "Settings"}; const char currencyItems[3][5] = {"sat", "USD", "EUR"}; char decimalplacesOutput[20]; int menuItemCheck[5] = {0, 0, 0, 0, 1}; @@ -265,7 +265,7 @@ void loop() menuLoop(); } - if (selection == "LNPoS") + if (selection == "Online PoS") { lnMain(); } @@ -1484,7 +1484,7 @@ bool getInvoice() return false; } - const String toPost = "{\"out\": false,\"amount\" : " + String(noSats.toInt()) + ", \"memo\" :\"LNPoS-" + String(random(1, 1000)) + "\"}"; + const String toPost = "{\"out\": false,\"amount\" : " + String(noSats.toInt()) + ", \"memo\" :\"Online PoS-" + String(random(1, 1000)) + "\"}"; const String url = "/api/v1/payments"; client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + lnbitsServerChar + "\r\n" + "User-Agent: ESP32\r\n" + "X-Api-Key: " + invoiceChar + " \r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n" + "Content-Length: " + toPost.length() + "\r\n" + "\r\n" + toPost + "\n"); From 07f23ef4ab2ec9c83db9344cdf7ceee02bf7c657 Mon Sep 17 00:00:00 2001 From: arcbtc Date: Mon, 4 Aug 2025 01:29:20 +0100 Subject: [PATCH 08/10] ALL WORKING --- lnpos/lnpos.ino | 114 +++++++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/lnpos/lnpos.ino b/lnpos/lnpos.ino index 3c4f4e8..4e0e5f0 100644 --- a/lnpos/lnpos.ino +++ b/lnpos/lnpos.ino @@ -351,7 +351,7 @@ void accessPoint() } else if (pinToShow == securityPin) { - error(" SETTINGS", "HOLD 1 FOR USB", ""); + error(" SETTINGS", "HOLD 1 FOR USB \nHOLD 2 TO RESET", ""); // start portal (any key pressed on startup) int count = 0; while (count < 10) @@ -370,6 +370,10 @@ void accessPoint() return; } } + if (key == '2') + { + ESP.restart(); + } } } else @@ -1436,26 +1440,33 @@ bool getSats() return false; } - const String toPost = "{\"amount\" : 1, \"from\" :\"" + String(lncurrencyChar) + "\"}"; + const String toPost = "{\"amount\" : 1, \"from_\" :\"" + String(lncurrencyChar) + "\", \"to\" : \"sat\"}"; const String url = "/api/v1/conversion"; client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + String(lnbitsServerChar) + "\r\n" + "User-Agent: ESP32\r\n" + "X-Api-Key: " + String(invoiceChar) + " \r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n" + "Content-Length: " + toPost.length() + "\r\n" + "\r\n" + toPost + "\n"); + // Skip response headers while (client.connected()) { - const String line = client.readStringUntil('\n'); + String line = client.readStringUntil('\n'); if (line == "\r") - { break; - } } - const String line = client.readString(); - StaticJsonDocument<150> doc; - DeserializationError error = deserializeJson(doc, line); - if (error) + // Read entire body + String payload; + while (client.available()) + { + char c = client.read(); + payload += c; + } + + StaticJsonDocument<3000> doc; + DeserializationError jsonError = deserializeJson(doc, payload); + + if (jsonError) { Serial.print("deserializeJson() failed: "); - Serial.println(error.f_str()); + Serial.println(jsonError.f_str()); return false; } @@ -1487,29 +1498,39 @@ bool getInvoice() const String toPost = "{\"out\": false,\"amount\" : " + String(noSats.toInt()) + ", \"memo\" :\"Online PoS-" + String(random(1, 1000)) + "\"}"; const String url = "/api/v1/payments"; client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + lnbitsServerChar + "\r\n" + "User-Agent: ESP32\r\n" + "X-Api-Key: " + invoiceChar + " \r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n" + "Content-Length: " + toPost.length() + "\r\n" + "\r\n" + toPost + "\n"); - + // Skip response headers while (client.connected()) { - const String line = client.readStringUntil('\n'); - + String line = client.readStringUntil('\n'); if (line == "\r") - { break; - } } - const String line = client.readString(); - StaticJsonDocument<1000> doc; - DeserializationError error = deserializeJson(doc, line); - if (error) + // IMPORTANT, to skip "443\r\n + client.readStringUntil('\n'); + + // Read JSON payload + String payload; + while (client.connected()) + { + String line = client.readStringUntil('\n'); + if (line == "\r" || line.length() == 0) + break; + payload += line + "\n"; + } + + Serial.println(payload); + StaticJsonDocument<3000> doc; + DeserializationError jsonError = deserializeJson(doc, payload); + if (jsonError) { Serial.print("deserializeJson() failed: "); - Serial.println(error.f_str()); + Serial.println(jsonError.f_str()); return false; } const char *payment_hash = doc["checking_id"]; - const char *payment_request = doc["payment_request"]; + const char *payment_request = doc["bolt11"]; qrData = payment_request; dataId = payment_hash; @@ -1533,24 +1554,28 @@ bool checkInvoice() const String url = "/api/v1/payments/"; client.print(String("GET ") + url + dataId + " HTTP/1.1\r\n" + "Host: " + lnbitsServerChar + "\r\n" + "User-Agent: ESP32\r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n\r\n"); + // Skip response headers while (client.connected()) { - const String line = client.readStringUntil('\n'); + String line = client.readStringUntil('\n'); if (line == "\r") - { break; - } } - const String line = client.readString(); - Serial.println(line); - StaticJsonDocument<2000> doc; + // Read entire body + String payload; + while (client.available()) + { + char c = client.read(); + payload += c; + } - DeserializationError error = deserializeJson(doc, line); - if (error) + StaticJsonDocument<3000> doc; + DeserializationError jsonError = deserializeJson(doc, payload); + if (jsonError) { Serial.print("deserializeJson() failed: "); - Serial.println(error.f_str()); + Serial.println(jsonError.f_str()); return false; } if (doc["paid"]) @@ -1612,10 +1637,13 @@ bool makeLNURL() String secret; char hexbuffer[3]; - if (selection == "Offline PoS") { + if (selection == "Offline PoS") + { preparedURL = baseURLPoS; secret = secretPoS; - } else { + } + else + { // ATM preparedURL = baseURLATM; secret = secretATM; @@ -1624,7 +1652,8 @@ bool makeLNURL() int salt_length = 8; unsigned char salt[salt_length]; - for (int i = 0; i < salt_length; i++) { + for (int i = 0; i < salt_length; i++) + { salt[i] = random(0, 256); } @@ -1646,7 +1675,8 @@ bool makeLNURL() size_t payload_len = payload.length(); int padding = 16 - (payload_len % 16); payload_len += padding; - for (int i = 0; i < padding; i++) { + for (int i = 0; i < padding; i++) + { payload += String((char)padding); } @@ -1660,7 +1690,7 @@ bool makeLNURL() memcpy(salted + 16, encrypted, payload_len); preparedURL += "?p="; - preparedURL += toBase64(salted, payload_len+16, BASE64_URLSAFE); + preparedURL += toBase64(salted, payload_len + 16, BASE64_URLSAFE); Serial.println(preparedURL); char Buf[200]; @@ -1896,17 +1926,19 @@ void printSleepAnimationFrame(String text, int wait) } //////////ENCRYPTION/////////////// -void encrypt(unsigned char* key, unsigned char* iv, int length, const char* plainText, unsigned char* outputBuffer){ +void encrypt(unsigned char *key, unsigned char *iv, int length, const char *plainText, unsigned char *outputBuffer) +{ mbedtls_aes_context aes; mbedtls_aes_init(&aes); mbedtls_aes_setkey_enc(&aes, key, 256); // AES-256 requires a 32-byte key - mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iv, (const unsigned char*)plainText, outputBuffer); + mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iv, (const unsigned char *)plainText, outputBuffer); mbedtls_aes_free(&aes); } -void deriveKeyAndIV(const char* secret, unsigned char* salt, unsigned char* outputBuffer) { +void deriveKeyAndIV(const char *secret, unsigned char *salt, unsigned char *outputBuffer) +{ mbedtls_md5_context md5_ctx; - unsigned char data[24]; // 16 bytes key + 8 bytes salt + unsigned char data[24]; // 16 bytes key + 8 bytes salt unsigned char md5Output[16]; // 16 bytes for MD5 output memcpy(data, secret, 16); @@ -1922,7 +1954,8 @@ void deriveKeyAndIV(const char* secret, unsigned char* salt, unsigned char* outp unsigned char data_md5[16 + 16 + 8]; // 16 bytes md5 output + 16 bytes key + 8 bytes salt - for (int i = 16; i <= 48; i+=16) { + for (int i = 16; i <= 48; i += 16) + { memcpy(data_md5, md5Output, 16); memcpy(data_md5 + 16, data, 24); mbedtls_md5_init(&md5_ctx); @@ -1934,4 +1967,3 @@ void deriveKeyAndIV(const char* secret, unsigned char* salt, unsigned char* outp mbedtls_md5_free(&md5_ctx); } - From 58e4c5480a3f58012213ef66508a51246095dc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Mon, 4 Aug 2025 12:56:44 +0200 Subject: [PATCH 09/10] fixup! --- build-webinstaller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 build-webinstaller.sh diff --git a/build-webinstaller.sh b/build-webinstaller.sh old mode 100755 new mode 100644 index 2e9dd3c..f47ca6f --- a/build-webinstaller.sh +++ b/build-webinstaller.sh @@ -3,7 +3,7 @@ PROJECT_NAME=lnpos REPO=https://github.com/lnbits/lnpos/releases/download INSTALLER_PATH=./hardware-installer/public/firmware -git clone --branch headings --single-branch https://github.com/lnbits/hardware-installer.git +git clone https://github.com/lnbits/hardware-installer cp INSTALLER.md ./hardware-installer/public/INSTALLER.md cp versions.json ./hardware-installer/src/versions.json From 6c1a8955cc493c9a5884ca5b867a8f2a5071e733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Mon, 4 Aug 2025 13:00:16 +0200 Subject: [PATCH 10/10] fixup! --- config.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/config.js b/config.js index 0be8e75..c3362c1 100644 --- a/config.js +++ b/config.js @@ -45,7 +45,7 @@ export const elements = [ }, { name: "config_masterkey", - value: "xpub6CGXUdDautexBBybgGaFnhVwSzjVozfiGefFgHfaTjjKk1DVkNKzYM1akU8fJHafGBhaVY7tP5zkMorFi2vKPFmBjv8s6KwcPYkFG4C6khn", + value: "", label: "Onchain Extended Public Key", type: "text", }, @@ -61,31 +61,31 @@ export const elements = [ }, { name: "config_lncurrency", - value: "GBP", - label: "PoS Currency. ie: EUR", + value: "USD", + label: "PoS Currency. ie: GBP, EUR", type: "text", }, { name: "config_server", - value: "https://v1.lnbits.com", + value: "https://demo.lnbits.com", label: "LNbits Server", type: "text", }, { name: "config_invoice", - value: "517400f477ec44d7a9187b3bce88c721", + value: "", label: "Wallet Invoice Key", type: "text", }, { name: "config_wifi_ssid", - value: "ithurtswhenip", + value: "", label: "WiFi SSID", type: "text", }, { name: "config_wifi_password", - value: "qwertyu", + value: "", label: "WiFi Password", type: "text", }, @@ -95,8 +95,8 @@ export const elements = [ }, { name: "config_securitypin", - value: "878787", - label: "Security pin for settings and ATM mode", + value: "000000", + label: "Security pin for settings and ATM mode, 4-6 characters", type: "text", }, {