├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md └── src └── solend ├── api.py ├── constant.py ├── schema.py ├── solana_rpc.py └── wallet.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 erg-trading 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | solana = "*" 8 | anchorpy = "*" 9 | borsh-construct = "*" 10 | numpy = "*" 11 | 12 | [dev-packages] 13 | 14 | [requires] 15 | python_version = "3.9" 16 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "a5fdfd44aee74f76ccdb6a33fbd388cedc212d4ccc8f6db3cc5a7ec17db5786d" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.9" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "anchorpy": { 20 | "hashes": [ 21 | "sha256:d977ada7b800507b05ebcec43f4dbcbbb1217e47cf3eda5cb30b32e47e997bc2", 22 | "sha256:dd1619e4322d9dbeeaafe648b5559cd6051b393cda62fe9694537ba6a529e563" 23 | ], 24 | "index": "pypi", 25 | "version": "==0.9.2" 26 | }, 27 | "anyio": { 28 | "hashes": [ 29 | "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b", 30 | "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be" 31 | ], 32 | "markers": "python_full_version >= '3.6.2'", 33 | "version": "==3.6.1" 34 | }, 35 | "apischema": { 36 | "hashes": [ 37 | "sha256:5e53830269d17a3586103c71d7961f23df5fe8844f93afbcc3e7a1a7cbac0c75", 38 | "sha256:b1ffcc19831fceb99c175ce53d81125bb46b8b22a019f4d8307f6d23f13e5647" 39 | ], 40 | "markers": "python_version >= '3.6'", 41 | "version": "==0.16.6" 42 | }, 43 | "attrs": { 44 | "hashes": [ 45 | "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", 46 | "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" 47 | ], 48 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 49 | "version": "==21.4.0" 50 | }, 51 | "based58": { 52 | "hashes": [ 53 | "sha256:0506435e98836cc16e095e0d6dc428810e0acfb44bc2f3ac3e23e051a69c0e3e", 54 | "sha256:06f3c40b358b0c6fc6fc614c43bb11ef851b6d04e519ac1eda2833420cb43799", 55 | "sha256:14b01d91ac250300ca7f634e5bf70fb2b1b9aaa90cc14357943c7da525a35aff", 56 | "sha256:2a9db744be79c8087eebedbffced00c608b3ed780668ab3c59f1d16e72c84947", 57 | "sha256:3fb17f0aaaad0381c8b676623c870c1a56aca039e2a7c8416e65904d80a415f7", 58 | "sha256:745851792ce5fada615f05ec61d7f360d19c76950d1e86163b2293c63a5d43bc", 59 | "sha256:80804b346b34196c89dc7a3dc89b6021f910f4cd75aac41d433ca1880b1672dc", 60 | "sha256:852c37206374a62c5d3ef7f6777746e2ad9106beec4551539e9538633385e613", 61 | "sha256:8937e97fa8690164fd11a7c642f6d02df58facd2669ae7355e379ab77c48c924", 62 | "sha256:ab85804a401a7b5a7141fbb14ef5b5f7d85288357d1d3f0085d47e616cef8f5a", 63 | "sha256:aba18f6c869fade1d1551fe398a376440771d6ce288c54cba71b7090cf08af02", 64 | "sha256:ae7f17b67bf0c209da859a6b833504aa3b19dbf423cbd2369aa17e89299dc972", 65 | "sha256:d8dece575de525c1ad889d9ab239defb7a6ceffc48f044fe6e14a408fb05bef4", 66 | "sha256:f8448a71678bd1edc0a464033695686461ab9d6d0bc3282cb29b94f883583572" 67 | ], 68 | "markers": "python_version >= '3.7'", 69 | "version": "==0.1.1" 70 | }, 71 | "borsh-construct": { 72 | "hashes": [ 73 | "sha256:c916758ceba70085d8f456a1cc26991b88cb64233d347767766473b651b37263", 74 | "sha256:f584c791e2a03f8fc36e6c13011a27bcaf028c9c54ba89cd70f485a7d1c687ed" 75 | ], 76 | "index": "pypi", 77 | "version": "==0.1.0" 78 | }, 79 | "cachetools": { 80 | "hashes": [ 81 | "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693", 82 | "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1" 83 | ], 84 | "markers": "python_version ~= '3.5'", 85 | "version": "==4.2.4" 86 | }, 87 | "certifi": { 88 | "hashes": [ 89 | "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", 90 | "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" 91 | ], 92 | "markers": "python_version >= '3.6'", 93 | "version": "==2022.6.15" 94 | }, 95 | "cffi": { 96 | "hashes": [ 97 | "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", 98 | "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", 99 | "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", 100 | "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", 101 | "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", 102 | "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", 103 | "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", 104 | "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", 105 | "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", 106 | "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", 107 | "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", 108 | "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", 109 | "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", 110 | "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", 111 | "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", 112 | "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", 113 | "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", 114 | "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", 115 | "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", 116 | "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", 117 | "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", 118 | "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", 119 | "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", 120 | "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", 121 | "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", 122 | "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", 123 | "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", 124 | "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", 125 | "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", 126 | "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", 127 | "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", 128 | "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", 129 | "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", 130 | "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", 131 | "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", 132 | "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", 133 | "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", 134 | "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", 135 | "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", 136 | "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", 137 | "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", 138 | "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", 139 | "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", 140 | "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", 141 | "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", 142 | "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", 143 | "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", 144 | "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", 145 | "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", 146 | "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" 147 | ], 148 | "version": "==1.15.0" 149 | }, 150 | "charset-normalizer": { 151 | "hashes": [ 152 | "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", 153 | "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" 154 | ], 155 | "markers": "python_version >= '3.5'", 156 | "version": "==2.0.12" 157 | }, 158 | "construct": { 159 | "hashes": [ 160 | "sha256:730235fedf4f2fee5cfadda1d14b83ef1bf23790fb1cc579073e10f70a050883" 161 | ], 162 | "markers": "python_version >= '3.6'", 163 | "version": "==2.10.67" 164 | }, 165 | "construct-typing": { 166 | "hashes": [ 167 | "sha256:26da1ed7383c5dfe7f38a43c6281ad06bce2059bf02d5a0d2cc3c0e52632c0bd", 168 | "sha256:553ecf36b44ae8d87e2f9c28a6fc8ffd75d050bd0b66ac72e433046c45b52116" 169 | ], 170 | "markers": "python_version >= '3.7'", 171 | "version": "==0.5.2" 172 | }, 173 | "h11": { 174 | "hashes": [ 175 | "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", 176 | "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" 177 | ], 178 | "markers": "python_version >= '3.6'", 179 | "version": "==0.12.0" 180 | }, 181 | "httpcore": { 182 | "hashes": [ 183 | "sha256:036f960468759e633574d7c121afba48af6419615d36ab8ede979f1ad6276fa3", 184 | "sha256:369aa481b014cf046f7067fddd67d00560f2f00426e79569d99cb11245134af0" 185 | ], 186 | "markers": "python_version >= '3.6'", 187 | "version": "==0.13.7" 188 | }, 189 | "httpx": { 190 | "hashes": [ 191 | "sha256:979afafecb7d22a1d10340bafb403cf2cb75aff214426ff206521fc79d26408c", 192 | "sha256:9f99c15d33642d38bce8405df088c1c4cfd940284b4290cacbfb02e64f4877c6" 193 | ], 194 | "markers": "python_version >= '3.6'", 195 | "version": "==0.18.2" 196 | }, 197 | "idna": { 198 | "hashes": [ 199 | "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", 200 | "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" 201 | ], 202 | "markers": "python_version >= '3.5'", 203 | "version": "==3.3" 204 | }, 205 | "iniconfig": { 206 | "hashes": [ 207 | "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", 208 | "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" 209 | ], 210 | "version": "==1.1.1" 211 | }, 212 | "jsonrpcclient": { 213 | "hashes": [ 214 | "sha256:c0d475494b3e1b591ecdee7883739accaf5695edb673f16b7383b8c6bbdb1ca3" 215 | ], 216 | "version": "==4.0.2" 217 | }, 218 | "jsonrpcserver": { 219 | "hashes": [ 220 | "sha256:b15d3fd043ad0c40b2ff17f7df2ddaec2e880bb923b40d133939a107c97fde5c" 221 | ], 222 | "version": "==5.0.7" 223 | }, 224 | "jsonschema": { 225 | "hashes": [ 226 | "sha256:1c92d2db1900b668201f1797887d66453ab1fbfea51df8e4b46236689c427baf", 227 | "sha256:9d6397ba4a6c0bf0300736057f649e3e12ecbc07d3e81a0dacb72de4e9801957" 228 | ], 229 | "markers": "python_version >= '3.7'", 230 | "version": "==4.6.0" 231 | }, 232 | "more-itertools": { 233 | "hashes": [ 234 | "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f", 235 | "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb" 236 | ], 237 | "markers": "python_version >= '3.5'", 238 | "version": "==8.13.0" 239 | }, 240 | "numpy": { 241 | "hashes": [ 242 | "sha256:0791fbd1e43bf74b3502133207e378901272f3c156c4df4954cad833b1380207", 243 | "sha256:1ce7ab2053e36c0a71e7a13a7475bd3b1f54750b4b433adc96313e127b870887", 244 | "sha256:2d487e06ecbf1dc2f18e7efce82ded4f705f4bd0cd02677ffccfb39e5c284c7e", 245 | "sha256:37431a77ceb9307c28382c9773da9f306435135fae6b80b62a11c53cfedd8802", 246 | "sha256:3e1ffa4748168e1cc8d3cde93f006fe92b5421396221a02f2274aab6ac83b077", 247 | "sha256:425b390e4619f58d8526b3dcf656dde069133ae5c240229821f01b5f44ea07af", 248 | "sha256:43a8ca7391b626b4c4fe20aefe79fec683279e31e7c79716863b4b25021e0e74", 249 | "sha256:4c6036521f11a731ce0648f10c18ae66d7143865f19f7299943c985cdc95afb5", 250 | "sha256:59d55e634968b8f77d3fd674a3cf0b96e85147cd6556ec64ade018f27e9479e1", 251 | "sha256:64f56fc53a2d18b1924abd15745e30d82a5782b2cab3429aceecc6875bd5add0", 252 | "sha256:7228ad13744f63575b3a972d7ee4fd61815b2879998e70930d4ccf9ec721dce0", 253 | "sha256:9ce7df0abeabe7fbd8ccbf343dc0db72f68549856b863ae3dd580255d009648e", 254 | "sha256:a911e317e8c826ea632205e63ed8507e0dc877dcdc49744584dfc363df9ca08c", 255 | "sha256:b89bf9b94b3d624e7bb480344e91f68c1c6c75f026ed6755955117de00917a7c", 256 | "sha256:ba9ead61dfb5d971d77b6c131a9dbee62294a932bf6a356e48c75ae684e635b3", 257 | "sha256:c1d937820db6e43bec43e8d016b9b3165dcb42892ea9f106c70fb13d430ffe72", 258 | "sha256:cc7f00008eb7d3f2489fca6f334ec19ca63e31371be28fd5dad955b16ec285bd", 259 | "sha256:d4c5d5eb2ec8da0b4f50c9a843393971f31f1d60be87e0fb0917a49133d257d6", 260 | "sha256:e96d7f3096a36c8754207ab89d4b3282ba7b49ea140e4973591852c77d09eb76", 261 | "sha256:f0725df166cf4785c0bc4cbfb320203182b1ecd30fee6e541c8752a92df6aa32", 262 | "sha256:f3eb268dbd5cfaffd9448113539e44e2dd1c5ca9ce25576f7c04a5453edc26fa", 263 | "sha256:fb7a980c81dd932381f8228a426df8aeb70d59bbcda2af075b627bbc50207cba" 264 | ], 265 | "index": "pypi", 266 | "version": "==1.22.4" 267 | }, 268 | "oslash": { 269 | "hashes": [ 270 | "sha256:868aeb58a656f2ed3b73d9dd6abe387b20b74fc9413d3e8653b615b15bf728f3", 271 | "sha256:89b978443b7db3ac2666106bdc3680add3c886a6d8fcdd02fd062af86d29494f" 272 | ], 273 | "version": "==0.6.3" 274 | }, 275 | "packaging": { 276 | "hashes": [ 277 | "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", 278 | "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" 279 | ], 280 | "markers": "python_version >= '3.6'", 281 | "version": "==21.3" 282 | }, 283 | "pluggy": { 284 | "hashes": [ 285 | "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", 286 | "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" 287 | ], 288 | "markers": "python_version >= '3.6'", 289 | "version": "==1.0.0" 290 | }, 291 | "psutil": { 292 | "hashes": [ 293 | "sha256:068935df39055bf27a29824b95c801c7a5130f118b806eee663cad28dca97685", 294 | "sha256:0904727e0b0a038830b019551cf3204dd48ef5c6868adc776e06e93d615fc5fc", 295 | "sha256:0f15a19a05f39a09327345bc279c1ba4a8cfb0172cc0d3c7f7d16c813b2e7d36", 296 | "sha256:19f36c16012ba9cfc742604df189f2f28d2720e23ff7d1e81602dbe066be9fd1", 297 | "sha256:20b27771b077dcaa0de1de3ad52d22538fe101f9946d6dc7869e6f694f079329", 298 | "sha256:28976df6c64ddd6320d281128817f32c29b539a52bdae5e192537bc338a9ec81", 299 | "sha256:29a442e25fab1f4d05e2655bb1b8ab6887981838d22effa2396d584b740194de", 300 | "sha256:3054e923204b8e9c23a55b23b6df73a8089ae1d075cb0bf711d3e9da1724ded4", 301 | "sha256:32c52611756096ae91f5d1499fe6c53b86f4a9ada147ee42db4991ba1520e574", 302 | "sha256:3a76ad658641172d9c6e593de6fe248ddde825b5866464c3b2ee26c35da9d237", 303 | "sha256:44d1826150d49ffd62035785a9e2c56afcea66e55b43b8b630d7706276e87f22", 304 | "sha256:4b6750a73a9c4a4e689490ccb862d53c7b976a2a35c4e1846d049dcc3f17d83b", 305 | "sha256:56960b9e8edcca1456f8c86a196f0c3d8e3e361320071c93378d41445ffd28b0", 306 | "sha256:57f1819b5d9e95cdfb0c881a8a5b7d542ed0b7c522d575706a80bedc848c8954", 307 | "sha256:58678bbadae12e0db55186dc58f2888839228ac9f41cc7848853539b70490021", 308 | "sha256:645bd4f7bb5b8633803e0b6746ff1628724668681a434482546887d22c7a9537", 309 | "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87", 310 | "sha256:79c9108d9aa7fa6fba6e668b61b82facc067a6b81517cab34d07a84aa89f3df0", 311 | "sha256:91c7ff2a40c373d0cc9121d54bc5f31c4fa09c346528e6a08d1845bce5771ffc", 312 | "sha256:9272167b5f5fbfe16945be3db475b3ce8d792386907e673a209da686176552af", 313 | "sha256:944c4b4b82dc4a1b805329c980f270f170fdc9945464223f2ec8e57563139cf4", 314 | "sha256:a6a11e48cb93a5fa606306493f439b4aa7c56cb03fc9ace7f6bfa21aaf07c453", 315 | "sha256:a8746bfe4e8f659528c5c7e9af5090c5a7d252f32b2e859c584ef7d8efb1e689", 316 | "sha256:abd9246e4cdd5b554a2ddd97c157e292ac11ef3e7af25ac56b08b455c829dca8", 317 | "sha256:b14ee12da9338f5e5b3a3ef7ca58b3cba30f5b66f7662159762932e6d0b8f680", 318 | "sha256:b88f75005586131276634027f4219d06e0561292be8bd6bc7f2f00bdabd63c4e", 319 | "sha256:c7be9d7f5b0d206f0bbc3794b8e16fb7dbc53ec9e40bbe8787c6f2d38efcf6c9", 320 | "sha256:d2d006286fbcb60f0b391741f520862e9b69f4019b4d738a2a45728c7e952f1b", 321 | "sha256:db417f0865f90bdc07fa30e1aadc69b6f4cad7f86324b02aa842034efe8d8c4d", 322 | "sha256:e7e10454cb1ab62cc6ce776e1c135a64045a11ec4c6d254d3f7689c16eb3efd2", 323 | "sha256:f65f9a46d984b8cd9b3750c2bdb419b2996895b005aefa6cbaba9a143b1ce2c5", 324 | "sha256:fea896b54f3a4ae6f790ac1d017101252c93f6fe075d0e7571543510f11d2676" 325 | ], 326 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 327 | "version": "==5.9.1" 328 | }, 329 | "py": { 330 | "hashes": [ 331 | "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", 332 | "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" 333 | ], 334 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 335 | "version": "==1.11.0" 336 | }, 337 | "pycparser": { 338 | "hashes": [ 339 | "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", 340 | "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" 341 | ], 342 | "version": "==2.21" 343 | }, 344 | "pyheck": { 345 | "hashes": [ 346 | "sha256:0fb50b7d899d2a583ec2ac291b8ec2afb10f0e32c4ac290148d3da15927787f8", 347 | "sha256:1501fcfd15f7c05c6bfe38915f5e514ac95fc63e945f7d8b089d30c1b8fdb2c5", 348 | "sha256:316a842b94beff6e59a97dbcc590e9be92a932e59126b0faa9ac750384f27eaf", 349 | "sha256:44caf2b7a49d71fdeb0469e9f35886987ad815a8638b3c5b5c83f351d6aed413", 350 | "sha256:5b6169397395ff041f056bfb36c1957a788a1cd7cb967a927fcae7917ff1b6aa", 351 | "sha256:5c9fe372d540c5dbcb76bf062f951d998d0e14c906c842a52f1cd5de208e183a", 352 | "sha256:64201a6d213bec443aeb33f66c60cea61aaf6257e48a19159ac69a5afad4768e", 353 | "sha256:69387b70d910637ab6dc8dc378c8e0b4037cee2c51a9c6f64ce5331b010f5de3", 354 | "sha256:69d6509138909df92b2f2f837518dca118ef08ae3c804044ae511b81b7aecb4d", 355 | "sha256:8ce4a2e1b4778051b8f31183e321a034603f3957b6e95cf03bf5f231c8ea3066", 356 | "sha256:aa8dfd0883212f8495e0bae6eb6ea670c56f9b197b5fe6fb5cae9fd5ec56fb7c", 357 | "sha256:e519f80a0ef87a8f880bfdf239e396e238dcaed34bec1ea7ef526c4873220e82", 358 | "sha256:e9ba36060abc55127c3813de398b4013c05be6118cfae3cfa3d978f7b4c84dea", 359 | "sha256:e9d101e1c599227280e34eeccab0414246e70a91a1cabb4c4868dca284f2be7d" 360 | ], 361 | "markers": "python_version >= '3.7'", 362 | "version": "==0.1.5" 363 | }, 364 | "pynacl": { 365 | "hashes": [ 366 | "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858", 367 | "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d", 368 | "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93", 369 | "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1", 370 | "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92", 371 | "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff", 372 | "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba", 373 | "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394", 374 | "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b", 375 | "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543" 376 | ], 377 | "markers": "python_version >= '3.6'", 378 | "version": "==1.5.0" 379 | }, 380 | "pyparsing": { 381 | "hashes": [ 382 | "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", 383 | "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" 384 | ], 385 | "markers": "python_full_version >= '3.6.8'", 386 | "version": "==3.0.9" 387 | }, 388 | "pyrsistent": { 389 | "hashes": [ 390 | "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c", 391 | "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc", 392 | "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e", 393 | "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26", 394 | "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec", 395 | "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286", 396 | "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045", 397 | "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec", 398 | "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8", 399 | "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c", 400 | "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca", 401 | "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22", 402 | "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a", 403 | "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96", 404 | "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc", 405 | "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1", 406 | "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07", 407 | "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6", 408 | "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b", 409 | "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5", 410 | "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6" 411 | ], 412 | "markers": "python_version >= '3.7'", 413 | "version": "==0.18.1" 414 | }, 415 | "pytest": { 416 | "hashes": [ 417 | "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89", 418 | "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134" 419 | ], 420 | "markers": "python_version >= '3.6'", 421 | "version": "==6.2.5" 422 | }, 423 | "pytest-asyncio": { 424 | "hashes": [ 425 | "sha256:6d895b02432c028e6957d25fc936494e78c6305736e785d9fee408b1efbc7ff4", 426 | "sha256:e0fe5dbea40516b661ef1bcfe0bd9461c2847c4ef4bb40012324f2454fb7d56d" 427 | ], 428 | "markers": "python_version >= '3.7'", 429 | "version": "==0.17.2" 430 | }, 431 | "pytest-xprocess": { 432 | "hashes": [ 433 | "sha256:6f2aba817d842518d9d9dfb7e9adfe2a6e354a4359f4166bef0822ef4be1c9db", 434 | "sha256:fd9f30ed1584b5833bc34494748adf0fb9de3ca7bacc4e88ad71989c21cba266" 435 | ], 436 | "markers": "python_version >= '3.5'", 437 | "version": "==0.18.1" 438 | }, 439 | "requests": { 440 | "hashes": [ 441 | "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f", 442 | "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b" 443 | ], 444 | "markers": "python_version >= '3.7' and python_version < '4.0'", 445 | "version": "==2.28.0" 446 | }, 447 | "rfc3986": { 448 | "extras": [ 449 | "idna2008" 450 | ], 451 | "hashes": [ 452 | "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", 453 | "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" 454 | ], 455 | "version": "==1.5.0" 456 | }, 457 | "sniffio": { 458 | "hashes": [ 459 | "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", 460 | "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" 461 | ], 462 | "markers": "python_version >= '3.5'", 463 | "version": "==1.2.0" 464 | }, 465 | "solana": { 466 | "hashes": [ 467 | "sha256:57c98be97d944440146780a4e175c0dbf50a988d75f05d81b5083620bf4331b0", 468 | "sha256:6c43a6013bc0b5358cafd94a4fa091d30f7917fe578960329a8977b9dd1b21a5" 469 | ], 470 | "index": "pypi", 471 | "version": "==0.23.2" 472 | }, 473 | "sumtypes": { 474 | "hashes": [ 475 | "sha256:1a6ff095e06a1885f340ddab803e0f38e3f9bed81f9090164ca9682e04e96b43", 476 | "sha256:3e9d71322dd927d25d935072f8be7daec655ea292fd392359a5bb2c1e53dfdc3" 477 | ], 478 | "version": "==0.1a6" 479 | }, 480 | "toml": { 481 | "hashes": [ 482 | "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", 483 | "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" 484 | ], 485 | "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", 486 | "version": "==0.10.2" 487 | }, 488 | "toolz": { 489 | "hashes": [ 490 | "sha256:6b312d5e15138552f1bda8a4e66c30e236c831b612b2bf0005f8a1df10a4bc33", 491 | "sha256:a5700ce83414c64514d82d60bcda8aabfde092d1c1a8663f9200c07fdcc6da8f" 492 | ], 493 | "markers": "python_version >= '3.5'", 494 | "version": "==0.11.2" 495 | }, 496 | "types-cachetools": { 497 | "hashes": [ 498 | "sha256:48301115189d4879d0960baac5a8a2b2d31ce6129b2ce3b915000ed337284898", 499 | "sha256:b1cb18aaff25d2ad47a060413c660c39fadddb01f72012dd1134584b1fdaada5" 500 | ], 501 | "version": "==4.2.10" 502 | }, 503 | "typing-extensions": { 504 | "hashes": [ 505 | "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", 506 | "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" 507 | ], 508 | "markers": "python_version >= '3.7'", 509 | "version": "==4.2.0" 510 | }, 511 | "urllib3": { 512 | "hashes": [ 513 | "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14", 514 | "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e" 515 | ], 516 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", 517 | "version": "==1.26.9" 518 | }, 519 | "websockets": { 520 | "hashes": [ 521 | "sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af", 522 | "sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c", 523 | "sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76", 524 | "sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47", 525 | "sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69", 526 | "sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079", 527 | "sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c", 528 | "sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55", 529 | "sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02", 530 | "sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559", 531 | "sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3", 532 | "sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e", 533 | "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978", 534 | "sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98", 535 | "sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae", 536 | "sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755", 537 | "sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d", 538 | "sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991", 539 | "sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1", 540 | "sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680", 541 | "sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247", 542 | "sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f", 543 | "sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2", 544 | "sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7", 545 | "sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4", 546 | "sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667", 547 | "sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb", 548 | "sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094", 549 | "sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36", 550 | "sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79", 551 | "sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500", 552 | "sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e", 553 | "sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582", 554 | "sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442", 555 | "sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd", 556 | "sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6", 557 | "sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731", 558 | "sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4", 559 | "sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d", 560 | "sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8", 561 | "sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f", 562 | "sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677", 563 | "sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8", 564 | "sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9", 565 | "sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e", 566 | "sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b", 567 | "sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916", 568 | "sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4" 569 | ], 570 | "markers": "python_version >= '3.7'", 571 | "version": "==10.3" 572 | }, 573 | "zstandard": { 574 | "hashes": [ 575 | "sha256:208fa6bead577b2607205640078ee452e81fe20fe96321623c632bad9ebd7148", 576 | "sha256:2a2ac752162ba5cbc869c60c4a4e54e890b2ee2ffb57d3ff159feab1ae4518db", 577 | "sha256:37e50501baaa935f13a1820ab2114f74313b5cb4cfff8146acb8c5b18cdced2a", 578 | "sha256:3cf96ace804945e53bc3e5294097e5fa32a2d43bc52416c632b414b870ee0a21", 579 | "sha256:42f3c02c7021073cafbc6cd152b288c56a25e585518861589bb08b063b6d2ad2", 580 | "sha256:4768449d8d1b0785309ace288e017cc5fa42e11a52bf08c90d9c3eb3a7a73cc6", 581 | "sha256:477f172807a9fa83467b30d7c58876af1410d20177c554c27525211edf535bae", 582 | "sha256:49cd09ccbd1e3c0e2690dd62ebf95064d84aa42b9db381867e0b138631f969f2", 583 | "sha256:59eadb9f347d40e8f7ef77caffd0c04a31e82c1df82fe2d2a688032429d750ac", 584 | "sha256:60943f71e3117583655a1eb76188a7cc78a25267ef09cc74be4d25a0b0c8b947", 585 | "sha256:787efc741e61e00ffe5e65dac99b0dc5c88b9421012a207a91b869a8b1164921", 586 | "sha256:7a3a1aa9528087f6f4c47f4ece2d5e6a160527821263fb8174ff36429233e093", 587 | "sha256:7d2e7abac41d2b4b18f03575aca860d2cb647c343e13c23d6c769106a3db2f6f", 588 | "sha256:802109f67328c5b822d4fdac28e1cf65a24de2e2e99d76cdbeee9121cedb1b6c", 589 | "sha256:8aedd38d357f6d5e2facd88ce62b4976afdc29db57216a23f14a0cd0ca05a8a3", 590 | "sha256:8fd386d0ec1f9343f1776391d9e60d4eedced0a0b0e625bb89b91f6d05f70e83", 591 | "sha256:90a9ba3a9c16b86afcb785b3c9418af39ccfb238fd5f6e429166e3ca8542b01f", 592 | "sha256:91a228a077fc7cd8486c273788d4a006a37d060cb4293f471eb0325c3113af68", 593 | "sha256:9cf18c156b3a108197a8bf90b37d03c31c8ef35a7c18807b321d96b74e12c301", 594 | "sha256:9ec62a4c2dbb0a86ee5138c16ef133e59a23ac108f8d7ac97aeb61d410ce6857", 595 | "sha256:a1991cdf2e81e643b53fb8d272931d2bdf5f4e70d56a457e1ef95bde147ae627", 596 | "sha256:a628f20d019feb0f3a171c7a55cc4f75681f3b8c1bd7a5009165a487314887cd", 597 | "sha256:a71809ec062c5b7acf286ba6d4484e6fe8130fc2b93c25e596bb34e7810c79b2", 598 | "sha256:a7756a9446f83c81101f6c0a48c3bfd8d387a249933c57b0d095ca8b20541337", 599 | "sha256:a827b9c464ee966524f8e82ec1aabb4a77ff9514cae041667fa81ae2ec8bd3e9", 600 | "sha256:b1ad6d2952b41d9a0ea702a474cc08c05210c6289e29dd496935c9ca3c7fb45c", 601 | "sha256:b4e671c4c0804cdf752be26f260058bb858fbdaaef1340af170635913ecca01e", 602 | "sha256:bd842ae3dbb7cba88beb022161c819fa80ca7d0c5a4ddd209e7daae85d904e49", 603 | "sha256:bdf691a205bc492956e6daef7a06fb38f8cbe8b2c1cb0386f35f4412c360c9e9", 604 | "sha256:c19d1e06569c277dcc872d80cbadf14a29e8199e013ff2a176d169f461439a40", 605 | "sha256:c81fd9386449df0ebf1ab3e01187bb30d61122c74df53ba4880a2454d866e55d", 606 | "sha256:d0e9fec68e304fb35c559c44530213adbc7d5918bdab906a45a0f40cd56c4de2", 607 | "sha256:d1405caa964ba11b2396bd9fd19940440217345752e192c936d084ba5fe67dcb", 608 | "sha256:d5373a56b90052f171c8634fedc53a6ac371e6c742606e9825772a394bdbd4b0", 609 | "sha256:d78aac2ffc4e88ab1cbcad844669924c24e24c7c255de9628a18f14d832007c5", 610 | "sha256:d916018289d2f9a882e90d2e3bd41652861ce11b5ecd8515fa07ad31d97d56e5", 611 | "sha256:db993a56e21d903893933887984ca9b0d274f2b1db7b3cf21ba129783953864f", 612 | "sha256:de1aa618306a741e0497878b7f845fd6c397e52dd096fb76ed791e7268887176", 613 | "sha256:e37c4e21f696d6bcdbbc7caf98dffa505d04c0053909b9db0a6e8ca3b935eb07", 614 | "sha256:ef62eb3bcfd6d786f439828bb544ebd3936432db669403e0b8f48e424f1d55f1", 615 | "sha256:f0c87f097d6867833a839b086eb8d03676bb87c2efa067a131099f04aa790683", 616 | "sha256:f2e3ea5e4d5ecf3faefd4a5294acb6af1f0578b0cdd75d6b4529c45deaa54d6f", 617 | "sha256:f502fe79757434292174b04db114f9e25c767b2d5ca9e759d118b22a66f445f8", 618 | "sha256:fa9194cb91441df7242aa3ddc4cb184be38876cb10dd973674887f334bafbfb6" 619 | ], 620 | "markers": "python_version >= '3.6'", 621 | "version": "==0.17.0" 622 | } 623 | }, 624 | "develop": {} 625 | } 626 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solend Python Explorer 2 | A python library for interacting with solend. In current state this library provides the ability to parse the position of a wallet. 3 | 4 | Usage 5 | 6 | ``` 7 | from solend.wallet import fetch_obligation_by_wallet 8 | fetch_obligation_by_wallet("3oSE9CtGMQeAdtkm2U3ENhEpkFMfvrckJMA8QwVsuRbE") 9 | ``` 10 | Output 11 | ``` 12 | { 13 | "deposits": [ 14 | { 15 | "asset": "SOL", 16 | "amount": 4000016.620523712 17 | } 18 | ], 19 | "borrows": [ 20 | { 21 | "asset": "USDT", 22 | "amount": 0.49660628370575016 23 | }, 24 | { 25 | "asset": "USDC", 26 | "amount": 72833116.89264491 27 | } 28 | ], 29 | "liquidation_threshold": 12022575880.969307, 30 | "user_total_deposit": 141442069.1878742, 31 | "user_total_borrow": 72833135.5969685, 32 | "borrow_limit": 106081551.89090565, 33 | "borrow_utilization": 0.6865768297947805, 34 | "net_account_value": 68608933.5909057 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /src/solend/api.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from urllib.parse import urljoin 3 | 4 | 5 | def solend_market_config(deployment="production", 6 | solend_api="https://api.solend.fi" 7 | ): 8 | response = requests.get(urljoin(solend_api, f"/v1/config?deployment={deployment}")) 9 | if response.status_code == 200: 10 | config = response.json() 11 | return config 12 | else: 13 | raise Exception(f"Solend API Status Code: {response.status_code} | {response.text}") -------------------------------------------------------------------------------- /src/solend/constant.py: -------------------------------------------------------------------------------- 1 | WAD = 1000000000000000000 2 | -------------------------------------------------------------------------------- /src/solend/schema.py: -------------------------------------------------------------------------------- 1 | from borsh_construct import CStruct, U8, U64, U128 2 | from anchorpy.borsh_extension import BorshPubkey, Padding 3 | 4 | 5 | RESERVE_SCHEMA = CStruct( 6 | "version" / U8, 7 | "slot" / U64, 8 | "stale" / U8, 9 | "lendingMarket" / BorshPubkey, 10 | "liquidityMintPubkey" / BorshPubkey, 11 | "liquidityMintDecimals" / U8, 12 | "liquiditySupplyPubkey" / BorshPubkey, 13 | "pythOracle" / BorshPubkey, 14 | "switchboardOracle" / BorshPubkey, 15 | "availableAmount" / U64, 16 | "borrowedAmountWads" / U128, 17 | "cumulativeBorrowRateWads" / U128, 18 | "marketPrice" / U128, 19 | "collateralMintPubkey" / BorshPubkey, 20 | "collateralMintTotalSupply" / U64, 21 | "collateralSupplyPubkey" / BorshPubkey, 22 | "optimalUtilizationRate" / U8, 23 | "loanToValueRatio" / U8, 24 | "liquidationBonus" / U8, 25 | "liquidationThreshold" / U8, 26 | "minBorrowRate" / U8, 27 | "optimalBorrowRate" / U8, 28 | "maxBorrowRate" / U8, 29 | "borrowFeeWad" / U64, 30 | "flashLoanFeeWad" / U64, 31 | "hostFeePercentage" / U8, 32 | "depositLimit" / U64, 33 | "borrowLimit" / U64, 34 | "feeReceiver" / BorshPubkey 35 | ) 36 | 37 | DEPOSIT_SCHEMA = CStruct( 38 | "depositReserve" / BorshPubkey, 39 | "depositedAmount" / U64, 40 | "marketValue" / U128, 41 | "padding" / Padding(32) 42 | ) 43 | 44 | BORROW_SCHEMA = CStruct( 45 | "borrowReserve" / BorshPubkey, 46 | "cumulativeBorrowRateWads" / U128, 47 | "borrowAmountWads" / U128, 48 | "marketValue" / U128, 49 | "padding" / Padding(32) 50 | ) 51 | 52 | ACCOUNT_SCHEMA = CStruct( 53 | "version" / U8, 54 | "slot" / U64, 55 | "stale" / U8, 56 | "lendingMarket"/ BorshPubkey, 57 | "owner" / BorshPubkey, 58 | "depositedValue" / U128, 59 | "borrowedValue" / U128, 60 | "allowedBorrowValue" / U128, 61 | "unhealthyBorrowValue" / U128, 62 | "padding" / Padding(64), 63 | "depositsLen" / U8, 64 | "borrowsLen" / U8, 65 | "deposits" / DEPOSIT_SCHEMA[lambda this: this.depositsLen], 66 | "borrows" / BORROW_SCHEMA[lambda this: this.borrowsLen] 67 | ) 68 | 69 | INSTRUCTION_SCHEMA = CStruct( 70 | "instruction" / U8 71 | ) 72 | 73 | LIQUIDATION_INSTRUCTION_SCHEMA = CStruct( 74 | "instruction" / U8, 75 | "liquidityAmount" / U64 76 | ) 77 | -------------------------------------------------------------------------------- /src/solend/solana_rpc.py: -------------------------------------------------------------------------------- 1 | from solana.utils.helpers import decode_byte_string 2 | from solana.rpc.api import Client, MemcmpOpt 3 | 4 | 5 | def query_solana_account( 6 | account, 7 | layout=None, 8 | solana_http_rpc="https://api.mainnet-beta.solana.com" 9 | ): 10 | http_client = Client(endpoint=solana_http_rpc) 11 | account_info = http_client.get_account_info(account) 12 | data = account_info["result"]["value"]["data"][0] 13 | data = decode_byte_string(data) 14 | if layout: 15 | data = layout.parse(data) 16 | return data 17 | 18 | 19 | def get_program_accounts( 20 | address, 21 | data_size, 22 | memcmp_offset, 23 | memcmp_bytes, 24 | encoding="base64", 25 | solana_rpc="https://api.mainnet-beta.solana.com", 26 | timeout=60 27 | ): 28 | http_client = Client(endpoint=solana_rpc, timeout=timeout) 29 | memcmp_opts = [MemcmpOpt(offset=memcmp_offset, bytes=memcmp_bytes)] 30 | data = http_client.get_program_accounts( 31 | pubkey=address, 32 | encoding=encoding, 33 | data_size=data_size, 34 | memcmp_opts=memcmp_opts 35 | ) 36 | return data 37 | 38 | 39 | if __name__ == "__main__": 40 | program_account = "So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo" 41 | main_pool = "4UpD2fh7xH3VP9QQaXtsS1YY3bxzWhtfpks7FatyKvdY" 42 | data = get_program_accounts(program_account, 619, 10, main_pool) 43 | print(data) 44 | -------------------------------------------------------------------------------- /src/solend/wallet.py: -------------------------------------------------------------------------------- 1 | from solend.api import solend_market_config 2 | from solend.solana_rpc import query_solana_account 3 | from solend.schema import ACCOUNT_SCHEMA, RESERVE_SCHEMA 4 | from solend.constant import WAD 5 | from solana.publickey import PublicKey 6 | import numpy as np 7 | 8 | 9 | def solend_wallet_account_state( 10 | wallet_address, 11 | market="main", 12 | deployment="production", 13 | solend_api="https://api.solend.fi", 14 | solana_http_rpc="https://api.mainnet-beta.solana.com", 15 | ): 16 | config = solend_market_config(deployment, solend_api) 17 | market_metadata = next((m for m in config["markets"] if m["name"] == market)) 18 | if market_metadata: 19 | market_address = market_metadata["address"] 20 | program_id = config["programID"] 21 | account_address = PublicKey.create_with_seed(PublicKey(wallet_address), 22 | market_address[0:32], 23 | PublicKey(program_id)) 24 | data = query_solana_account(account_address, layout=ACCOUNT_SCHEMA, solana_http_rpc=solana_http_rpc) 25 | return data 26 | 27 | 28 | def compute_deposit_quantity(deposit, reserve): 29 | total_borrow_wads = reserve.borrowedAmountWads 30 | total_supply_wads = reserve.availableAmount * WAD 31 | total_deposit_wads = total_borrow_wads + total_supply_wads 32 | c_token_exchange_rate = total_deposit_wads / reserve.collateralMintTotalSupply / WAD 33 | amount = np.floor(deposit.depositedAmount * c_token_exchange_rate) 34 | amount = amount / 10**reserve.liquidityMintDecimals 35 | return amount 36 | 37 | 38 | def compute_borrow_quantity(borrow, reserve): 39 | amount = borrow.borrowAmountWads * \ 40 | reserve.cumulativeBorrowRateWads / borrow.cumulativeBorrowRateWads / WAD 41 | amount = amount / 10**reserve.liquidityMintDecimals 42 | return amount 43 | 44 | 45 | def load_price(reserve): 46 | return reserve.marketPrice / WAD 47 | 48 | 49 | def load_reserve(address, market_metadata, solana_rpc): 50 | config = next((m for m in market_metadata["reserves"] if m["address"] == str(address))) 51 | reserve = query_solana_account(config["address"], layout=RESERVE_SCHEMA, solana_http_rpc=solana_rpc) 52 | return reserve, config["asset"] 53 | 54 | 55 | def calculate_positions( 56 | account_payload, 57 | market_metadata, 58 | solana_rpc 59 | ): 60 | user_total_deposit = 0 61 | user_total_borrow = 0 62 | borrow_limit = 0 63 | liquidation_threshold = 0 64 | deposits_parsed = [] 65 | borrows_parsed = [] 66 | 67 | for deposit in account_payload.deposits: 68 | reserve, asset = load_reserve(deposit.depositReserve, market_metadata, solana_rpc) 69 | 70 | ltv = reserve.loanToValueRatio / 100 71 | liq_threshold = reserve.liquidationThreshold / 100 72 | supply_amount = compute_deposit_quantity(deposit, reserve) 73 | price = load_price(reserve) 74 | 75 | supply_amount_usd = supply_amount * price 76 | user_total_deposit += supply_amount_usd 77 | borrow_limit += supply_amount_usd * ltv 78 | liquidation_threshold += supply_amount_usd * liq_threshold 79 | deposits_parsed.append({ 80 | "asset": asset, 81 | "amount": supply_amount, 82 | "amount_usd": supply_amount_usd 83 | }) 84 | 85 | for borrow in account_payload.borrows: 86 | reserve, asset = load_reserve(borrow.borrowReserve, market_metadata, solana_rpc) 87 | borrow_amount = compute_borrow_quantity(borrow, reserve) 88 | price = load_price(reserve) 89 | 90 | borrow_amount_usd = borrow_amount * price 91 | user_total_borrow += borrow_amount_usd 92 | borrows_parsed.append({ 93 | "asset": asset, 94 | "amount": borrow_amount, 95 | "amount_usd": borrow_amount_usd 96 | }) 97 | 98 | return { 99 | "deposits": deposits_parsed, 100 | "borrows": borrows_parsed, 101 | "liquidation_threshold": liquidation_threshold, 102 | "user_total_deposit": user_total_deposit, 103 | "user_total_borrow": user_total_borrow, 104 | "borrow_limit": borrow_limit, 105 | "borrow_utilization": user_total_borrow / borrow_limit if borrow_limit else np.nan, 106 | "net_account_value": user_total_deposit - user_total_borrow 107 | } 108 | 109 | 110 | def fetch_obligation_by_wallet( 111 | address, 112 | market="main", 113 | deployment="production", 114 | solend_api="https://api.solend.fi", 115 | solana_rpc="https://api.mainnet-beta.solana.com", 116 | ): 117 | config = solend_market_config(deployment, solend_api) 118 | market_metadata = next((m for m in config["markets"] if m["name"] == market)) 119 | account_payload = solend_wallet_account_state(address, market, deployment, solend_api, solana_rpc) 120 | 121 | obligation = calculate_positions(account_payload, market_metadata, solana_rpc) 122 | return obligation 123 | 124 | 125 | if __name__ == "__main__": 126 | obligation = fetch_obligation_by_wallet("3oSE9CtGMQeAdtkm2U3ENhEpkFMfvrckJMA8QwVsuRbE") 127 | print(obligation) --------------------------------------------------------------------------------