|
| 1 | +import pytest |
| 2 | + |
| 3 | +from pythclient.pythaccounts import ( |
| 4 | + PythPriceAccount, |
| 5 | + PythPriceType, |
| 6 | + PythPriceStatus, |
| 7 | + PythProductAccount, |
| 8 | +) |
| 9 | +from pythclient.solana import SolanaPublicKey |
| 10 | + |
| 11 | + |
| 12 | +# Yes, this sucks, but it is actually a monster datastructure (2K) |
| 13 | +@pytest.fixture |
| 14 | +def price_account_bytes(): |
| 15 | + return bytes([ |
| 16 | + 1, 0, 0, 0, 248, 255, 255, 255, 19, 0, 0, 0, 16, 0, 0, 0, 219, |
| 17 | + 169, 82, 6, 0, 0, 0, 0, 218, 169, 82, 6, 0, 0, 0, 0, 120, 92, |
| 18 | + 108, 119, 16, 0, 0, 0, 159, 58, 142, 201, 0, 0, 0, 0, 220, 33, |
| 19 | + 254, 28, 1, 0, 0, 0, 250, 57, 21, 3, 0, 0, 0, 0, 28, 243, 103, |
| 20 | + 147, 0, 0, 0, 0, 220, 33, 254, 28, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, |
| 21 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 214, 3, 61, 115, 62, 39, 149, |
| 22 | + 12, 46, 3, 81, 226, 80, 84, 145, 205, 145, 84, 130, 79, 113, |
| 23 | + 109, 149, 19, 81, 76, 116, 185, 249, 143, 88, 0, 0, 0, 0, 0, 0, |
| 24 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 25 | + 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 32, 31, 203, 118, |
| 26 | + 16, 0, 0, 0, 196, 42, 45, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 27 | + 0, 32, 31, 203, 118, 16, 0, 0, 0, 228, 239, 46, 2, 0, 0, 0, 0, |
| 28 | + 1, 0, 0, 0, 0, 0, 0, 0, 219, 169, 82, 6, 0, 0, 0, 0, 247, 102, |
| 29 | + 125, 187, 141, 124, 211, 23, 33, 137, 65, 74, 35, 194, 107, 82, |
| 30 | + 29, 140, 25, 198, 69, 4, 85, 85, 227, 226, 142, 130, 86, 142, |
| 31 | + 101, 120, 96, 88, 157, 118, 16, 0, 0, 0, 96, 16, 72, 1, 0, 0, 0, |
| 32 | + 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, 96, 88, |
| 33 | + 157, 118, 16, 0, 0, 0, 96, 16, 72, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, |
| 34 | + 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 22, 15, 186, 193, 58, 247, |
| 35 | + 221, 216, 5, 211, 23, 10, 61, 224, 198, 189, 151, 18, 106, 30, |
| 36 | + 2, 192, 210, 89, 208, 168, 110, 248, 33, 214, 229, 199, 32, 31, |
| 37 | + 203, 118, 16, 0, 0, 0, 11, 37, 238, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, |
| 38 | + 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, 32, 31, 203, 118, 16, 0, |
| 39 | + 0, 0, 11, 37, 238, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, |
| 40 | + 169, 82, 6, 0, 0, 0, 0, 5, 210, 6, 79, 51, 28, 255, 221, 202, |
| 41 | + 190, 150, 250, 54, 85, 36, 221, 100, 244, 179, 134, 232, 133, |
| 42 | + 163, 77, 21, 44, 190, 174, 4, 44, 234, 245, 200, 28, 60, 113, |
| 43 | + 16, 0, 0, 0, 84, 1, 125, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, |
| 44 | + 217, 169, 82, 6, 0, 0, 0, 0, 200, 28, 60, 113, 16, 0, 0, 0, 84, |
| 45 | + 1, 125, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 218, 169, 82, 6, |
| 46 | + 0, 0, 0, 0, 226, 185, 143, 38, 144, 132, 212, 136, 5, 17, 200, |
| 47 | + 17, 93, 206, 240, 79, 83, 199, 226, 7, 153, 46, 3, 255, 209, 38, |
| 48 | + 223, 148, 77, 228, 219, 4, 64, 120, 135, 213, 13, 0, 0, 0, 64, |
| 49 | + 84, 137, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 215, 206, 58, 6, |
| 50 | + 0, 0, 0, 0, 64, 120, 135, 213, 13, 0, 0, 0, 64, 84, 137, 0, 0, |
| 51 | + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 215, 206, 58, 6, 0, 0, 0, 0, |
| 52 | + 26, 229, 2, 163, 233, 66, 184, 177, 28, 195, 116, 73, 107, 77, |
| 53 | + 156, 92, 57, 248, 12, 93, 172, 31, 69, 159, 53, 162, 14, 193, |
| 54 | + 184, 115, 8, 157, 208, 187, 67, 117, 16, 0, 0, 0, 112, 215, 93, |
| 55 | + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, |
| 56 | + 0, 208, 187, 67, 117, 16, 0, 0, 0, 112, 215, 93, 0, 0, 0, 0, 0, |
| 57 | + 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 13, 195, |
| 58 | + 188, 234, 145, 85, 105, 118, 8, 176, 95, 4, 167, 10, 208, 154, |
| 59 | + 65, 81, 114, 170, 155, 181, 247, 64, 135, 58, 192, 120, 43, 43, |
| 60 | + 26, 69, 128, 52, 253, 126, 16, 0, 0, 0, 232, 245, 166, 42, 0, 0, |
| 61 | + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, 128, |
| 62 | + 52, 253, 126, 16, 0, 0, 0, 232, 245, 166, 42, 0, 0, 0, 0, 1, 0, |
| 63 | + 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 7, 242, 203, 57, |
| 64 | + 253, 176, 41, 220, 81, 120, 77, 40, 239, 23, 145, 29, 151, 193, |
| 65 | + 166, 156, 133, 114, 58, 27, 98, 85, 179, 66, 83, 67, 173, 117, |
| 66 | + 160, 226, 148, 120, 16, 0, 0, 0, 64, 120, 125, 1, 0, 0, 0, 0, |
| 67 | + 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 160, 226, |
| 68 | + 148, 120, 16, 0, 0, 0, 64, 120, 125, 1, 0, 0, 0, 0, 1, 0, 0, 0, |
| 69 | + 0, 0, 0, 0, 218, 169, 82, 6, 0, 0, 0, 0, 159, 62, 165, 123, 212, |
| 70 | + 9, 186, 0, 196, 13, 146, 174, 87, 19, 65, 194, 126, 60, 47, 126, |
| 71 | + 223, 172, 225, 194, 74, 81, 177, 161, 92, 49, 178, 183, 0, 126, |
| 72 | + 195, 118, 16, 0, 0, 0, 0, 144, 208, 3, 0, 0, 0, 0, 1, 0, 0, 0, |
| 73 | + 0, 0, 0, 0, 214, 169, 82, 6, 0, 0, 0, 0, 0, 126, 195, 118, 16, |
| 74 | + 0, 0, 0, 0, 144, 208, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, |
| 75 | + 214, 169, 82, 6, 0, 0, 0, 0, 67, 130, 143, 163, 97, 157, 166, |
| 76 | + 188, 174, 214, 137, 23, 222, 29, 124, 206, 146, 23, 222, 199, |
| 77 | + 43, 174, 18, 48, 99, 255, 123, 231, 221, 47, 150, 62, 159, 181, |
| 78 | + 99, 119, 16, 0, 0, 0, 32, 208, 252, 3, 0, 0, 0, 0, 1, 0, 0, 0, |
| 79 | + 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, 159, 181, 99, 119, 16, |
| 80 | + 0, 0, 0, 208, 12, 252, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, |
| 81 | + 217, 169, 82, 6, 0, 0, 0, 0, 24, 131, 177, 36, 109, 218, 93, |
| 82 | + 7, 23, 61, 189, 56, 213, 103, 0, 7, 21, 132, 44, 31, 208, 232, |
| 83 | + 150, 231, 11, 10, 109, 210, 229, 26, 79, 151, 144, 137, 61, 122, |
| 84 | + 16, 0, 0, 0, 160, 126, 38, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, |
| 85 | + 0, 212, 169, 82, 6, 0, 0, 0, 0, 144, 137, 61, 122, 16, 0, 0, 0, |
| 86 | + 160, 126, 38, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 212, 169, |
| 87 | + 82, 6, 0, 0, 0, 0, 67, 183, 120, 75, 111, 133, 102, 203, 50, |
| 88 | + 131, 101, 251, 206, 11, 64, 70, 21, 35, 186, 236, 231, 133, 23, |
| 89 | + 179, 21, 92, 49, 218, 163, 56, 41, 143, 160, 154, 172, 118, 16, |
| 90 | + 0, 0, 0, 224, 202, 212, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, |
| 91 | + 216, 169, 82, 6, 0, 0, 0, 0, 160, 154, 172, 118, 16, 0, 0, 0, |
| 92 | + 224, 202, 212, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, |
| 93 | + 82, 6, 0, 0, 0, 0, 245, 157, 221, 239, 204, 22, 107, 45, 137, |
| 94 | + 164, 163, 204, 243, 254, 196, 187, 75, 152, 161, 81, 180, 192, |
| 95 | + 55, 255, 97, 94, 187, 120, 66, 227, 61, 117, 0, 0, 0, 0, 0, 0, |
| 96 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 97 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 98 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 234, 211, |
| 99 | + 227, 211, 75, 204, 133, 52, 187, 44, 101, 14, 178, 122, 140, |
| 100 | + 140, 63, 26, 34, 214, 136, 40, 67, 40, 83, 140, 66, 168, 232, |
| 101 | + 35, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 102 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 103 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 104 | + 0, 0, 0, 0, 208, 202, 51, 28, 245, 217, 238, 113, 107, 200, 198, |
| 105 | + 144, 163, 0, 171, 168, 64, 59, 55, 20, 28, 182, 59, 2, 101, 192, |
| 106 | + 152, 192, 197, 142, 99, 172, 64, 201, 15, 119, 16, 0, 0, 0, 136, |
| 107 | + 239, 116, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, |
| 108 | + 6, 0, 0, 0, 0, 64, 201, 15, 119, 16, 0, 0, 0, 136, 239, 116, 2, |
| 109 | + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, |
| 110 | + 0, 95, 201, 100, 254, 33, 2, 195, 77, 93, 166, 252, 229, 65, |
| 111 | + 29, 127, 158, 185, 150, 131, 95, 215, 104, 121, 35, 237, 240, |
| 112 | + 7, 225, 234, 201, 211, 155, 32, 31, 203, 118, 16, 0, 0, 0, 240, |
| 113 | + 200, 210, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, |
| 114 | + 6, 0, 0, 0, 0, 32, 31, 203, 118, 16, 0, 0, 0, 240, 200, 210, 0, |
| 115 | + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, |
| 116 | + 0, 236, 134, 220, 52, 87, 253, 170, 21, 115, 40, 210, 64, 157, |
| 117 | + 52, 1, 211, 207, 173, 70, 128, 138, 176, 68, 25, 60, 30, 126, |
| 118 | + 201, 250, 213, 207, 98, 182, 181, 235, 121, 16, 0, 0, 0, 154, |
| 119 | + 18, 9, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, |
| 120 | + 0, 0, 0, 0, 182, 181, 235, 121, 16, 0, 0, 0, 154, 18, 9, 3, 0, |
| 121 | + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, |
| 122 | + 216, 111, 132, 13, 235, 226, 237, 166, 102, 133, 155, 248, 194, |
| 123 | + 199, 66, 195, 230, 71, 190, 78, 23, 109, 252, 82, 37, 216, 4, |
| 124 | + 241, 212, 159, 226, 45, 79, 113, 43, 118, 16, 0, 0, 0, 81, 0, |
| 125 | + 222, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, |
| 126 | + 0, 0, 0, 0, 79, 113, 43, 118, 16, 0, 0, 0, 81, 0, 222, 1, 0, 0, |
| 127 | + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 247, |
| 128 | + 161, 48, 122, 139, 67, 39, 7, 240, 246, 215, 179, 231, 181, 3, |
| 129 | + 65, 69, 2, 98, 159, 30, 232, 249, 196, 246, 181, 145, 85, 137, |
| 130 | + 26, 36, 46, 217, 99, 81, 121, 16, 0, 0, 0, 132, 31, 32, 2, 0, |
| 131 | + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, |
| 132 | + 217, 99, 81, 121, 16, 0, 0, 0, 132, 31, 32, 2, 0, 0, 0, 0, 1, |
| 133 | + 0, 0, 0, 0, 0, 0, 0, 217, 169, 82, 6, 0, 0, 0, 0, 16, 57, 177, |
| 134 | + 245, 250, 4, 188, 2, 13, 7, 120, 109, 84, 117, 4, 108, 217, 244, |
| 135 | + 11, 5, 110, 116, 96, 223, 36, 38, 142, 16, 0, 124, 14, 157, 159, |
| 136 | + 131, 52, 120, 16, 0, 0, 0, 97, 237, 72, 2, 0, 0, 0, 0, 1, 0, 0, |
| 137 | + 0, 0, 0, 0, 0, 216, 169, 82, 6, 0, 0, 0, 0, 159, 131, 52, 120, |
| 138 | + 16, 0, 0, 0, 97, 237, 72, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, |
| 139 | + 0, 217, 169, 82, 6, 0, 0, 0, 0, |
| 140 | + ]) |
| 141 | + |
| 142 | + |
| 143 | +@pytest.fixture |
| 144 | +def price_account_key(): |
| 145 | + return SolanaPublicKey("5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe") |
| 146 | + |
| 147 | + |
| 148 | +def test_price_account(price_account_bytes, price_account_key, solana_client): |
| 149 | + price_account = PythPriceAccount( |
| 150 | + key=price_account_key, |
| 151 | + solana=solana_client, |
| 152 | + ) |
| 153 | + price_account.update_from(buffer=price_account_bytes, version=2, offset=0) |
| 154 | + |
| 155 | + assert price_account.price_type == PythPriceType.PRICE |
| 156 | + assert price_account.exponent == -8 |
| 157 | + assert price_account.num_components == 19 |
| 158 | + assert len(price_account.price_components) == price_account.num_components |
| 159 | + assert price_account.last_slot == 106080731 |
| 160 | + assert price_account.valid_slot == 106080730 |
| 161 | + assert price_account.product_account_key == SolanaPublicKey( |
| 162 | + "5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw" |
| 163 | + ) |
| 164 | + assert price_account.next_price_account_key is None |
| 165 | + assert dict(price_account.aggregate_price_info) == { |
| 166 | + "raw_price": 70712500000, |
| 167 | + "raw_confidence_interval": 36630500, |
| 168 | + "price_status": PythPriceStatus.TRADING, |
| 169 | + "slot": 106080731, |
| 170 | + "exponent": -8, |
| 171 | + "price": 707.125, |
| 172 | + "confidence_interval": 0.366305, |
| 173 | + } |
| 174 | + assert price_account.min_publishers == 0 |
| 175 | + |
| 176 | + # Only assert the first element of the 19 price components |
| 177 | + assert dict(price_account.price_components[0]) == { |
| 178 | + "publisher_key": SolanaPublicKey( |
| 179 | + "HekM1hBawXQu6wK6Ah1yw1YXXeMUDD2bfCHEzo25vnEB" |
| 180 | + ), |
| 181 | + "last_aggregate_price_info": { |
| 182 | + "raw_price": 70709500000, |
| 183 | + "raw_confidence_interval": 21500000, |
| 184 | + "price_status": PythPriceStatus.TRADING, |
| 185 | + "slot": 106080728, |
| 186 | + "exponent": -8, |
| 187 | + "price": 707.095, |
| 188 | + "confidence_interval": 0.215, |
| 189 | + }, |
| 190 | + "latest_price_info": { |
| 191 | + "raw_price": 70709500000, |
| 192 | + "raw_confidence_interval": 21500000, |
| 193 | + "price_status": PythPriceStatus.TRADING, |
| 194 | + "slot": 106080729, |
| 195 | + "exponent": -8, |
| 196 | + "price": 707.095, |
| 197 | + "confidence_interval": 0.215, |
| 198 | + }, |
| 199 | + "exponent": -8, |
| 200 | + } |
| 201 | + |
| 202 | + |
| 203 | +def test_price_account_str(price_account_bytes, price_account_key, solana_client): |
| 204 | + price_account = PythPriceAccount( |
| 205 | + key=price_account_key, |
| 206 | + solana=solana_client, |
| 207 | + ) |
| 208 | + expected_empty = "PythPriceAccount PythPriceType.UNKNOWN (5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe)" |
| 209 | + assert str(price_account) == expected_empty |
| 210 | + |
| 211 | + expected = "PythPriceAccount PythPriceType.PRICE (5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe)" |
| 212 | + price_account.update_from(buffer=price_account_bytes, version=2, offset=0) |
| 213 | + assert str(price_account) == expected |
| 214 | + |
| 215 | + price_account.product = PythProductAccount( |
| 216 | + key="5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw", |
| 217 | + solana=solana_client, |
| 218 | + ) |
| 219 | + price_account.product.attrs = { |
| 220 | + "symbol": "FOO/BAR", |
| 221 | + } |
| 222 | + expected_with_product = "PythPriceAccount FOO/BAR PythPriceType.PRICE (5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe)" |
| 223 | + assert str(price_account) == expected_with_product |
| 224 | + |
| 225 | + |
| 226 | +def test_price_account_agregate_properties( |
| 227 | + price_account_bytes, price_account_key, solana_client |
| 228 | +): |
| 229 | + price_account = PythPriceAccount( |
| 230 | + key=price_account_key, |
| 231 | + solana=solana_client, |
| 232 | + ) |
| 233 | + price_account.update_from(buffer=price_account_bytes, version=2, offset=0) |
| 234 | + assert price_account.aggregate_price == 707.125 |
| 235 | + assert price_account.aggregate_price_confidence_interval == 0.366305 |
0 commit comments