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