diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml
index 4d6c6d4da..71713d88f 100644
--- a/.github/workflows/mypy.yml
+++ b/.github/workflows/mypy.yml
@@ -5,10 +5,9 @@ on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
- if: ${{ 'false' == 'true' }} # skip mypy for now
steps:
- uses: actions/checkout@v1
- uses: jpetrucciani/mypy-check@master
with:
mypy_flags: '--install-types --non-interactive'
- path: lnbits
+ path: 'lnbits'
diff --git a/Pipfile b/Pipfile
index f8c42a9dd..a0cef805a 100644
--- a/Pipfile
+++ b/Pipfile
@@ -36,9 +36,11 @@ pycryptodomex = "*"
[dev-packages]
black = "==20.8b1"
-pytest = "*"
-pytest-cov = "*"
-mypy = "*"
-pytest-asyncio = "*"
-requests = "*"
mock = "*"
+mypy = "*"
+pytest = "*"
+pytest-asyncio = "*"
+pytest-cov = "*"
+requests = "*"
+types-mock = "*"
+types-protobuf = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index 42d471c6f..6a478e4c2 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "503e9942306106e40621c59f37a3ab866b483f8c5f27b879c1c6783dca30949f"
+ "sha256": "08e53fc6f1fcc021b33f9b2c5ae3bd6dbde815d4b317e9341ab02cf5b625acbc"
},
"pipfile-spec": 6,
"requires": {
@@ -29,6 +29,7 @@
"sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b",
"sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"
],
+ "markers": "python_full_version >= '3.6.2'",
"version": "==3.6.1"
},
"asyncio": {
@@ -46,6 +47,7 @@
"sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
"sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.4.0"
},
"bech32": {
@@ -53,6 +55,7 @@
"sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899",
"sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"bitstring": {
@@ -76,6 +79,7 @@
"sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
"sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
],
+ "markers": "python_version >= '3.6'",
"version": "==2022.6.15"
},
"cffi": {
@@ -139,6 +143,7 @@
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
],
+ "markers": "python_version >= '3.7'",
"version": "==8.1.3"
},
"ecdsa": {
@@ -177,6 +182,7 @@
"sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6",
"sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"
],
+ "markers": "python_version >= '3.6'",
"version": "==0.12.0"
},
"httpcore": {
@@ -184,6 +190,7 @@
"sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6",
"sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"
],
+ "markers": "python_version >= '3.7'",
"version": "==0.15.0"
},
"httptools": {
@@ -238,6 +245,7 @@
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
],
+ "markers": "python_version >= '3.5'",
"version": "==3.3"
},
"jinja2": {
@@ -307,6 +315,7 @@
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
],
+ "markers": "python_version >= '3.7'",
"version": "==2.1.1"
},
"marshmallow": {
@@ -314,6 +323,7 @@
"sha256:00040ab5ea0c608e8787137627a8efae97fabd60552a05dc889c888f814e75eb",
"sha256:635fb65a3285a31a30f276f30e958070f5214c7196202caa5c7ecf28f5274bc7"
],
+ "markers": "python_version >= '3.7'",
"version": "==3.17.0"
},
"outcome": {
@@ -321,6 +331,7 @@
"sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672",
"sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"
],
+ "markers": "python_version >= '3.7'",
"version": "==1.2.0"
},
"packaging": {
@@ -328,6 +339,7 @@
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
],
+ "markers": "python_version >= '3.6'",
"version": "==21.3"
},
"psycopg2-binary": {
@@ -473,6 +485,7 @@
"sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e",
"sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"
],
+ "markers": "python_full_version >= '3.6.1'",
"version": "==1.9.1"
},
"pyngrok": {
@@ -487,6 +500,7 @@
"sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
"sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
],
+ "markers": "python_full_version >= '3.6.8'",
"version": "==3.0.9"
},
"pypng": {
@@ -517,6 +531,7 @@
"sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f",
"sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"
],
+ "markers": "python_version >= '3.5'",
"version": "==0.20.0"
},
"pyyaml": {
@@ -562,9 +577,13 @@
"sha256:026c0de2ee8385d1255b9c2426cd4f03fe9177ac94c09979bc601946c8493aa0",
"sha256:99142650756ef1998ce0661568f54a47dac8c638fb27e3816c02536575dbba8c"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.6.0.post0"
},
"rfc3986": {
+ "extras": [
+ "idna2008"
+ ],
"hashes": [
"sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835",
"sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"
@@ -600,6 +619,14 @@
"index": "pypi",
"version": "==0.14.0"
},
+ "setuptools": {
+ "hashes": [
+ "sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16",
+ "sha256:c04b44a57a6265fe34a4a444e965884716d34bae963119a76353434d6f18e450"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==63.2.0"
+ },
"shortuuid": {
"hashes": [
"sha256:459f12fa1acc34ff213b1371467c0325169645a31ed989e268872339af7563d5",
@@ -613,6 +640,7 @@
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==1.16.0"
},
"sniffio": {
@@ -620,6 +648,7 @@
"sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663",
"sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"
],
+ "markers": "python_version >= '3.5'",
"version": "==1.2.0"
},
"sqlalchemy": {
@@ -676,17 +705,18 @@
},
"sse-starlette": {
"hashes": [
- "sha256:840607fed361360cc76f8408a25f0eca887e7cab3c3ee44f9762f179428e2bd4",
- "sha256:ca2de945af80b83f1efda6144df9e13db83880b3b87c660044b64f199395e8b7"
+ "sha256:14608559d40e3e7c6385e8c5a7b88468f7fc40c2277673a1fe8d26568e8d7c65",
+ "sha256:72438ed39b1612d1ea6d89a7c0af8afee6de0389dcbe2e77539001e78b5aa89c"
],
"index": "pypi",
- "version": "==0.10.3"
+ "version": "==1.0.0"
},
"starlette": {
"hashes": [
"sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf",
"sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"
],
+ "markers": "python_version >= '3.6'",
"version": "==0.19.1"
},
"typing-extensions": {
@@ -698,6 +728,9 @@
"version": "==4.3.0"
},
"uvicorn": {
+ "extras": [
+ "standard"
+ ],
"hashes": [
"sha256:c19a057deb1c5bb060946e2e5c262fc01590c6529c0af2c3d9ce941e89bc30e0",
"sha256:cade07c403c397f9fe275492a48c1b869efd175d5d8a692df649e6e7e2ed8f4e"
@@ -815,6 +848,7 @@
"sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
"sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==21.4.0"
},
"black": {
@@ -829,6 +863,7 @@
"sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
"sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
],
+ "markers": "python_version >= '3.6'",
"version": "==2022.6.15"
},
"charset-normalizer": {
@@ -836,6 +871,7 @@
"sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5",
"sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"
],
+ "markers": "python_version >= '3.6'",
"version": "==2.1.0"
},
"click": {
@@ -843,9 +879,13 @@
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
],
+ "markers": "python_version >= '3.7'",
"version": "==8.1.3"
},
"coverage": {
+ "extras": [
+ "toml"
+ ],
"hashes": [
"sha256:0895ea6e6f7f9939166cc835df8fa4599e2d9b759b02d1521b574e13b859ac32",
"sha256:0f211df2cba951ffcae210ee00e54921ab42e2b64e0bf2c0befc977377fb09b7",
@@ -889,6 +929,7 @@
"sha256:f23876b018dfa5d3e98e96f5644b109090f16a4acb22064e0f06933663005d39",
"sha256:f7bd0ffbcd03dc39490a1f40b2669cc414fae0c4e16b77bb26806a4d0b7d1452"
],
+ "markers": "python_version >= '3.7'",
"version": "==6.4.2"
},
"idna": {
@@ -896,6 +937,7 @@
"sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
"sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
],
+ "markers": "python_version >= '3.5'",
"version": "==3.3"
},
"iniconfig": {
@@ -954,6 +996,7 @@
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
],
+ "markers": "python_version >= '3.6'",
"version": "==21.3"
},
"pathspec": {
@@ -968,6 +1011,7 @@
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
],
+ "markers": "python_version >= '3.6'",
"version": "==1.0.0"
},
"py": {
@@ -975,6 +1019,7 @@
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.11.0"
},
"pyparsing": {
@@ -982,6 +1027,7 @@
"sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
"sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
],
+ "markers": "python_full_version >= '3.6.8'",
"version": "==3.0.9"
},
"pytest": {
@@ -1010,82 +1056,83 @@
},
"regex": {
"hashes": [
- "sha256:00d2e907d3c5e4f85197c8d2263a9cc2d34bf234a9c6236ae42a3fb0bc09b759",
- "sha256:0186edcda692c38381db8ac257c2d023fd2e08818d45dc5bee4ed84212045f51",
- "sha256:06c509bd7dcb7966bdb03974457d548e54d8327bad5b0c917e87248edc43e2eb",
- "sha256:0a3f3f45c5902eb4d90266002ccb035531ae9b9278f6d5e8028247c34d192099",
- "sha256:0c1821146b429e6fdbd13ea10f26765e48d5284bc79749468cfbfe3ceb929f0d",
- "sha256:0d93167b7d7731fa9ff9fdc1bae84ec9c7133b01a35f8cc04e926d48da6ce1f7",
- "sha256:0fd8c3635fa03ef79d07c7b3ed693b3f3930ccb52c0c51761c3296a7525b135c",
- "sha256:119091c675e6ad19da8770f89aa1d52f4ad2a2018d631956f3e90c45882df880",
- "sha256:121981ba84309dabefd5e1debd49be6d51624e54b4d44bfc184cd8d555ff1df1",
- "sha256:1244e9b9b4b81c9c34e8a84273ffaeebdc78abc98a5b02dcdd49845eb3c63bd7",
- "sha256:12e1404dfb4e928d3273a10e3468877fe84bdcd3c50b655a2c9613cfc5d9fe63",
- "sha256:13d74951c14708f00700bb29475129ecbc40e01b4029c62ee7bfe9d1f59f31ce",
- "sha256:162a5939a6fdf48658d3565eeff35acdd207e07367bf5caaff3d9ea7cb77d7a9",
- "sha256:1703490c5b850fa9cef1af00c58966756042e6ca22f4fb5bb857345cd535834f",
- "sha256:18e6203cfd81df42a987175aaeed7ba46bcb42130cd81763e2d5edcff0006d5d",
- "sha256:192c2784833aea6fc7b004730bf1b91b8b8c6b998b30271aaf3bd8adfef20a96",
- "sha256:1948d3ceac5b2d55bc93159c1e0679a256a87a54c735be5cef4543a9e692dbb9",
- "sha256:206a327e628bc529d64b21ff79a5e2564f5aec7dc7abcd4b2e8a4b271ec10550",
- "sha256:2e5db20412f0db8798ff72473d16da5f13ec808e975b49188badb2462f529fa9",
- "sha256:2f94b0befc811fe74a972b1739fffbf74c0dc1a91102aca8e324aa4f2c6991bd",
- "sha256:303676797c4c7978726e74eb8255d68f7125a3a29da71ff453448f2117290e9a",
- "sha256:34ae4f35db30caa4caf85c55069fcb7a05966a3a5ba6e9e1dab5477d84fbb08a",
- "sha256:3c6df8be7d1dd35a0d9a200fbc29f888c4452c8882d284f87608046152e049e6",
- "sha256:402fa998c5988d11ed34585eb65740dcebd0fd11844d12eb0a6b4be178eb9c64",
- "sha256:40a28759d345c0bb1f5b0ac74ac04f5d48136019522c95c0ec4b07786f67ce20",
- "sha256:414ae507ba88264444baf771fec43ce0adcd4c5dbb304d3e0716f3f4d4499d2e",
- "sha256:42da079e31ae9818ffa7a35cdd16ab7104e3f7eca9c0958040aede827b2e55c6",
- "sha256:473a7d21932ce7c314953b33c32e63df690181860edcdf14bba1278cdf71b07f",
- "sha256:49fcb45931a693b0e901972c5e077ea2cf30ec39da699645c43cb8b1542c6e14",
- "sha256:4c5913cb9769038bd03e42318955c2f15a688384a6a0b807bcfc8271603d9277",
- "sha256:4cfeb71095c8d8380a5df5a38ff94d27a3f483717e509130a822b4d6400b7991",
- "sha256:4dc74f0171eede67d79a79c06eca0fe5b7b280dbb8c27ad1fae4ced2ad66268f",
- "sha256:5b1cffff2d9f832288fe516021cb81c95c57c0067b13a82f1d2daabdbc2f4270",
- "sha256:601c99ac775b6c89699a48976f3dbb000b47d3ca59362c8abc9582e6d0780d91",
- "sha256:667a06bb8d72b6da3d9cf38dac4ba969688868ed2279a692e993d2c0e1c30aba",
- "sha256:673549a0136c7893f567ed71ab5225ed3701c79b17c0a7faee846c645fc24010",
- "sha256:67bd3bdd27db7a6460384869dd4b9c54267d805b67d70b20495bb5767f8e051c",
- "sha256:727edff0a4eaff3b6d26cbb50216feac9055aba7e6290eec23c061c2fe2fab55",
- "sha256:782627a1cb8fbb1c78d8e841f5b71c2c683086c038f975bebdac7cce7678a96f",
- "sha256:7d462ba84655abeddae4dfc517fe1afefb5430b3b5acb0a954de12a47aea7183",
- "sha256:8ab39aa445d00902c43a1e951871bedc7f18d095a21eccba153d594faac34aea",
- "sha256:8e2075ed4ea2e231e2e98b16cfa5dae87e9a6045a71104525e1efc29aa8faa8e",
- "sha256:9daeccb2764bf4cc280c40c6411ae176bb0876948e536590a052b3d647254c95",
- "sha256:9e4006942334fa954ebd32fa0728718ec870f95f4ba7cda9edc46dd49c294f22",
- "sha256:9f1c8fffd4def0b76c0947b8cb261b266e31041785dc2dc2db7569407a2f54fe",
- "sha256:a00cd58a30a1041c193777cb1bc090200b05ff4b073d5935738afd1023e63069",
- "sha256:a0220a7a16fd4bfc700661f920510defd31ef7830ce992d5cc51777aa8ccd724",
- "sha256:a048f91823862270905cb22ef88038b08aac852ce48e0ecc4b4bf1b895ec37d9",
- "sha256:a3c47c71fde0c5d584402e67546c81af9951540f1f622d821e9c20761556473a",
- "sha256:a6d9ea727fd1233ee746bf44dd37e7d4320b3ed8ff09e73d7638c969b28d280f",
- "sha256:ab0709daedc1099bbd4371ae17eeedd4efc1cf70fcdcfe5de1374a0944b61f80",
- "sha256:ab1cb36b411f16da6e057ef8e6657dd0af36f59a667f07e0b4b617e44e53d7b2",
- "sha256:ae1c5b435d44aa91d48cc710f20c3485e0584a3ad3565d5ae031d61a35f674f4",
- "sha256:b279b9bb401af41130fd2a09427105100bc8c624ed45da1c81c1c0d0aa639734",
- "sha256:b72a4ec79a15f6066d14ae1c472b743af4b4ecee14420e8d6e4a336b49b8f21c",
- "sha256:c2cd93725911c0159d597b90c96151070ef7e0e67604637e2f2abe06c34bf079",
- "sha256:c7c5f914b0eb5242c09f91058b80295525897e873b522575ab235b48db125597",
- "sha256:d07d849c9e2eca80adb85d3567302a47195a603ad7b1f0a07508e253c041f954",
- "sha256:d2672d68cf6c8452b6758fc3cd2d8feac966d511eed79a68182a5297b473af9c",
- "sha256:d35bbcbf70d14f724e7489746cf68efe122796578addd98f91428e144d0ad266",
- "sha256:d40b4447784dbe0896a6d10a178f6724598161f942c56f5a60dc0ef7fe63f7a1",
- "sha256:d561dcb0fb0ab858291837d51330696a45fd3ba6912a332a4ee130e5484b9e47",
- "sha256:d7f5ccfff648093152cadf6d886c7bd922047532f72024c953a79c7553aac2fe",
- "sha256:dce6b2ad817e3eb107f8704782b091b0631dd3adf47f14bdc086165d05b528b0",
- "sha256:e1fdda3ec7e9785065b67941693995cab95b54023a21db9bf39e54cc7b2c3526",
- "sha256:e2a262ec85c595fc8e1f3162cafc654d2219125c00ea3a190c173cea70d2cc7a",
- "sha256:e2fc1e3928c1189c0382c547c17717c6d9f425fffe619ef94270fe4c6c8be0a6",
- "sha256:ea27acd97a752cfefa9907da935e583efecb302e6e9866f37565968c8407ad58",
- "sha256:ee769a438827e443ed428e66d0aa7131c653ecd86ddc5d4644a81ed1d93af0e7",
- "sha256:f32e0d1c7e7b0b9c3cac76f3d278e7ee6b99c95672d2c1c6ea625033431837c0",
- "sha256:f355caec5bbce20421dc26e53787b10e32fd0df68db2b795435217210c08d69c",
- "sha256:f87e9108bb532f8a1fc6bf7e69b930a35c7b0267b8fef0a3ede0bcb4c5aaa531",
- "sha256:f8a2fd2f62a77536e4e3193303bec380df40d99e253b1c8f9b6eafa07eaeff67",
- "sha256:fbdf4fc6adf38fab1091c579ece3fe9f493bd0f1cfc3d2c76d2e52461ca4f8a9"
+ "sha256:045682b6457f0224deb10c9720b8008dc798b1ad4331de9302fd4b615211e5a5",
+ "sha256:04e3869fc6fc24b75d38e7547797bb0a82d6cccd49e8ce6ae21a0b87aeb9fac7",
+ "sha256:073bd76a1f03e05a6ca0df705b6117f75b10c340af068b55becb1334fc6426c2",
+ "sha256:0aa48740a1385cb668ffd828a7e2c8078ce29c72d64651c8226bd2b7cb5dba0c",
+ "sha256:0e380ebd841201f980ab022d07033be12c9438a9b2e0f60324c9e3ba31790918",
+ "sha256:0f9b8ef2e46d627b2a85d3f4fe433ead283c420adcf9461906c3db10766dd3b1",
+ "sha256:10d3a5dda21a125cfdc31e45ae6ce6bdd1e45cb194199801248d6580be8dc337",
+ "sha256:11965ae779a0ccfb6d17996d531e2f522124e04d98cc65742b96bf8f50758ab9",
+ "sha256:1c61175730596266015c4e005c65cbfeeb1ef019ccd024870169c6593a26bdb0",
+ "sha256:1d1d79a87a33fbd6573e30eb53969a4190035894c4390a0787fb823e9e86b72f",
+ "sha256:1f0bf228c948f543876f4fb310322a4ff7e398667dd58aeb4815dc9e30bf867e",
+ "sha256:2026a1c108752e48577f9720076bf6e31a60aaf0c3000fffad4e2527fdffbe95",
+ "sha256:204705b7ec16267d39870a19e72e832b12739dc48a26d923a9cb94043660d50f",
+ "sha256:248b16534d1ef8f10a72cda0f97b3dfa25b3d9123a7e726d1594cb07a541bba0",
+ "sha256:27b5011449213dfd880e592ea6d311d00739e87d9512bad507ee18c9c92a20ac",
+ "sha256:2880d21e9507869ab1636e50461afb9ffb08797f1cb76f70d3ad52e7dd13a335",
+ "sha256:2d3f9fc885ecd8b0eb248d0e190aa7264b977cc23b6da7c08444065170c57e2e",
+ "sha256:2d8b50ae3cbaaa2e5ed89ed81fc025ec64b1a54c4f34e6bdaad9dc63fc2afa6b",
+ "sha256:3ff5b2b6a136307a5551e7821d83ab12c46f57c32bf23a27877c9c6bdb55aa61",
+ "sha256:40b4436466d47271fe3b4df63e55307c91a40cda0875a9ff3b7231a08394b283",
+ "sha256:435c94d5939a7cf4b0af1cce30d196451bae441ebe64f63d08517ab490ceb385",
+ "sha256:4c0b7c413d4a8a55d72df18acbeb50276eee19cec7e2f54ed3bddc46bc3b3aeb",
+ "sha256:4cfe87490d0a801749b42491ef7e968342e5787decbf57d5402fc2c17f7302e3",
+ "sha256:4f480661cd0809a1177b09581c12c9ceff9ca989e4a0c8c0f10379dffa3b4c4c",
+ "sha256:53370620db6058dbb464324b053fee8608518d76ff6352b2835d71e2ae8ef293",
+ "sha256:53eca0cece2ddb592b8dd9746f0b258d0c8a45f5a3ac8eb96833058f64778fca",
+ "sha256:5751bfe0d939d7110396510a39e48ee928b36b55177207c47766b093886a3945",
+ "sha256:5d750f99c40a7e994df1cf1295bbb3e873417ca69508664fe9f65db92e46ca40",
+ "sha256:6019737db5c46a24f307eae5069fced0752e3a22380398bbefbef77b068b9537",
+ "sha256:605ca47681c7405723a4970d66d13fa3a3a66efa6b8499d7ab7bce1ddb44a36f",
+ "sha256:69120a8fb1eb932b6e3ededb16448be6444eb952f9350c21dddbef947fea5690",
+ "sha256:72713de336b8d895f91aad34f5591f33d1d8727bd739af3ae2657411ef6e0739",
+ "sha256:74077b462a9b255c5fca247484f46b0f25c32676fe4645cb6b5304b2d997357a",
+ "sha256:74f0067495a842f7cc198b14031a2893d377bed38e19d785f35095082ab5a556",
+ "sha256:817a0618c149d77e493963cd98851ff49d6ab8bcab247fdbf85bb89a14dca5c3",
+ "sha256:869a0f6405ec569863e09909617138af575b5e2bc5181184e60f339a4c8a6d7a",
+ "sha256:86b0cf786efd587c27abd1d07020c555a82275bba3506d916d42aed7a3744967",
+ "sha256:8cbc407c44003a1cb4aaa2d48cc19b45dde07ba0ae2f541c6750ad18f8c118f5",
+ "sha256:90e082f262cf858cbcde330999ea5612e12918982033b716d2c5d8b1bc7a01db",
+ "sha256:95d8f1083ff4546ec14fb46dc41b042d372258f8c319df1e2316d8fe1bd3f085",
+ "sha256:97211bae1bc51f153764485a54d8d1130196cae33d02285c33732b26c5328b8d",
+ "sha256:98dbaf6a86991e2b09f4d8a7669b4304755bda519565971dc3b87ee00fd6eab2",
+ "sha256:9e297ff33172853e9a9e46dbb0c2ebf44fb38ebefce659698df4eb9dfce0a748",
+ "sha256:9e64492c8105312f080e25e457db70f9b0d02e6ba3c1ea14468087b0e3aa876f",
+ "sha256:a11241808e59deec8314792bbd8a6f0a8a7a95b742709e134c73a3216dbb26ae",
+ "sha256:a33c36dcc1760d66f1969d7d3dc8956f45a3d502178053074b8489f67718138f",
+ "sha256:a4e1e7ba8c58c1f0b828418f9a2635c0f6344bf107308b8fe65f234a13c8462a",
+ "sha256:a55c4d5e5076cc5ece625dd1f7015c9a0818ba1f9ad9db421b495d7ece088e56",
+ "sha256:a6f5cc82e1fa380eb6b8040d626df6ba9f492b6886527f53d59838b11e9caaef",
+ "sha256:a96826b5c9dc68417ddb29843998473f9c2c047911e6fca36a9f81a898087b01",
+ "sha256:acf6cbcc19d86f44e8a9d3cf1f6946a71dc55c2ec8ae374c547b1eefd83b954f",
+ "sha256:b4be25d3c640a35671431d8ef8cd522319254074b150147fcacad90c91ea42c2",
+ "sha256:b5a31abc27f9bda7a455bfa1e1bd623da50e3a343a040084c879d07394a93481",
+ "sha256:bb812e590e3881a93d4d291270440b3795fa4c0bc1b03ba15fe1cc88d2ea4347",
+ "sha256:bbd542b4afd2ed5491a480e9b15f4bca13e0170ef1895064fd15741382fdebe0",
+ "sha256:bf27111f56b762238bd3ce4c5e8ad34167d85dd3c077721a0c093517526a94af",
+ "sha256:c7a4dc9436b7a55c36daa3959e92d70337c547651ebeda685dd6bb083f0b77ab",
+ "sha256:c88a1068ac8e5dc579d5104903fa2c488448c1137e580a77d1438d98070c4243",
+ "sha256:c8cffb5040bf432355cfe51378072f20087609694066ace80710bdba04cf9ce2",
+ "sha256:c944921b0e77f1923dd89cda65534223ac107e24d71b1dfe174237faa5efd32a",
+ "sha256:ca2a7233275acf0087ecd15e5fb0eeb722a1f4de453b49bb1443edf2c2f5a997",
+ "sha256:cf0a3b9744f94693f3ebcca1c259354f0043c19a4ce938f80ad6d1816b8fd8f0",
+ "sha256:dbe2f16a66f64a00dc9ccc0db7f8b5ff014f409840e03675eb431f03b50ddffd",
+ "sha256:deb7b067b3b9751c60dc7f6de68476138d550c074a5016ba944cc55863fa86d1",
+ "sha256:df669bacbda209e9b00928f1d00432b27a16c3e051f9f7e5ea306f9b78bf3e7c",
+ "sha256:e2dd4ca82c2241be9582d2ae060070f2bccb0c98295b608009d5cc6e6041eaed",
+ "sha256:e432cf909c53506da4c8308753b2671ee37d2d8d1de8b4b54ab76e91ca7ba0b5",
+ "sha256:e4e7f1aba3aaf08e11d33fd5c2d8dd8cbf573049474e11256c91e3ba3d5e1642",
+ "sha256:e51ab7fbfe5ac3002b9aee527bcb164b17fd92f5663ebf2a4e5917dd9d577864",
+ "sha256:ea00c7f86405d88995e7bab5609e343fdedfe1ffc8191d3b5ed0f8c7f5eb17ec",
+ "sha256:f7006d7c74e25f8bc592604a5a72ba624f10ebd5c0683ab4d3e940a88ac0098c",
+ "sha256:f93e3e5acf82812ea92a1ccdcce690aab18c4044dd824f6b959d2b6069d84312",
+ "sha256:fa8a4bc81b15f49c57ede3fd636786c6619179661acf2430fcc387d75bf28d33",
+ "sha256:fc44c49f33dd75e58b5ff2a5ac50c96c84b6b209d36b4790c85bca08a3b9017d"
],
- "version": "==2022.7.9"
+ "markers": "python_version >= '3.6'",
+ "version": "==2022.7.24"
},
"requests": {
"hashes": [
@@ -1100,6 +1147,7 @@
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
"version": "==0.10.2"
},
"tomli": {
@@ -1107,6 +1155,7 @@
"sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
],
+ "markers": "python_version >= '3.7'",
"version": "==2.0.1"
},
"typed-ast": {
@@ -1136,8 +1185,25 @@
"sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3",
"sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"
],
+ "markers": "python_version >= '3.6'",
"version": "==1.5.4"
},
+ "types-mock": {
+ "hashes": [
+ "sha256:4535fbb3912b88a247d43cdb41db0c8b2e187138986f6f01a989717e56105848",
+ "sha256:a849bc2d966063f4946013bf404822ee2b96f77a8dccda4174b70ab61c5293fe"
+ ],
+ "index": "pypi",
+ "version": "==4.0.15"
+ },
+ "types-protobuf": {
+ "hashes": [
+ "sha256:d291388678af91bb045fafa864f142dc4ac22f5d4cdca097c7d8d8a32fa9b3ab",
+ "sha256:d2b26861b0cb46a3c8669b0df507b7ef72e487da66d61f9f3576aa76ce028a83"
+ ],
+ "index": "pypi",
+ "version": "==3.19.22"
+ },
"typing-extensions": {
"hashes": [
"sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02",
@@ -1151,6 +1217,7 @@
"sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec",
"sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6"
],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'",
"version": "==1.26.10"
}
}
diff --git a/lnbits/app.py b/lnbits/app.py
index 19482b067..e1594a7b4 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -17,7 +17,6 @@ from loguru import logger
import lnbits.settings
from lnbits.core.tasks import register_task_listeners
-from .commands import db_migrate, handle_assets
from .core import core_app
from .core.views.generic import core_html_routes
from .helpers import (
@@ -93,7 +92,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
check_funding_source(app)
register_assets(app)
register_routes(app)
- # register_commands(app)
register_async_tasks(app)
register_exception_handlers(app)
@@ -146,12 +144,6 @@ def register_routes(app: FastAPI) -> None:
)
-def register_commands(app: FastAPI):
- """Register Click commands."""
- app.cli.add_command(db_migrate)
- app.cli.add_command(handle_assets)
-
-
def register_assets(app: FastAPI):
"""Serve each vendored asset separately or a bundle."""
diff --git a/lnbits/core/crud.py b/lnbits/core/crud.py
index 770e2906a..db802d7bb 100644
--- a/lnbits/core/crud.py
+++ b/lnbits/core/crud.py
@@ -113,7 +113,7 @@ async def create_wallet(
async def update_wallet(
wallet_id: str, new_name: str, conn: Optional[Connection] = None
) -> Optional[Wallet]:
- await (conn or db).execute(
+ return await (conn or db).execute(
"""
UPDATE wallets SET
name = ?
diff --git a/lnbits/core/models.py b/lnbits/core/models.py
index ab73b7020..0f7eba737 100644
--- a/lnbits/core/models.py
+++ b/lnbits/core/models.py
@@ -106,6 +106,8 @@ class Payment(BaseModel):
@property
def tag(self) -> Optional[str]:
+ if self.extra is None:
+ return ""
return self.extra.get("tag")
@property
diff --git a/lnbits/core/services.py b/lnbits/core/services.py
index 0b565ebb9..b9aec8997 100644
--- a/lnbits/core/services.py
+++ b/lnbits/core/services.py
@@ -109,18 +109,15 @@ async def pay_invoice(
raise ValueError("Amount in invoice is too high.")
# put all parameters that don't change here
- PaymentKwargs = TypedDict(
- "PaymentKwargs",
- {
- "wallet_id": str,
- "payment_request": str,
- "payment_hash": str,
- "amount": int,
- "memo": str,
- "extra": Optional[Dict],
- },
- )
- payment_kwargs: PaymentKwargs = dict(
+ class PaymentKwargs(TypedDict):
+ wallet_id: str
+ payment_request: str
+ payment_hash: str
+ amount: int
+ memo: str
+ extra: Optional[Dict]
+
+ payment_kwargs: PaymentKwargs = PaymentKwargs(
wallet_id=wallet_id,
payment_request=payment_request,
payment_hash=invoice.payment_hash,
@@ -272,6 +269,7 @@ async def perform_lnurlauth(
cb = urlparse(callback)
k1 = unhexlify(parse_qs(cb.query)["k1"][0])
+
key = wallet.wallet.lnurlauth_key(cb.netloc)
def int_to_bytes_suitable_der(x: int) -> bytes:
diff --git a/lnbits/core/tasks.py b/lnbits/core/tasks.py
index 5fea769d4..07b8a8933 100644
--- a/lnbits/core/tasks.py
+++ b/lnbits/core/tasks.py
@@ -55,7 +55,7 @@ async def dispatch_webhook(payment: Payment):
data = payment.dict()
try:
logger.debug("sending webhook", payment.webhook)
- r = await client.post(payment.webhook, json=data, timeout=40)
+ r = await client.post(payment.webhook, json=data, timeout=40) # type: ignore
await mark_webhook_sent(payment, r.status_code)
except (httpx.ConnectError, httpx.RequestError):
await mark_webhook_sent(payment, -1)
diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py
index bc3e759fa..b1366b077 100644
--- a/lnbits/core/views/api.py
+++ b/lnbits/core/views/api.py
@@ -3,7 +3,7 @@ import hashlib
import json
from binascii import unhexlify
from http import HTTPStatus
-from typing import Dict, List, Optional, Union
+from typing import Dict, List, Optional, Tuple, Union
from urllib.parse import ParseResult, parse_qs, urlencode, urlparse, urlunparse
import httpx
@@ -185,7 +185,7 @@ async def api_payments_create_invoice(data: CreateInvoiceData, wallet: Wallet):
assert (
data.lnurl_balance_check is not None
), "lnurl_balance_check is required"
- save_balance_check(wallet.id, data.lnurl_balance_check)
+ await save_balance_check(wallet.id, data.lnurl_balance_check)
async with httpx.AsyncClient() as client:
try:
@@ -248,7 +248,7 @@ async def api_payments_pay_invoice(bolt11: str, wallet: Wallet):
)
async def api_payments_create(
wallet: WalletTypeInfo = Depends(require_invoice_key),
- invoiceData: CreateInvoiceData = Body(...),
+ invoiceData: CreateInvoiceData = Body(...), # type: ignore
):
if invoiceData.out is True and wallet.wallet_type == 0:
if not invoiceData.bolt11:
@@ -291,7 +291,7 @@ async def api_payments_pay_lnurl(
timeout=40,
)
if r.is_error:
- raise httpx.ConnectError
+ raise httpx.ConnectError("LNURL callback connection error")
except (httpx.ConnectError, httpx.RequestError):
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
@@ -354,7 +354,7 @@ async def subscribe(request: Request, wallet: Wallet):
logger.debug("adding sse listener", payment_queue)
api_invoice_listeners.append(payment_queue)
- send_queue: asyncio.Queue[tuple[str, Payment]] = asyncio.Queue(0)
+ send_queue: asyncio.Queue[Tuple[str, Payment]] = asyncio.Queue(0)
async def payment_received() -> None:
while True:
@@ -393,16 +393,13 @@ async def api_payments_sse(
async def api_payment(payment_hash, X_Api_Key: Optional[str] = Header(None)):
# We use X_Api_Key here because we want this call to work with and without keys
# If a valid key is given, we also return the field "details", otherwise not
- wallet = None
- try:
- if X_Api_Key.extra:
- logger.warning("No key")
- except:
- wallet = await get_wallet_for_key(X_Api_Key)
+ wallet = await get_wallet_for_key(X_Api_Key) if type(X_Api_Key) == str else None
+
+ # we have to specify the wallet id here, because postgres and sqlite return internal payments in different order
+ # and get_standalone_payment otherwise just fetches the first one, causing unpredictable results
payment = await get_standalone_payment(
payment_hash, wallet_id=wallet.id if wallet else None
- ) # we have to specify the wallet id here, because postgres and sqlite return internal payments in different order
- # and get_standalone_payment otherwise just fetches the first one, causing unpredictable results
+ )
if payment is None:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Payment does not exist."
@@ -612,8 +609,8 @@ class ConversionData(BaseModel):
async def api_fiat_as_sats(data: ConversionData):
output = {}
if data.from_ == "sat":
- output["sats"] = int(data.amount)
output["BTC"] = data.amount / 100000000
+ output["sats"] = int(data.amount)
for currency in data.to.split(","):
output[currency.strip().upper()] = await satoshis_amount_as_fiat(
data.amount, currency.strip()
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 44666ce16..21572b285 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -55,9 +55,9 @@ async def home(request: Request, lightning: str = None):
)
async def extensions(
request: Request,
- user: User = Depends(check_user_exists),
- enable: str = Query(None),
- disable: str = Query(None),
+ user: User = Depends(check_user_exists), # type: ignore
+ enable: str = Query(None), # type: ignore
+ disable: str = Query(None), # type: ignore
):
extension_to_enable = enable
extension_to_disable = disable
@@ -88,7 +88,7 @@ async def extensions(
# Update user as his extensions have been updated
if extension_to_enable or extension_to_disable:
- user = await get_user(user.id)
+ user = await get_user(user.id) # type: ignore
return template_renderer().TemplateResponse(
"core/extensions.html", {"request": request, "user": user.dict()}
@@ -109,10 +109,10 @@ nothing: create everything
""",
)
async def wallet(
- request: Request = Query(None),
- nme: Optional[str] = Query(None),
- usr: Optional[UUID4] = Query(None),
- wal: Optional[UUID4] = Query(None),
+ request: Request = Query(None), # type: ignore
+ nme: Optional[str] = Query(None), # type: ignore
+ usr: Optional[UUID4] = Query(None), # type: ignore
+ wal: Optional[UUID4] = Query(None), # type: ignore
):
user_id = usr.hex if usr else None
wallet_id = wal.hex if wal else None
@@ -121,7 +121,7 @@ async def wallet(
if not user_id:
user = await get_user((await create_account()).id)
- logger.info(f"Create user {user.id}")
+ logger.info(f"Create user {user.id}") # type: ignore
else:
user = await get_user(user_id)
if not user:
@@ -135,22 +135,22 @@ async def wallet(
if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
user.admin = True
if not wallet_id:
- if user.wallets and not wallet_name:
- wallet = user.wallets[0]
+ if user.wallets and not wallet_name: # type: ignore
+ wallet = user.wallets[0] # type: ignore
else:
- wallet = await create_wallet(user_id=user.id, wallet_name=wallet_name)
+ wallet = await create_wallet(user_id=user.id, wallet_name=wallet_name) # type: ignore
logger.info(
- f"Created new wallet {wallet_name if wallet_name else '(no name)'} for user {user.id}"
+ f"Created new wallet {wallet_name if wallet_name else '(no name)'} for user {user.id}" # type: ignore
)
return RedirectResponse(
- f"/wallet?usr={user.id}&wal={wallet.id}",
+ f"/wallet?usr={user.id}&wal={wallet.id}", # type: ignore
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
)
logger.debug(f"Access wallet {wallet_name}{'of user '+ user.id if user else ''}")
- wallet = user.get_wallet(wallet_id)
- if not wallet:
+ userwallet = user.get_wallet(wallet_id) # type: ignore
+ if not userwallet:
return template_renderer().TemplateResponse(
"error.html", {"request": request, "err": "Wallet not found"}
)
@@ -159,10 +159,10 @@ async def wallet(
"core/wallet.html",
{
"request": request,
- "user": user.dict(),
- "wallet": wallet.dict(),
+ "user": user.dict(), # type: ignore
+ "wallet": userwallet.dict(),
"service_fee": service_fee,
- "web_manifest": f"/manifest/{user.id}.webmanifest",
+ "web_manifest": f"/manifest/{user.id}.webmanifest", # type: ignore
},
)
@@ -216,20 +216,20 @@ async def lnurl_full_withdraw_callback(request: Request):
@core_html_routes.get("/deletewallet", response_class=RedirectResponse)
-async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query(...)):
+async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query(...)): # type: ignore
user = await get_user(usr)
- user_wallet_ids = [u.id for u in user.wallets]
+ user_wallet_ids = [u.id for u in user.wallets] # type: ignore
if wal not in user_wallet_ids:
raise HTTPException(HTTPStatus.FORBIDDEN, "Not your wallet.")
else:
- await delete_wallet(user_id=user.id, wallet_id=wal)
+ await delete_wallet(user_id=user.id, wallet_id=wal) # type: ignore
user_wallet_ids.remove(wal)
logger.debug("Deleted wallet {wal} of user {user.id}")
if user_wallet_ids:
return RedirectResponse(
- url_for("/wallet", usr=user.id, wal=user_wallet_ids[0]),
+ url_for("/wallet", usr=user.id, wal=user_wallet_ids[0]), # type: ignore
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
)
@@ -242,7 +242,7 @@ async def deletewallet(request: Request, wal: str = Query(...), usr: str = Query
async def lnurl_balance_notify(request: Request, service: str):
bc = await get_balance_check(request.query_params.get("wal"), service)
if bc:
- redeem_lnurl_withdraw(bc.wallet, bc.url)
+ await redeem_lnurl_withdraw(bc.wallet, bc.url)
@core_html_routes.get(
@@ -252,7 +252,7 @@ async def lnurlwallet(request: Request):
async with db.connect() as conn:
account = await create_account(conn=conn)
user = await get_user(account.id, conn=conn)
- wallet = await create_wallet(user_id=user.id, conn=conn)
+ wallet = await create_wallet(user_id=user.id, conn=conn) # type: ignore
asyncio.create_task(
redeem_lnurl_withdraw(
@@ -265,7 +265,7 @@ async def lnurlwallet(request: Request):
)
return RedirectResponse(
- f"/wallet?usr={user.id}&wal={wallet.id}",
+ f"/wallet?usr={user.id}&wal={wallet.id}", # type: ignore
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index e65b9041a..6685cfb2d 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -1,4 +1,5 @@
from http import HTTPStatus
+from typing import Union
from cerberus import Validator # type: ignore
from fastapi import status
@@ -29,20 +30,21 @@ class KeyChecker(SecurityBase):
self._key_type = "invoice"
self._api_key = api_key
if api_key:
- self.model: APIKey = APIKey(
+ key = APIKey(
**{"in": APIKeyIn.query},
name="X-API-KEY",
description="Wallet API Key - QUERY",
)
else:
- self.model: APIKey = APIKey(
+ key = APIKey(
**{"in": APIKeyIn.header},
name="X-API-KEY",
description="Wallet API Key - HEADER",
)
- self.wallet = None
+ self.wallet = None # type: ignore
+ self.model: APIKey = key
- async def __call__(self, request: Request) -> Wallet:
+ async def __call__(self, request: Request):
try:
key_value = (
self._api_key
@@ -52,7 +54,7 @@ class KeyChecker(SecurityBase):
# FIXME: Find another way to validate the key. A fetch from DB should be avoided here.
# Also, we should not return the wallet here - thats silly.
# Possibly store it in a Redis DB
- self.wallet = await get_wallet_for_key(key_value, self._key_type)
+ self.wallet = await get_wallet_for_key(key_value, self._key_type) # type: ignore
if not self.wallet:
raise HTTPException(
status_code=HTTPStatus.UNAUTHORIZED,
@@ -120,8 +122,8 @@ api_key_query = APIKeyQuery(
async def get_key_type(
r: Request,
- api_key_header: str = Security(api_key_header),
- api_key_query: str = Security(api_key_query),
+ api_key_header: str = Security(api_key_header), # type: ignore
+ api_key_query: str = Security(api_key_query), # type: ignore
) -> WalletTypeInfo:
# 0: admin
# 1: invoice
@@ -134,9 +136,9 @@ async def get_key_type(
token = api_key_header if api_key_header else api_key_query
try:
- checker = WalletAdminKeyChecker(api_key=token)
- await checker.__call__(r)
- wallet = WalletTypeInfo(0, checker.wallet)
+ admin_checker = WalletAdminKeyChecker(api_key=token)
+ await admin_checker.__call__(r)
+ wallet = WalletTypeInfo(0, admin_checker.wallet) # type: ignore
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (
LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS
):
@@ -153,9 +155,9 @@ async def get_key_type(
raise
try:
- checker = WalletInvoiceKeyChecker(api_key=token)
- await checker.__call__(r)
- wallet = WalletTypeInfo(1, checker.wallet)
+ invoice_checker = WalletInvoiceKeyChecker(api_key=token)
+ await invoice_checker.__call__(r)
+ wallet = WalletTypeInfo(1, invoice_checker.wallet) # type: ignore
if (LNBITS_ADMIN_USERS and wallet.wallet.user not in LNBITS_ADMIN_USERS) and (
LNBITS_ADMIN_EXTENSIONS and pathname in LNBITS_ADMIN_EXTENSIONS
):
@@ -167,15 +169,16 @@ async def get_key_type(
if e.status_code == HTTPStatus.BAD_REQUEST:
raise
if e.status_code == HTTPStatus.UNAUTHORIZED:
- return WalletTypeInfo(2, None)
+ return WalletTypeInfo(2, None) # type: ignore
except:
raise
+ return wallet
async def require_admin_key(
r: Request,
- api_key_header: str = Security(api_key_header),
- api_key_query: str = Security(api_key_query),
+ api_key_header: str = Security(api_key_header), # type: ignore
+ api_key_query: str = Security(api_key_query), # type: ignore
):
token = api_key_header if api_key_header else api_key_query
@@ -193,8 +196,8 @@ async def require_admin_key(
async def require_invoice_key(
r: Request,
- api_key_header: str = Security(api_key_header),
- api_key_query: str = Security(api_key_query),
+ api_key_header: str = Security(api_key_header), # type: ignore
+ api_key_query: str = Security(api_key_query), # type: ignore
):
token = api_key_header if api_key_header else api_key_query
diff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py
index 45ee4de05..56e6b06ca 100644
--- a/lnbits/extensions/events/views_api.py
+++ b/lnbits/extensions/events/views_api.py
@@ -133,7 +133,8 @@ async def api_ticket_send_ticket(event_id, payment_hash, data: CreateTicket):
if not ticket:
raise HTTPException(
- status_code=HTTPStatus.NOT_FOUND, detail=f"Event could not be fetched."
+ status_code=HTTPStatus.NOT_FOUND,
+ detail=f"Event could not be fetched.",
)
return {"paid": True, "ticket_id": ticket.id}
diff --git a/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html b/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
index 4f921bb57..afe24c423 100644
--- a/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
+++ b/lnbits/extensions/lnurlpayout/templates/lnurlpayout/_api_docs.html
@@ -4,12 +4,7 @@
label="API info"
:content-inset-level="0.5"
>
-
+
@@ -38,7 +33,6 @@
expand-separator
label="Create a lnurlpayout"
>
-
List[Extension]:
- output = []
+ output: List[Extension] = []
if "all" in self._disabled:
return output
diff --git a/lnbits/tasks.py b/lnbits/tasks.py
index 86863f98f..f4d0a928d 100644
--- a/lnbits/tasks.py
+++ b/lnbits/tasks.py
@@ -66,7 +66,7 @@ async def webhook_handler():
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
-internal_invoice_queue = asyncio.Queue(0)
+internal_invoice_queue: asyncio.Queue = asyncio.Queue(0)
async def internal_invoice_listener():
diff --git a/lnbits/utils/exchange_rates.py b/lnbits/utils/exchange_rates.py
index 0432b364a..2801146b5 100644
--- a/lnbits/utils/exchange_rates.py
+++ b/lnbits/utils/exchange_rates.py
@@ -1,5 +1,5 @@
import asyncio
-from typing import Callable, NamedTuple
+from typing import Callable, List, NamedTuple
import httpx
from loguru import logger
@@ -227,10 +227,10 @@ async def btc_price(currency: str) -> float:
"TO": currency.upper(),
"to": currency.lower(),
}
- rates = []
- tasks = []
+ rates: List[float] = []
+ tasks: List[asyncio.Task] = []
- send_channel = asyncio.Queue()
+ send_channel: asyncio.Queue = asyncio.Queue()
async def controller():
failures = 0
diff --git a/lnbits/wallets/eclair.py b/lnbits/wallets/eclair.py
index c878d0d19..ab99c699d 100644
--- a/lnbits/wallets/eclair.py
+++ b/lnbits/wallets/eclair.py
@@ -7,7 +7,10 @@ from typing import AsyncGenerator, Dict, Optional
import httpx
from loguru import logger
-from websockets import connect
+
+# TODO: https://github.com/lnbits/lnbits-legend/issues/764
+# mypy https://github.com/aaugustin/websockets/issues/940
+from websockets import connect # type: ignore
from websockets.exceptions import (
ConnectionClosed,
ConnectionClosedError,
diff --git a/lnbits/wallets/fake.py b/lnbits/wallets/fake.py
index 3859d33c5..3126ee46a 100644
--- a/lnbits/wallets/fake.py
+++ b/lnbits/wallets/fake.py
@@ -28,7 +28,7 @@ class FakeWallet(Wallet):
logger.info(
"FakeWallet funding source is for using LNbits as a centralised, stand-alone payment system with brrrrrr."
)
- return StatusResponse(None, float("inf"))
+ return StatusResponse(None, 1000000000)
async def create_invoice(
self,
@@ -82,7 +82,7 @@ class FakeWallet(Wallet):
invoice = decode(bolt11)
if (
hasattr(invoice, "checking_id")
- and invoice.checking_id[6:] == data["privkey"][:6]
+ and invoice.checking_id[6:] == data["privkey"][:6] # type: ignore
):
return PaymentResponse(True, invoice.payment_hash, 0)
else:
@@ -97,7 +97,7 @@ class FakeWallet(Wallet):
return PaymentStatus(None)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
- self.queue = asyncio.Queue(0)
+ self.queue: asyncio.Queue = asyncio.Queue(0)
while True:
value = await self.queue.get()
yield value
diff --git a/lnbits/wallets/lnpay.py b/lnbits/wallets/lnpay.py
index 7171ec3fb..18b4f8bbe 100644
--- a/lnbits/wallets/lnpay.py
+++ b/lnbits/wallets/lnpay.py
@@ -119,7 +119,7 @@ class LNPayWallet(Wallet):
return PaymentStatus(statuses[r.json()["settled"]])
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
- self.queue = asyncio.Queue(0)
+ self.queue: asyncio.Queue = asyncio.Queue(0)
while True:
value = await self.queue.get()
yield value
diff --git a/lnbits/wallets/macaroon/macaroon.py b/lnbits/wallets/macaroon/macaroon.py
index 2183dacb8..091551238 100644
--- a/lnbits/wallets/macaroon/macaroon.py
+++ b/lnbits/wallets/macaroon/macaroon.py
@@ -73,10 +73,10 @@ class AESCipher(object):
final_key += key
return final_key[:output]
- def decrypt(self, encrypted: str) -> str:
+ def decrypt(self, encrypted: str) -> str: # type: ignore
"""Decrypts a string using AES-256-CBC."""
passphrase = self.passphrase
- encrypted = base64.b64decode(encrypted)
+ encrypted = base64.b64decode(encrypted) # type: ignore
assert encrypted[0:8] == b"Salted__"
salt = encrypted[8:16]
key_iv = self.bytes_to_key(passphrase.encode(), salt, 32 + 16)
@@ -84,7 +84,7 @@ class AESCipher(object):
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
try:
- return self.unpad(aes.decrypt(encrypted[16:])).decode()
+ return self.unpad(aes.decrypt(encrypted[16:])).decode() # type: ignore
except UnicodeDecodeError:
raise ValueError("Wrong passphrase")
diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py
index d503b4dd9..be82365dd 100644
--- a/lnbits/wallets/opennode.py
+++ b/lnbits/wallets/opennode.py
@@ -127,7 +127,7 @@ class OpenNodeWallet(Wallet):
return PaymentStatus(statuses[r.json()["data"]["status"]])
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
- self.queue = asyncio.Queue(0)
+ self.queue: asyncio.Queue = asyncio.Queue(0)
while True:
value = await self.queue.get()
yield value
diff --git a/mypy.ini b/mypy.ini
index 735f89e05..e5a974b51 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -1,7 +1,8 @@
[mypy]
ignore_missing_imports = True
-exclude = lnbits/wallets/lnd_grpc_files/
-exclude = lnbits/extensions/
-
+exclude = (?x)(
+ ^lnbits/extensions.
+ | ^lnbits/wallets/lnd_grpc_files.
+ )
[mypy-lnbits.wallets.lnd_grpc_files.*]
follow_imports = skip
diff --git a/result b/result
new file mode 120000
index 000000000..b0acd55c0
--- /dev/null
+++ b/result
@@ -0,0 +1 @@
+/nix/store/ds9c48q7hnkdmpzy3aq14kc1x9wrrszd-python3.9-lnbits-0.1.0
\ No newline at end of file
diff --git a/tests/core/views/test_api.py b/tests/core/views/test_api.py
index 6a5f82ecb..dfd2b32ae 100644
--- a/tests/core/views/test_api.py
+++ b/tests/core/views/test_api.py
@@ -1,6 +1,7 @@
import pytest
import pytest_asyncio
from lnbits.core.crud import get_wallet
+from lnbits.core.views.api import api_payment
from ...helpers import get_random_invoice_data
@@ -155,3 +156,26 @@ async def test_decode_invoice(client, invoice):
)
assert response.status_code < 300
assert response.json()["payment_hash"] == invoice["payment_hash"]
+
+
+# check api_payment() internal function call (NOT API): payment status
+@pytest.mark.asyncio
+async def test_api_payment_without_key(invoice):
+ # check the payment status
+ response = await api_payment(invoice["payment_hash"])
+ assert type(response) == dict
+ assert response["paid"] == True
+ # no key, that's why no "details"
+ assert "details" not in response
+
+
+# check api_payment() internal function call (NOT API): payment status
+@pytest.mark.asyncio
+async def test_api_payment_with_key(invoice, inkey_headers_from):
+ # check the payment status
+ response = await api_payment(
+ invoice["payment_hash"], inkey_headers_from["X-Api-Key"]
+ )
+ assert type(response) == dict
+ assert response["paid"] == True
+ assert "details" in response