diff --git a/.env.example b/.env.example index d9d790f9c..11ae45d80 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,9 @@ +#For more information on .env files, their content and format: https://pypi.org/project/python-dotenv/ + HOST=127.0.0.1 PORT=5000 -# uvicorn variable, allow https behind a proxy +# uvicorn variable, uncomment to allow https behind a proxy # FORWARDED_ALLOW_IPS="*" DEBUG=false diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index b6966bfa4..18445899c 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -24,7 +24,9 @@ jobs: with: poetry-version: ${{ matrix.poetry-version }} - name: Install packages - run: poetry install + run: | + poetry config virtualenvs.create false + poetry install - name: Check black run: make checkblack - name: Check isort diff --git a/.github/workflows/migrations.yml b/.github/workflows/migrations.yml index 11429665e..6725d845c 100644 --- a/.github/workflows/migrations.yml +++ b/.github/workflows/migrations.yml @@ -36,6 +36,7 @@ jobs: poetry-version: ${{ matrix.poetry-version }} - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install sudo apt install unzip - name: Run migrations diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 6868455e4..4c47fafc6 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -21,6 +21,7 @@ jobs: poetry-version: ${{ matrix.poetry-version }} - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests run: poetry run mypy diff --git a/.github/workflows/regtest.yml b/.github/workflows/regtest.yml index 99687032b..ecba4090b 100644 --- a/.github/workflows/regtest.yml +++ b/.github/workflows/regtest.yml @@ -29,6 +29,7 @@ jobs: sudo chmod -R a+rwx . - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests env: @@ -72,6 +73,7 @@ jobs: sudo chmod -R a+rwx . - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests env: @@ -116,6 +118,7 @@ jobs: sudo chmod -R a+rwx . - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests env: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7409b03e5..dbbddf980 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,6 +44,7 @@ jobs: poetry-version: ${{ matrix.poetry-version }} - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests run: make test @@ -80,6 +81,7 @@ jobs: poetry-version: ${{ matrix.poetry-version }} - name: Install dependencies run: | + poetry config virtualenvs.create false poetry install - name: Run tests env: diff --git a/.prettierrc b/.prettierrc index 224c6ee0f..725c3980a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -7,6 +7,6 @@ "singleQuote": true, "trailingComma": "none", "useTabs": false, - "jsxBracketSameLine": false, + "bracketSameLine": false, "bracketSpacing": false } diff --git a/Makefile b/Makefile index ebf2a8729..22d79f113 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,9 @@ check: mypy checkprettier checkisort checkblack prettier: $(shell find lnbits -name "*.js" -o -name ".html") ./node_modules/.bin/prettier --write lnbits/static/js/*.js lnbits/core/static/js/*.js lnbits/extensions/*/templates/*/*.html ./lnbits/core/templates/core/*.html lnbits/templates/*.html lnbits/extensions/*/static/js/*.js lnbits/extensions/*/static/components/*/*.js lnbits/extensions/*/static/components/*/*.html +pyright: + ./node_modules/.bin/pyright + black: poetry run black . diff --git a/docs/guide/faq.md b/docs/guide/faq.md new file mode 100644 index 000000000..1ccf3e289 --- /dev/null +++ b/docs/guide/faq.md @@ -0,0 +1,268 @@ +--- +layout: default +title: FAQ +nav_order: 5 +--- + + +# FAQ - Frequently Asked Questions + +## Install options +
LNbits is not a node management software but a ⚡️LN only accounting system on top of a funding source.
+ +If you want to send sats from the same node that is the funding source of your LNbits, you will need to edit the lnd.conf file. The parameters to be included are:
+ +``` +allow-circular-route=1 +allow-self-payment=1 +``` + +If you want your setup to stay behind tor then only apps, pos and wallets that have tor activated can communicate with your wallets. Most likely you will have trouble when people try to redeem your voucher through onion or when importing your lnbits wallets into a wallet-app that doesnt support tor. If you plan to let LNbits wallets interact with plain internet shops and services you should consider setting up hybrid mode for your node.
+This means that you might not have access to some files which would allow certain administrative functions. E.g. on Voltage lnd.conf can not be edited. Payments from your node to LNbits wallets can therefore not be configurated in this case atm so you will need to take an extra wallet to send from funding source->wallet x->LNbits wallet (only) for the initial funding of the wallet.
+Step by step guide how to convert your Tor only node into a clearnet node to make apps like LNbits accessible via https.
+There are several ways to run a LNbits instance funded from different sources. It is importan to choose a source that has a good liquidity and good peers connected. If you use LNbits for public services your users´ payments can then flow happily in both directions. If you would like to fund your LNbits wallet via btc please see section Troubleshooting.
+The LNbits manual shows you which sources can be used and how to configure each: CLN, LND, LNPay, Cliche, OpenNode as well as bots.
+When you run your LNbits in clearnet basically everyone can generate a wallet on it. Since the funds of your node are bound to these wallets you might want to prevent that. There are two ways to do so:
+Please note that all entries in the .env file will not be the taken into account once you activated the admin extension.
+Bad news, this is a routing error that might have quite a lot of reasons. Let´s try a few of the most possible problems and their solutions. First choose your setup
+Always save a copy of your wallet-URL, Export2phone-QR or LNDhub for your own wallets in a safe place. LNbits CANNOT help you to recover them when lost.
+Always save a copy of your wallet-URL, Export2phone-QR or LNDhub for your own wallets in a safe place. + You can find all LNbits users and wallet-IDs in your LNbits user manager extension or in your sqlite database. + To edit or read the LNbits database, go to the LNbits /data folder and look for the file called sqlite.db. + You can open and edit it with excel or with a dedicated SQL-Editor like SQLite browser.
+When you create a LNURL-p, by default the comment box is not filled. That means comments are not allowed to be attached to payments.
+
In order to allow comments, add the characters lenght of the box, from 1 to 250. Once you put a number there, + the comment box will be displayed in the payment process. You can also edit a LNURL-p already created and add that number.
+ + + +There are multiple ways to exchange sats from onchain btc to LN btc (resp. to LNbits).
+If the user do not have full acceess of your LNbits, is just an external user, can use swap services like Boltz, FixedFloat, DiamondHands or ZigZag.
+This is useful if you provide only LNURL/LN invoices from your LNbits instance, but a payer only has onchain sats so + they will have to the swap those sats first on their side.
+The procedure is simple: user sends onchain btc to the swap service and provides the LNURL / LN invoice from LNbits as destination of the swap.
+Keep in mind that this is a separate wallet, not the LN btc one that is represented by LNbits as "your wallet" upon your LN funding source. + This onchain wallet can be used also to swap LN btc to (e.g. your hardwarewallet) by using the LNbits Boltz or Deezy extension. + If you run a webshop that is linked to your LNbits for LN payments, it is very handy to regularily drain all the sats from LN into onchain. + This leads to more space in your LN channels to be able to receive new fresh sats.
+Procedure:
+When you receive a payment in LNbits, the transaction log will display only a resumed type of the transaction. + + + +
In your transaction overview you will find a little green arrow for received and a red arrow for sended funds.
+
If you click on those arrows, a details popup shows attached messages as well as the sender´s name if given.
+In LNbits this is currently not possible to do - but to receive. This is only possible if the sender's LN wallet supports LUD-18 (nameDesc) like e.g. Open Bitcion Wallet - OBW does. You will then see an alias/pseudonym in the details section of your LNbits transactions (click the arrows). Note that you can give any name there and it might not be related to the real sender´s name(!) if your receive such.
+ + +Open your LNbits with the account / wallet you want to use, go to "manage extensions" and activate the LNDHUB extension.
+Then open the LNDHUB extension, choose the wallet you want to use and scan the QR code you want to use: "admin" or "invoice only", depending on the security level you want for that wallet.
+You can use Zeus or Bluewallet as wallet apps for a lndhub account.
+Keep in mind: if your LNbits instance is Tor only, you must use also theose apps behind Tor and open the LNbits page through your Tor .onion address.
+LNbits has all sorts of open APIs and tools to program and connect to a lot of different devices for a gazillion of use-cases. Let us know what you did with it ! Come to the Makerbits Telegram Group if you are interested in building or if you need help with a project - we got you!
+ +This is a do-it-yourself project consisting of a mini-computer (Raspberry Pi Zero), a coin acceptor, a display, a 3D printed case, and a Bitcoin Lightning wallet as a funding source. It exchanges fiat coins for valuable Bitcoin Lightning ⚡ Satoshis. The user can pick up the Satoshis via QR code (LNURL-withdraw) on a mobile phone wallet. It works based on BTCPayer server, LNTXBOT is not longer an option. You can get the components as individual parts and build the case yourself e.g. from Fulmo who also made a guide on it. The shop offers payments in Bitcoin and Lightning ⚡. The code can be found on the ATM github project page>.
+The LNpos is a self-sufficient point of sale terminal which allows offline onchain payments and an offline Lightning ATM for withdrawals. Free and open source software, free from intermediaries, with integrated battery, WLAN, DIY. You can get the 3D print as well as the whole kit from the LNbits shop from 👇 Ressources. It allows +
+
+
The hardwarewallet is a very cheap solution for builders. The projects´ code and installation instructions for the LNbits hardware wallet can be found on github
+
+
+
Candy dispenser, vending machines (online), grabbing machines, jukeboxes, bandits and all sorts of other things have already been build with LNbits´ tools. Further info see 👇 Ressources.
+
+
+
This code works similar to the LNpos. Note that the setup-video for the vending machine misses the new way of installing it via the new LNURLdevices extension. The vending machine project code resides on github.
+
+
+
LNbits is a powerful solution for merchants, due to the easy setup with various extensions, that can be used for many scenarios.
+Here is an overview of the LNbits tools available for a small restaurant as well as a hotel
+LNbits has two swap extensions integrated: Boltz and Deezy.
+For a merchant that uses LNbits to receive BTC payments through LN, this is very handy to move the received sats from LN channels into onchain wallets. It not only helps you HODLing but is also freeing up "space in your channels" so you are ready to receive more sats.
+Boltz has an option to setup an automated swap triggered by a certain amount received.
+Printed voucher links or tippingcards
+To generate voucher you will need LNbits to be available in clearnet. Please consider running your own LNbits instance for this.
+LNURLw are strings that represent a faucet-link to a wallet. By scanning it, everyone will be able to withdraw sats from it. A LNURLw can be either a QR that leads to a static link or to one that responds with new invoices every time it is scanned (click "no assmilking"). You can create these QR by adding the LNURLw extension and generate the vouchertype you need.
+Creating a NFC card for a wallet
+To generate links for your cards you will need LNbits to be available in clearnet. Please consider running your own LNbits instance for this.
++
NON CUSTODIAL atomic swap service
+
+ Link:
+ https://boltz.exchange
+
+
+ README:
+ read more
+
+ Extension created by, + dni +
+
- Submarine and Reverse Submarine Swaps on LNbits via boltz.exchange
- API
-
- Link : - https://boltz.exchange - -
-- More details -
-- Created by, - dni + onchain_amount_received = amount - (amount * boltz_fee / 100) - + lockup_fee - claim_fee
+98.000 = 100.000 - 500 - 500 - 1000
GET
- /boltz/api/v1/swap/reverse
- JSON list of reverse submarine swaps
- curl -X GET {{ root_url }}/boltz/api/v1/swap/reverse -H "X-Api-Key:
- {{ user.wallets[0].adminkey }}"
-
- POST
- /boltz/api/v1/swap/reverse
- {"wallet": <string>, "onchain_address": <string>,
- "amount": <integer>, "instant_settlement":
- <boolean>}
- JSON create a reverse-submarine swaps
- curl -X POST {{ root_url }}/boltz/api/v1/swap/reverse -H "X-Api-Key:
- {{ user.wallets[0].adminkey }}"
-
- + onchain_payment + lockup_fee = amount + (amount * boltz_fee / 100) + + claim_fee + lockup_fee +
+101.000 + lockup_fee = 100.000 + 500 + 500 + lockup_fee
+GET /boltz/api/v1/swap
- JSON list of submarine swaps
- curl -X GET {{ root_url }}/boltz/api/v1/swap -H "X-Api-Key: {{
- user.wallets[0].adminkey }}"
-
- POST /boltz/api/v1/swap
- {"wallet": <string>, "refund_address": <string>,
- "amount": <integer>}
- JSON create a submarine swaps
- curl -X POST {{ root_url }}/boltz/api/v1/swap -H "X-Api-Key: {{
- user.wallets[0].adminkey }}"
-
- POST
- /boltz/api/v1/swap/refund/{swap_id}
- JSON submarine swap
- curl -X GET {{ root_url }}/boltz/api/v1/swap/refund/{swap_id} -H
- "X-Api-Key: {{ user.wallets[0].adminkey }}"
-
- POST
- /boltz/api/v1/swap/status/{swap_id}
- swap status
- curl -X GET {{ root_url }}/boltz/api/v1/swap/status/{swap_id} -H
- "X-Api-Key: {{ user.wallets[0].adminkey }}"
-
- GET
- /boltz/api/v1/swap/check
- JSON pending swaps
- curl -X GET {{ root_url }}/boltz/api/v1/swap/check -H "X-Api-Key: {{
- user.wallets[0].adminkey }}"
-
- GET
- /boltz/api/v1/swap/boltz
- JSON boltz config
- curl -X GET {{ root_url }}/boltz/api/v1/swap/boltz -H "X-Api-Key: {{
- user.wallets[0].inkey }}"
-
- GET
- /boltz/api/v1/swap/mempool
- mempool url
- curl -X GET {{ root_url }}/boltz/api/v1/swap/mempool -H "X-Api-Key:
- {{ user.wallets[0].inkey }}"
-
- curl -X GET http://YOUR-TOR-ADDRESS
diff --git a/lnbits/extensions/market/models.json b/lnbits/extensions/market/models.json
new file mode 100644
index 000000000..05bb4b11f
--- /dev/null
+++ b/lnbits/extensions/market/models.json
@@ -0,0 +1,227 @@
+{
+ "shipping_zones": [
+ "Free (digital)",
+ "Worldwide",
+ "Europe",
+ "Australia",
+ "Austria",
+ "Belgium",
+ "Brazil",
+ "Canada",
+ "Denmark",
+ "Finland",
+ "France",
+ "Germany",
+ "Greece",
+ "Hong Kong",
+ "Hungary",
+ "Ireland",
+ "Indonesia",
+ "Israel",
+ "Italy",
+ "Japan",
+ "Kazakhstan",
+ "Korea",
+ "Luxembourg",
+ "Malaysia",
+ "Mexico",
+ "Netherlands",
+ "New Zealand",
+ "Norway",
+ "Poland",
+ "Portugal",
+ "Russia",
+ "Saudi Arabia",
+ "Singapore",
+ "Spain",
+ "Sweden",
+ "Switzerland",
+ "Thailand",
+ "Turkey",
+ "Ukraine",
+ "United Kingdom**",
+ "United States***",
+ "Vietnam",
+ "China"
+ ],
+ "categories": [
+ "Fashion (clothing and accessories)",
+ "Health (and beauty)",
+ "Toys (and baby equipment)",
+ "Media (Books and CDs)",
+ "Groceries (Food and Drink)",
+ "Technology (Phones and Computers)",
+ "Home (furniture and accessories)",
+ "Gifts (flowers, cards, etc)",
+ "Adult",
+ "Other"
+ ],
+ "currency": {
+ "BTC": "Bitcoin",
+ "SAT": "Bitcoin satoshis",
+ "AED": "United Arab Emirates Dirham",
+ "AFN": "Afghan Afghani",
+ "ALL": "Albanian Lek",
+ "AMD": "Armenian Dram",
+ "ANG": "Netherlands Antillean Gulden",
+ "AOA": "Angolan Kwanza",
+ "ARS": "Argentine Peso",
+ "AUD": "Australian Dollar",
+ "AWG": "Aruban Florin",
+ "AZN": "Azerbaijani Manat",
+ "BAM": "Bosnia and Herzegovina Convertible Mark",
+ "BBD": "Barbadian Dollar",
+ "BDT": "Bangladeshi Taka",
+ "BGN": "Bulgarian Lev",
+ "BHD": "Bahraini Dinar",
+ "BIF": "Burundian Franc",
+ "BMD": "Bermudian Dollar",
+ "BND": "Brunei Dollar",
+ "BOB": "Bolivian Boliviano",
+ "BRL": "Brazilian Real",
+ "BSD": "Bahamian Dollar",
+ "BTN": "Bhutanese Ngultrum",
+ "BWP": "Botswana Pula",
+ "BYN": "Belarusian Ruble",
+ "BYR": "Belarusian Ruble",
+ "BZD": "Belize Dollar",
+ "CAD": "Canadian Dollar",
+ "CDF": "Congolese Franc",
+ "CHF": "Swiss Franc",
+ "CLF": "Unidad de Fomento",
+ "CLP": "Chilean Peso",
+ "CNH": "Chinese Renminbi Yuan Offshore",
+ "CNY": "Chinese Renminbi Yuan",
+ "COP": "Colombian Peso",
+ "CRC": "Costa Rican Colón",
+ "CUC": "Cuban Convertible Peso",
+ "CVE": "Cape Verdean Escudo",
+ "CZK": "Czech Koruna",
+ "DJF": "Djiboutian Franc",
+ "DKK": "Danish Krone",
+ "DOP": "Dominican Peso",
+ "DZD": "Algerian Dinar",
+ "EGP": "Egyptian Pound",
+ "ERN": "Eritrean Nakfa",
+ "ETB": "Ethiopian Birr",
+ "EUR": "Euro",
+ "FJD": "Fijian Dollar",
+ "FKP": "Falkland Pound",
+ "GBP": "British Pound",
+ "GEL": "Georgian Lari",
+ "GGP": "Guernsey Pound",
+ "GHS": "Ghanaian Cedi",
+ "GIP": "Gibraltar Pound",
+ "GMD": "Gambian Dalasi",
+ "GNF": "Guinean Franc",
+ "GTQ": "Guatemalan Quetzal",
+ "GYD": "Guyanese Dollar",
+ "HKD": "Hong Kong Dollar",
+ "HNL": "Honduran Lempira",
+ "HRK": "Croatian Kuna",
+ "HTG": "Haitian Gourde",
+ "HUF": "Hungarian Forint",
+ "IDR": "Indonesian Rupiah",
+ "ILS": "Israeli New Sheqel",
+ "IMP": "Isle of Man Pound",
+ "INR": "Indian Rupee",
+ "IQD": "Iraqi Dinar",
+ "ISK": "Icelandic Króna",
+ "JEP": "Jersey Pound",
+ "JMD": "Jamaican Dollar",
+ "JOD": "Jordanian Dinar",
+ "JPY": "Japanese Yen",
+ "KES": "Kenyan Shilling",
+ "KGS": "Kyrgyzstani Som",
+ "KHR": "Cambodian Riel",
+ "KMF": "Comorian Franc",
+ "KRW": "South Korean Won",
+ "KWD": "Kuwaiti Dinar",
+ "KYD": "Cayman Islands Dollar",
+ "KZT": "Kazakhstani Tenge",
+ "LAK": "Lao Kip",
+ "LBP": "Lebanese Pound",
+ "LKR": "Sri Lankan Rupee",
+ "LRD": "Liberian Dollar",
+ "LSL": "Lesotho Loti",
+ "LYD": "Libyan Dinar",
+ "MAD": "Moroccan Dirham",
+ "MDL": "Moldovan Leu",
+ "MGA": "Malagasy Ariary",
+ "MKD": "Macedonian Denar",
+ "MMK": "Myanmar Kyat",
+ "MNT": "Mongolian Tögrög",
+ "MOP": "Macanese Pataca",
+ "MRO": "Mauritanian Ouguiya",
+ "MUR": "Mauritian Rupee",
+ "MVR": "Maldivian Rufiyaa",
+ "MWK": "Malawian Kwacha",
+ "MXN": "Mexican Peso",
+ "MYR": "Malaysian Ringgit",
+ "MZN": "Mozambican Metical",
+ "NAD": "Namibian Dollar",
+ "NGN": "Nigerian Naira",
+ "NIO": "Nicaraguan Córdoba",
+ "NOK": "Norwegian Krone",
+ "NPR": "Nepalese Rupee",
+ "NZD": "New Zealand Dollar",
+ "OMR": "Omani Rial",
+ "PAB": "Panamanian Balboa",
+ "PEN": "Peruvian Sol",
+ "PGK": "Papua New Guinean Kina",
+ "PHP": "Philippine Peso",
+ "PKR": "Pakistani Rupee",
+ "PLN": "Polish Złoty",
+ "PYG": "Paraguayan Guaraní",
+ "QAR": "Qatari Riyal",
+ "RON": "Romanian Leu",
+ "RSD": "Serbian Dinar",
+ "RUB": "Russian Ruble",
+ "RWF": "Rwandan Franc",
+ "SAR": "Saudi Riyal",
+ "SBD": "Solomon Islands Dollar",
+ "SCR": "Seychellois Rupee",
+ "SEK": "Swedish Krona",
+ "SGD": "Singapore Dollar",
+ "SHP": "Saint Helenian Pound",
+ "SLL": "Sierra Leonean Leone",
+ "SOS": "Somali Shilling",
+ "SRD": "Surinamese Dollar",
+ "SSP": "South Sudanese Pound",
+ "STD": "São Tomé and Príncipe Dobra",
+ "SVC": "Salvadoran Colón",
+ "SZL": "Swazi Lilangeni",
+ "THB": "Thai Baht",
+ "TJS": "Tajikistani Somoni",
+ "TMT": "Turkmenistani Manat",
+ "TND": "Tunisian Dinar",
+ "TOP": "Tongan Paʻanga",
+ "TRY": "Turkish Lira",
+ "TTD": "Trinidad and Tobago Dollar",
+ "TWD": "New Taiwan Dollar",
+ "TZS": "Tanzanian Shilling",
+ "UAH": "Ukrainian Hryvnia",
+ "UGX": "Ugandan Shilling",
+ "USD": "US Dollar",
+ "UYU": "Uruguayan Peso",
+ "UZS": "Uzbekistan Som",
+ "VEF": "Venezuelan Bolívar",
+ "VES": "Venezuelan Bolívar Soberano",
+ "VND": "Vietnamese Đồng",
+ "VUV": "Vanuatu Vatu",
+ "WST": "Samoan Tala",
+ "XAF": "Central African Cfa Franc",
+ "XAG": "Silver (Troy Ounce)",
+ "XAU": "Gold (Troy Ounce)",
+ "XCD": "East Caribbean Dollar",
+ "XDR": "Special Drawing Rights",
+ "XOF": "West African Cfa Franc",
+ "XPD": "Palladium",
+ "XPF": "Cfp Franc",
+ "XPT": "Platinum",
+ "YER": "Yemeni Rial",
+ "ZAR": "South African Rand",
+ "ZMW": "Zambian Kwacha",
+ "ZWL": "Zimbabwean Dollar"
+ }
+}
diff --git a/lnbits/extensions/market/templates/market/index.html b/lnbits/extensions/market/templates/market/index.html
index 77e3acced..0f8fa78bb 100644
--- a/lnbits/extensions/market/templates/market/index.html
+++ b/lnbits/extensions/market/templates/market/index.html
@@ -803,9 +803,8 @@
self.productDialog.data = _.clone(link._data)
if (self.productDialog.data.categories) {
- self.productDialog.data.categories = self.productDialog.data.categories.split(
- ','
- )
+ self.productDialog.data.categories =
+ self.productDialog.data.categories.split(',')
}
if (self.productDialog.data.image.startsWith('data:')) {
self.productDialog.url = false
diff --git a/lnbits/extensions/satspay/templates/satspay/index.html b/lnbits/extensions/satspay/templates/satspay/index.html
index 5a1c62f4d..74b3d2ccc 100644
--- a/lnbits/extensions/satspay/templates/satspay/index.html
+++ b/lnbits/extensions/satspay/templates/satspay/index.html
@@ -809,7 +809,8 @@
this.createTheme(wallet, data)
},
sendFormDataCharge: function () {
- this.formDialogCharge.data.custom_css = this.formDialogCharge.data.custom_css?.id
+ this.formDialogCharge.data.custom_css =
+ this.formDialogCharge.data.custom_css?.id
const data = this.formDialogCharge.data
const wallet = this.g.user.wallets[0].inkey
data.amount = parseInt(data.amount)
diff --git a/lnbits/extensions/smtp/templates/smtp/index.html b/lnbits/extensions/smtp/templates/smtp/index.html
index c64cdcfa2..4b00cd082 100644
--- a/lnbits/extensions/smtp/templates/smtp/index.html
+++ b/lnbits/extensions/smtp/templates/smtp/index.html
@@ -574,11 +574,12 @@
.inkey
)
.then(function (response) {
- self.emailaddresses = _.reject(self.emailaddresses, function (
- obj
- ) {
- return obj.id == emailaddressId
- })
+ self.emailaddresses = _.reject(
+ self.emailaddresses,
+ function (obj) {
+ return obj.id == emailaddressId
+ }
+ )
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
diff --git a/lnbits/extensions/subdomains/templates/subdomains/index.html b/lnbits/extensions/subdomains/templates/subdomains/index.html
index e8d8ec57d..a39773e71 100644
--- a/lnbits/extensions/subdomains/templates/subdomains/index.html
+++ b/lnbits/extensions/subdomains/templates/subdomains/index.html
@@ -484,9 +484,8 @@
var link = _.findWhere(this.domains, {id: formId})
console.log(link.id)
this.domainDialog.data = _.clone(link)
- this.domainDialog.data.allowed_record_types = link.allowed_record_types.split(
- ', '
- )
+ this.domainDialog.data.allowed_record_types =
+ link.allowed_record_types.split(', ')
this.domainDialog.show = true
},
updateDomain: function (wallet, data) {
diff --git a/lnbits/extensions/tpos/templates/tpos/tpos.html b/lnbits/extensions/tpos/templates/tpos/tpos.html
index bf97bf2b6..438fc22ea 100644
--- a/lnbits/extensions/tpos/templates/tpos/tpos.html
+++ b/lnbits/extensions/tpos/templates/tpos/tpos.html
@@ -500,6 +500,7 @@
.post('/tpos/api/v1/tposs/' + this.tposId + '/invoices', null, {
params: {
amount: this.sat,
+ memo: this.amountFormatted,
tipAmount: this.tipAmountSat
}
})
diff --git a/lnbits/extensions/tpos/views_api.py b/lnbits/extensions/tpos/views_api.py
index ada54b3f9..1be1428d9 100644
--- a/lnbits/extensions/tpos/views_api.py
+++ b/lnbits/extensions/tpos/views_api.py
@@ -58,7 +58,7 @@ async def api_tpos_delete(
@tpos_ext.post("/api/v1/tposs/{tpos_id}/invoices", status_code=HTTPStatus.CREATED)
async def api_tpos_create_invoice(
- tpos_id: str, amount: int = Query(..., ge=1), tipAmount: int = 0
+ tpos_id: str, amount: int = Query(..., ge=1), memo: str = "", tipAmount: int = 0
) -> dict:
tpos = await get_tpos(tpos_id)
@@ -75,7 +75,7 @@ async def api_tpos_create_invoice(
payment_hash, payment_request = await create_invoice(
wallet_id=tpos.wallet,
amount=amount,
- memo=f"{tpos.name}",
+ memo=f"{memo} to {tpos.name}" if memo else f"{tpos.name}",
extra={
"tag": "tpos",
"tipAmount": tipAmount,
diff --git a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js
index 004f092ba..27d40ce97 100644
--- a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js
+++ b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js
@@ -174,11 +174,12 @@ async function walletList(path) {
'/watchonly/api/v1/wallet/' + walletAccountId,
this.adminkey
)
- this.walletAccounts = _.reject(this.walletAccounts, function (
- obj
- ) {
- return obj.id === walletAccountId
- })
+ this.walletAccounts = _.reject(
+ this.walletAccounts,
+ function (obj) {
+ return obj.id === walletAccountId
+ }
+ )
await this.refreshWalletAccounts()
} catch (error) {
this.$q.notify({
diff --git a/lnbits/settings.py b/lnbits/settings.py
index af887fc75..4ccb2cad4 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -8,7 +8,7 @@ from typing import List, Optional
import httpx
from loguru import logger
-from pydantic import BaseSettings, Field, validator
+from pydantic import BaseSettings, Extra, Field, validator
def list_parse_fallback(v):
@@ -33,6 +33,7 @@ class LNbitsSettings(BaseSettings):
env_file_encoding = "utf-8"
case_sensitive = False
json_loads = list_parse_fallback
+ extra = Extra.ignore
class UsersSettings(LNbitsSettings):
diff --git a/package-lock.json b/package-lock.json
index f2ff24bdd..db16d6f3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,31 +1,54 @@
{
- "name": "lnbits-legend",
+ "name": "main",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"devDependencies": {
- "prettier": "2.1.1"
+ "prettier": "2.8.3",
+ "pyright": "1.1.289"
}
},
"node_modules/prettier": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
- "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
+ "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/pyright": {
+ "version": "1.1.289",
+ "resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.289.tgz",
+ "integrity": "sha512-fG3STxnwAt3i7bxbXUPJdYNFrcOWHLwCSEOySH2foUqtYdzWLcxDez0Kgl1X8LMQx0arMJ6HRkKghxfRD1/z6g==",
+ "dev": true,
+ "bin": {
+ "pyright": "index.js",
+ "pyright-langserver": "langserver.index.js"
+ },
+ "engines": {
+ "node": ">=12.0.0"
}
}
},
"dependencies": {
"prettier": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
- "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz",
+ "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==",
+ "dev": true
+ },
+ "pyright": {
+ "version": "1.1.289",
+ "resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.289.tgz",
+ "integrity": "sha512-fG3STxnwAt3i7bxbXUPJdYNFrcOWHLwCSEOySH2foUqtYdzWLcxDez0Kgl1X8LMQx0arMJ6HRkKghxfRD1/z6g==",
"dev": true
}
}
diff --git a/package.json b/package.json
index 19d34f128..de2a17915 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"devDependencies": {
- "prettier": "2.1.1"
+ "prettier": "2.8.3",
+ "pyright": "1.1.289"
}
}
diff --git a/poetry.lock b/poetry.lock
index 5a99e198f..46dc503bf 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -175,6 +175,24 @@ d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
+[[package]]
+name = "boltz-client"
+version = "0.1.2"
+description = "python boltz client"
+category = "main"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "boltz_client-0.1.2-py3-none-any.whl", hash = "sha256:2fb0814c7c3ea88d039e71088648df27db0c036b777b0618bd30638dd76ebe90"},
+ {file = "boltz_client-0.1.2.tar.gz", hash = "sha256:b360c0ff26f2dea62af6457de4d8c46e434cd24b607ed3aa71494409b57e082b"},
+]
+
+[package.dependencies]
+click = ">=8"
+embit = ">=0.4"
+httpx = ">=0.23"
+websockets = ">=10"
+
[[package]]
name = "cashu"
version = "0.8.2"
@@ -532,10 +550,10 @@ files = [
cffi = ">=1.12"
[package.extras]
-docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"]
+docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx_rtd_theme"]
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
-sdist = ["setuptools-rust (>=0.11.4)"]
+sdist = ["setuptools_rust (>=0.11.4)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"]
@@ -1784,7 +1802,7 @@ mssql = ["pyodbc"]
mssql-pymssql = ["pymssql"]
mssql-pyodbc = ["pyodbc"]
mysql = ["mysqlclient"]
-oracle = ["cx-oracle"]
+oracle = ["cx_oracle"]
postgresql = ["psycopg2"]
postgresql-pg8000 = ["pg8000 (<1.16.6)"]
postgresql-psycopg2binary = ["psycopg2-binary"]
@@ -2094,4 +2112,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
[metadata]
lock-version = "2.0"
python-versions = "^3.10 | ^3.9 | ^3.8 | ^3.7"
-content-hash = "9daf94dd600a7e23dcefcc8752fae1694e0084e56553dc578a63272776a8fe53"
+content-hash = "b2d22a2a33b4c0a4491b5519b28772435c15747b407a150ffa591bcf6ccb56a6"
diff --git a/pyproject.toml b/pyproject.toml
index 68e06db5e..da873a125 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -62,7 +62,8 @@ protobuf = "^4.21.6"
Cerberus = "^1.3.4"
async-timeout = "^4.0.2"
pyln-client = "0.11.1"
-cashu = "0.8.2"
+cashu = "^0.8.2"
+boltz-client = "^0.1.2"
[tool.poetry.dev-dependencies]
@@ -85,11 +86,18 @@ lnbits = "lnbits.server:main"
[tool.isort]
profile = "black"
+[tool.pyright]
+include = [
+ "lnbits"
+]
+exclude = [
+ "lnbits/wallets/lnd_grpc_files",
+]
+
[tool.mypy]
files = "lnbits"
exclude = """(?x)(
- ^lnbits/extensions/boltz.
- | ^lnbits/wallets/lnd_grpc_files.
+ ^lnbits/wallets/lnd_grpc_files.
)"""
[[tool.mypy.overrides]]
diff --git a/requirements.txt b/requirements.txt
index c5332811a..1a0872db8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -7,6 +7,7 @@ attrs==22.2.0 ; python_version >= "3.7" and python_version < "4.0"
base58==2.1.1 ; python_version >= "3.7" and python_version < "4.0"
bech32==1.2.0 ; python_version >= "3.7" and python_version < "4.0"
bitstring==3.1.9 ; python_version >= "3.7" and python_version < "4.0"
+boltz-client==0.1.2 ; python_version >= "3.7" and python_version < "4.0"
cashu==0.8.2 ; python_version >= "3.7" and python_version < "4.0"
cerberus==1.3.4 ; python_version >= "3.7" and python_version < "4.0"
certifi==2022.12.7 ; python_version >= "3.7" and python_version < "4.0"
diff --git a/tests/extensions/boltz/conftest.py b/tests/extensions/boltz/conftest.py
index b9ef78875..1eba452a9 100644
--- a/tests/extensions/boltz/conftest.py
+++ b/tests/extensions/boltz/conftest.py
@@ -1,17 +1,6 @@
-import asyncio
-import json
-import secrets
-
-import pytest
import pytest_asyncio
-from lnbits.core.crud import create_account, create_wallet, get_wallet
-from lnbits.extensions.boltz.boltz import create_reverse_swap, create_swap
-from lnbits.extensions.boltz.models import (
- CreateReverseSubmarineSwap,
- CreateSubmarineSwap,
-)
-from tests.mocks import WALLET
+from lnbits.extensions.boltz.models import CreateReverseSubmarineSwap
@pytest_asyncio.fixture(scope="session")
@@ -22,4 +11,4 @@ async def reverse_swap(from_wallet):
onchain_address="bcrt1q4vfyszl4p8cuvqh07fyhtxve5fxq8e2ux5gx43",
amount=20_000,
)
- return await create_reverse_swap(data)
+ return data
diff --git a/tests/extensions/boltz/test_api.py b/tests/extensions/boltz/test_api.py
index 0266f9400..057bdab5c 100644
--- a/tests/extensions/boltz/test_api.py
+++ b/tests/extensions/boltz/test_api.py
@@ -1,7 +1,6 @@
import pytest
-import pytest_asyncio
-from tests.helpers import is_fake, is_regtest
+from tests.helpers import is_fake
@pytest.mark.asyncio
diff --git a/tests/extensions/boltz/test_swap.py b/tests/extensions/boltz/test_swap.py
deleted file mode 100644
index ab5954acb..000000000
--- a/tests/extensions/boltz/test_swap.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import asyncio
-
-import pytest
-import pytest_asyncio
-
-from lnbits.extensions.boltz.boltz import create_reverse_swap, create_swap
-from lnbits.extensions.boltz.crud import (
- create_reverse_submarine_swap,
- create_submarine_swap,
- get_reverse_submarine_swap,
- get_submarine_swap,
-)
-from tests.extensions.boltz.conftest import reverse_swap
-from tests.helpers import is_fake, is_regtest
-
-
-@pytest.mark.asyncio
-@pytest.mark.skipif(is_fake, reason="this test is only passes in regtest")
-async def test_create_reverse_swap(client, reverse_swap):
- swap, wait_for_onchain = reverse_swap
- assert swap.status == "pending"
- assert swap.id is not None
- assert swap.boltz_id is not None
- assert swap.claim_privkey is not None
- assert swap.onchain_address is not None
- assert swap.lockup_address is not None
- newswap = await create_reverse_submarine_swap(swap)
- await wait_for_onchain
- newswap = await get_reverse_submarine_swap(swap.id)
- assert newswap is not None
- assert newswap.status == "complete"