Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbe2dfbd82 | ||
|
|
5442a2e5fe | ||
|
|
58b4d8c84f | ||
|
|
f5c6c8a072 | ||
|
|
9d5ab4a2d6 | ||
|
|
32f704459f | ||
|
|
e4795182ca | ||
|
|
3297dbdaab | ||
|
|
a65a5985e6 | ||
|
|
77eac494ad | ||
|
|
4498f59607 | ||
|
|
6322913310 | ||
|
|
be2f34a045 | ||
|
|
cce0c89168 | ||
|
|
58cc197c89 | ||
|
|
bbb6d0eda9 | ||
|
|
c03068f0ec | ||
|
|
e8f352930d | ||
|
|
bf2c560db5 | ||
|
|
63189a6196 | ||
|
|
9990690332 | ||
|
|
ee163cc342 | ||
|
|
cf27f7e11b | ||
|
|
12986865c8 | ||
|
|
aac0fc741a | ||
|
|
c33f95d64b | ||
|
|
eb7255b34f | ||
|
|
3982798d5e | ||
|
|
ded1ebd4e7 | ||
|
|
c261d4e333 | ||
|
|
7b1400e238 | ||
|
|
7c2048bc6b | ||
|
|
2b1d5664fe | ||
|
|
5403686e20 | ||
|
|
e90c72fc8b | ||
|
|
1910ef54a4 | ||
|
|
45686f9482 | ||
|
|
a6b0d214af | ||
|
|
2a1a2a936b | ||
|
|
060275d1ae | ||
|
|
abb54d2538 | ||
|
|
98fc472a40 | ||
|
|
4034429042 | ||
|
|
ca212b8736 | ||
|
|
4c2593629d | ||
|
|
612d85ca2a | ||
|
|
b25b92dddc | ||
|
|
f01376ebe1 | ||
|
|
03acde19b8 | ||
|
|
1de533ca9c | ||
|
|
ce2037400c | ||
|
|
379fe12979 | ||
|
|
a285f53753 | ||
|
|
ed36eed112 | ||
|
|
ddf6f574f6 | ||
|
|
4f7c4e8b4e | ||
|
|
f2a82ddd0f | ||
|
|
3cec316683 | ||
|
|
c23b5e674b | ||
|
|
8bf8222c31 | ||
|
|
0c19e966cc | ||
|
|
9fbda5a6e0 | ||
|
|
3d7d39073f | ||
|
|
ae26aebdf8 | ||
|
|
c43f442fb9 | ||
|
|
f97a6d0418 | ||
|
|
7cd2fa5f6a | ||
|
|
6015552aab | ||
|
|
8748c02b20 | ||
|
|
6e04d4aa93 | ||
|
|
4a955f7b77 | ||
|
|
227143728d | ||
|
|
7330555c37 | ||
|
|
09831fe325 | ||
|
|
c7dda6fe85 | ||
|
|
285bbab055 | ||
|
|
b73010a506 | ||
|
|
9c951fe1cb | ||
|
|
f7dfb633d6 | ||
|
|
e32286b610 | ||
|
|
fe2687b514 | ||
|
|
1adde99e1b | ||
|
|
33dcc9c8aa | ||
|
|
db563bc131 | ||
|
|
35d2fa31e0 | ||
|
|
399637280c | ||
|
|
f46916b215 | ||
|
|
94aa79d1e5 | ||
|
|
10dacf1d16 | ||
|
|
bdaacfdd56 | ||
|
|
4fa77b3654 | ||
|
|
400e14d6c9 | ||
|
|
09f247432f | ||
|
|
fd195dd4f0 | ||
|
|
0038227680 | ||
|
|
89dec0bc0b | ||
|
|
a55a835504 | ||
|
|
c1266a6657 | ||
|
|
b78f08e2e6 | ||
|
|
298ef03787 | ||
|
|
dd80b1873c | ||
|
|
f7672e053b | ||
|
|
281e9d2dee | ||
|
|
3f0d11b026 | ||
|
|
0c997d2850 | ||
|
|
cb0beea7cd | ||
|
|
4ed783878d | ||
|
|
3846b5cc18 | ||
|
|
57b8915101 | ||
|
|
4f3f7e8dff | ||
|
|
a42c266a35 | ||
|
|
b03b2db3f8 | ||
|
|
5347db445d | ||
|
|
2a15b65385 | ||
|
|
7f1952acfc | ||
|
|
d8920b4bac | ||
|
|
3b46505027 | ||
|
|
ba3ac3f73d | ||
|
|
81d460ccc8 | ||
|
|
e6bb6c49b3 | ||
|
|
82ffa8a6e2 | ||
|
|
adc1af1f21 | ||
|
|
a05d6ad7dc | ||
|
|
be592f53b8 | ||
|
|
8e74eca435 | ||
|
|
8a28d2cf46 | ||
|
|
d36886fcbf | ||
|
|
3bbc9fbf6e | ||
|
|
1d4539f3ef | ||
|
|
215b20f7db | ||
|
|
c034b54822 | ||
|
|
261ca2149d | ||
|
|
eaa67c8ea6 | ||
|
|
db287d6997 | ||
|
|
b85bf7e41c | ||
|
|
84b82dd9b5 | ||
|
|
3df5b01375 | ||
|
|
2e6a59e2a0 | ||
|
|
2f91561166 | ||
|
|
b307772be2 | ||
|
|
d14d2ccc86 | ||
|
|
0f26ec47e2 | ||
|
|
40065e300b | ||
|
|
bbdb8a317f | ||
|
|
668085262c | ||
|
|
508400684a | ||
|
|
3273556f7b | ||
|
|
d36144bf36 | ||
|
|
444479011e | ||
|
|
8ac713abcf | ||
|
|
728bc5294f | ||
|
|
fd2f331bdf | ||
|
|
2aebbb89cb | ||
|
|
532c011495 | ||
|
|
e2802df9ce | ||
|
|
cc181e2cc3 | ||
|
|
1b8ba41715 | ||
|
|
648be9aecb | ||
|
|
292af97dc9 | ||
|
|
bcdd537214 | ||
|
|
514c5e4825 | ||
|
|
9b9581487d | ||
|
|
d443f31a9a | ||
|
|
3951da5df3 | ||
|
|
5f3a1e5b24 | ||
|
|
b1a6ccd425 | ||
|
|
adc40e581f | ||
|
|
c6b0b0c161 | ||
|
|
bf5b14580b | ||
|
|
088c02862b | ||
|
|
a05980900e | ||
|
|
77019def08 | ||
|
|
ae6a3307b1 | ||
|
|
8cb15c6a87 | ||
|
|
389dbb58a9 | ||
|
|
2d02f61fa7 | ||
|
|
7497ac723f | ||
|
|
711a145e1e | ||
|
|
05e3db01ba | ||
|
|
6158c07e0a | ||
|
|
ce505aaf62 | ||
|
|
09f9a48037 | ||
|
|
700c1cfcd4 | ||
|
|
7d2463e53f | ||
|
|
a2ecd9bd3b | ||
|
|
b0de692147 | ||
|
|
dcd53c76d7 | ||
|
|
6ed90c6111 | ||
|
|
babef6d7bc | ||
|
|
e2205a65e9 | ||
|
|
32d55dfb18 | ||
|
|
60e0d0eae4 | ||
|
|
9cef1febe1 | ||
|
|
4c9032fedc | ||
|
|
5b6f222e5e | ||
|
|
47235d01bf | ||
|
|
32efe83136 | ||
|
|
c4c099e693 | ||
|
|
f26ca0e624 | ||
|
|
5f496f1809 | ||
|
|
f1cbf8cc70 | ||
|
|
8b7fccb744 | ||
|
|
66d3486674 | ||
|
|
2dbd217f6d | ||
|
|
fea9ae8f97 | ||
|
|
4e81bbc43c | ||
|
|
83650b8f28 | ||
|
|
50a3501dd2 | ||
|
|
526a3fd139 | ||
|
|
3b996b3444 | ||
|
|
c72c9e4a5e | ||
|
|
60a71a5ac9 | ||
|
|
26c3ccccc3 | ||
|
|
963e25934d | ||
|
|
55d9f8a062 | ||
|
|
700c8ba21f | ||
|
|
cbc255b4e7 | ||
|
|
2fe1e5031e | ||
|
|
f2cdac7875 | ||
|
|
165405bdc3 | ||
|
|
f86d71524d | ||
|
|
4d6d59f1c5 | ||
|
|
7a709898e5 | ||
|
|
121bfc7913 | ||
|
|
a04ccec445 | ||
|
|
2611fc5e1a | ||
|
|
cd5c306b22 | ||
|
|
ca6a7819f6 | ||
|
|
29c0ea9856 | ||
|
|
c82ed58d68 | ||
|
|
59a3867c50 | ||
|
|
0fca4e6866 | ||
|
|
3f9e65a179 | ||
|
|
92bde9de6f | ||
|
|
9b3158599c | ||
|
|
206fb49df5 | ||
|
|
cc0ad9b04b | ||
|
|
39902dd8ac | ||
|
|
324e4ab89b | ||
|
|
68bf0a487f | ||
|
|
3acf7e0fd7 | ||
|
|
edaf13abe1 | ||
|
|
b3649a70ce | ||
|
|
80ab628643 | ||
|
|
76363c0142 | ||
|
|
80c18c2201 | ||
|
|
fcf9b86b87 | ||
|
|
1113a3d2f8 | ||
|
|
c899dbf893 | ||
|
|
be137b2a03 | ||
|
|
122d780fe8 | ||
|
|
12be027b18 | ||
|
|
dfeef40037 | ||
|
|
a7b4fe4dd0 | ||
|
|
f4ec64d6f5 | ||
|
|
9a0d39199e | ||
|
|
77d82d9511 | ||
|
|
5464b91cc6 | ||
|
|
64ff87952a | ||
|
|
0de39e4c52 | ||
|
|
60bc384d22 | ||
|
|
ca7ea0e143 | ||
|
|
23d50248de | ||
|
|
ad4e54a2f6 | ||
|
|
e659df27ae | ||
|
|
6dc3c06fe8 | ||
|
|
776956f166 | ||
|
|
4c5203acba | ||
|
|
d80070a041 | ||
|
|
1c00cb4c4e | ||
|
|
736505603e | ||
|
|
c243da79e1 | ||
|
|
2677f38090 | ||
|
|
41d05d2402 | ||
|
|
0f38584566 | ||
|
|
2b7fb8667e | ||
|
|
ca18846bfb | ||
|
|
4ba372d29b | ||
|
|
bdc2d24366 | ||
|
|
3de06c1d4c | ||
|
|
b51149d895 | ||
|
|
e0fef55366 | ||
|
|
e2aac5f94a | ||
|
|
8f44f84c7f | ||
|
|
d53a61ec86 | ||
|
|
cf18f79c14 | ||
|
|
beb8011b4c | ||
|
|
38a601b665 | ||
|
|
11a3483ce5 | ||
|
|
1db133b741 | ||
|
|
716dce0093 | ||
|
|
3b53442172 | ||
|
|
253d94a47d | ||
|
|
fb1129a49b | ||
|
|
1cc56d6e44 | ||
|
|
9e2983a735 | ||
|
|
a6fcba95de | ||
|
|
c8c535834e | ||
|
|
b8d7c2e3e3 | ||
|
|
0283d4727b | ||
|
|
a4ab732478 | ||
|
|
0dc121a796 | ||
|
|
a827131457 | ||
|
|
2174537f76 | ||
|
|
53fca2406a | ||
|
|
0eaba284ae | ||
|
|
378f359a76 | ||
|
|
5460d96b5d | ||
|
|
b1353edc84 | ||
|
|
9129fed6e5 | ||
|
|
7c4abacaca | ||
|
|
3664c7d81b | ||
|
|
f75b87c5a5 | ||
|
|
1c228216cd | ||
|
|
cec3c12795 | ||
|
|
0d0d12e85b | ||
|
|
3a16e69be5 | ||
|
|
4ae8e3909f | ||
|
|
6e18bb3b1d | ||
|
|
be153e13a6 | ||
|
|
4c01dfd0ab | ||
|
|
b57c7a1343 | ||
|
|
da62acdf50 | ||
|
|
cc95e4fc0a | ||
|
|
7f5647c6e1 | ||
|
|
c636d63bc0 | ||
|
|
30c98ef857 | ||
|
|
debecde50f | ||
|
|
cd2cdd1184 | ||
|
|
f5c25d75ff | ||
|
|
780cc62942 | ||
|
|
165568c905 | ||
|
|
976a48d8f9 | ||
|
|
35cbbbe0ed | ||
|
|
772769c981 | ||
|
|
1ba2bd1766 | ||
|
|
4afa345a7d | ||
|
|
5c03359f32 | ||
|
|
04120505f0 | ||
|
|
7bd9dd65f8 | ||
|
|
5f57ecb2e1 | ||
|
|
9123f1d805 | ||
|
|
7050c4a554 | ||
|
|
62afb0b534 | ||
|
|
5157ca5608 | ||
|
|
315617c027 | ||
|
|
7d33b4dec6 | ||
|
|
2345f69c71 | ||
|
|
3cef2fb4d5 | ||
|
|
2bbf5513b2 | ||
|
|
c146f06178 | ||
|
|
5903704b61 | ||
|
|
90d8db651b | ||
|
|
557283a3d1 | ||
|
|
88b84dcf75 | ||
|
|
45d190eaca | ||
|
|
6d32328509 | ||
|
|
ba470e7417 | ||
|
|
4a16e46f88 | ||
|
|
ada0d99a84 | ||
|
|
e486fc4316 | ||
|
|
6e5c6f4e0b | ||
|
|
21ddcaf173 | ||
|
|
6085b994f6 | ||
|
|
7c3bf05868 | ||
|
|
8bce5b4a09 | ||
|
|
7a6077301f | ||
|
|
3f2767462f | ||
|
|
ecc37d11df | ||
|
|
0589d151da | ||
|
|
47cd6c6410 | ||
|
|
65688f9e0e | ||
|
|
5eb2a95ef2 | ||
|
|
282b39d27a | ||
|
|
f21e3d317a | ||
|
|
c2af7cf8f2 | ||
|
|
0958a4c693 | ||
|
|
c687181130 | ||
|
|
685f1ec0b6 | ||
|
|
e0069b6f7d | ||
|
|
cf48762ff2 | ||
|
|
31a7545a19 | ||
|
|
5cd8e8fb97 | ||
|
|
96e4090174 | ||
|
|
0bbebab90b | ||
|
|
57dac0ef47 | ||
|
|
6c3d24551b | ||
|
|
e7dc6d7a5a | ||
|
|
a63b7f611e | ||
|
|
82e15dc36d | ||
|
|
6f96037cb5 | ||
|
|
b6da84b8b2 | ||
|
|
41209f074c | ||
|
|
c47964c942 | ||
|
|
5f13a634e5 | ||
|
|
40af520fe7 | ||
|
|
1e506e0f8c | ||
|
|
96ea5803d4 | ||
|
|
7d99459f50 | ||
|
|
8fa090f435 | ||
|
|
d3c60d197c | ||
|
|
ad8550f7f5 | ||
|
|
a899aa439d | ||
|
|
e0e075b350 | ||
|
|
34ff14547e | ||
|
|
681a80d456 | ||
|
|
ed5f2673ce | ||
|
|
43e87603e2 | ||
|
|
d056416b47 | ||
|
|
1bcf94131d | ||
|
|
17b607b6c3 | ||
|
|
5a16d1dd8b | ||
|
|
144b74306a | ||
|
|
16b9fa956d | ||
|
|
b6af4b9877 | ||
|
|
3f368e721d | ||
|
|
22b4257636 | ||
|
|
ca7a631032 | ||
|
|
da5bbd17af | ||
|
|
b58f3f5c3e | ||
|
|
8c30194f59 | ||
|
|
dc9ec37490 | ||
|
|
5175e77eec | ||
|
|
9553c5467c | ||
|
|
a1f07e3274 | ||
|
|
58deb2eb14 | ||
|
|
83caad7f1b | ||
|
|
26c3cc9126 | ||
|
|
1a231dfb0d | ||
|
|
712d0425d0 | ||
|
|
eaa5db517f | ||
|
|
88c3850d1b | ||
|
|
943df72ae9 | ||
|
|
67ab11a036 | ||
|
|
c87ef7526b | ||
|
|
bccf2d52ad | ||
|
|
be6dbdd3e4 | ||
|
|
3c34ee9897 | ||
|
|
9ad97813e3 | ||
|
|
028f04e47f | ||
|
|
4974c9247f | ||
|
|
1ffe6a11bf | ||
|
|
19699ea445 | ||
|
|
d98ccfb12a | ||
|
|
41cb056b0f | ||
|
|
48bda0bdea | ||
|
|
1b393c7b67 | ||
|
|
f52e518b7b | ||
|
|
08970cff88 | ||
|
|
6d38ca6453 | ||
|
|
60db4bc66b | ||
|
|
0661237b28 | ||
|
|
6ccac712a8 | ||
|
|
3d4877940c | ||
|
|
70fc95ef27 | ||
|
|
463f65d25c | ||
|
|
09d176c82e | ||
|
|
fce96baf3d | ||
|
|
c6785c533f | ||
|
|
64de021149 | ||
|
|
de9e17a1a0 | ||
|
|
987bccea2e | ||
|
|
1434b86b8f | ||
|
|
a398b2201f | ||
|
|
f015837c38 | ||
|
|
5b51588995 | ||
|
|
7383e521e5 | ||
|
|
b10f05786c | ||
|
|
a212351528 | ||
|
|
55c01af260 | ||
|
|
1cf6ffad2b | ||
|
|
00d0ab9de1 | ||
|
|
b38e60a9a7 | ||
|
|
29f7e46439 | ||
|
|
fa0add8564 | ||
|
|
5bec38c404 | ||
|
|
43b66b6507 | ||
|
|
7e370b3a23 | ||
|
|
2b270a3c9f | ||
|
|
cf0d9a2d3f | ||
|
|
5d70622819 | ||
|
|
fcebdb6d6f | ||
|
|
3d020b5159 | ||
|
|
530d1bcd03 | ||
|
|
a4151c2941 | ||
|
|
a801d30fb6 | ||
|
|
1fe9b605dd | ||
|
|
ecfd822d94 | ||
|
|
a5e4d68993 | ||
|
|
ca5c002d37 | ||
|
|
6e28760da4 | ||
|
|
a253c4edb5 | ||
|
|
7c96525d35 | ||
|
|
3f0457efc2 | ||
|
|
bfb241d995 | ||
|
|
314ad8c3f2 | ||
|
|
aa85371f82 | ||
|
|
d0a08dadd9 | ||
|
|
eeff764345 | ||
|
|
4870ec4f40 | ||
|
|
1c3cfbfa0c | ||
|
|
3c9b7de6c7 | ||
|
|
22e5488f16 | ||
|
|
b37887993e | ||
|
|
75361cb0ff | ||
|
|
894992bc4c | ||
|
|
d955fab169 | ||
|
|
580d225387 | ||
|
|
d48f59e48d | ||
|
|
108b49ea03 | ||
|
|
9295349886 | ||
|
|
a51658ffac | ||
|
|
47f08e9e04 | ||
|
|
7906ae63dc | ||
|
|
0e76271dba | ||
|
|
e117619e34 | ||
|
|
67b416fe80 | ||
|
|
78dbfa46fa | ||
|
|
01db9261d5 | ||
|
|
674c38b384 | ||
|
|
0700e824eb | ||
|
|
0362eaf472 | ||
|
|
696b3964e6 | ||
|
|
5d0c2eed7b | ||
|
|
e4c3289ad8 | ||
|
|
4449bdae6f | ||
|
|
064957db81 | ||
|
|
ccd89ef0a6 | ||
|
|
47beb5f41f | ||
|
|
9f205392a3 | ||
|
|
adce7ccbee | ||
|
|
b83b3a9437 | ||
|
|
147dbcf24f | ||
|
|
2afff1b41f | ||
|
|
d1a1be49c5 | ||
|
|
4b6ad647a2 | ||
|
|
04f656cafa | ||
|
|
09bbd5f6c9 | ||
|
|
dbc3df6d09 | ||
|
|
26865f92e3 | ||
|
|
73045de73d | ||
|
|
6d3491b9f1 | ||
|
|
886f3a3c08 | ||
|
|
c72f976895 | ||
|
|
ab8b381d8b | ||
|
|
443e29a3be | ||
|
|
117bb5717a | ||
|
|
5fb76baa16 | ||
|
|
274b3498d4 | ||
|
|
fa9e1c53e1 | ||
|
|
3ebf7eb424 | ||
|
|
7d11e6f9a5 | ||
|
|
a0d6384b01 | ||
|
|
47afe2cfc6 | ||
|
|
c37a2fc756 | ||
|
|
e2545276bb | ||
|
|
4219409ef8 | ||
|
|
c9e64d2a32 | ||
|
|
41db3b2e35 | ||
|
|
ebe15dada6 | ||
|
|
c2cb5dc574 | ||
|
|
ba451348c0 | ||
|
|
ec76b11666 | ||
|
|
7603f9e6c1 | ||
|
|
b50eab11c0 | ||
|
|
66d05c1771 | ||
|
|
fd7c3d7e10 | ||
|
|
28d4c7d808 | ||
|
|
43d36fbcf6 | ||
|
|
e54eef2369 | ||
|
|
296842858f | ||
|
|
ba8849a3e9 | ||
|
|
e333c3d8d9 | ||
|
|
0fe6a21624 | ||
|
|
0abedb81c6 | ||
|
|
08eda72d4b | ||
|
|
70d4126c84 | ||
|
|
dcccab705c | ||
|
|
e45ff6d026 | ||
|
|
b49c2314e7 | ||
|
|
0ac085756a | ||
|
|
542a690c89 | ||
|
|
ff23ead797 | ||
|
|
ae55e4fbf7 | ||
|
|
b17412163d | ||
|
|
46dcbf9a42 | ||
|
|
193dfcc32f | ||
|
|
a81011cf94 | ||
|
|
d43a8b2e11 | ||
|
|
dff859ba68 | ||
|
|
5169b6ee69 | ||
|
|
f4405667fe | ||
|
|
49ff636305 | ||
|
|
d77d686c76 | ||
|
|
502c6a3451 | ||
|
|
b58c77683d | ||
|
|
b9f82fc549 | ||
|
|
25b8dba607 | ||
|
|
1bc4f2c334 | ||
|
|
aee8ac6b0a | ||
|
|
aa7e30070f | ||
|
|
64b5855f65 | ||
|
|
d7ff9e706e | ||
|
|
15ba6f6261 | ||
|
|
8c88a880c6 | ||
|
|
74566cce7b | ||
|
|
16f6deed5e | ||
|
|
40edc131fe | ||
|
|
3e014b38e6 | ||
|
|
b4cfdbffab | ||
|
|
cbfb6f8f59 | ||
|
|
b5bc15ab8b | ||
|
|
0b343fc0f8 | ||
|
|
e7f9693873 | ||
|
|
a0a5c3185d | ||
|
|
151d4693a9 | ||
|
|
cdb27d8ec2 | ||
|
|
055e4d1261 | ||
|
|
bf753255ab | ||
|
|
e2230ef454 | ||
|
|
0f5b01b856 | ||
|
|
82787c96c6 | ||
|
|
f89028d5fe | ||
|
|
ba24a2e917 | ||
|
|
b549bbf46b | ||
|
|
1e87f58f36 | ||
|
|
f643426067 | ||
|
|
94d26c76ec | ||
|
|
8fe262a712 | ||
|
|
122ee968cb | ||
|
|
d2ff350db9 | ||
|
|
9100aabbac | ||
|
|
1e73f69253 | ||
|
|
7153cb4158 | ||
|
|
999dc6f8a5 | ||
|
|
724574afe7 | ||
|
|
0352a30b6b | ||
|
|
41b4cd5c55 | ||
|
|
89f16f3123 | ||
|
|
261a4eede3 |
+14
-3
@@ -1,4 +1,4 @@
|
|||||||
25
|
31
|
||||||
1.4.2
|
1.4.2
|
||||||
1.6.2
|
1.6.2
|
||||||
1.11.2
|
1.11.2
|
||||||
@@ -8,9 +8,20 @@
|
|||||||
2.8.2
|
2.8.2
|
||||||
3.2.2
|
3.2.2
|
||||||
3.2.3
|
3.2.3
|
||||||
|
|
||||||
3.3.2
|
3.3.2
|
||||||
3.6.2
|
3.6.2
|
||||||
3.6.3
|
3.6.3
|
||||||
3.6.4
|
3.6.4
|
||||||
3.7.2
|
3.7.2
|
||||||
|
3.7.3
|
||||||
|
3.9.2
|
||||||
|
3.9.3
|
||||||
|
3.10.2
|
||||||
|
4.0.2
|
||||||
|
4.0.3
|
||||||
|
4.6.2
|
||||||
|
4.7.2
|
||||||
|
4.9.2
|
||||||
|
4.11.2
|
||||||
|
|
||||||
|
4.16.2
|
||||||
@@ -24,8 +24,6 @@ module.exports = {
|
|||||||
...base.rules,
|
...base.rules,
|
||||||
// add override for any (a metric ton of them, initial conversion)
|
// add override for any (a metric ton of them, initial conversion)
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
// these should be removed, there are 8 of them as errors
|
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
||||||
// this seems very broken atm, false positives
|
// this seems very broken atm, false positives
|
||||||
'@typescript-eslint/unbound-method': 'off'
|
'@typescript-eslint/unbound-method': 'off'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
name: 'Lock Threads'
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1/2 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lock:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: dessant/lock-threads@v2
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GH_PAT_BOT }}
|
||||||
|
issue-lock-inactive-days: '7'
|
||||||
|
issue-lock-comment: >
|
||||||
|
This thread has been automatically locked since there has not been
|
||||||
|
any recent activity after it was closed. Please open a new issue
|
||||||
|
if you think you have a related problem or query.
|
||||||
|
pr-lock-inactive-days: '2'
|
||||||
|
pr-lock-comment: >
|
||||||
|
This pull request has been automatically locked since there
|
||||||
|
has not been any recent activity after it was closed.
|
||||||
|
Please open a new issue for related bugs.
|
||||||
@@ -6,11 +6,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
master:
|
master:
|
||||||
|
if: "! startsWith(github.event.head_commit.message, '[CI Skip]')"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
step: ['build:release']
|
step: ['build:release']
|
||||||
name: ${{ matrix.step }}
|
name: ${{ matrix.step }}
|
||||||
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/api'"
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -25,10 +25,3 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
yarn install --immutable | grep -v 'YN0013'
|
yarn install --immutable | grep -v 'YN0013'
|
||||||
yarn ${{ matrix.step }}
|
yarn ${{ matrix.step }}
|
||||||
|
|
||||||
dummy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: dummy
|
|
||||||
run: |
|
|
||||||
echo "Dummy skip step"
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
name: Semgrep
|
||||||
|
on:
|
||||||
|
pull_request: {}
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && (!github.event.pull_request || github.event.pull_request.head.repo.full_name == github.repository)"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: returntocorp/semgrep-action@v1
|
||||||
|
with:
|
||||||
|
auditOn: push
|
||||||
|
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
|
||||||
|
publishDeployment: 1395
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name: 'Close stale issues and PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 2/2 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GH_PAT_BOT }}
|
||||||
|
stale-issue-message: 'This issue has been open for 21 days with no activity and is not labelled as an enhancement. It will be closed in 7 days.'
|
||||||
|
stale-issue-label: 'stale'
|
||||||
|
exempt-issue-labels: '-size-l,-size-m,-size-s,-size-xl,-size-xs,[bug]'
|
||||||
|
days-before-stale: 21
|
||||||
|
days-before-close: 7
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
build
|
||||||
|
coverage
|
||||||
|
packages
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
module.exports = require('@polkadot/dev/config/prettier.cjs');
|
||||||
+7
-9
File diff suppressed because one or more lines are too long
+7
-9
File diff suppressed because one or more lines are too long
Vendored
-55
File diff suppressed because one or more lines are too long
+591
File diff suppressed because one or more lines are too long
+1
-1
@@ -10,4 +10,4 @@ plugins:
|
|||||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||||
spec: "@yarnpkg/plugin-version"
|
spec: "@yarnpkg/plugin-version"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-2.4.0.cjs
|
yarnPath: .yarn/releases/yarn-3.0.0-rc.2.cjs
|
||||||
|
|||||||
+508
@@ -1,5 +1,513 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 4.17.1 Jul 5, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Allows cleaner access to multiple `.at` queries via new API.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Added `Emergency` to `ElectionPhase` (Thanks to https://github.com/arjanz)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Added `await api.at(<blockHash>)` to retrieve API instances at a point
|
||||||
|
- Added `fallbackType` for type classes (only struct, as defined)
|
||||||
|
- Allow `instances` API config to drive derive collective locations
|
||||||
|
- Ensure correct registry is attached to historic metadata
|
||||||
|
- Align static metadata with latest Substrate
|
||||||
|
|
||||||
|
|
||||||
|
## 4.16.2 Jun 27, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for Polkadot with runtime >= 9050.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Correct `CompactAssignments` & `RawSolution` types for Polkadot
|
||||||
|
|
||||||
|
|
||||||
|
## 4.16.1 Jun 26, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for full from-genesis queries on Kusama.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Adjust types for uniques (Thanks to https://github.com/Yuripetusko)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Add Kusama, Polkadot & Westend 9050 upgrade blocks
|
||||||
|
- Add Kusama & Westend 9070 upgrade blocks
|
||||||
|
- Adjust API decoration to lazy-create event and storage types
|
||||||
|
- Use TS `override` as applicable (with `--noImplicitOverrides` option)
|
||||||
|
- Add missing historic `Heartbeat: HeartbeatTo244` mapping to Kusama
|
||||||
|
- Remove duplication from contracts registry
|
||||||
|
- Add explicit check for scale-info 0.7+ (contracts index lookups)
|
||||||
|
- Align static metadata with latest Substrate
|
||||||
|
|
||||||
|
|
||||||
|
## 4.15.1 Jun 19, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Medium. Recommended for all chains where Xcm is used (addition of new `XcmOrigin`)
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Added `ChargeAssetTxPayment` extension (Thanks to https://github.com/apopiak)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Allow for type decoding of nested fixed vectors, tuples and structs
|
||||||
|
- Added `childstate_getKeysPaged` RPC
|
||||||
|
- Add `XcmOrigin` mapping for `OriginCaller` generation
|
||||||
|
- Align static metadata with latest Substrate
|
||||||
|
- Adjust error message for contracts V3 (extrinsic from runtime)
|
||||||
|
- Correct module optionality in `api.derive.balances.account`
|
||||||
|
- Add alias for `GenericAddress` -> `GenericMultiAddress`
|
||||||
|
- Adjust metadata doc generation (keep spaces between subsequent lines)
|
||||||
|
|
||||||
|
|
||||||
|
## 4.14.1 Jun 14, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Internal adjustment only, no major external usage changes.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Adjust types for uniques (Thanks to https://github.com/hamidra)
|
||||||
|
- Add `ValidationCodeHash` type (Thanks to https://github.com/andresilva)
|
||||||
|
- Extend `OriginCaller` type creation (Thanks to https://github.com/xlc)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Do strict length checking on `[u8; <length>]` type inputs
|
||||||
|
- Adjust keys/entries retrieval batch sizes
|
||||||
|
- Add upgrade block for Kusama 9040
|
||||||
|
- Use `BN` imports from `@polkadot/util`
|
||||||
|
|
||||||
|
|
||||||
|
## 4.13.1 Jun 6, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Medium. Required for users connecting to Statemine and future Kusama upgrades.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Overrides for `westmint` spec (same as `statemint`)
|
||||||
|
- Adjust `tx.session.setKeys` TS augmentation to allow `string` & `Uint8Array` keys
|
||||||
|
- Add & adjust types for latest Cumulus code
|
||||||
|
- Added 9031-9033 upgrade block for Westend
|
||||||
|
- Update static metadata to latest Substrate
|
||||||
|
- Optimize map retrieval with split page sizes for keys & values
|
||||||
|
- Sanitizing `BN` imports to `type`-only as required
|
||||||
|
|
||||||
|
|
||||||
|
## 4.12.1 May 30, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Internal adjustment only, no major external usage changes.
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
|
||||||
|
- Update `FundInfo` type with Polkadot (Thanks to https://github.com/arjanz)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Allow storage queries with default keys values
|
||||||
|
- Align identity `Data` to limit to 32 bytes in the `Raw` enum (as per Substrate)
|
||||||
|
- Align static (test & docs-only) metadata with latest Substrate master
|
||||||
|
- Added 9030 upgrade blocks for Kusama & Westend
|
||||||
|
- Cleanup of Eth pallet RPC definitions
|
||||||
|
- Cleanup README for `@polkadot/rpc-core` (recommended for internal-usage only)
|
||||||
|
- Cleanup internal tests (no dangling handles, cater for Jest 27)
|
||||||
|
|
||||||
|
|
||||||
|
## 4.11.2 May 24, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended where users are having TS mismatches with type definitions created on older versions.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Add backwards-compatible TS-only `AugmentedQueryDoubleMap` type (unused now in type generation)
|
||||||
|
|
||||||
|
|
||||||
|
## 4.11.1 May 23, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users using staking entries on Polkadot and users of Substrate master.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Fix metadata v13 storage decoding on `NMap`
|
||||||
|
- Add augmentation & keys/entries for NMap types
|
||||||
|
- Return additional error information from internal u8a decoding failures
|
||||||
|
- Adjust Westend types for 16 nominators-only
|
||||||
|
- Add support for `DisallowSigned` (as per shell runtime) extension
|
||||||
|
- Display small hex-slice with u8a decoding failures
|
||||||
|
- Add `state_getChildReadProof` RPC
|
||||||
|
- Cleanup Rococo known types (only as used)
|
||||||
|
- Under Node.js allow for WS receiving up to 16MB messages
|
||||||
|
- Update entries/keys for max of 256 items per call
|
||||||
|
|
||||||
|
|
||||||
|
## 4.10.1 May 17, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Medium. Recommended for uses of Polkadot/Kusama 9010 runtimes.
|
||||||
|
|
||||||
|
- **Breaking change** Support for the contracts V2 compatibility has been dropped in `@polkadot/api-contract`
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Expose RPC definitions via `.meta` (Thanks to https://github.com/jiqiang90)
|
||||||
|
- Adjust staking derives for chain-specific optional fields (https://github.com/WoeOm)
|
||||||
|
- Update base Centrifuge types (Thanks to https://github.com/branan)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Allow for `Bounded*` type usage (as per latest Substrate)
|
||||||
|
- Adjust internal TS definitions for providers
|
||||||
|
- Fix `ContractRx` query result definitions (no extra Observable)
|
||||||
|
- Handle contract call RPC result directly as `Raw` (returned as hex)
|
||||||
|
- Use `BN_*` constants as non-specified defaults in contract interfaces
|
||||||
|
- Remove all type overrides for node/node-template (API tracks latest)
|
||||||
|
- Contracts ABI now supports metadata version where indexes are 0-based
|
||||||
|
- Remove support for the old-style V2 contracts from `@polkadot/api-contract`
|
||||||
|
- Adjust historic decoration, return as-at registry via `getHeader`, `getMetadata` & `getRuntimeVersion`
|
||||||
|
- Adjust `VecFixed` to allow for the handling of hex inputs
|
||||||
|
- Adjust `Compact<*>` to allow for wrapped `toBigInt()` conversions
|
||||||
|
- Fix `isPedantic` decoding to correctly handle `Text`
|
||||||
|
- Cater for new `phragmenElection` module naming
|
||||||
|
- Add Kusama & Westend 9010 upgrade blocks
|
||||||
|
- Adjust `CompactSolution` for 24 nominators
|
||||||
|
- Bump static metadata to latest Substrate
|
||||||
|
|
||||||
|
|
||||||
|
## 4.9.1 May 6, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Medium. Required for the next v0.9.0 Polkadot/Kusama chain upgrades where parachains are used.
|
||||||
|
|
||||||
|
- **Breaking change** The previously deprecated contracts interfaces, has been removed. Update to `<myContract>.query.*`, `<myContract>.tx.*` and `<myCode>.tx.*` interfaces as per the previous code usage hints.
|
||||||
|
- **Important** By default the `isPedantic` mode is now switched on for storage queries. This means that the API will fail on any types where the input/output decoding doesn't match 100%
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Re-add isPedantic check on storage decoding
|
||||||
|
- `ConsensusEngineId` now implements `[u8;4]` (mapping closer to Rust source)
|
||||||
|
- Additional Xcm types
|
||||||
|
- Adjust parachain types
|
||||||
|
- Remove error logging on createType (details passed in error)
|
||||||
|
- Adjust `ContractInfo` type as per latest Substrate
|
||||||
|
- Adjust `DigestItem` type as per latest Substrate
|
||||||
|
- Adjust re-encoding of `BitVec` based on decoded length
|
||||||
|
- Added `contracts_instantiate`, `state_traceBlock` & `system_reservedPeers` RPCs
|
||||||
|
- Prepare for auto-capability detection with historic `.at` queries
|
||||||
|
- Add known upgrade block for Westend 900 & 9000
|
||||||
|
- Remove all deprecated interfaces inside `@polkadot/api-contracts`
|
||||||
|
- Initial support for NMap storage keys
|
||||||
|
- Support metadata v13 from Substrate (upcoming upgrade)
|
||||||
|
- Optimize historic metadata retrieval from rpc core
|
||||||
|
|
||||||
|
|
||||||
|
## 4.8.1 May 2, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended when using or developing for parachains.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- De-alias xcm `Outcome` (used in multiple pallettes)
|
||||||
|
- Adjust xcm types as per latest, e.g. `XcmError`
|
||||||
|
- Fix generate of well-known storage keys (e.g. `:code`)
|
||||||
|
- Optimize metadata unknown type validation
|
||||||
|
- Allow metadata creation for `Map` or `Record`
|
||||||
|
- Expose additional camelCase `method` on `AbiMessage` (maps to decorated name)
|
||||||
|
- Added explicit double-byte ss58 `AccountId` encoding test
|
||||||
|
- Add known upgrade block for Polkadot v30
|
||||||
|
- Cleanup WebSocket handlers when close event has been received
|
||||||
|
- Update to latest Substrate metadata
|
||||||
|
|
||||||
|
|
||||||
|
## 4.7.2 Apr 26, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users of 4.7.1 using nvm
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Update `EthBlock`/`EthHeader` types (as per Rust origin)
|
||||||
|
- Updated Xcm `OriginKind` enum
|
||||||
|
- Add derives for `membership`
|
||||||
|
- Cleanups on encodedLength calculations
|
||||||
|
- Update `.nvmrc` to reflect engines changes
|
||||||
|
|
||||||
|
|
||||||
|
## 4.7.1 Apr 25, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users following Substrate master.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjust Struct decoding with better error messages on invalid input objects
|
||||||
|
- Add support for new `BoundedVec` type
|
||||||
|
- Expand `Data` type (as used in identity), with all is/as getters
|
||||||
|
- Updated `Xcm` types (with Plularity)
|
||||||
|
- Adjust `DispatchError` type as per current Substrate master
|
||||||
|
- Adjusted Statemint `Proxy` type
|
||||||
|
- Remove metadata generation dependency on well-known.json (dedupe)
|
||||||
|
- Adjust WebSocket reconnection delay from 1s to 2.5s
|
||||||
|
- Revert Beefy keys addition for Westend
|
||||||
|
- Add explicit `engines` config to `package.json`
|
||||||
|
- Support for `None` in `RewardDestination`
|
||||||
|
- Align with latest substrate metadata
|
||||||
|
|
||||||
|
|
||||||
|
## 4.6.2 Apr 19, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users of Kusama/Polkadot.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Correct Kusama/Polkadot runtime 30 session key definitions
|
||||||
|
|
||||||
|
|
||||||
|
## 4.6.1 Apr 19, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended if used in a Node.js 15.x environment.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Assert keypair validity in signing operations
|
||||||
|
- Expose `internalError` on submittable results (e.g. event decoding errors)
|
||||||
|
- Simplify session derives for old/new
|
||||||
|
- Add Statemint to known types
|
||||||
|
- Add support for `rpc.beefy.subscribeJustifications`
|
||||||
|
- Update Xcm types
|
||||||
|
- Explicitly handle `isReadyOrError` with `Api.create`
|
||||||
|
- Add Kusama upgrade block for 2030
|
||||||
|
|
||||||
|
|
||||||
|
## 4.5.1 Apr 12, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended with usage with the Rococo testnet.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Update parachain types as per latest Polkadot
|
||||||
|
- Cater for `Keys` with `BEEFY` session keys
|
||||||
|
- Update `Keys` injection to allow for on-chain type detection
|
||||||
|
- Add `Westend` known upgrade block for runtime 50
|
||||||
|
- Align types with latest Substrate master
|
||||||
|
- Adjust keepalive `system_health` timer
|
||||||
|
|
||||||
|
|
||||||
|
## 4.4.1 Apr 5, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended with usage with the Rococo testnet.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Add `ServiceQuality` type for Cumulus
|
||||||
|
- Adjust XCM MultiLocation type (X5 to X8 junctions)
|
||||||
|
- Add Polkadot 29 upgrade block
|
||||||
|
|
||||||
|
|
||||||
|
## 4.3.1 Mar 29, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Fix documentation on ABI parameters (Thanks to https://github.com/vminkov)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Warn on usage of deprecated contract interfaces
|
||||||
|
- Update `ParaInfo` type
|
||||||
|
- Council should be optional in treasury derives
|
||||||
|
- Allow extraction of session derives indexes with no staking
|
||||||
|
|
||||||
|
|
||||||
|
## 4.2.1 Mar 22, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended when tracking the latest updates from Substrate.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Fix contract even decoding on Substrate 3 (Thanks to https://github.com/vminkov)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjust `Extender{Header, SignedBlock}` types to ensure at-block `Header` types are used
|
||||||
|
- Explicit definition for new Rococo triple refcount `AccountData` types
|
||||||
|
- Convert metadata private class fields to ES-private
|
||||||
|
- Adjust `SignedBlock` type for new `justifications` field
|
||||||
|
- Optimize society derive for multi accounts
|
||||||
|
- Bump metadata to latest substrate version
|
||||||
|
|
||||||
|
|
||||||
|
## 4.1.1 Mar 15, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended when tracking the latest updates from Substrate.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Fix author extraction for last block in a session
|
||||||
|
- Expand `SignerPayload` to inject/expose custom signed extensions
|
||||||
|
- `ConsensusEngineId` formats non-Ascii engines correctly
|
||||||
|
- Allow `getBlock/Header` derives to use as-at registry (instead of latest)
|
||||||
|
- Cleanup `RpcCore` augmentation (removing TS warnings on typegen chains)
|
||||||
|
- Add upgrade block for Kusama 2029
|
||||||
|
- Ensure that type alias overrides also apply to map keys
|
||||||
|
- Check type generation against fallbacks (build-time only sanity check)
|
||||||
|
- Add `mmr_generateProof` RPC
|
||||||
|
- Align types with latest substrate master
|
||||||
|
- Apply latest Polkadot auctions/crowdloan/parachains/slots types
|
||||||
|
|
||||||
|
|
||||||
|
## 4.0.3 Mar 8, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended if you use the API to sync the full chain, most notably Polkadot.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Re-add unused historical `SudoBalances` to `ProxyType` (Thanks to https://github.com/emostov)
|
||||||
|
|
||||||
|
|
||||||
|
## 4.0.2 Mar 8, 2021
|
||||||
|
|
||||||
|
Upgrade priority: High. Required if you are using 4.0.1 in a Node.js environment.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Fix import from `@polkadot/x-rxjs` in Node environments (From common)
|
||||||
|
- Add correct types for `Phase` is new validator elections module
|
||||||
|
|
||||||
|
|
||||||
|
## 4.0.1 Mar 7, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users wanting to keep updated with chain changes.
|
||||||
|
|
||||||
|
**Important** In the 4.0 version the default package type has been changed to ESM modules by default. This should not affect usage, however since the output formats changed, a new major version is required.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Expose `unknownTypes` on the registry interface (Thanks to https://github.com/ii-ii-ii)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Build to ESM by default (with cjs versions via export map)
|
||||||
|
- Enum `.toSON()` now encodes all keys as `camelCase` (aligning with the output from Substrate)
|
||||||
|
- Add `createdAtHash?: Hash` to `Codec` interface (filled-in by storage retrievals)
|
||||||
|
- Expose the source hash as `wamHash` on Abi parsed instances
|
||||||
|
- Use `parentHash` when creating mortal era (handles frequent forks better)
|
||||||
|
- Add `AccountInfoWithTripleRefCount` to cater for latest Substrate
|
||||||
|
- Add upgrade block for Westend 49
|
||||||
|
|
||||||
|
|
||||||
|
## 3.11.1 Feb 28, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users wanting to keep updated with chain changes.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Clean Websocket states on disconnects (Thanks to https://github.com/ianhe8x)
|
||||||
|
- Support for C-like indexed enums (Thanks to https://github.com/xlc)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjust council derives to cater for current-generation candidate mapping
|
||||||
|
- Allow for override of codec hasher (& output type)
|
||||||
|
- Adjust submittables to submit hex-encoded addresses to queries
|
||||||
|
- Adjust initialization to always retrieve tx version from Metadata only
|
||||||
|
- Update election types as per latest Substrate
|
||||||
|
- Add types for the new gilt module
|
||||||
|
- Upgrade to the latest Substrate metadata
|
||||||
|
- Adjust package detection to check for local monorepo dependencies
|
||||||
|
- Ensure that metadata `.toJSON()` does apply type aliasses
|
||||||
|
|
||||||
|
|
||||||
|
## 3.10.2 Feb 23, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Medium. Recommended for users of chains where `MultiAddress` is in-use and blocks are decoded.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Fix decoding for `MultiAddress` enum where non-`AccountId` variable-lengths are provided as part of a stream
|
||||||
|
- Added known Polkadot 28 upgrade block
|
||||||
|
- Update for latest Substrate contracts `Schedule` types
|
||||||
|
|
||||||
|
|
||||||
|
## 3.10.1 Feb 22, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjust ConsumedWeight types to align with Rust module code
|
||||||
|
- Check for connection status in subscription unsubscribe
|
||||||
|
- Adjust staking reward derives ordering for better performance
|
||||||
|
- Adapt detection imports to remove `.json` dependencies (Better behavior using Node.js with ESM)
|
||||||
|
|
||||||
|
|
||||||
|
## 3.9.3 Feb 16, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for parachain builders since it contains the updated parachain types.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjusted parachain `PersistedValidationData` structure
|
||||||
|
|
||||||
|
|
||||||
|
## 3.9.2 Feb 15, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for parachain builders since it contains the latest parachain types.
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Update README links (Thanks to https://github.com/wirednkod)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Added missing Culmulus `ParachainInherentData` & `MessageQueueChain` types
|
||||||
|
- Add alias for `system_unstable_networkState` RPC
|
||||||
|
|
||||||
|
|
||||||
|
## 3.9.1 Feb 14, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low.
|
||||||
|
|
||||||
|
- **Important** The `Result<T, E>` has been updated in the generation and the base types to follow the Rust version 100%. This means `{as, is}Error` is now available as `{as, is}Err` on the `Result` type. The older versions can still be used, but the `*Error` interfaces are now marked as deprecated.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Adjust `Result<T, E>` interface to be 100% compatible with the Rust version
|
||||||
|
- Add the `2028` upgrade to the known upgrades (optimizing certain `.at` queries)
|
||||||
|
- Adjust council derives to cater for latest Substrate & Polkadot
|
||||||
|
- Adjust Rococo know type definitions to cater for the latest update
|
||||||
|
- Update types for latest Polkadot/Substrate
|
||||||
|
- Add generic arguments for TypeScript users to `.entries/.keys` to deal with the key typings
|
||||||
|
|
||||||
|
|
||||||
|
## 3.8.1 Feb 7, 2021
|
||||||
|
|
||||||
|
Upgrade priority: Low. Recommended for users of the latest Substrate master, especially using contracts.
|
||||||
|
|
||||||
|
- **Important** The `api-contract` `Code` now supports deploying the code and a contract in on operation. This aligns with the latest Substrate where code cannot be uploaded with a contract. The `createBlueprint` is therefore deprecated, use `code.tx.<constructor>(...)` to deploy code. (Compatible with both old and new versions of Substrate)
|
||||||
|
|
||||||
|
Contributed:
|
||||||
|
|
||||||
|
- Add support for latest Frontier RPCs (Thanks to https://github.com/jnaviask)
|
||||||
|
- Fix user-supplied signed extensions type signature (Thanks to https://github.com/ntduan)
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Expand `api-contract` to allow for `Code` to deploy contract alongside code. `createBlueprint` is now deprecated, replaced by `createContract` or the preferred `code.tx.<constructor>`, which uploads and deploys the code in one operation. This aligns with the current Substrate master contracts implementation.
|
||||||
|
- Allow for signed extensions to be supplied inside type bundles
|
||||||
|
- Ensure that the auto-connect state is checked on auto-connections (respecting disconnect)
|
||||||
|
- Added `CancelProxy` to `ProxyTypes on Polkadot, Kusama & Westend
|
||||||
|
- Updated to latest Substrate metadata
|
||||||
|
|
||||||
|
|
||||||
|
## 3.7.3 Feb 2, 2021
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
- Added Polkadot upgrade block for runtime 27 (known checkpoint optimization)
|
||||||
|
|
||||||
|
|
||||||
## 3.7.2 Feb 2, 2021
|
## 3.7.2 Feb 2, 2021
|
||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
# @polkadot/api
|
# @polkadot/api
|
||||||
|
|
||||||
This library provides a clean wrapper around all the methods exposed by a Polkadot/Substrate network client and defines all the types exposed by a node. For complete documentation around the classes, interfaces and their use, visit the [documentation portal](https://polkadot.js.org/api/).
|
This library provides a clean wrapper around all the methods exposed by a Polkadot/Substrate network client and defines all the types exposed by a node. For complete documentation around the classes, interfaces and their use, visit the [documentation portal](https://polkadot.js.org/docs/api/).
|
||||||
|
|
||||||
If you are an existing user, please be sure to track the [CHANGELOG](CHANGELOG.md) and [UPGRADING](UPGRADING.md) guides when changing versions.
|
If you are an existing user, please be sure to track the [CHANGELOG](CHANGELOG.md) and [UPGRADING](UPGRADING.md) guides when changing versions.
|
||||||
|
|
||||||
@@ -21,8 +21,8 @@ The API is split up into a number of internal packages -
|
|||||||
|
|
||||||
- [@polkadot/api](packages/api/) The API library, providing both Promise and RxJS Observable-based interfaces. This is the main user-facing entry point.
|
- [@polkadot/api](packages/api/) The API library, providing both Promise and RxJS Observable-based interfaces. This is the main user-facing entry point.
|
||||||
- [@polkadot/api-derive](packages/api-derive/) Derived results that are injected into the API, allowing for combinations of various query results (only used internally and exposed on the Api instances via `api.derive.*`)
|
- [@polkadot/api-derive](packages/api-derive/) Derived results that are injected into the API, allowing for combinations of various query results (only used internally and exposed on the Api instances via `api.derive.*`)
|
||||||
- [@polkadot/api-metadata](packages/api-metadata/) Base extrinsic, storage and constant injectors for injection
|
- [@polkadot/metadata](packages/metadata/) Base extrinsic, storage and constant injectors for injection
|
||||||
- [@polkadot/rpc-core](packages/rpc-core/) Wrapper around all [JSON-RPC methods](https://polkadot.js.org/api/substrate/rpc.html) exposed by a Polkadot network client
|
- [@polkadot/rpc-core](packages/rpc-core/) Wrapper around all [JSON-RPC methods](https://polkadot.js.org/docs/substrate/rpc) exposed by a Polkadot network client
|
||||||
- [@polkadot/rpc-provider](packages/rpc-provider/) Providers for connecting to nodes, including WebSockets and Http
|
- [@polkadot/rpc-provider](packages/rpc-provider/) Providers for connecting to nodes, including WebSockets and Http
|
||||||
|
|
||||||
Type definitions for interfaces as exposed by Polkadot & Substrate clients -
|
Type definitions for interfaces as exposed by Polkadot & Substrate clients -
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
const config = require('@polkadot/dev/config/jest.cjs');
|
const config = require('@polkadot/dev/config/jest.cjs');
|
||||||
|
|
||||||
module.exports = Object.assign({}, config, {
|
module.exports = {
|
||||||
|
...config,
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'@polkadot/api-(contract|derive)(.*)$': '<rootDir>/packages/api-$1/src/$2',
|
'@polkadot/api-(contract|derive)(.*)$': '<rootDir>/packages/api-$1/src/$2',
|
||||||
// eslint-disable-next-line sort-keys
|
// eslint-disable-next-line sort-keys
|
||||||
@@ -26,5 +27,6 @@ module.exports = Object.assign({}, config, {
|
|||||||
'<rootDir>/packages/types/build',
|
'<rootDir>/packages/types/build',
|
||||||
'<rootDir>/packages/types-known/build'
|
'<rootDir>/packages/types-known/build'
|
||||||
],
|
],
|
||||||
resolver: '@polkadot/dev/config/jest-resolver.cjs'
|
testTimeout: 30000,
|
||||||
});
|
transformIgnorePatterns: ['/node_modules/(?!@polkadot|@babel/runtime/helpers/esm/)']
|
||||||
|
};
|
||||||
+10
-10
@@ -8,7 +8,7 @@
|
|||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.3.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn build:interfaces && polkadot-dev-build-ts",
|
"build": "yarn build:interfaces && polkadot-dev-build-ts",
|
||||||
@@ -20,19 +20,19 @@
|
|||||||
"lint": "polkadot-dev-run-lint",
|
"lint": "polkadot-dev-run-lint",
|
||||||
"clean": "polkadot-dev-clean-build",
|
"clean": "polkadot-dev-clean-build",
|
||||||
"postinstall": "polkadot-dev-yarn-only",
|
"postinstall": "polkadot-dev-yarn-only",
|
||||||
"test": "polkadot-dev-run-test --coverage --runInBand --testPathIgnorePatterns e2e",
|
"test": "polkadot-dev-run-test --coverage --forceExit --runInBand --testPathIgnorePatterns e2e",
|
||||||
"test:one": "polkadot-dev-run-test",
|
"test:one": "polkadot-dev-run-test --detectOpenHandles --forceExit",
|
||||||
"test:watch": "polkadot-dev-run-test --watch"
|
"test:watch": "polkadot-dev-run-test --watch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.10",
|
"@babel/core": "^7.14.6",
|
||||||
"@babel/register": "^7.12.10",
|
"@babel/register": "^7.14.5",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.14.6",
|
||||||
"@polkadot/dev": "^0.61.24",
|
"@polkadot/dev": "^0.62.44",
|
||||||
"@polkadot/ts": "^0.3.59",
|
"@polkadot/ts": "^0.4.2",
|
||||||
"@polkadot/typegen": "workspace:packages/typegen",
|
"@polkadot/typegen": "workspace:packages/typegen",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.23",
|
||||||
"copyfiles": "^2.4.1"
|
"copyfiles": "^2.4.1"
|
||||||
},
|
},
|
||||||
"version": "3.7.2"
|
"version": "4.17.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Abi } from '@polkadot/api-contract';
|
|||||||
|
|
||||||
const wsProvider = new WsProvider(<...Node Url...>);
|
const wsProvider = new WsProvider(<...Node Url...>);
|
||||||
const api = await ApiPromise.create({ provider: wsProvider });
|
const api = await ApiPromise.create({ provider: wsProvider });
|
||||||
const abi = new Abi(api.registry, <...JSON ABI...>);
|
const abi = new Abi(<...JSON ABI...>, api.registry.getChainProperties());
|
||||||
|
|
||||||
api.tx.contracts
|
api.tx.contracts
|
||||||
.call(<contract addr>, <value>, <max gas>, abi.messages.<method name>(<...params...>))
|
.call(<contract addr>, <value>, <max gas>, abi.messages.<method name>(<...params...>))
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/api-contract",
|
"name": "@polkadot/api-contract",
|
||||||
"version": "3.7.2",
|
"version": "4.17.1",
|
||||||
|
"type": "module",
|
||||||
"description": "Interfaces for interacting with contracts and contract ABIs",
|
"description": "Interfaces for interacting with contracts and contract ABIs",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"sideEffects": false,
|
"sideEffects": [
|
||||||
|
"./detectPackage.js",
|
||||||
|
"./detectPackage.cjs"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||||
"maintainers": [],
|
"maintainers": [],
|
||||||
"contributors": [],
|
"contributors": [],
|
||||||
@@ -12,11 +19,10 @@
|
|||||||
"bugs": "https://github.com/polkadot-js/api/issues",
|
"bugs": "https://github.com/polkadot-js/api/issues",
|
||||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.14.6",
|
||||||
"@polkadot/api": "3.7.2",
|
"@polkadot/api": "4.17.1",
|
||||||
"@polkadot/types": "3.7.2",
|
"@polkadot/types": "4.17.1",
|
||||||
"@polkadot/util": "^5.5.1",
|
"@polkadot/util": "^6.11.1",
|
||||||
"@polkadot/x-rxjs": "^5.5.1",
|
"@polkadot/x-rxjs": "^6.11.1"
|
||||||
"bn.js": "^4.11.9"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { blake2AsHex } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
import abis from '../test/contracts';
|
import abis from '../test/contracts';
|
||||||
import { Abi } from '.';
|
import { Abi } from '.';
|
||||||
|
|
||||||
interface JSONAbi {
|
interface JSONAbi {
|
||||||
|
source: {
|
||||||
|
compiler: string,
|
||||||
|
hash: string,
|
||||||
|
language: string,
|
||||||
|
wasm: string
|
||||||
|
},
|
||||||
spec: {
|
spec: {
|
||||||
messages: {
|
messages: {
|
||||||
name: string[] | string
|
name: string[] | string
|
||||||
@@ -27,4 +35,18 @@ describe('Abi', (): void => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('has the correct hash for the source', (): void => {
|
||||||
|
const bundle = abis.ink_flipperBundle as JSONAbi;
|
||||||
|
const abi = new Abi(bundle as any);
|
||||||
|
|
||||||
|
// manual
|
||||||
|
expect(bundle.source.hash).toEqual(blake2AsHex(bundle.source.wasm));
|
||||||
|
|
||||||
|
// the Codec hash
|
||||||
|
expect(bundle.source.hash).toEqual(abi.project.source.wasm.hash.toHex());
|
||||||
|
|
||||||
|
// the hash as per the actual Abi
|
||||||
|
expect(bundle.source.hash).toEqual(abi.project.source.wasmHash.toHex());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,12 +6,10 @@ import type { ChainProperties, ContractConstructorSpec, ContractEventSpec, Contr
|
|||||||
import type { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
|
import type { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
|
||||||
import type { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
|
import type { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
|
||||||
|
|
||||||
import { assert, assertReturn, compactAddLength, compactStripLength, isNumber, isObject, isString, logger, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
|
import { assert, assertReturn, compactAddLength, compactStripLength, isNumber, isObject, isString, logger, stringCamelCase, stringify, u8aConcat, u8aToHex } from '@polkadot/util';
|
||||||
|
|
||||||
import { MetaRegistry } from './MetaRegistry';
|
import { MetaRegistry } from './MetaRegistry';
|
||||||
|
|
||||||
const EMPTY_U8A = new Uint8Array();
|
|
||||||
|
|
||||||
const l = logger('Abi');
|
const l = logger('Abi');
|
||||||
|
|
||||||
function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string | number): T {
|
function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string | number): T {
|
||||||
@@ -21,7 +19,7 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
|
|||||||
? list.find(({ identifier }) => [identifier, stringCamelCase(identifier)].includes(messageOrId.toString()))
|
? list.find(({ identifier }) => [identifier, stringCamelCase(identifier)].includes(messageOrId.toString()))
|
||||||
: messageOrId;
|
: messageOrId;
|
||||||
|
|
||||||
return assertReturn(message, `Attempted to call an invalid contract interface, ${JSON.stringify(messageOrId)}`);
|
return assertReturn(message, () => `Attempted to call an invalid contract interface, ${stringify(messageOrId)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Abi {
|
export class Abi {
|
||||||
@@ -45,13 +43,13 @@ export class Abi {
|
|||||||
assert(isObject(json) && !Array.isArray(json) && json.metadataVersion && isObject(json.spec) && !Array.isArray(json.spec) && Array.isArray(json.spec.constructors) && Array.isArray(json.spec.messages), 'Invalid JSON ABI structure supplied, expected a recent metadata version');
|
assert(isObject(json) && !Array.isArray(json) && json.metadataVersion && isObject(json.spec) && !Array.isArray(json.spec) && Array.isArray(json.spec.constructors) && Array.isArray(json.spec.messages), 'Invalid JSON ABI structure supplied, expected a recent metadata version');
|
||||||
|
|
||||||
this.json = json;
|
this.json = json;
|
||||||
this.registry = new MetaRegistry(chainProperties);
|
this.registry = new MetaRegistry(json.metadataVersion as string, chainProperties);
|
||||||
this.project = this.registry.createType('ContractProject', json);
|
this.project = this.registry.createType('ContractProject', json);
|
||||||
|
|
||||||
this.registry.setMetaTypes(this.project.types);
|
this.registry.setMetaTypes(this.project.types);
|
||||||
|
|
||||||
this.project.types.forEach((_, index) =>
|
this.project.types.forEach((_, index) =>
|
||||||
this.registry.getMetaTypeDef({ type: this.registry.createType('SiLookupTypeId', index + 1) })
|
this.registry.getMetaTypeDef({ type: this.registry.createType('SiLookupTypeId', index + this.registry.typeOffset) })
|
||||||
);
|
);
|
||||||
this.constructors = this.project.spec.constructors.map((spec: ContractConstructorSpec, index) =>
|
this.constructors = this.project.spec.constructors.map((spec: ContractConstructorSpec, index) =>
|
||||||
this.#createMessage(spec, index, {
|
this.#createMessage(spec, index, {
|
||||||
@@ -81,7 +79,7 @@ export class Abi {
|
|||||||
const index = data[0];
|
const index = data[0];
|
||||||
const event = this.#events[index];
|
const event = this.#events[index];
|
||||||
|
|
||||||
assert(event, `Unable to find event with index ${index}`);
|
assert(event, () => `Unable to find event with index ${index}`);
|
||||||
|
|
||||||
return event.fromU8a(data.subarray(1));
|
return event.fromU8a(data.subarray(1));
|
||||||
}
|
}
|
||||||
@@ -118,7 +116,7 @@ export class Abi {
|
|||||||
type: this.registry.getMetaTypeDef(arg.type)
|
type: this.registry.getMetaTypeDef(arg.type)
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
l.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
|
l.error(`Error expanding argument ${index} in ${stringify(spec)}`);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -129,7 +127,7 @@ export class Abi {
|
|||||||
const args = this.#createArgs(spec.args, spec);
|
const args = this.#createArgs(spec.args, spec);
|
||||||
const event = {
|
const event = {
|
||||||
args,
|
args,
|
||||||
docs: spec.docs.map((doc) => doc.toString()),
|
docs: spec.docs.map((d) => d.toString()),
|
||||||
fromU8a: (data: Uint8Array): DecodedEvent => ({
|
fromU8a: (data: Uint8Array): DecodedEvent => ({
|
||||||
args: this.#decodeArgs(args, data),
|
args: this.#decodeArgs(args, data),
|
||||||
event
|
event
|
||||||
@@ -143,19 +141,21 @@ export class Abi {
|
|||||||
|
|
||||||
#createMessage = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
|
#createMessage = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
|
||||||
const args = this.#createArgs(spec.args, spec);
|
const args = this.#createArgs(spec.args, spec);
|
||||||
|
const identifier = spec.name.toString();
|
||||||
const message = {
|
const message = {
|
||||||
...add,
|
...add,
|
||||||
args,
|
args,
|
||||||
docs: spec.docs.map((doc) => doc.toString()),
|
docs: spec.docs.map((d) => d.toString()),
|
||||||
fromU8a: (data: Uint8Array): DecodedMessage => ({
|
fromU8a: (data: Uint8Array): DecodedMessage => ({
|
||||||
args: this.#decodeArgs(args, data),
|
args: this.#decodeArgs(args, data),
|
||||||
message
|
message
|
||||||
}),
|
}),
|
||||||
identifier: spec.name.toString(),
|
identifier,
|
||||||
index,
|
index,
|
||||||
|
method: stringCamelCase(identifier),
|
||||||
selector: spec.selector,
|
selector: spec.selector,
|
||||||
toU8a: (params: CodecArg[], additional?: Uint8Array) =>
|
toU8a: (params: CodecArg[]) =>
|
||||||
this.#encodeArgs(spec, args, params, additional)
|
this.#encodeArgs(spec, args, params)
|
||||||
};
|
};
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
@@ -185,14 +185,13 @@ export class Abi {
|
|||||||
return message.fromU8a(trimmed.subarray(4));
|
return message.fromU8a(trimmed.subarray(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
#encodeArgs = ({ name, selector }: ContractMessageSpec | ContractConstructorSpec, args: AbiParam[], data: CodecArg[], additional = EMPTY_U8A): Uint8Array => {
|
#encodeArgs = ({ name, selector }: ContractMessageSpec | ContractConstructorSpec, args: AbiParam[], data: CodecArg[]): Uint8Array => {
|
||||||
assert(data.length === args.length, `Expected ${args.length} arguments to contract message '${name.toString()}', found ${data.length}`);
|
assert(data.length === args.length, () => `Expected ${args.length} arguments to contract message '${name.toString()}', found ${data.length}`);
|
||||||
|
|
||||||
return compactAddLength(
|
return compactAddLength(
|
||||||
u8aConcat(
|
u8aConcat(
|
||||||
this.registry.createType('ContractSelector', selector).toU8a(),
|
this.registry.createType('ContractSelector', selector).toU8a(),
|
||||||
...args.map(({ type }, index) => this.registry.createType(type.type as 'Text', data[index]).toU8a()),
|
...args.map(({ type }, index) => this.registry.createType(type.type as 'Text', data[index]).toU8a())
|
||||||
additional
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ interface PartialTypeSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convert the offset into project-specific, index-1
|
// convert the offset into project-specific, index-1
|
||||||
export function getRegistryOffset (id: SiLookupTypeId): number {
|
export function getRegistryOffset (id: SiLookupTypeId, typeOffset: number): number {
|
||||||
return id.toNumber() - 1;
|
return id.toNumber() - typeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRIMITIVE_ALIAS: Record<string, keyof InterfaceTypes> = {
|
const PRIMITIVE_ALIAS: Record<string, keyof InterfaceTypes> = {
|
||||||
@@ -28,11 +28,18 @@ const PRIMITIVE_ALWAYS = ['AccountId', 'AccountIndex', 'Address', 'Balance'];
|
|||||||
export class MetaRegistry extends TypeRegistry {
|
export class MetaRegistry extends TypeRegistry {
|
||||||
public readonly metaTypeDefs: TypeDef[] = [];
|
public readonly metaTypeDefs: TypeDef[] = [];
|
||||||
|
|
||||||
|
public readonly typeOffset;
|
||||||
|
|
||||||
#siTypes: SiType[] = [];
|
#siTypes: SiType[] = [];
|
||||||
|
|
||||||
constructor (chainProperties?: ChainProperties) {
|
constructor (metadataVersion: string, chainProperties?: ChainProperties) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
const [major, minor] = metadataVersion.split('.').map((n) => parseInt(n, 10));
|
||||||
|
|
||||||
|
// type indexes are 1-based pre 0.7 and 0-based post
|
||||||
|
this.typeOffset = (major === 0 && minor < 7) ? 1 : 0;
|
||||||
|
|
||||||
if (chainProperties) {
|
if (chainProperties) {
|
||||||
this.setChainProperties(chainProperties);
|
this.setChainProperties(chainProperties);
|
||||||
}
|
}
|
||||||
@@ -43,7 +50,7 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getMetaTypeDef (typeSpec: PartialTypeSpec): TypeDef {
|
public getMetaTypeDef (typeSpec: PartialTypeSpec): TypeDef {
|
||||||
const offset = getRegistryOffset(typeSpec.type);
|
const offset = getRegistryOffset(typeSpec.type, this.typeOffset);
|
||||||
let typeDef = this.metaTypeDefs[offset];
|
let typeDef = this.metaTypeDefs[offset];
|
||||||
|
|
||||||
if (!typeDef) {
|
if (!typeDef) {
|
||||||
@@ -78,19 +85,22 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#getMetaType = (id: SiLookupTypeId): SiType => {
|
#getMetaType = (id: SiLookupTypeId): SiType => {
|
||||||
const type = this.#siTypes[getRegistryOffset(id)];
|
const type = this.#siTypes[getRegistryOffset(id, this.typeOffset)];
|
||||||
|
|
||||||
assert(!isUndefined(type), `getMetaType:: Unable to find ${id.toNumber()} in type values`);
|
assert(!isUndefined(type), () => `getMetaType:: Unable to find ${id.toNumber()} in type values`);
|
||||||
|
|
||||||
return this.createType('SiType', type);
|
return this.createType('SiType', type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#extract = (type: SiType, id: SiLookupTypeId): TypeDef => {
|
#extract = (type: SiType, id: SiLookupTypeId): TypeDef => {
|
||||||
const path = [...type.path];
|
const path = [...type.path];
|
||||||
const pathFinal = path.length ? path[path.length - 1].toString() : '';
|
const isPrimitivePath = !!path.length && (
|
||||||
|
(path.length > 2 && path[0].eq('ink_env') && path[1].eq('types')) ||
|
||||||
|
PRIMITIVE_ALWAYS.includes(path[path.length - 1].toString())
|
||||||
|
);
|
||||||
let typeDef: Omit<TypeDef, 'type'>;
|
let typeDef: Omit<TypeDef, 'type'>;
|
||||||
|
|
||||||
if (type.path.join('::').startsWith('ink_env::types::') || PRIMITIVE_ALWAYS.includes(pathFinal)) {
|
if (isPrimitivePath) {
|
||||||
typeDef = this.#extractPrimitivePath(type);
|
typeDef = this.#extractPrimitivePath(type);
|
||||||
} else if (type.def.isPrimitive) {
|
} else if (type.def.isPrimitive) {
|
||||||
typeDef = this.#extractPrimitive(type);
|
typeDef = this.#extractPrimitive(type);
|
||||||
@@ -116,7 +126,7 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
: {}
|
: {}
|
||||||
),
|
),
|
||||||
...(path.length > 1
|
...(path.length > 1
|
||||||
? { namespace: path.map((segment) => segment.toString()).join('::') }
|
? { namespace: path.map((s) => s.toString()).join('::') }
|
||||||
: {}
|
: {}
|
||||||
),
|
),
|
||||||
...(type.params.length > 0
|
...(type.params.length > 0
|
||||||
@@ -128,7 +138,7 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#extractArray = ({ len: length, type }: SiTypeDefArray): Omit<TypeDef, 'type'> => {
|
#extractArray = ({ len: length, type }: SiTypeDefArray): Omit<TypeDef, 'type'> => {
|
||||||
assert(!length || length.toNumber() <= 256, 'MetaRegistry: Only support for [Type; <length>], where length > 256');
|
assert(!length || length.toNumber() <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.VecFixed,
|
info: TypeDefInfo.VecFixed,
|
||||||
@@ -144,27 +154,25 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
]),
|
]),
|
||||||
[true, true]);
|
[true, true]);
|
||||||
|
|
||||||
let info;
|
assert(isTuple || isStruct, 'Invalid fields type detected, expected either Tuple or Struct');
|
||||||
|
|
||||||
// check for tuple first (no fields may be available)
|
const sub = fields.map(({ name, type }) => ({
|
||||||
if (isTuple) {
|
...this.getMetaTypeDef({ type }),
|
||||||
info = TypeDefInfo.Tuple;
|
...(name.isSome
|
||||||
} else if (isStruct) {
|
? { name: name.unwrap().toString() }
|
||||||
info = TypeDefInfo.Struct;
|
: {}
|
||||||
} else {
|
)
|
||||||
throw new Error('Invalid fields type detected, expected either Tuple or Struct');
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
const sub = fields.map(({ name, type }) => {
|
|
||||||
return {
|
|
||||||
...this.getMetaTypeDef({ type }),
|
|
||||||
...(name.isSome ? { name: name.unwrap().toString() } : {})
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return isTuple && sub.length === 1
|
return isTuple && sub.length === 1
|
||||||
? sub[0]
|
? sub[0]
|
||||||
: { info, sub };
|
: {
|
||||||
|
// check for tuple first (no fields may be available)
|
||||||
|
info: isTuple
|
||||||
|
? TypeDefInfo.Tuple
|
||||||
|
: TypeDefInfo.Struct,
|
||||||
|
sub
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#extractPrimitive = (type: SiType): TypeDef => {
|
#extractPrimitive = (type: SiType): TypeDef => {
|
||||||
@@ -184,7 +192,7 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#extractSequence = ({ type }: SiTypeDefSequence, id: SiLookupTypeId): Omit<TypeDef, 'type'> => {
|
#extractSequence = ({ type }: SiTypeDefSequence, id: SiLookupTypeId): Omit<TypeDef, 'type'> => {
|
||||||
assert(!!type, `ContractRegistry: Invalid sequence type found at id ${id.toString()}`);
|
assert(!!type, () => `ContractRegistry: Invalid sequence type found at id ${id.toString()}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.Vec,
|
info: TypeDefInfo.Vec,
|
||||||
@@ -205,32 +213,28 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
const { params, path } = this.#getMetaType(id);
|
const { params, path } = this.#getMetaType(id);
|
||||||
const specialVariant = path[0].toString();
|
const specialVariant = path[0].toString();
|
||||||
|
|
||||||
if (specialVariant === 'Option') {
|
return specialVariant === 'Option'
|
||||||
return {
|
? {
|
||||||
info: TypeDefInfo.Option,
|
info: TypeDefInfo.Option,
|
||||||
sub: this.getMetaTypeDef({ type: params[0] })
|
sub: this.getMetaTypeDef({ type: params[0] })
|
||||||
};
|
}
|
||||||
} else if (specialVariant === 'Result') {
|
: specialVariant === 'Result'
|
||||||
return {
|
? {
|
||||||
info: TypeDefInfo.Result,
|
info: TypeDefInfo.Result,
|
||||||
sub: params.map((type, index) => ({
|
sub: params.map((type, index) => ({
|
||||||
name: ['Ok', 'Error'][index],
|
name: ['Ok', 'Error'][index],
|
||||||
...this.getMetaTypeDef({ type })
|
...this.getMetaTypeDef({ type })
|
||||||
}))
|
}))
|
||||||
};
|
}
|
||||||
}
|
: {
|
||||||
|
info: TypeDefInfo.Enum,
|
||||||
return {
|
sub: this.#extractVariantSub(variants)
|
||||||
info: TypeDefInfo.Enum,
|
};
|
||||||
sub: this.#extractVariantSub(variants)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#extractVariantSub = (variants: SiVariant[]): TypeDef[] => {
|
#extractVariantSub = (variants: SiVariant[]): TypeDef[] => {
|
||||||
const isAllUnitVariants = variants.every(({ fields }) => fields.length === 0);
|
return variants.every(({ fields }) => fields.length === 0)
|
||||||
|
? variants.map(({ discriminant, name }) => ({
|
||||||
if (isAllUnitVariants) {
|
|
||||||
return variants.map(({ discriminant, name }) => ({
|
|
||||||
...(
|
...(
|
||||||
discriminant.isSome
|
discriminant.isSome
|
||||||
? { ext: { discriminant: discriminant.unwrap().toNumber() } }
|
? { ext: { discriminant: discriminant.unwrap().toNumber() } }
|
||||||
@@ -239,14 +243,10 @@ export class MetaRegistry extends TypeRegistry {
|
|||||||
info: TypeDefInfo.Plain,
|
info: TypeDefInfo.Plain,
|
||||||
name: name.toString(),
|
name: name.toString(),
|
||||||
type: 'Null'
|
type: 'Null'
|
||||||
}));
|
}))
|
||||||
}
|
: variants.map(({ fields, name }) => withTypeString({
|
||||||
|
|
||||||
return variants.map(({ fields, name }) =>
|
|
||||||
withTypeString({
|
|
||||||
...this.#extractFields(fields),
|
...this.#extractFields(fields),
|
||||||
name: name.toString()
|
name: name.toString()
|
||||||
})
|
}));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
|||||||
import type { AnyJson, Registry } from '@polkadot/types/types';
|
import type { AnyJson, Registry } from '@polkadot/types/types';
|
||||||
|
|
||||||
import { ApiBase } from '@polkadot/api/base';
|
import { ApiBase } from '@polkadot/api/base';
|
||||||
import { assert } from '@polkadot/util';
|
import { assert, isFunction } from '@polkadot/util';
|
||||||
|
|
||||||
import { Abi } from '../Abi';
|
import { Abi } from '../Abi';
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ export abstract class Base<ApiType extends ApiTypes> {
|
|||||||
this.registry = this.abi.registry;
|
this.registry = this.abi.registry;
|
||||||
this._decorateMethod = decorateMethod;
|
this._decorateMethod = decorateMethod;
|
||||||
|
|
||||||
assert(this.api.rx.tx.contracts && this.api.rx.tx.contracts.putCode, 'You need to connect to a node with the contracts module, the metadata does not enable api.tx.contracts on this instance');
|
assert(!!(api && api.isConnected && api.tx && api.tx.contracts && Object.keys(api.tx.contracts).length), 'Your API has not been initialized correctly and it not decorated with the runtime interfaces for contracts as retrieved from the on-chain runtime');
|
||||||
|
assert(isFunction(api.tx.contracts.instantiateWithCode), 'You need to connect to a chain with a runtime with a V3 contracts module. The runtime does not expose api.tx.contracts.instantiateWithCode');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,44 +6,17 @@ import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
|||||||
import type { AccountId, EventRecord, Hash } from '@polkadot/types/interfaces';
|
import type { AccountId, EventRecord, Hash } from '@polkadot/types/interfaces';
|
||||||
import type { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types';
|
import type { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types';
|
||||||
import type { AbiConstructor, BlueprintOptions } from '../types';
|
import type { AbiConstructor, BlueprintOptions } from '../types';
|
||||||
import type { BlueprintDeploy, ContractGeneric, MapConstructorExec } from './types';
|
import type { MapConstructorExec } from './types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { SubmittableResult } from '@polkadot/api';
|
import { SubmittableResult } from '@polkadot/api';
|
||||||
import { ApiBase } from '@polkadot/api/base';
|
import { ApiBase } from '@polkadot/api/base';
|
||||||
import { Bytes } from '@polkadot/types';
|
import { BN_ZERO, isUndefined } from '@polkadot/util';
|
||||||
import { compactAddLength, isUndefined, stringCamelCase, u8aToU8a } from '@polkadot/util';
|
|
||||||
import { randomAsU8a } from '@polkadot/util-crypto';
|
|
||||||
|
|
||||||
import { Abi } from '../Abi';
|
import { Abi } from '../Abi';
|
||||||
import { applyOnEvent, extractOptions, isOptions } from '../util';
|
import { applyOnEvent } from '../util';
|
||||||
import { Base } from './Base';
|
import { Base } from './Base';
|
||||||
import { Contract } from './Contract';
|
import { Contract } from './Contract';
|
||||||
|
import { createBluePrintTx, encodeSalt } from './util';
|
||||||
const EMPTY_SALT = new Uint8Array();
|
|
||||||
|
|
||||||
function createTx <ApiType extends ApiTypes> (fn: (options: BlueprintOptions, params: CodecArg[]) => SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>>): BlueprintDeploy<ApiType> {
|
|
||||||
return (options: BigInt | string | number | BN | BlueprintOptions, ...params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> =>
|
|
||||||
isOptions(options)
|
|
||||||
? fn(options, params)
|
|
||||||
: fn(...extractOptions(options, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWithId <T> (fn: (constructorOrId: AbiConstructor | string | number, options: BlueprintOptions, params: CodecArg[]) => T): ContractGeneric<BlueprintOptions, T> {
|
|
||||||
return (constructorOrId: AbiConstructor | string | number, options: BigInt | string | number | BN | BlueprintOptions, ...params: CodecArg[]): T =>
|
|
||||||
isOptions(options)
|
|
||||||
? fn(constructorOrId, options, params)
|
|
||||||
: fn(constructorOrId, ...extractOptions(options, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeSalt (salt: Uint8Array | string | null = randomAsU8a()) {
|
|
||||||
return salt instanceof Bytes
|
|
||||||
? salt
|
|
||||||
: salt && salt.length
|
|
||||||
? compactAddLength(u8aToU8a(salt))
|
|
||||||
: EMPTY_SALT;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BlueprintSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
|
export class BlueprintSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
|
||||||
public readonly contract?: Contract<ApiType>;
|
public readonly contract?: Contract<ApiType>;
|
||||||
@@ -61,25 +34,16 @@ export class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
*/
|
*/
|
||||||
public readonly codeHash: Hash;
|
public readonly codeHash: Hash;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @description Deprecated. Use `.tx.<constructorName>`. Creates a contract in a non-deterministic way.
|
|
||||||
*/
|
|
||||||
public readonly createContract: ContractGeneric<BlueprintOptions, SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>>>;
|
|
||||||
|
|
||||||
readonly #tx: MapConstructorExec<ApiType> = {};
|
readonly #tx: MapConstructorExec<ApiType> = {};
|
||||||
|
|
||||||
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, codeHash: string | Hash | Uint8Array, decorateMethod: DecorateMethod<ApiType>) {
|
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, codeHash: string | Hash | Uint8Array, decorateMethod: DecorateMethod<ApiType>) {
|
||||||
super(api, abi, decorateMethod);
|
super(api, abi, decorateMethod);
|
||||||
|
|
||||||
this.codeHash = this.registry.createType('Hash', codeHash);
|
this.codeHash = this.registry.createType('Hash', codeHash);
|
||||||
this.createContract = createWithId(this.#deploy);
|
|
||||||
|
|
||||||
this.abi.constructors.forEach((c): void => {
|
this.abi.constructors.forEach((c): void => {
|
||||||
const messageName = stringCamelCase(c.identifier);
|
if (isUndefined(this.#tx[c.method])) {
|
||||||
|
this.#tx[c.method] = createBluePrintTx((o, p) => this.#deploy(c, o, p));
|
||||||
if (isUndefined(this.#tx[messageName])) {
|
|
||||||
this.#tx[messageName] = createTx((o, p) => this.#deploy(c, o, p));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -88,20 +52,19 @@ export class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
return this.#tx;
|
return this.#tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#deploy = (constructorOrId: AbiConstructor | string| number, { gasLimit = 0, salt, value = 0 }: BlueprintOptions, params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
|
#deploy = (constructorOrId: AbiConstructor | string | number, { gasLimit = BN_ZERO, salt, value = BN_ZERO }: BlueprintOptions, params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
|
||||||
const encodedSalt = encodeSalt(salt);
|
return this.api.tx.contracts
|
||||||
const withSalt = this.api.tx.contracts.instantiate.meta.args.length === 5;
|
.instantiate(
|
||||||
const encoded = this.abi.findConstructor(constructorOrId).toU8a(params, withSalt ? EMPTY_SALT : encodedSalt);
|
value,
|
||||||
const tx = withSalt
|
gasLimit,
|
||||||
? this.api.tx.contracts.instantiate(value, gasLimit, this.codeHash, encoded, encodedSalt)
|
this.codeHash,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
this.abi.findConstructor(constructorOrId).toU8a(params),
|
||||||
// @ts-ignore old style with salt included
|
encodeSalt(salt)
|
||||||
: this.api.tx.contracts.instantiate(value, gasLimit, this.codeHash, encoded);
|
)
|
||||||
|
.withResultTransform((result: ISubmittableResult) =>
|
||||||
return tx.withResultTransform((result: ISubmittableResult) =>
|
new BlueprintSubmittableResult(result, applyOnEvent(result, ['Instantiated'], ([record]: EventRecord[]) =>
|
||||||
new BlueprintSubmittableResult(result, applyOnEvent(result, 'Instantiated', ([record]: EventRecord[]) =>
|
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
|
||||||
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
|
))
|
||||||
))
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,31 +3,39 @@
|
|||||||
|
|
||||||
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
||||||
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
||||||
import type { EventRecord, Hash } from '@polkadot/types/interfaces';
|
import type { EventRecord } from '@polkadot/types/interfaces';
|
||||||
import type { AnyJson, ISubmittableResult } from '@polkadot/types/types';
|
import type { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types';
|
||||||
|
import type { AbiConstructor, BlueprintOptions } from '../types';
|
||||||
|
import type { MapConstructorExec } from './types';
|
||||||
|
|
||||||
import { SubmittableResult } from '@polkadot/api';
|
import { SubmittableResult } from '@polkadot/api';
|
||||||
import { ApiBase } from '@polkadot/api/base';
|
import { ApiBase } from '@polkadot/api/base';
|
||||||
import { assert, compactAddLength, isWasm, u8aToU8a } from '@polkadot/util';
|
import { assert, BN_ZERO, compactAddLength, isUndefined, isWasm, u8aToU8a } from '@polkadot/util';
|
||||||
|
|
||||||
import { Abi } from '../Abi';
|
import { Abi } from '../Abi';
|
||||||
import { applyOnEvent } from '../util';
|
import { applyOnEvent } from '../util';
|
||||||
import { Base } from './Base';
|
import { Base } from './Base';
|
||||||
import { Blueprint } from './Blueprint';
|
import { Blueprint } from './Blueprint';
|
||||||
|
import { Contract } from './Contract';
|
||||||
|
import { createBluePrintTx, encodeSalt } from './util';
|
||||||
|
|
||||||
export class CodeSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
|
export class CodeSubmittableResult<ApiType extends ApiTypes> extends SubmittableResult {
|
||||||
public readonly blueprint?: Blueprint<ApiType>;
|
public readonly blueprint?: Blueprint<ApiType>;
|
||||||
|
public readonly contract?: Contract<ApiType>;
|
||||||
|
|
||||||
constructor (result: ISubmittableResult, blueprint?: Blueprint<ApiType>) {
|
constructor (result: ISubmittableResult, blueprint?: Blueprint<ApiType>, contract?: Contract<ApiType>) {
|
||||||
super(result);
|
super(result);
|
||||||
|
|
||||||
this.blueprint = blueprint;
|
this.blueprint = blueprint;
|
||||||
|
this.contract = contract;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
|
export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
|
||||||
public readonly code: Uint8Array;
|
public readonly code: Uint8Array;
|
||||||
|
|
||||||
|
readonly #tx: MapConstructorExec<ApiType> = {};
|
||||||
|
|
||||||
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer | null | undefined, decorateMethod: DecorateMethod<ApiType>) {
|
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer | null | undefined, decorateMethod: DecorateMethod<ApiType>) {
|
||||||
super(api, abi, decorateMethod);
|
super(api, abi, decorateMethod);
|
||||||
|
|
||||||
@@ -36,18 +44,37 @@ export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
: u8aToU8a(wasm);
|
: u8aToU8a(wasm);
|
||||||
|
|
||||||
assert(isWasm(this.code), 'No WASM code provided');
|
assert(isWasm(this.code), 'No WASM code provided');
|
||||||
|
|
||||||
|
this.abi.constructors.forEach((c): void => {
|
||||||
|
if (isUndefined(this.#tx[c.method])) {
|
||||||
|
this.#tx[c.method] = createBluePrintTx((o, p) => this.#instantiate(c, o, p));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public get tx (): MapConstructorExec<ApiType> {
|
||||||
* @description Deploy the code bundle, creating a Blueprint.
|
return this.#tx;
|
||||||
*/
|
}
|
||||||
public createBlueprint (): SubmittableExtrinsic<ApiType, CodeSubmittableResult<ApiType>> {
|
|
||||||
|
#instantiate = (constructorOrId: AbiConstructor | string | number, { gasLimit = BN_ZERO, salt, value = BN_ZERO }: BlueprintOptions, params: CodecArg[]): SubmittableExtrinsic<ApiType, CodeSubmittableResult<ApiType>> => {
|
||||||
return this.api.tx.contracts
|
return this.api.tx.contracts
|
||||||
.putCode(compactAddLength(this.code))
|
.instantiateWithCode(
|
||||||
|
value,
|
||||||
|
gasLimit,
|
||||||
|
compactAddLength(this.code),
|
||||||
|
this.abi.findConstructor(constructorOrId).toU8a(params),
|
||||||
|
encodeSalt(salt)
|
||||||
|
)
|
||||||
.withResultTransform((result: ISubmittableResult) =>
|
.withResultTransform((result: ISubmittableResult) =>
|
||||||
new CodeSubmittableResult(result, applyOnEvent(result, 'CodeStored', ([record]: EventRecord[]) =>
|
new CodeSubmittableResult(result, ...(applyOnEvent(result, ['CodeStored', 'Instantiated'], (records: EventRecord[]) =>
|
||||||
new Blueprint<ApiType>(this.api, this.abi, record.event.data[0] as Hash, this._decorateMethod)
|
records.reduce<[Blueprint<ApiType>?, Contract<ApiType>?]>(([blueprint, contract], { event }) =>
|
||||||
))
|
this.api.events.contracts.Instantiated.is(event)
|
||||||
|
? [blueprint, new Contract<ApiType>(this.api, this.abi, event.data[1], this._decorateMethod)]
|
||||||
|
: this.api.events.contracts.CodeStored.is(event)
|
||||||
|
? [new Blueprint<ApiType>(this.api, this.abi, event.data[0], this._decorateMethod), contract]
|
||||||
|
: [blueprint, contract],
|
||||||
|
[])
|
||||||
|
) || []))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,25 +4,25 @@
|
|||||||
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
||||||
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
||||||
import type { Bytes } from '@polkadot/types';
|
import type { Bytes } from '@polkadot/types';
|
||||||
import type { AccountId, ContractExecResult, EventRecord, Weight } from '@polkadot/types/interfaces';
|
import type { AccountId, EventRecord, Weight } from '@polkadot/types/interfaces';
|
||||||
import type { AnyJson, CodecArg, ISubmittableResult, Registry } from '@polkadot/types/types';
|
import type { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types';
|
||||||
import type { AbiMessage, ContractCallOutcome, ContractOptions, DecodedEvent } from '../types';
|
import type { AbiMessage, ContractCallOutcome, ContractOptions, DecodedEvent } from '../types';
|
||||||
import type { ContractCallResult, ContractCallSend, ContractGeneric, ContractQuery, ContractTx, MapMessageQuery, MapMessageTx } from './types';
|
import type { ContractCallResult, ContractCallSend, ContractQuery, ContractTx, MapMessageQuery, MapMessageTx } from './types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { SubmittableResult } from '@polkadot/api';
|
import { SubmittableResult } from '@polkadot/api';
|
||||||
import { ApiBase } from '@polkadot/api/base';
|
import { ApiBase } from '@polkadot/api/base';
|
||||||
import { assert, bnToBn, isFunction, isUndefined, logger, stringCamelCase } from '@polkadot/util';
|
import { createTypeUnsafe } from '@polkadot/types';
|
||||||
|
import { assert, BN, BN_HUNDRED, BN_ONE, BN_ZERO, bnToBn, isFunction, isUndefined, logger } from '@polkadot/util';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { Abi } from '../Abi';
|
import { Abi } from '../Abi';
|
||||||
import { applyOnEvent, extractOptions, formatData, isOptions } from '../util';
|
import { applyOnEvent, extractOptions, isOptions } from '../util';
|
||||||
import { Base } from './Base';
|
import { Base } from './Base';
|
||||||
|
|
||||||
// As per Rust, 5 * GAS_PER_SEC
|
// As per Rust, 5 * GAS_PER_SEC
|
||||||
const MAX_CALL_GAS = new BN(5_000_000_000_000).subn(1);
|
const MAX_CALL_GAS = new BN(5_000_000_000_000).isub(BN_ONE);
|
||||||
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
|
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
|
||||||
|
|
||||||
const l = logger('Contract');
|
const l = logger('Contract');
|
||||||
|
|
||||||
function createQuery <ApiType extends ApiTypes> (fn: (origin: string | AccountId | Uint8Array, options: ContractOptions, params: CodecArg[]) => ContractCallResult<ApiType, ContractCallOutcome>): ContractQuery<ApiType> {
|
function createQuery <ApiType extends ApiTypes> (fn: (origin: string | AccountId | Uint8Array, options: ContractOptions, params: CodecArg[]) => ContractCallResult<ApiType, ContractCallOutcome>): ContractQuery<ApiType> {
|
||||||
@@ -39,13 +39,6 @@ function createTx <ApiType extends ApiTypes> (fn: (options: ContractOptions, par
|
|||||||
: fn(...extractOptions(options, params));
|
: fn(...extractOptions(options, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWithId <T> (fn: (messageOrId: AbiMessage | string | number, options: ContractOptions, params: CodecArg[]) => T): ContractGeneric<ContractOptions, T> {
|
|
||||||
return (messageOrId: AbiMessage | string | number, options: BigInt | string | number | BN | ContractOptions, ...params: CodecArg[]): T =>
|
|
||||||
isOptions(options)
|
|
||||||
? fn(messageOrId, options, params)
|
|
||||||
: fn(messageOrId, ...extractOptions(options, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ContractSubmittableResult extends SubmittableResult {
|
export class ContractSubmittableResult extends SubmittableResult {
|
||||||
public readonly contractEvents?: DecodedEvent[];
|
public readonly contractEvents?: DecodedEvent[];
|
||||||
|
|
||||||
@@ -56,51 +49,12 @@ export class ContractSubmittableResult extends SubmittableResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// map from a JSON result to current-style ContractExecResult
|
|
||||||
function mapExecResult (registry: Registry, json: Record<string, AnyJson>): ContractExecResult {
|
|
||||||
if (!Object.keys(json).some((key) => ['error', 'success'].includes(key))) {
|
|
||||||
return registry.createType('ContractExecResult', json);
|
|
||||||
}
|
|
||||||
|
|
||||||
const from = registry.createType('ContractExecResultTo260', json);
|
|
||||||
|
|
||||||
if (from.isSuccess) {
|
|
||||||
const s = from.asSuccess;
|
|
||||||
|
|
||||||
return registry.createType('ContractExecResult', {
|
|
||||||
gasConsumed: s.gasConsumed,
|
|
||||||
result: {
|
|
||||||
ok: {
|
|
||||||
data: s.data,
|
|
||||||
flags: s.flags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// in the old format error has no additional information,
|
|
||||||
// map it as-is with an "unknown" error
|
|
||||||
return registry.createType('ContractExecResult', { result: { err: { other: 'unknown' } } });
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
||||||
/**
|
/**
|
||||||
* @description The on-chain address for this contract
|
* @description The on-chain address for this contract
|
||||||
*/
|
*/
|
||||||
public readonly address: AccountId;
|
public readonly address: AccountId;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @description Deprecated. Use `.tx.<messageName>` to send a transaction.
|
|
||||||
*/
|
|
||||||
public readonly exec: ContractGeneric<ContractOptions, SubmittableExtrinsic<ApiType>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* @description Deprecated. Use `.tx.<messageName>` to send a transaction.
|
|
||||||
*/
|
|
||||||
public readonly read: ContractGeneric<ContractOptions, ContractCallSend<ApiType>>;
|
|
||||||
|
|
||||||
readonly #query: MapMessageQuery<ApiType> = {};
|
readonly #query: MapMessageQuery<ApiType> = {};
|
||||||
|
|
||||||
readonly #tx: MapMessageTx<ApiType> = {};
|
readonly #tx: MapMessageTx<ApiType> = {};
|
||||||
@@ -109,18 +63,14 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
super(api, abi, decorateMethod);
|
super(api, abi, decorateMethod);
|
||||||
|
|
||||||
this.address = this.registry.createType('AccountId', address);
|
this.address = this.registry.createType('AccountId', address);
|
||||||
this.exec = createWithId(this.#exec);
|
|
||||||
this.read = createWithId(this.#read);
|
|
||||||
|
|
||||||
this.abi.messages.forEach((m): void => {
|
this.abi.messages.forEach((m): void => {
|
||||||
const messageName = stringCamelCase(m.identifier);
|
if (isUndefined(this.#tx[m.method])) {
|
||||||
|
this.#tx[m.method] = createTx((o, p) => this.#exec(m, o, p));
|
||||||
if (isUndefined(this.#tx[messageName])) {
|
|
||||||
this.#tx[messageName] = createTx((o, p) => this.#exec(m, o, p));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUndefined(this.#query[messageName])) {
|
if (isUndefined(this.#query[m.method])) {
|
||||||
this.#query[messageName] = createQuery((f, o, p) => this.#read(m, o, p).send(f));
|
this.#query[m.method] = createQuery((f, o, p) => this.#read(m, o, p).send(f));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -142,21 +92,27 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
#getGas = (_gasLimit: BigInt | BN | string | number, isCall = false): BN => {
|
#getGas = (_gasLimit: BigInt | BN | string | number, isCall = false): BN => {
|
||||||
const gasLimit = bnToBn(_gasLimit);
|
const gasLimit = bnToBn(_gasLimit);
|
||||||
|
|
||||||
return gasLimit.lten(0)
|
return gasLimit.lte(BN_ZERO)
|
||||||
? isCall
|
? isCall
|
||||||
? MAX_CALL_GAS
|
? MAX_CALL_GAS
|
||||||
: (this.api.consts.system.blockWeights
|
: (this.api.consts.system.blockWeights
|
||||||
? this.api.consts.system.blockWeights.maxBlock
|
? this.api.consts.system.blockWeights.maxBlock
|
||||||
: this.api.consts.system.maximumBlockWeight as Weight
|
: this.api.consts.system.maximumBlockWeight as Weight
|
||||||
).muln(64).divn(100)
|
).muln(64).div(BN_HUNDRED)
|
||||||
: gasLimit;
|
: gasLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#exec = (messageOrId: AbiMessage | string | number, { gasLimit = 0, value = 0 }: ContractOptions, params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
|
#exec = (messageOrId: AbiMessage | string | number, { gasLimit = BN_ZERO, value = BN_ZERO }: ContractOptions, params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
|
||||||
return this.api.tx.contracts
|
return this.api.tx.contracts
|
||||||
.call(this.address, value, this.#getGas(gasLimit), this.abi.findMessage(messageOrId).toU8a(params))
|
.call(
|
||||||
|
this.address,
|
||||||
|
value,
|
||||||
|
this.#getGas(gasLimit),
|
||||||
|
this.abi.findMessage(messageOrId).toU8a(params)
|
||||||
|
)
|
||||||
.withResultTransform((result: ISubmittableResult) =>
|
.withResultTransform((result: ISubmittableResult) =>
|
||||||
new ContractSubmittableResult(result, applyOnEvent(result, 'ContractExecution', (records: EventRecord[]) =>
|
// ContractEmitted is the current generation, ContractExecution is the previous generation
|
||||||
|
new ContractSubmittableResult(result, applyOnEvent(result, ['ContractEmitted', 'ContractExecution'], (records: EventRecord[]) =>
|
||||||
records
|
records
|
||||||
.map(({ event: { data: [, data] } }): DecodedEvent | null => {
|
.map(({ event: { data: [, data] } }): DecodedEvent | null => {
|
||||||
try {
|
try {
|
||||||
@@ -172,7 +128,7 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#read = (messageOrId: AbiMessage | string | number, { gasLimit = 0, value = 0 }: ContractOptions, params: CodecArg[]): ContractCallSend<ApiType> => {
|
#read = (messageOrId: AbiMessage | string | number, { gasLimit = BN_ZERO, value = BN_ZERO }: ContractOptions, params: CodecArg[]): ContractCallSend<ApiType> => {
|
||||||
assert(this.hasRpcContractsCall, ERROR_NO_CALL);
|
assert(this.hasRpcContractsCall, ERROR_NO_CALL);
|
||||||
|
|
||||||
const message = this.abi.findMessage(messageOrId);
|
const message = this.abi.findMessage(messageOrId);
|
||||||
@@ -180,24 +136,24 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
|
|||||||
return {
|
return {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
|
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
|
||||||
this.api.rx.rpc.contracts.call.json({
|
this.api.rx.rpc.contracts
|
||||||
dest: this.address,
|
.call({
|
||||||
gasLimit: this.#getGas(gasLimit, true),
|
dest: this.address,
|
||||||
inputData: message.toU8a(params),
|
gasLimit: this.#getGas(gasLimit, true),
|
||||||
origin,
|
inputData: message.toU8a(params),
|
||||||
value
|
origin,
|
||||||
}).pipe(map((json): ContractCallOutcome => {
|
value
|
||||||
const { debugMessage, gasConsumed, result } = mapExecResult(this.registry, json.toJSON());
|
})
|
||||||
|
.pipe(
|
||||||
return {
|
map(({ debugMessage, gasConsumed, result }): ContractCallOutcome => ({
|
||||||
debugMessage,
|
debugMessage,
|
||||||
gasConsumed,
|
gasConsumed,
|
||||||
output: result.isOk && message.returnType
|
output: result.isOk && message.returnType
|
||||||
? formatData(this.registry, result.asOk.data, message.returnType)
|
? createTypeUnsafe(this.registry, message.returnType.type, [result.asOk.data.toU8a(true)], { isPedantic: true })
|
||||||
: null,
|
: null,
|
||||||
result
|
result
|
||||||
};
|
}))
|
||||||
}))
|
)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ import { TypeRegistry } from '@polkadot/types';
|
|||||||
const registry = new TypeRegistry();
|
const registry = new TypeRegistry();
|
||||||
|
|
||||||
export const mockApi = {
|
export const mockApi = {
|
||||||
|
isConnected: true,
|
||||||
registry,
|
registry,
|
||||||
rx: {
|
tx: {
|
||||||
tx: {
|
contracts: {
|
||||||
contracts: {
|
instantiateWithCode: (): never => {
|
||||||
putCode: (): never => {
|
throw new Error('mock');
|
||||||
throw new Error('mock');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type BN from 'bn.js';
|
|
||||||
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
||||||
import type { ApiTypes, ObsInnerType } from '@polkadot/api/types';
|
import type { ApiTypes, ObsInnerType } from '@polkadot/api/types';
|
||||||
import type { AccountId } from '@polkadot/types/interfaces';
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
import type { CodecArg } from '@polkadot/types/types';
|
import type { CodecArg } from '@polkadot/types/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { AbiMessage, BlueprintOptions, ContractCallOutcome, ContractOptions } from '../types';
|
import type { AbiMessage, BlueprintOptions, ContractCallOutcome, ContractOptions } from '../types';
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export interface ContractGeneric<O, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ContractCallResult<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
|
export type ContractCallResult<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
|
||||||
? Observable<Observable<T>>
|
? Observable<T>
|
||||||
: Promise<ObsInnerType<Observable<T>>>;
|
: Promise<ObsInnerType<Observable<T>>>;
|
||||||
|
|
||||||
export interface ContractCallSend<ApiType extends ApiTypes> {
|
export interface ContractCallSend<ApiType extends ApiTypes> {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { SubmittableResult } from '@polkadot/api';
|
||||||
|
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
|
||||||
|
import type { ApiTypes } from '@polkadot/api/types';
|
||||||
|
import type { CodecArg } from '@polkadot/types/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
|
import type { AbiConstructor, BlueprintOptions } from '../types';
|
||||||
|
import type { BlueprintDeploy, ContractGeneric } from './types';
|
||||||
|
|
||||||
|
import { Bytes } from '@polkadot/types';
|
||||||
|
import { compactAddLength, u8aToU8a } from '@polkadot/util';
|
||||||
|
import { randomAsU8a } from '@polkadot/util-crypto';
|
||||||
|
|
||||||
|
import { extractOptions, isOptions } from '../util';
|
||||||
|
|
||||||
|
export const EMPTY_SALT = new Uint8Array();
|
||||||
|
|
||||||
|
export function createBluePrintTx <ApiType extends ApiTypes, R extends SubmittableResult> (fn: (options: BlueprintOptions, params: CodecArg[]) => SubmittableExtrinsic<ApiType, R>): BlueprintDeploy<ApiType> {
|
||||||
|
return (options: BigInt | string | number | BN | BlueprintOptions, ...params: CodecArg[]): SubmittableExtrinsic<ApiType, R> =>
|
||||||
|
isOptions(options)
|
||||||
|
? fn(options, params)
|
||||||
|
: fn(...extractOptions(options, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createBluePrintWithId <T> (fn: (constructorOrId: AbiConstructor | string | number, options: BlueprintOptions, params: CodecArg[]) => T): ContractGeneric<BlueprintOptions, T> {
|
||||||
|
return (constructorOrId: AbiConstructor | string | number, options: BigInt | string | number | BN | BlueprintOptions, ...params: CodecArg[]): T =>
|
||||||
|
isOptions(options)
|
||||||
|
? fn(constructorOrId, options, params)
|
||||||
|
: fn(constructorOrId, ...extractOptions(options, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encodeSalt (salt: Uint8Array | string | null = randomAsU8a()): Uint8Array {
|
||||||
|
return salt instanceof Bytes
|
||||||
|
? salt
|
||||||
|
: salt && salt.length
|
||||||
|
? compactAddLength(u8aToU8a(salt))
|
||||||
|
: EMPTY_SALT;
|
||||||
|
}
|
||||||
@@ -30,14 +30,12 @@ async function checkContract (api: ApiPromise, pairs: TestKeyringMap): Promise<v
|
|||||||
// execute
|
// execute
|
||||||
await contract.tx.inc({ gasLimit: 1234 }, 123).signAndSend(pairs.eve);
|
await contract.tx.inc({ gasLimit: 1234 }, 123).signAndSend(pairs.eve);
|
||||||
await contract.tx.inc(123, 456, 69).signAndSend(pairs.eve);
|
await contract.tx.inc(123, 456, 69).signAndSend(pairs.eve);
|
||||||
|
|
||||||
// deprecated
|
|
||||||
await contract.read('get', {}).send(pairs.eve.address);
|
|
||||||
await contract.exec('inc', {}, 123).signAndSend(pairs.dave);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main (): Promise<void> {
|
async function main (): Promise<void> {
|
||||||
const api = await ApiPromise.create();
|
const api = await ApiPromise.create({
|
||||||
|
hasher: (data: Uint8Array): Uint8Array => data
|
||||||
|
});
|
||||||
const pairs = createTestPairs();
|
const pairs = createTestPairs();
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { packageInfo as apiInfo } from '@polkadot/api/packageInfo';
|
||||||
|
import { packageInfo as typesInfo } from '@polkadot/types/packageInfo';
|
||||||
|
import { detectPackage } from '@polkadot/util';
|
||||||
|
|
||||||
|
import { packageInfo } from './packageInfo';
|
||||||
|
|
||||||
|
detectPackage(packageInfo, typeof __dirname !== 'undefined' && __dirname, [apiInfo, typesInfo]);
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
export { Abi } from './Abi';
|
import './detectPackage';
|
||||||
|
|
||||||
export { Blueprint as BlueprintRx, Code as CodeRx, Contract as ContractRx } from './rx';
|
export { Abi } from './Abi';
|
||||||
|
export { packageInfo } from './packageInfo';
|
||||||
export { Blueprint as BlueprintPromise, Code as CodePromise, Contract as ContractPromise } from './promise';
|
export { Blueprint as BlueprintPromise, Code as CodePromise, Contract as ContractPromise } from './promise';
|
||||||
|
export { Blueprint as BlueprintRx, Code as CodeRx, Contract as ContractRx } from './rx';
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
|
export const packageInfo = { name: '@polkadot/api-contract', version: '4.17.1' };
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
// Copyright 2017-2021 @polkadot/api-contract authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type BN from 'bn.js';
|
|
||||||
import type { ApiBase } from '@polkadot/api/base';
|
import type { ApiBase } from '@polkadot/api/base';
|
||||||
import type { ApiTypes } from '@polkadot/api/types';
|
import type { ApiTypes } from '@polkadot/api/types';
|
||||||
import type { Text, u64 } from '@polkadot/types';
|
import type { Text, u64 } from '@polkadot/types';
|
||||||
import type { ContractExecResultResult, ContractSelector } from '@polkadot/types/interfaces';
|
import type { ContractExecResultResult, ContractSelector } from '@polkadot/types/interfaces';
|
||||||
import type { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
|
import type { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Abi } from '.';
|
import type { Abi } from '.';
|
||||||
|
|
||||||
export interface ContractBase<ApiType extends ApiTypes> {
|
export interface ContractBase<ApiType extends ApiTypes> {
|
||||||
@@ -39,9 +39,10 @@ export interface AbiMessage {
|
|||||||
isConstructor?: boolean;
|
isConstructor?: boolean;
|
||||||
isMutating?: boolean;
|
isMutating?: boolean;
|
||||||
isPayable?: boolean;
|
isPayable?: boolean;
|
||||||
|
method: string;
|
||||||
returnType?: TypeDef | null;
|
returnType?: TypeDef | null;
|
||||||
selector: ContractSelector;
|
selector: ContractSelector;
|
||||||
toU8a: (params: CodecArg[], additional?: Uint8Array) => Uint8Array;
|
toU8a: (params: CodecArg[]) => Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AbiConstructor = AbiMessage;
|
export type AbiConstructor = AbiMessage;
|
||||||
|
|||||||
@@ -2,27 +2,20 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { SubmittableResult } from '@polkadot/api';
|
import type { SubmittableResult } from '@polkadot/api';
|
||||||
import type { Raw } from '@polkadot/types';
|
|
||||||
import type { EventRecord } from '@polkadot/types/interfaces';
|
import type { EventRecord } from '@polkadot/types/interfaces';
|
||||||
import type { Codec, CodecArg, Registry, TypeDef } from '@polkadot/types/types';
|
import type { CodecArg } from '@polkadot/types/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { BlueprintOptions, ContractOptions } from './types';
|
import type { BlueprintOptions, ContractOptions } from './types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { createTypeUnsafe } from '@polkadot/types/create';
|
|
||||||
import { isBigInt, isBn, isNumber, isString } from '@polkadot/util';
|
import { isBigInt, isBn, isNumber, isString } from '@polkadot/util';
|
||||||
|
|
||||||
type ContractEvents = 'CodeStored' | 'ContractExecution' | 'Instantiated';
|
type ContractEvents = 'CodeStored' | 'ContractEmitted' | 'ContractExecution' | 'Instantiated';
|
||||||
|
|
||||||
type TOptions = BlueprintOptions | ContractOptions;
|
type TOptions = BlueprintOptions | ContractOptions;
|
||||||
|
|
||||||
export function formatData (registry: Registry, data: Raw, { type }: TypeDef): Codec {
|
export function applyOnEvent <T> (result: SubmittableResult, types: ContractEvents[], fn: (records: EventRecord[]) => T): T | undefined {
|
||||||
return createTypeUnsafe(registry, type, [data], { isPedantic: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function applyOnEvent <T> (result: SubmittableResult, type: ContractEvents, fn: (records: EventRecord[]) => T): T | undefined {
|
|
||||||
if (result.isInBlock || result.isFinalized) {
|
if (result.isInBlock || result.isFinalized) {
|
||||||
const records = result.filterRecords('contracts', type);
|
const records = result.filterRecords('contracts', types);
|
||||||
|
|
||||||
if (records.length) {
|
if (records.length) {
|
||||||
return fn(records);
|
return fn(records);
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"info": 6,
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -6,5 +6,6 @@ export { default as dns } from './dns.json';
|
|||||||
export { default as erc20 } from './erc20.json';
|
export { default as erc20 } from './erc20.json';
|
||||||
export { default as erc721 } from './erc721.json';
|
export { default as erc721 } from './erc721.json';
|
||||||
export { default as flipper } from './flipper.json';
|
export { default as flipper } from './flipper.json';
|
||||||
|
export { default as flipperBundle } from './flipper.contract.json';
|
||||||
export { default as incrementer } from './incrementer.json';
|
export { default as incrementer } from './incrementer.json';
|
||||||
export { default as multisigPlain } from './multisig_plain.json';
|
export { default as multisigPlain } from './multisig_plain.json';
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/api-derive",
|
"name": "@polkadot/api-derive",
|
||||||
"version": "3.7.2",
|
"version": "4.17.1",
|
||||||
|
"type": "module",
|
||||||
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"sideEffects": false,
|
"sideEffects": [
|
||||||
|
"./detectPackage.js",
|
||||||
|
"./detectPackage.cjs"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||||
"maintainers": [],
|
"maintainers": [],
|
||||||
"contributors": [],
|
"contributors": [],
|
||||||
@@ -12,17 +19,16 @@
|
|||||||
"bugs": "https://github.com/polkadot-js/api/issues",
|
"bugs": "https://github.com/polkadot-js/api/issues",
|
||||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.14.6",
|
||||||
"@polkadot/api": "3.7.2",
|
"@polkadot/api": "4.17.1",
|
||||||
"@polkadot/rpc-core": "3.7.2",
|
"@polkadot/rpc-core": "4.17.1",
|
||||||
"@polkadot/types": "3.7.2",
|
"@polkadot/types": "4.17.1",
|
||||||
"@polkadot/util": "^5.5.1",
|
"@polkadot/util": "^6.11.1",
|
||||||
"@polkadot/util-crypto": "^5.5.1",
|
"@polkadot/util-crypto": "^6.11.1",
|
||||||
"@polkadot/x-rxjs": "^5.5.1",
|
"@polkadot/x-rxjs": "^6.11.1"
|
||||||
"bn.js": "^4.11.9"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@polkadot/keyring": "^5.5.1",
|
"@polkadot/keyring": "^6.11.1",
|
||||||
"@polkadot/rpc-provider": "3.7.2"
|
"@polkadot/rpc-provider": "4.17.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,11 @@ function parseFlags (address: AccountId | Address | string | null | undefined, [
|
|||||||
*/
|
*/
|
||||||
export function flags (instanceId: string, api: ApiInterfaceRx): (address?: AccountId | Address | string | null) => Observable<DeriveAccountFlags> {
|
export function flags (instanceId: string, api: ApiInterfaceRx): (address?: AccountId | Address | string | null) => Observable<DeriveAccountFlags> {
|
||||||
return memo(instanceId, (address?: AccountId | Address | string | null): Observable<DeriveAccountFlags> => {
|
return memo(instanceId, (address?: AccountId | Address | string | null): Observable<DeriveAccountFlags> => {
|
||||||
const councilSection = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
const councilSection = api.query.phragmenElection
|
||||||
|
? 'phragmenElection'
|
||||||
|
: api.query.electionsPhragmen
|
||||||
|
? 'electionsPhragmen'
|
||||||
|
: 'elections';
|
||||||
|
|
||||||
return combineLatest<FlagsIntermediate>([
|
return combineLatest<FlagsIntermediate>([
|
||||||
address && api.query[councilSection]?.members
|
address && api.query[councilSection]?.members
|
||||||
|
|||||||
@@ -17,13 +17,25 @@ type BalanceResult = [Balance, Balance, Balance, Balance];
|
|||||||
|
|
||||||
type Result = [Index, BalanceResult[]];
|
type Result = [Index, BalanceResult[]];
|
||||||
|
|
||||||
|
type DeriveCustomAccount = ApiInterfaceRx['derive'] & {
|
||||||
|
[custom: string]: {
|
||||||
|
customAccount?: ApiInterfaceRx['query']['balances']['account']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function zeroBalance (api: ApiInterfaceRx) {
|
||||||
|
return api.registry.createType('Balance');
|
||||||
|
}
|
||||||
|
|
||||||
function getBalance (api: ApiInterfaceRx, [freeBalance, reservedBalance, frozenFee, frozenMisc]: BalanceResult): DeriveBalancesAccountData {
|
function getBalance (api: ApiInterfaceRx, [freeBalance, reservedBalance, frozenFee, frozenMisc]: BalanceResult): DeriveBalancesAccountData {
|
||||||
|
const votingBalance = api.registry.createType('Balance', freeBalance.toBn());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
freeBalance,
|
freeBalance,
|
||||||
frozenFee,
|
frozenFee,
|
||||||
frozenMisc,
|
frozenMisc,
|
||||||
reservedBalance,
|
reservedBalance,
|
||||||
votingBalance: api.registry.createType('Balance', freeBalance.toBn())
|
votingBalance
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,16 +61,32 @@ function queryBalancesFree (api: ApiInterfaceRx, accountId: AccountId): Observab
|
|||||||
]).pipe(
|
]).pipe(
|
||||||
map(([freeBalance, reservedBalance, accountNonce]): Result => [
|
map(([freeBalance, reservedBalance, accountNonce]): Result => [
|
||||||
accountNonce,
|
accountNonce,
|
||||||
[[freeBalance, reservedBalance, api.registry.createType('Balance'), api.registry.createType('Balance')]]
|
[[freeBalance, reservedBalance, zeroBalance(api), zeroBalance(api)]]
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function querySystemNonce (api: ApiInterfaceRx, accountId: AccountId): Observable<Result> {
|
||||||
|
return api.query.system.accountNonce<Index>(accountId).pipe(
|
||||||
|
map((accountNonce): Result => [
|
||||||
|
accountNonce,
|
||||||
|
[[zeroBalance(api), zeroBalance(api), zeroBalance(api), zeroBalance(api)]]
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId, modules: string[] = ['balances']): Observable<Result> {
|
function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId, modules: string[] = ['balances']): Observable<Result> {
|
||||||
const balances = modules.map((m): QueryableStorageMultiArg<'rxjs'> => [api.query[m].account, accountId]);
|
const balances = modules.map(
|
||||||
|
(m): QueryableStorageMultiArg<'rxjs'> => [
|
||||||
|
(api.derive as DeriveCustomAccount)[m]?.customAccount || api.query[m].account,
|
||||||
|
accountId
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
const extract = (data: AccountData[]) =>
|
const extract = (data: AccountData[]) =>
|
||||||
data.map(({ feeFrozen, free, miscFrozen, reserved }): BalanceResult => [free, reserved, feeFrozen, miscFrozen]);
|
data.map(({ feeFrozen, free, miscFrozen, reserved }): BalanceResult => [free, reserved, feeFrozen, miscFrozen]);
|
||||||
|
|
||||||
|
// NOTE this is for the first case where we do have instances specified
|
||||||
return isFunction(api.query.system.account)
|
return isFunction(api.query.system.account)
|
||||||
? api.queryMulti<[AccountInfo, ...(AccountData[])]>([[api.query.system.account, accountId], ...balances]).pipe(
|
? api.queryMulti<[AccountInfo, ...(AccountData[])]>([[api.query.system.account, accountId], ...balances]).pipe(
|
||||||
map(([{ nonce }, ...balances]): Result => [nonce, extract(balances)])
|
map(([{ nonce }, ...balances]): Result => [nonce, extract(balances)])
|
||||||
@@ -68,16 +96,29 @@ function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId, module
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Result> {
|
function querySystemAccount (api: ApiInterfaceRx, accountId: AccountId): Observable<Result> {
|
||||||
// AccountInfo is current, support old, eg. Edgeware
|
// AccountInfo is current, support old, eg. Edgeware
|
||||||
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
|
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
|
||||||
map((infoOrTuple): Result => {
|
map((infoOrTuple): Result => {
|
||||||
const { feeFrozen, free, miscFrozen, reserved } = (infoOrTuple as AccountInfo).nonce
|
const data = (infoOrTuple as AccountInfo).nonce
|
||||||
? (infoOrTuple as AccountInfo).data
|
? (infoOrTuple as AccountInfo).data
|
||||||
: (infoOrTuple as [Index, AccountData])[1];
|
: (infoOrTuple as [Index, AccountData])[1];
|
||||||
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
|
|
||||||
|
|
||||||
return [accountNonce, [[free, reserved, feeFrozen, miscFrozen]]];
|
const nonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
|
||||||
|
|
||||||
|
if (!data || data.isEmpty) {
|
||||||
|
return [
|
||||||
|
nonce,
|
||||||
|
[[zeroBalance(api), zeroBalance(api), zeroBalance(api), zeroBalance(api)]]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { feeFrozen, free, miscFrozen, reserved } = data;
|
||||||
|
|
||||||
|
return [
|
||||||
|
nonce,
|
||||||
|
[[free, reserved, feeFrozen, miscFrozen]]
|
||||||
|
];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -99,6 +140,10 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
|||||||
*/
|
*/
|
||||||
export function account (instanceId: string, api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAccount> {
|
export function account (instanceId: string, api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAccount> {
|
||||||
const balanceInstances = api.registry.getModuleInstances(api.runtimeVersion.specName.toString(), 'balances');
|
const balanceInstances = api.registry.getModuleInstances(api.runtimeVersion.specName.toString(), 'balances');
|
||||||
|
const empty: Result = [
|
||||||
|
api.registry.createType('Index'),
|
||||||
|
[[zeroBalance(api), zeroBalance(api), zeroBalance(api), zeroBalance(api)]]
|
||||||
|
];
|
||||||
|
|
||||||
return memo(instanceId, (address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAccount> =>
|
return memo(instanceId, (address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAccount> =>
|
||||||
api.derive.accounts.accountId(address).pipe(
|
api.derive.accounts.accountId(address).pipe(
|
||||||
@@ -108,19 +153,17 @@ export function account (instanceId: string, api: ApiInterfaceRx): (address: Acc
|
|||||||
of(accountId),
|
of(accountId),
|
||||||
balanceInstances
|
balanceInstances
|
||||||
? queryBalancesAccount(api, accountId, balanceInstances)
|
? queryBalancesAccount(api, accountId, balanceInstances)
|
||||||
: isFunction(api.query.system.account)
|
: isFunction(api.query.system?.account)
|
||||||
? queryCurrent(api, accountId)
|
? querySystemAccount(api, accountId)
|
||||||
: isFunction(api.query.balances.account)
|
: isFunction(api.query.balances?.account)
|
||||||
? queryBalancesAccount(api, accountId)
|
? queryBalancesAccount(api, accountId)
|
||||||
: queryBalancesFree(api, accountId)
|
: isFunction(api.query.balances?.freeBalance)
|
||||||
])
|
? queryBalancesFree(api, accountId)
|
||||||
: of([
|
: isFunction(api.query.system?.accountNonce)
|
||||||
api.registry.createType('AccountId'),
|
? querySystemNonce(api, accountId)
|
||||||
[
|
: of(empty)
|
||||||
api.registry.createType('Index'),
|
|
||||||
[[api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance')]]
|
|
||||||
]
|
|
||||||
])
|
])
|
||||||
|
: of([api.registry.createType('AccountId'), empty])
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
map((result): DeriveBalancesAccount => calcBalances(api, result))
|
map((result): DeriveBalancesAccount => calcBalances(api, result))
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import type { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLoc
|
|||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveBalancesAccount, DeriveBalancesAccountData, DeriveBalancesAll, DeriveBalancesAllAccountData } from '../types';
|
import type { DeriveBalancesAccount, DeriveBalancesAccountData, DeriveBalancesAll, DeriveBalancesAllAccountData } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN, bnMax, isFunction } from '@polkadot/util';
|
||||||
|
|
||||||
import { bnMax } from '@polkadot/util';
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
@@ -27,6 +25,12 @@ interface AllLocked {
|
|||||||
vestingLocked: Balance
|
vestingLocked: Balance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeriveCustomLocks = ApiInterfaceRx['derive'] & {
|
||||||
|
[custom: string]: {
|
||||||
|
customLocks?: ApiInterfaceRx['query']['balances']['locks']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const VESTING_ID = '0x76657374696e6720';
|
const VESTING_ID = '0x76657374696e6720';
|
||||||
|
|
||||||
function calcLocked (api: ApiInterfaceRx, bestNumber: BlockNumber, locks: (BalanceLock | BalanceLockTo212)[]): AllLocked {
|
function calcLocked (api: ApiInterfaceRx, bestNumber: BlockNumber, locks: (BalanceLock | BalanceLockTo212)[]): AllLocked {
|
||||||
@@ -38,11 +42,11 @@ function calcLocked (api: ApiInterfaceRx, bestNumber: BlockNumber, locks: (Balan
|
|||||||
if (Array.isArray(locks)) {
|
if (Array.isArray(locks)) {
|
||||||
// only get the locks that are valid until passed the current block
|
// only get the locks that are valid until passed the current block
|
||||||
lockedBreakdown = (locks as BalanceLockTo212[]).filter(({ until }): boolean => !until || (bestNumber && until.gt(bestNumber)));
|
lockedBreakdown = (locks as BalanceLockTo212[]).filter(({ until }): boolean => !until || (bestNumber && until.gt(bestNumber)));
|
||||||
allLocked = lockedBreakdown.some(({ amount }) => amount.isMax());
|
allLocked = lockedBreakdown.some(({ amount }) => amount && amount.isMax());
|
||||||
vestingLocked = api.registry.createType('Balance', lockedBreakdown.filter(({ id }) => id.eq(VESTING_ID)).reduce((result: BN, { amount }) => result.iadd(amount), new BN(0)));
|
vestingLocked = api.registry.createType('Balance', lockedBreakdown.filter(({ id }) => id.eq(VESTING_ID)).reduce((result: BN, { amount }) => result.iadd(amount), new BN(0)));
|
||||||
|
|
||||||
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
|
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
|
||||||
const notAll = lockedBreakdown.filter(({ amount }) => !amount.isMax());
|
const notAll = lockedBreakdown.filter(({ amount }) => amount && !amount.isMax());
|
||||||
|
|
||||||
if (notAll.length) {
|
if (notAll.length) {
|
||||||
lockedBalance = api.registry.createType('Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
|
lockedBalance = api.registry.createType('Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
|
||||||
@@ -54,11 +58,10 @@ function calcLocked (api: ApiInterfaceRx, bestNumber: BlockNumber, locks: (Balan
|
|||||||
|
|
||||||
function calcShared (api: ApiInterfaceRx, bestNumber: BlockNumber, data: DeriveBalancesAccountData, locks: (BalanceLock | BalanceLockTo212)[]): DeriveBalancesAllAccountData {
|
function calcShared (api: ApiInterfaceRx, bestNumber: BlockNumber, data: DeriveBalancesAccountData, locks: (BalanceLock | BalanceLockTo212)[]): DeriveBalancesAllAccountData {
|
||||||
const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks);
|
const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks);
|
||||||
const availableBalance = api.registry.createType('Balance', allLocked ? 0 : bnMax(new BN(0), data.freeBalance.sub(lockedBalance)));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
availableBalance,
|
availableBalance: api.registry.createType('Balance', allLocked ? 0 : bnMax(new BN(0), data.freeBalance.sub(lockedBalance))),
|
||||||
lockedBalance,
|
lockedBalance,
|
||||||
lockedBreakdown,
|
lockedBreakdown,
|
||||||
vestingLocked
|
vestingLocked
|
||||||
@@ -75,8 +78,6 @@ function calcBalances (api: ApiInterfaceRx, [data, bestNumber, [vesting, allLock
|
|||||||
const vestedNow = isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : new BN(0);
|
const vestedNow = isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : new BN(0);
|
||||||
const vestedBalance = vestedNow.gt(vestingTotal) ? vestingTotal : api.registry.createType('Balance', vestedNow);
|
const vestedBalance = vestedNow.gt(vestingTotal) ? vestingTotal : api.registry.createType('Balance', vestedNow);
|
||||||
const isVesting = isStarted && !shared.vestingLocked.isZero();
|
const isVesting = isStarted && !shared.vestingLocked.isZero();
|
||||||
const vestedClaimable = api.registry.createType('Balance', isVesting ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) : 0);
|
|
||||||
const vestingEndBlock = api.registry.createType('BlockNumber', isVesting ? vestingTotal.div(perBlock).add(startingBlock) : 0);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...shared,
|
...shared,
|
||||||
@@ -85,8 +86,8 @@ function calcBalances (api: ApiInterfaceRx, [data, bestNumber, [vesting, allLock
|
|||||||
additional: allLocks.filter((_, index) => index !== 0).map((l, index) => calcShared(api, bestNumber, data.additional[index], l)),
|
additional: allLocks.filter((_, index) => index !== 0).map((l, index) => calcShared(api, bestNumber, data.additional[index], l)),
|
||||||
isVesting,
|
isVesting,
|
||||||
vestedBalance,
|
vestedBalance,
|
||||||
vestedClaimable,
|
vestedClaimable: api.registry.createType('Balance', isVesting ? shared.vestingLocked.sub(vestingTotal.sub(vestedBalance)) : 0),
|
||||||
vestingEndBlock,
|
vestingEndBlock: api.registry.createType('BlockNumber', isVesting ? vestingTotal.div(perBlock).add(startingBlock) : 0),
|
||||||
vestingPerBlock: perBlock,
|
vestingPerBlock: perBlock,
|
||||||
vestingTotal
|
vestingTotal
|
||||||
};
|
};
|
||||||
@@ -112,11 +113,17 @@ function queryOld (api: ApiInterfaceRx, accountId: AccountId): Observable<Result
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isNonNullable = <T>(nullable: T): nullable is NonNullable<T> => !!nullable;
|
||||||
|
|
||||||
// current (balances, vesting)
|
// current (balances, vesting)
|
||||||
function queryCurrent (api: ApiInterfaceRx, accountId: AccountId, balanceInstances: string[] = ['balances']): Observable<ResultBalance> {
|
function queryCurrent (api: ApiInterfaceRx, accountId: AccountId, balanceInstances: string[] = ['balances']): Observable<ResultBalance> {
|
||||||
const lockCalls = balanceInstances.map((m) => api.query[m].locks);
|
const lockCalls = balanceInstances.map(
|
||||||
|
(m): ApiInterfaceRx['query']['balances']['locks'] | undefined =>
|
||||||
|
(api.derive as DeriveCustomLocks)[m]?.customLocks || api.query[m as 'balances']?.locks
|
||||||
|
);
|
||||||
|
|
||||||
const lockEmpty = lockCalls.map((c) => !c);
|
const lockEmpty = lockCalls.map((c) => !c);
|
||||||
const lockQueries = lockCalls.filter((c) => c).map((c): QueryableStorageMultiArg<'rxjs'> => [c, accountId]);
|
const lockQueries = lockCalls.filter(isNonNullable).map((c): QueryableStorageMultiArg<'rxjs'> => [c, accountId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
api.query.vesting?.vesting
|
api.query.vesting?.vesting
|
||||||
@@ -166,7 +173,7 @@ export function all (instanceId: string, api: ApiInterfaceRx): (address: Account
|
|||||||
? combineLatest([
|
? combineLatest([
|
||||||
of(account),
|
of(account),
|
||||||
api.derive.chain.bestNumber(),
|
api.derive.chain.bestNumber(),
|
||||||
api.query.system?.account || api.query.balances?.account
|
isFunction(api.query.system?.account) || isFunction(api.query.balances?.account)
|
||||||
? queryCurrent(api, account.accountId, balanceInstances)
|
? queryCurrent(api, account.accountId, balanceInstances)
|
||||||
: queryOld(api, account.accountId)
|
: queryOld(api, account.accountId)
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe('bounties derive', () => {
|
|||||||
let storageKey: (index: number) => StorageKey;
|
let storageKey: (index: number) => StorageKey;
|
||||||
let defaultBounty: () => Bounty;
|
let defaultBounty: () => Bounty;
|
||||||
let emptyOption: <T extends Codec> (typeName: keyof InterfaceTypes) => Option<T>;
|
let emptyOption: <T extends Codec> (typeName: keyof InterfaceTypes) => Option<T>;
|
||||||
let optionOf: <T extends Codec> (value: T)=> Option<T>;
|
let optionOf: <T extends Codec> (value: T) => Option<T>;
|
||||||
let bountyIndex: (index: number) => BountyIndex;
|
let bountyIndex: (index: number) => BountyIndex;
|
||||||
let proposalIndex: (index: number) => ProposalIndex;
|
let proposalIndex: (index: number) => ProposalIndex;
|
||||||
let bytes: (value: string) => Bytes;
|
let bytes: (value: string) => Bytes;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { DeriveBounties, DeriveCollectiveProposal } from '@polkadot/api-derive/types';
|
import type { DeriveBounties, DeriveCollectiveProposal } from '@polkadot/api-derive/types';
|
||||||
import type { Bytes, Option, StorageKey } from '@polkadot/types';
|
import type { Bytes, Option } from '@polkadot/types';
|
||||||
import type { Bounty, BountyIndex, ProposalIndex } from '@polkadot/types/interfaces';
|
import type { Bounty, BountyIndex, ProposalIndex } from '@polkadot/types/interfaces';
|
||||||
|
|
||||||
import { memo } from '@polkadot/api-derive/util';
|
import { memo } from '@polkadot/api-derive/util';
|
||||||
@@ -32,21 +32,25 @@ function parseResult ([maybeBounties, maybeDescriptions, ids, bountyProposals]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function bounties (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveBounties> {
|
export function bounties (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveBounties> {
|
||||||
const bountyBase = api.query.bounties ? api.query.bounties : api.query.treasury;
|
const bountyBase = api.query.bounties || api.query.treasury;
|
||||||
|
|
||||||
return memo(instanceId, (): Observable<DeriveBounties> =>
|
return memo(instanceId, (): Observable<DeriveBounties> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
bountyBase.bountyCount<BountyIndex>(),
|
bountyBase.bountyCount<BountyIndex>(),
|
||||||
api.query.council ? api.query.council.proposalCount<ProposalIndex>() : of(0)
|
api.query.council
|
||||||
|
? api.query.council.proposalCount<ProposalIndex>()
|
||||||
|
: of(0)
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(() =>
|
switchMap(() =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
bountyBase.bounties.keys(),
|
bountyBase.bounties.keys<[BountyIndex]>(),
|
||||||
api.derive.council ? api.derive.council.proposals() : of([])
|
api.derive.council
|
||||||
|
? api.derive.council.proposals()
|
||||||
|
: of([])
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
switchMap(([keys, proposals]): Observable<Result> => {
|
switchMap(([keys, proposals]): Observable<Result> => {
|
||||||
const ids = (keys as StorageKey<[BountyIndex]>[]).map(({ args: [id] }) => id);
|
const ids = keys.map(({ args: [id] }) => id);
|
||||||
|
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
bountyBase.bounties.multi<Option<Bounty>>(ids),
|
bountyBase.bounties.multi<Option<Bounty>>(ids),
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { SignedBlockExtended } from '../type/types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { catchError, map } from '@polkadot/x-rxjs/operators';
|
import { catchError, map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { SignedBlockExtended } from '../type';
|
import { createSignedBlockExtended } from '../type';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,7 @@ export function getBlock (instanceId: string, api: ApiInterfaceRx): (hash: Uint8
|
|||||||
: of([])
|
: of([])
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([signedBlock, events, validators]): SignedBlockExtended =>
|
map(([signedBlock, events, validators]): SignedBlockExtended =>
|
||||||
new SignedBlockExtended(api.registry, signedBlock, events, validators)
|
createSignedBlockExtended(api.registry, signedBlock, events, validators)
|
||||||
),
|
),
|
||||||
catchError((): Observable<undefined> =>
|
catchError((): Observable<undefined> =>
|
||||||
// where rpc.chain.getHeader throws, we will land here - it can happen that
|
// where rpc.chain.getHeader throws, we will land here - it can happen that
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { HeaderExtended } from '../type/types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { catchError, map } from '@polkadot/x-rxjs/operators';
|
import { catchError, map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { HeaderExtended } from '../type';
|
import { createHeaderExtended } from '../type';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,7 @@ export function getHeader (instanceId: string, api: ApiInterfaceRx): (hash: Uint
|
|||||||
: of([])
|
: of([])
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([header, validators]): HeaderExtended =>
|
map(([header, validators]): HeaderExtended =>
|
||||||
new HeaderExtended(api.registry, header, validators)
|
createHeaderExtended(header.registry, header, validators)
|
||||||
),
|
),
|
||||||
catchError((): Observable<undefined> =>
|
catchError((): Observable<undefined> =>
|
||||||
// where rpc.chain.getHeader throws, we will land here - it can happen that
|
// where rpc.chain.getHeader throws, we will land here - it can happen that
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { AccountId, EventRecord, SignedBlock } from '@polkadot/types/interfaces';
|
import type { Vec } from '@polkadot/types';
|
||||||
|
import type { EventRecord, SignedBlock } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { HeaderExtended, SignedBlockExtended } from '../type/types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { SignedBlockExtended } from '../type';
|
import { createSignedBlockExtended } from '../type';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,17 +20,17 @@ import { memo } from '../util';
|
|||||||
export function subscribeNewBlocks (instanceId: string, api: ApiInterfaceRx): () => Observable<SignedBlockExtended> {
|
export function subscribeNewBlocks (instanceId: string, api: ApiInterfaceRx): () => Observable<SignedBlockExtended> {
|
||||||
return memo(instanceId, (): Observable<SignedBlockExtended> =>
|
return memo(instanceId, (): Observable<SignedBlockExtended> =>
|
||||||
api.derive.chain.subscribeNewHeads().pipe(
|
api.derive.chain.subscribeNewHeads().pipe(
|
||||||
switchMap((header): Observable<[SignedBlock, EventRecord[], AccountId[] | undefined]> => {
|
switchMap((header): Observable<[SignedBlock, Vec<EventRecord>, HeaderExtended]> => {
|
||||||
const blockHash = header.hash;
|
const blockHash = header.createdAtHash || header.hash;
|
||||||
|
|
||||||
return combineLatest(
|
return combineLatest(
|
||||||
api.rpc.chain.getBlock(blockHash),
|
api.rpc.chain.getBlock(blockHash),
|
||||||
api.query.system.events.at(blockHash),
|
api.query.system.events.at(blockHash),
|
||||||
of(header.validators)
|
of(header)
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
map(([block, events, validators]) =>
|
map(([block, events, header]) =>
|
||||||
new SignedBlockExtended(api.registry, block, events, validators)
|
createSignedBlockExtended(block.registry, block, events, header.validators)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { HeaderExtended } from '../type/types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { HeaderExtended } from '../type';
|
import { createHeaderExtended } from '../type';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,10 +30,13 @@ export function subscribeNewHeads (instanceId: string, api: ApiInterfaceRx): ()
|
|||||||
api.rpc.chain.subscribeNewHeads(),
|
api.rpc.chain.subscribeNewHeads(),
|
||||||
api.query.session
|
api.query.session
|
||||||
? api.query.session.validators()
|
? api.query.session.validators()
|
||||||
: of([])
|
: of(undefined)
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([header, validators]): HeaderExtended =>
|
map(([header, validators]): HeaderExtended => {
|
||||||
new HeaderExtended(api.registry, header, validators)
|
header.createdAtHash = header.hash;
|
||||||
)
|
|
||||||
));
|
return createHeaderExtended(header.registry, header, validators);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
|
||||||
|
export function getInstance (api: ApiInterfaceRx, section: string): string {
|
||||||
|
const instances = api.registry.getModuleInstances(api.runtimeVersion.specName.toString(), section);
|
||||||
|
|
||||||
|
return instances && instances.length
|
||||||
|
? instances[0]
|
||||||
|
: section;
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export * from './members';
|
||||||
|
export * from './prime';
|
||||||
export * from './proposals';
|
export * from './proposals';
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { Collective } from './types';
|
||||||
|
|
||||||
|
import { isFunction } from '@polkadot/util';
|
||||||
|
import { of } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
import { getInstance } from './getInstance';
|
||||||
|
|
||||||
|
export function members (instanceId: string, api: ApiInterfaceRx, _section: Collective): () => Observable<AccountId[]> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
|
|
||||||
|
return memo(instanceId, (): Observable<AccountId[]> =>
|
||||||
|
isFunction(api.query[section]?.members)
|
||||||
|
? api.query[section as 'council'].members()
|
||||||
|
: of([])
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { Option } from '@polkadot/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { isFunction } from '@polkadot/util';
|
||||||
|
import { of } from '@polkadot/x-rxjs';
|
||||||
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
import { getInstance } from './getInstance';
|
||||||
|
|
||||||
|
export function prime (instanceId: string, api: ApiInterfaceRx, _section: string): () => Observable<AccountId | null> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
|
|
||||||
|
return memo(instanceId, (): Observable<AccountId | null> =>
|
||||||
|
isFunction(api.query[section as 'council']?.prime)
|
||||||
|
? api.query[section as 'council'].prime<Option<AccountId>>().pipe(
|
||||||
|
map((optPrime): AccountId | null =>
|
||||||
|
optPrime.unwrapOr(null)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: of(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,16 +2,18 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Option } from '@polkadot/types';
|
import type { Option, u32 } from '@polkadot/types';
|
||||||
import type { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
import type { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveCollectiveProposal } from '../types';
|
import type { DeriveCollectiveProposal } from '../types';
|
||||||
|
import type { Collective } from './types';
|
||||||
|
|
||||||
import { isFunction } from '@polkadot/util';
|
import { isFunction } from '@polkadot/util';
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { catchError, map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { catchError, map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
import { getInstance } from './getInstance';
|
||||||
|
|
||||||
type Result = [(Hash | Uint8Array | string)[], (Option<Proposal> | null)[], Option<Votes>[]];
|
type Result = [(Hash | Uint8Array | string)[], (Option<Proposal> | null)[], Option<Votes>[]];
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ function parse (api: ApiInterfaceRx, [hashes, proposals, votes]: Result): Derive
|
|||||||
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
|
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _proposalsFrom (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): (hashes: (Hash | Uint8Array | string)[]) => Observable<DeriveCollectiveProposal[]> {
|
function _proposalsFrom (instanceId: string, api: ApiInterfaceRx, section: string): (hashes: (Hash | Uint8Array | string)[]) => Observable<DeriveCollectiveProposal[]> {
|
||||||
return memo(instanceId, (hashes: (Hash | Uint8Array | string)[]): Observable<DeriveCollectiveProposal[]> =>
|
return memo(instanceId, (hashes: (Hash | Uint8Array | string)[]): Observable<DeriveCollectiveProposal[]> =>
|
||||||
(isFunction(api.query[section]?.proposals) && hashes.length
|
(isFunction(api.query[section]?.proposals) && hashes.length
|
||||||
? combineLatest<Result>([
|
? combineLatest<Result>([
|
||||||
@@ -49,19 +51,48 @@ function _proposalsFrom (instanceId: string, api: ApiInterfaceRx, section: 'coun
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function proposals (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): () => Observable<DeriveCollectiveProposal[]> {
|
export function hasProposals (instanceId: string, api: ApiInterfaceRx, _section: Collective): () => Observable<boolean> {
|
||||||
const proposalsFrom = _proposalsFrom(instanceId, api, section);
|
const section = getInstance(api, _section);
|
||||||
|
|
||||||
return memo(instanceId, (): Observable<DeriveCollectiveProposal[]> =>
|
return memo(instanceId, (): Observable<boolean> =>
|
||||||
isFunction(api.query[section]?.proposals)
|
of(isFunction(api.query[section]?.proposals))
|
||||||
? api.query[section].proposals().pipe(
|
|
||||||
switchMap(proposalsFrom)
|
|
||||||
)
|
|
||||||
: of([] as DeriveCollectiveProposal[])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function proposal (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
export function proposalCount (instanceId: string, api: ApiInterfaceRx, _section: Collective): () => Observable<u32 | null> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
|
|
||||||
|
return memo(instanceId, (): Observable<u32 | null> =>
|
||||||
|
isFunction(api.query[section].proposalCount)
|
||||||
|
? api.query[section as 'council'].proposalCount()
|
||||||
|
: of(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalHashes (instanceId: string, api: ApiInterfaceRx, _section: Collective): () => Observable<Hash[]> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
|
|
||||||
|
return memo(instanceId, (): Observable<Hash[]> =>
|
||||||
|
isFunction(api.query[section]?.proposals)
|
||||||
|
? api.query[section as 'council'].proposals()
|
||||||
|
: of([])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposals (instanceId: string, api: ApiInterfaceRx, _section: Collective): () => Observable<DeriveCollectiveProposal[]> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
|
const proposalsFrom = _proposalsFrom(instanceId, api, section);
|
||||||
|
const getHashes = proposalHashes(instanceId, api, _section);
|
||||||
|
|
||||||
|
return memo(instanceId, (): Observable<DeriveCollectiveProposal[]> =>
|
||||||
|
getHashes().pipe(
|
||||||
|
switchMap(proposalsFrom)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposal (instanceId: string, api: ApiInterfaceRx, _section: Collective): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
||||||
|
const section = getInstance(api, _section);
|
||||||
const proposalsFrom = _proposalsFrom(instanceId, api, section);
|
const proposalsFrom = _proposalsFrom(instanceId, api, section);
|
||||||
|
|
||||||
return memo(instanceId, (hash: Hash | Uint8Array | string): Observable<DeriveCollectiveProposal | null> =>
|
return memo(instanceId, (hash: Hash | Uint8Array | string): Observable<DeriveCollectiveProposal | null> =>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export type Collective = 'council' | 'membership' | 'technicalCommittee';
|
||||||
@@ -2,11 +2,10 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveContractFees } from '../types';
|
import type { DeriveContractFees } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { of } from '@polkadot/x-rxjs';
|
import { of } from '@polkadot/x-rxjs';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export * from './members';
|
||||||
|
export * from './prime';
|
||||||
export * from './proposals';
|
export * from './proposals';
|
||||||
export * from './votes';
|
export * from './votes';
|
||||||
export * from './votesOf';
|
export * from './votesOf';
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { members as collectiveMembers } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function members (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId[]> {
|
||||||
|
return memo(instanceId, collectiveMembers(instanceId, api, 'council'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { prime as collectivePrime } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function prime (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId | null> {
|
||||||
|
return memo(instanceId, collectivePrime(instanceId, api, 'council'));
|
||||||
|
}
|
||||||
@@ -2,17 +2,30 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { u32 } from '@polkadot/types';
|
||||||
import type { Hash } from '@polkadot/types/interfaces';
|
import type { Hash } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveCollectiveProposal } from '../types';
|
import type { DeriveCollectiveProposal } from '../types';
|
||||||
|
|
||||||
import { proposal as collectiveProposal, proposals as collectiveProposals } from '../collective';
|
import { hasProposals as collectiveHasProposals, proposal as collectiveProposal, proposalCount as collectiveProposalCount, proposalHashes as collectiveProposalHashes, proposals as collectiveProposals } from '../collective';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function hasProposals (instanceId: string, api: ApiInterfaceRx): () => Observable<boolean> {
|
||||||
|
return memo(instanceId, collectiveHasProposals(instanceId, api, 'council'));
|
||||||
|
}
|
||||||
|
|
||||||
export function proposal (instanceId: string, api: ApiInterfaceRx): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
export function proposal (instanceId: string, api: ApiInterfaceRx): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
||||||
return memo(instanceId, collectiveProposal(instanceId, api));
|
return memo(instanceId, collectiveProposal(instanceId, api, 'council'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalCount (instanceId: string, api: ApiInterfaceRx): () => Observable<u32 | null> {
|
||||||
|
return memo(instanceId, collectiveProposalCount(instanceId, api, 'council'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalHashes (instanceId: string, api: ApiInterfaceRx): () => Observable<Hash[]> {
|
||||||
|
return memo(instanceId, collectiveProposalHashes(instanceId, api, 'council'));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
|
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
|
||||||
return memo(instanceId, collectiveProposals(instanceId, api));
|
return memo(instanceId, collectiveProposals(instanceId, api, 'council'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,46 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx, QueryableModuleStorage } from '@polkadot/api/types';
|
||||||
import type { Vec } from '@polkadot/types';
|
import type { Vec } from '@polkadot/types';
|
||||||
import type { AccountId, Balance } from '@polkadot/types/interfaces';
|
import type { AccountId, Balance, Voter } from '@polkadot/types/interfaces';
|
||||||
import type { ITuple } from '@polkadot/types/types';
|
import type { ITuple } from '@polkadot/types/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveCouncilVote, DeriveCouncilVotes } from '../types';
|
import type { DeriveCouncilVote, DeriveCouncilVotes } from '../types';
|
||||||
|
|
||||||
import { combineLatest } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
function retrieveStakeOf (api: ApiInterfaceRx): Observable<[AccountId, Balance][]> {
|
// Voter is current tuple is 2.x-era
|
||||||
return (api.query.electionsPhragmen || api.query.elections).stakeOf.entries<Balance>().pipe(
|
type VoteEntry = Voter | ITuple<[Balance, Vec<AccountId>]>;
|
||||||
|
|
||||||
|
function isVoter (value: VoteEntry): value is Voter {
|
||||||
|
return !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrieveStakeOf (elections: QueryableModuleStorage<'rxjs'>): Observable<[AccountId, Balance][]> {
|
||||||
|
return elections.stakeOf.entries<Balance, [AccountId]>().pipe(
|
||||||
map((entries) =>
|
map((entries) =>
|
||||||
entries.map(([key, stake]) => [key.args[0] as AccountId, stake])
|
entries.map(([{ args: [accountId] }, stake]) => [accountId, stake])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrieveVoteOf (api: ApiInterfaceRx): Observable<[AccountId, AccountId[]][]> {
|
function retrieveVoteOf (elections: QueryableModuleStorage<'rxjs'>): Observable<[AccountId, AccountId[]][]> {
|
||||||
return (api.query.electionsPhragmen || api.query.elections).votesOf.entries<Vec<AccountId>>().pipe(
|
return elections.votesOf.entries<Vec<AccountId>, [AccountId]>().pipe(
|
||||||
map((entries) =>
|
map((entries) =>
|
||||||
entries.map(([key, votes]) => [key.args[0] as AccountId, votes])
|
entries.map(([{ args: [accountId] }, votes]) => [accountId, votes])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrievePrev (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
|
function retrievePrev (api: ApiInterfaceRx, elections: QueryableModuleStorage<'rxjs'>): Observable<DeriveCouncilVotes> {
|
||||||
return combineLatest([retrieveStakeOf(api), retrieveVoteOf(api)]).pipe(
|
return combineLatest([
|
||||||
|
retrieveStakeOf(elections),
|
||||||
|
retrieveVoteOf(elections)
|
||||||
|
]).pipe(
|
||||||
map(([stakes, votes]): DeriveCouncilVotes => {
|
map(([stakes, votes]): DeriveCouncilVotes => {
|
||||||
const result: DeriveCouncilVotes = [];
|
const result: DeriveCouncilVotes = [];
|
||||||
|
|
||||||
@@ -53,22 +63,27 @@ function retrievePrev (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrieveCurrent (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
|
function retrieveCurrent (elections: QueryableModuleStorage<'rxjs'>): Observable<DeriveCouncilVotes> {
|
||||||
const elections = (api.query.electionsPhragmen || api.query.elections);
|
return elections.voting.entries<VoteEntry, [AccountId]>().pipe(
|
||||||
|
|
||||||
return elections.voting.entries<ITuple<[Balance, Vec<AccountId>]>>().pipe(
|
|
||||||
map((entries): DeriveCouncilVotes =>
|
map((entries): DeriveCouncilVotes =>
|
||||||
entries.map(([key, [stake, votes]]): [AccountId, DeriveCouncilVote] =>
|
entries.map(([{ args: [accountId] }, value]): [AccountId, DeriveCouncilVote] => [
|
||||||
[key.args[0] as AccountId, { stake, votes }]
|
accountId,
|
||||||
)
|
isVoter(value)
|
||||||
|
? { stake: value.stake, votes: value.votes }
|
||||||
|
: { stake: value[0], votes: value[1] }
|
||||||
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function votes (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCouncilVotes> {
|
export function votes (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCouncilVotes> {
|
||||||
|
const elections = api.query.phragmenElection || api.query.electionsPhragmen || api.query.elections;
|
||||||
|
|
||||||
return memo(instanceId, (): Observable<DeriveCouncilVotes> =>
|
return memo(instanceId, (): Observable<DeriveCouncilVotes> =>
|
||||||
(api.query.electionsPhragmen || api.query.elections).stakeOf
|
elections
|
||||||
? retrievePrev(api)
|
? elections.stakeOf
|
||||||
: retrieveCurrent(api)
|
? retrievePrev(api, elections)
|
||||||
|
: retrieveCurrent(elections)
|
||||||
|
: of([])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function schedulerEntries (api: ApiInterfaceRx): Observable<[BlockNumber[], Opti
|
|||||||
api.query.scheduler.agenda.keys()
|
api.query.scheduler.agenda.keys()
|
||||||
),
|
),
|
||||||
switchMap((keys) => {
|
switchMap((keys) => {
|
||||||
const blockNumbers = keys.map((key) => key.args[0]);
|
const blockNumbers = keys.map(({ args: [blockNumber] }) => blockNumber);
|
||||||
|
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
of(blockNumbers),
|
of(blockNumbers),
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Option } from '@polkadot/types';
|
import type { Option } from '@polkadot/types';
|
||||||
import type { AccountId, ReferendumInfo, ReferendumInfoFinished, ReferendumInfoTo239, Vote, VotingDelegating, VotingDirect, VotingDirectVote } from '@polkadot/types/interfaces';
|
import type { AccountId, ReferendumInfo, ReferendumInfoFinished, ReferendumInfoTo239, Vote, VotingDelegating, VotingDirect, VotingDirectVote } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveDemocracyLock } from '../types';
|
import type { DeriveDemocracyLock } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { BN_ZERO, isUndefined } from '@polkadot/util';
|
import { BN_ZERO, isUndefined } from '@polkadot/util';
|
||||||
import { of } from '@polkadot/x-rxjs';
|
import { of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function parse ([proposals, images, optDepositors]: Result): DeriveProposal[] {
|
|||||||
|
|
||||||
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveProposal[]> {
|
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveProposal[]> {
|
||||||
return memo(instanceId, (): Observable<DeriveProposal[]> =>
|
return memo(instanceId, (): Observable<DeriveProposal[]> =>
|
||||||
api.query.democracy?.publicProps && api.query.democracy?.preimages
|
isFunction(api.query.democracy?.publicProps) && isFunction(api.query.democracy?.preimages)
|
||||||
? api.query.democracy.publicProps<Proposals>().pipe(
|
? api.query.democracy.publicProps<Proposals>().pipe(
|
||||||
switchMap((proposals) =>
|
switchMap((proposals) =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { ReferendumIndex } from '@polkadot/types/interfaces';
|
import type { ReferendumIndex } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { of } from '@polkadot/x-rxjs';
|
import { of } from '@polkadot/x-rxjs';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Option, Vec } from '@polkadot/types';
|
import type { Option, Vec } from '@polkadot/types';
|
||||||
import type { AccountId, ReferendumInfo, ReferendumInfoTo239, Vote, Voting, VotingDelegating, VotingDirectVote } from '@polkadot/types/interfaces';
|
import type { AccountId, ReferendumInfo, ReferendumInfoTo239, Vote, Voting, VotingDelegating, VotingDirectVote } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
|
import type { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { isFunction } from '@polkadot/util';
|
import { isFunction } from '@polkadot/util';
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
@@ -67,9 +66,9 @@ function extractVotes (mapped: [AccountId, Voting][], referendumId: BN): DeriveR
|
|||||||
}
|
}
|
||||||
|
|
||||||
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
|
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
|
||||||
return api.query.democracy.votingOf.entries<Voting>().pipe(
|
return api.query.democracy.votingOf.entries<Voting, [AccountId]>().pipe(
|
||||||
map((allVoting): DeriveReferendumVote[] => {
|
map((allVoting): DeriveReferendumVote[] => {
|
||||||
const mapped = allVoting.map(([key, voting]): [AccountId, Voting] => [key.args[0], voting]);
|
const mapped = allVoting.map(([{ args: [accountId] }, voting]): [AccountId, Voting] => [accountId, voting]);
|
||||||
const votes = extractVotes(mapped, referendumId);
|
const votes = extractVotes(mapped, referendumId);
|
||||||
const delegations = mapped
|
const delegations = mapped
|
||||||
.filter(([, voting]) => voting.isDelegating)
|
.filter(([, voting]) => voting.isDelegating)
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
|
|
||||||
import { bnSqrt } from '@polkadot/util';
|
import { bnSqrt } from '@polkadot/util';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type BN from 'bn.js';
|
|
||||||
import type { Vec } from '@polkadot/types';
|
import type { Vec } from '@polkadot/types';
|
||||||
import type { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal, ReferendumIndex, ReferendumInfoTo239, ReferendumStatus, Vote, VoteThreshold } from '@polkadot/types/interfaces';
|
import type { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal, ReferendumIndex, ReferendumInfoTo239, ReferendumStatus, Vote, VoteThreshold } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
|
|
||||||
export interface DeriveDemocracyLock {
|
export interface DeriveDemocracyLock {
|
||||||
balance: Balance;
|
balance: Balance;
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import type { AccountId, Balance, BlockNumber, PreimageStatus, Proposal, Referen
|
|||||||
import type { ITuple } from '@polkadot/types/types';
|
import type { ITuple } from '@polkadot/types/types';
|
||||||
import type { DeriveProposalImage, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes, DeriveReferendumVoteState } from '../types';
|
import type { DeriveProposalImage, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes, DeriveReferendumVoteState } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN, bnSqrt } from '@polkadot/util';
|
||||||
|
|
||||||
import { bnSqrt } from '@polkadot/util';
|
|
||||||
|
|
||||||
type PreimageInfo = [Bytes, AccountId, Balance, BlockNumber];
|
type PreimageInfo = [Bytes, AccountId, Balance, BlockNumber];
|
||||||
type OldPreimage = ITuple<PreimageInfo>;
|
type OldPreimage = ITuple<PreimageInfo>;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import { packageInfo as apiInfo } from '@polkadot/api/packageInfo';
|
||||||
|
import { packageInfo as coreInfo } from '@polkadot/rpc-core/packageInfo';
|
||||||
|
import { packageInfo as typesInfo } from '@polkadot/types/packageInfo';
|
||||||
|
import { detectPackage } from '@polkadot/util';
|
||||||
|
|
||||||
|
import { packageInfo } from './packageInfo';
|
||||||
|
|
||||||
|
detectPackage(packageInfo, typeof __dirname !== 'undefined' && __dirname, [apiInfo, coreInfo, typesInfo]);
|
||||||
@@ -3,40 +3,88 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { u32, Vec } from '@polkadot/types';
|
import type { u32, Vec } from '@polkadot/types';
|
||||||
import type { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces';
|
import type { AccountId, Balance, BlockNumber, SeatHolder } from '@polkadot/types/interfaces';
|
||||||
import type { ITuple } from '@polkadot/types/types';
|
import type { ITuple } from '@polkadot/types/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveElectionsInfo } from './types';
|
import type { DeriveElectionsInfo } from './types';
|
||||||
|
|
||||||
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
|
// SeatHolder is current tuple is 2.x-era Substrate
|
||||||
|
type Member = SeatHolder | ITuple<[AccountId, Balance]>;
|
||||||
|
|
||||||
|
type Candidate = AccountId | ITuple<[AccountId, Balance]>;
|
||||||
|
|
||||||
|
function isSeatHolder (value: Member): value is SeatHolder {
|
||||||
|
return !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCandidateTuple (value: Candidate): value is ITuple<[AccountId, Balance]> {
|
||||||
|
return Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAccountTuple (value: Member): [AccountId, Balance] {
|
||||||
|
return isSeatHolder(value)
|
||||||
|
? [value.who, value.stake]
|
||||||
|
: value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCandidate (value: Candidate): AccountId {
|
||||||
|
return isCandidateTuple(value)
|
||||||
|
? value[0]
|
||||||
|
: value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortAccounts ([, balanceA]: [AccountId, Balance], [, balanceB]: [AccountId, Balance]): number {
|
||||||
return balanceB.cmp(balanceA);
|
return balanceB.cmp(balanceA);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
|
function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
|
||||||
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
const elections = api.query.phragmenElection
|
||||||
|
? 'phragmenElection'
|
||||||
|
: api.query.electionsPhragmen
|
||||||
|
? 'electionsPhragmen'
|
||||||
|
: api.query.elections
|
||||||
|
? 'elections'
|
||||||
|
: null;
|
||||||
|
const [council] = api.registry.getModuleInstances(api.runtimeVersion.specName.toString(), 'council') || ['council'];
|
||||||
|
|
||||||
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
|
return (
|
||||||
api.query.council.members,
|
elections
|
||||||
api.query[section].candidates,
|
? api.queryMulti<[Vec<AccountId>, Vec<Candidate>, Vec<Member>, Vec<Member>]>([
|
||||||
api.query[section].members,
|
api.query[council].members,
|
||||||
api.query[section].runnersUp
|
api.query[elections].candidates,
|
||||||
]).pipe(
|
api.query[elections].members,
|
||||||
|
api.query[elections].runnersUp
|
||||||
|
])
|
||||||
|
: combineLatest<[Vec<AccountId>, Candidate[], Member[], Member[]]>([
|
||||||
|
api.query[council].members(),
|
||||||
|
of([]),
|
||||||
|
of([]),
|
||||||
|
of([])
|
||||||
|
])
|
||||||
|
).pipe(
|
||||||
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
|
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
|
||||||
candidacyBond: api.consts[section].candidacyBond as Balance,
|
...(
|
||||||
|
elections
|
||||||
|
? {
|
||||||
|
candidacyBond: api.consts[elections].candidacyBond as Balance,
|
||||||
|
desiredRunnersUp: api.consts[elections].desiredRunnersUp as u32,
|
||||||
|
desiredSeats: api.consts[elections].desiredMembers as u32,
|
||||||
|
termDuration: api.consts[elections].termDuration as BlockNumber,
|
||||||
|
votingBond: api.consts[elections].votingBond as Balance
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
),
|
||||||
candidateCount: api.registry.createType('u32', candidates.length),
|
candidateCount: api.registry.createType('u32', candidates.length),
|
||||||
candidates,
|
candidates: candidates.map(getCandidate),
|
||||||
desiredRunnersUp: api.consts[section].desiredRunnersUp as u32,
|
|
||||||
desiredSeats: api.consts[section].desiredMembers as u32,
|
|
||||||
members: members.length
|
members: members.length
|
||||||
? members.sort(sortAccounts)
|
? members.map(getAccountTuple).sort(sortAccounts)
|
||||||
: councilMembers.map((accountId): [AccountId, Balance] => [accountId, api.registry.createType('Balance')]),
|
: councilMembers.map((accountId): [AccountId, Balance] => [accountId, api.registry.createType('Balance')]),
|
||||||
runnersUp: runnersUp.sort(sortAccounts),
|
runnersUp: runnersUp.map(getAccountTuple).sort(sortAccounts)
|
||||||
termDuration: api.consts[section].termDuration as BlockNumber,
|
|
||||||
votingBond: api.consts[section].votingBond as Balance
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ export interface DeriveElectionsInfo {
|
|||||||
candidates: AccountId[];
|
candidates: AccountId[];
|
||||||
candidateCount: u32;
|
candidateCount: u32;
|
||||||
candidacyBond?: Balance;
|
candidacyBond?: Balance;
|
||||||
desiredRunnersUp: u32;
|
desiredRunnersUp?: u32;
|
||||||
desiredSeats: u32;
|
desiredSeats?: u32;
|
||||||
members: [AccountId, Balance][];
|
members: [AccountId, Balance][];
|
||||||
nextVoterSet?: SetIndex;
|
nextVoterSet?: SetIndex;
|
||||||
runnersUp: [AccountId, Balance][];
|
runnersUp: [AccountId, Balance][];
|
||||||
termDuration: BlockNumber;
|
termDuration?: BlockNumber;
|
||||||
voteCount?: VoteIndex;
|
voteCount?: VoteIndex;
|
||||||
voterCount?: SetIndex;
|
voterCount?: SetIndex;
|
||||||
votingBond?: Balance;
|
votingBond?: Balance;
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ describe('derive', (): void => {
|
|||||||
api.isReady.subscribe(() => done());
|
api.isReady.subscribe(() => done());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await api.disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
testFunction(api)('accounts', 'idAndIndex', []);
|
testFunction(api)('accounts', 'idAndIndex', []);
|
||||||
testFunction(api)('accounts', 'idToIndex', []);
|
testFunction(api)('accounts', 'idToIndex', []);
|
||||||
testFunction(api)('accounts', 'indexes', []);
|
testFunction(api)('accounts', 'indexes', []);
|
||||||
@@ -80,7 +84,11 @@ describe('derive', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeAll((done): void => {
|
beforeAll((done): void => {
|
||||||
api.isReady.subscribe((): void => done());
|
api.isReady.subscribe(() => done());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await api.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
// override
|
// override
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import './detectPackage';
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { AnyFunction } from '@polkadot/types/types';
|
import type { AnyFunction } from '@polkadot/types/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
@@ -14,6 +16,7 @@ import * as council from './council';
|
|||||||
import * as democracy from './democracy';
|
import * as democracy from './democracy';
|
||||||
import * as elections from './elections';
|
import * as elections from './elections';
|
||||||
import * as imOnline from './imOnline';
|
import * as imOnline from './imOnline';
|
||||||
|
import * as membership from './membership';
|
||||||
import * as parachains from './parachains';
|
import * as parachains from './parachains';
|
||||||
import * as session from './session';
|
import * as session from './session';
|
||||||
import * as society from './society';
|
import * as society from './society';
|
||||||
@@ -22,9 +25,15 @@ import * as technicalCommittee from './technicalCommittee';
|
|||||||
import * as treasury from './treasury';
|
import * as treasury from './treasury';
|
||||||
import * as tx from './tx';
|
import * as tx from './tx';
|
||||||
|
|
||||||
|
export { packageInfo } from './packageInfo';
|
||||||
export * from './type';
|
export * from './type';
|
||||||
|
|
||||||
export const derive = { accounts, balances, bounties, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury, tx };
|
interface Avail {
|
||||||
|
instances: string[];
|
||||||
|
withDetect?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const derive = { accounts, balances, bounties, chain, contracts, council, democracy, elections, imOnline, membership, parachains, session, society, staking, technicalCommittee, treasury, tx };
|
||||||
|
|
||||||
type DeriveSection<Section> = {
|
type DeriveSection<Section> = {
|
||||||
[Method in keyof Section]: Section[Method] extends AnyFunction
|
[Method in keyof Section]: Section[Method] extends AnyFunction
|
||||||
@@ -40,18 +49,19 @@ export type DeriveCustom = Record<string, Record<string, (instanceId: string, ap
|
|||||||
export type ExactDerive = DeriveAllSections<typeof derive>;
|
export type ExactDerive = DeriveAllSections<typeof derive>;
|
||||||
|
|
||||||
// Enable derive only if some of these modules are available
|
// Enable derive only if some of these modules are available
|
||||||
const deriveAvail: Record<string, string[]> = {
|
const deriveAvail: Record<string, Avail> = {
|
||||||
contracts: ['contracts'],
|
contracts: { instances: ['contracts'] },
|
||||||
council: ['council'],
|
council: { instances: ['council'], withDetect: true },
|
||||||
democracy: ['democracy'],
|
democracy: { instances: ['democracy'] },
|
||||||
elections: ['electionsPhragmen', 'elections'],
|
elections: { instances: ['phragmenElection', 'electionsPhragmen', 'elections', 'council'], withDetect: true },
|
||||||
imOnline: ['imOnline'],
|
imOnline: { instances: ['imOnline'] },
|
||||||
parachains: ['parachains', 'registrar'],
|
membership: { instances: ['membership'] },
|
||||||
session: ['session'],
|
parachains: { instances: ['parachains', 'registrar'] },
|
||||||
society: ['society'],
|
session: { instances: ['session'] },
|
||||||
staking: ['staking'],
|
society: { instances: ['society'] },
|
||||||
technicalCommittee: ['technicalCommittee'],
|
staking: { instances: ['staking'] },
|
||||||
treasury: ['treasury']
|
technicalCommittee: { instances: ['technicalCommittee'], withDetect: true },
|
||||||
|
treasury: { instances: ['treasury'] }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,11 +71,19 @@ const deriveAvail: Record<string, string[]> = {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
function injectFunctions<AllSections> (instanceId: string, api: ApiInterfaceRx, allSections: AllSections): DeriveAllSections<AllSections> {
|
function injectFunctions<AllSections> (instanceId: string, api: ApiInterfaceRx, allSections: AllSections): DeriveAllSections<AllSections> {
|
||||||
const queryKeys = Object.keys(api.query);
|
const queryKeys = Object.keys(api.query);
|
||||||
|
const specName = api.runtimeVersion.specName.toString();
|
||||||
|
|
||||||
return Object
|
return Object
|
||||||
.keys(allSections)
|
.keys(allSections)
|
||||||
.filter((sectionName): boolean =>
|
.filter((sectionName) =>
|
||||||
!deriveAvail[sectionName] || deriveAvail[sectionName].some((query): boolean => queryKeys.includes(query))
|
!deriveAvail[sectionName] ||
|
||||||
|
deriveAvail[sectionName].instances.some((q) => queryKeys.includes(q)) ||
|
||||||
|
(
|
||||||
|
deriveAvail[sectionName].withDetect &&
|
||||||
|
deriveAvail[sectionName].instances.some((q) =>
|
||||||
|
(api.registry.getModuleInstances(specName, q) || []).some((q) => queryKeys.includes(q))
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.reduce((deriveAcc, sectionName): DeriveAllSections<AllSections> => {
|
.reduce((deriveAcc, sectionName): DeriveAllSections<AllSections> => {
|
||||||
const section = allSections[sectionName as keyof AllSections];
|
const section = allSections[sectionName as keyof AllSections];
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export * from './members';
|
||||||
|
export * from './prime';
|
||||||
|
export * from './proposals';
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { members as collectiveMembers } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function members (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId[]> {
|
||||||
|
return memo(instanceId, collectiveMembers(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { prime as collectivePrime } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function prime (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId | null> {
|
||||||
|
return memo(instanceId, collectivePrime(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { u32 } from '@polkadot/types';
|
||||||
|
import type { Hash } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
import type { DeriveCollectiveProposal } from '../types';
|
||||||
|
|
||||||
|
import { hasProposals as collectiveHasProposals, proposal as collectiveProposal, proposalCount as collectiveProposalCount, proposalHashes as collectiveProposalHashes, proposals as collectiveProposals } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function hasProposals (instanceId: string, api: ApiInterfaceRx): () => Observable<boolean> {
|
||||||
|
return memo(instanceId, collectiveHasProposals(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposal (instanceId: string, api: ApiInterfaceRx): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
||||||
|
return memo(instanceId, collectiveProposal(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalCount (instanceId: string, api: ApiInterfaceRx): () => Observable<u32 | null> {
|
||||||
|
return memo(instanceId, collectiveProposalCount(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalHashes (instanceId: string, api: ApiInterfaceRx): () => Observable<Hash[]> {
|
||||||
|
return memo(instanceId, collectiveProposalHashes(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
|
||||||
|
return memo(instanceId, collectiveProposals(instanceId, api, 'membership'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// Auto-generated by @polkadot/dev, do not edit
|
||||||
|
|
||||||
|
export const packageInfo = { name: '@polkadot/api-derive', version: '4.17.1' };
|
||||||
@@ -13,7 +13,7 @@ import { map } from '@polkadot/x-rxjs/operators';
|
|||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
// parse into Indexes
|
// parse into Indexes
|
||||||
function parse ([activeEra, activeEraStart, currentEra, currentIndex, validatorCount]: [EraIndex, Option<Moment>, EraIndex, SessionIndex, u32]): DeriveSessionIndexes {
|
function parse ([currentIndex, activeEra, activeEraStart, currentEra, validatorCount]: [SessionIndex, EraIndex, Option<Moment>, EraIndex, u32]): DeriveSessionIndexes {
|
||||||
return {
|
return {
|
||||||
activeEra,
|
activeEra,
|
||||||
activeEraStart,
|
activeEraStart,
|
||||||
@@ -24,42 +24,57 @@ function parse ([activeEra, activeEraStart, currentEra, currentIndex, validatorC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// query based on latest
|
// query based on latest
|
||||||
function query (api: ApiInterfaceRx): Observable<DeriveSessionIndexes> {
|
function queryStaking (api: ApiInterfaceRx): Observable<DeriveSessionIndexes> {
|
||||||
return api.queryMulti<[Option<ActiveEraInfo>, Option<EraIndex>, SessionIndex, u32]>([
|
return api.queryMulti<[SessionIndex, Option<ActiveEraInfo>, Option<EraIndex>, u32]>([
|
||||||
|
api.query.session.currentIndex,
|
||||||
api.query.staking.activeEra,
|
api.query.staking.activeEra,
|
||||||
api.query.staking.currentEra,
|
api.query.staking.currentEra,
|
||||||
api.query.session.currentIndex,
|
|
||||||
api.query.staking.validatorCount
|
api.query.staking.validatorCount
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([activeOpt, currentEra, currentIndex, validatorCount]): DeriveSessionIndexes => {
|
map(([currentIndex, activeOpt, currentEra, validatorCount]): DeriveSessionIndexes => {
|
||||||
const { index, start } = activeOpt.unwrapOrDefault();
|
const { index, start } = activeOpt.unwrapOrDefault();
|
||||||
|
|
||||||
return parse([
|
return parse([
|
||||||
|
currentIndex,
|
||||||
index,
|
index,
|
||||||
start,
|
start,
|
||||||
currentEra.unwrapOrDefault(),
|
currentEra.unwrapOrDefault(),
|
||||||
currentIndex,
|
|
||||||
validatorCount
|
validatorCount
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// query based on latest
|
||||||
|
function querySession (api: ApiInterfaceRx): Observable<DeriveSessionIndexes> {
|
||||||
|
return api.query.session.currentIndex().pipe(
|
||||||
|
map((currentIndex): DeriveSessionIndexes => parse([
|
||||||
|
currentIndex,
|
||||||
|
api.registry.createType('EraIndex'),
|
||||||
|
api.registry.createType('Option<Moment>'),
|
||||||
|
api.registry.createType('EraIndex'),
|
||||||
|
api.registry.createType('u32')
|
||||||
|
]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// empty set when none is available
|
// empty set when none is available
|
||||||
function empty (api: ApiInterfaceRx): Observable<DeriveSessionIndexes> {
|
function empty (api: ApiInterfaceRx): Observable<DeriveSessionIndexes> {
|
||||||
return of(parse([
|
return of(parse([
|
||||||
|
api.registry.createType('SessionIndex', 1),
|
||||||
api.registry.createType('EraIndex'),
|
api.registry.createType('EraIndex'),
|
||||||
api.registry.createType('Option<Moment>'),
|
api.registry.createType('Option<Moment>'),
|
||||||
api.registry.createType('EraIndex'),
|
api.registry.createType('EraIndex'),
|
||||||
api.registry.createType('SessionIndex', 1),
|
|
||||||
api.registry.createType('u32')
|
api.registry.createType('u32')
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function indexes (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionIndexes> {
|
export function indexes (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionIndexes> {
|
||||||
return memo(instanceId, (): Observable<DeriveSessionIndexes> =>
|
return memo(instanceId, (): Observable<DeriveSessionIndexes> =>
|
||||||
api.query.session && api.query.staking
|
api.query.session
|
||||||
? query(api)
|
? api.query.staking
|
||||||
|
? queryStaking(api)
|
||||||
|
: querySession(api)
|
||||||
: empty(api)
|
: empty(api)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,71 +2,31 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { u64 } from '@polkadot/types';
|
|
||||||
import type { SessionIndex } from '@polkadot/types/interfaces';
|
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveSessionIndexes, DeriveSessionInfo } from '../types';
|
import type { DeriveSessionInfo } from '../types';
|
||||||
|
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
type ResultType = [boolean, u64, SessionIndex];
|
|
||||||
type Result = [ResultType, DeriveSessionIndexes];
|
|
||||||
|
|
||||||
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
|
|
||||||
return {
|
|
||||||
activeEra,
|
|
||||||
activeEraStart,
|
|
||||||
currentEra,
|
|
||||||
currentIndex,
|
|
||||||
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
|
||||||
isEpoch: hasBabe,
|
|
||||||
sessionLength: epochDuration,
|
|
||||||
sessionsPerEra,
|
|
||||||
validatorCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
|
||||||
return api.derive.session.indexes().pipe(
|
|
||||||
map((indexes): DeriveSessionInfo =>
|
|
||||||
createDerive(api, [
|
|
||||||
[
|
|
||||||
false,
|
|
||||||
api.registry.createType('u64', 1),
|
|
||||||
// we may have aura without staking (permissioned)
|
|
||||||
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
|
||||||
],
|
|
||||||
indexes
|
|
||||||
])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
|
||||||
return api.derive.session.indexes().pipe(
|
|
||||||
map((indexes) =>
|
|
||||||
createDerive(api, [
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
api.consts.babe.epochDuration,
|
|
||||||
// we may have babe without staking (permissioned)
|
|
||||||
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
|
||||||
],
|
|
||||||
indexes
|
|
||||||
])
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
||||||
*/
|
*/
|
||||||
export function info (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
|
export function info (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
|
||||||
return memo(instanceId, (): Observable<DeriveSessionInfo> =>
|
return memo(instanceId, (): Observable<DeriveSessionInfo> =>
|
||||||
api.consts.babe
|
api.derive.session.indexes().pipe(
|
||||||
? queryBabe(api)
|
map((indexes) => {
|
||||||
: queryAura(api)
|
const sessionLength = api.consts?.babe?.epochDuration || api.registry.createType('u64', 1);
|
||||||
|
const sessionsPerEra = api.consts?.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...indexes,
|
||||||
|
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(sessionLength)),
|
||||||
|
isEpoch: !!api.query.babe,
|
||||||
|
sessionLength,
|
||||||
|
sessionsPerEra
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultS
|
|||||||
combineLatest([
|
combineLatest([
|
||||||
of(info),
|
of(info),
|
||||||
// we may have no staking, but have babe (permissioned)
|
// we may have no staking, but have babe (permissioned)
|
||||||
api.query.staking
|
api.query.staking?.erasStartSessionIndex
|
||||||
? api.queryMulti<ResultSlots>([
|
? api.queryMulti<ResultSlots>([
|
||||||
api.query.babe.currentSlot,
|
api.query.babe.currentSlot,
|
||||||
api.query.babe.epochIndex,
|
api.query.babe.epochIndex,
|
||||||
@@ -69,7 +69,7 @@ function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultS
|
|||||||
*/
|
*/
|
||||||
export function progress (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
|
export function progress (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
|
||||||
return memo(instanceId, (): Observable<DeriveSessionProgress> =>
|
return memo(instanceId, (): Observable<DeriveSessionProgress> =>
|
||||||
api.consts.babe
|
api.query.babe
|
||||||
? queryBabe(api).pipe(
|
? queryBabe(api).pipe(
|
||||||
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
|
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
|
||||||
createDerive(api, info, slots)
|
createDerive(api, info, slots)
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { bool, Option, Vec } from '@polkadot/types';
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
import type { AccountId, Balance, BlockNumber, SocietyVote, StrikeCount, VouchingStatus } from '@polkadot/types/interfaces';
|
|
||||||
import type { ITuple } from '@polkadot/types/types';
|
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveSocietyMember } from '../types';
|
import type { DeriveSocietyMember } from '../types';
|
||||||
|
|
||||||
@@ -12,28 +10,13 @@ import { map } from '@polkadot/x-rxjs/operators';
|
|||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
type Result = [Vec<ITuple<[BlockNumber, Balance]>>, StrikeCount, Option<SocietyVote>, bool, Option<VouchingStatus>];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Get the member info for a society
|
* @description Get the member info for a society
|
||||||
*/
|
*/
|
||||||
export function member (instanceId: string, api: ApiInterfaceRx): (accountId: AccountId) => Observable<DeriveSocietyMember> {
|
export function member (instanceId: string, api: ApiInterfaceRx): (accountId: AccountId) => Observable<DeriveSocietyMember> {
|
||||||
return memo(instanceId, (accountId: AccountId): Observable<DeriveSocietyMember> =>
|
return memo(instanceId, (accountId: AccountId): Observable<DeriveSocietyMember> =>
|
||||||
api.queryMulti<Result>([
|
api.derive.society._members([accountId]).pipe(
|
||||||
[api.query.society.payouts, accountId],
|
map(([result]) => result)
|
||||||
[api.query.society.strikes, accountId],
|
|
||||||
[api.query.society.defenderVotes, accountId],
|
|
||||||
[api.query.society.suspendedMembers, accountId],
|
|
||||||
[api.query.society.vouching, accountId]
|
|
||||||
]).pipe(
|
|
||||||
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
|
|
||||||
accountId,
|
|
||||||
isSuspended: suspended.isTrue,
|
|
||||||
payouts,
|
|
||||||
strikes,
|
|
||||||
vote: defenderVotes.unwrapOr(undefined),
|
|
||||||
vouching: vouching.unwrapOr(undefined)
|
|
||||||
}))
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,51 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { AccountId } from '@polkadot/types/interfaces';
|
import type { bool, Option, Vec } from '@polkadot/types';
|
||||||
|
import type { AccountId, Balance, BlockNumber, SocietyVote, StrikeCount, VouchingStatus } from '@polkadot/types/interfaces';
|
||||||
|
import type { ITuple } from '@polkadot/types/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveSocietyMember } from '../types';
|
import type { DeriveSocietyMember } from '../types';
|
||||||
|
|
||||||
import { combineLatest } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
type Result = [AccountId[], Vec<ITuple<[BlockNumber, Balance]>>[], StrikeCount[], Option<SocietyVote>[], bool[], Option<VouchingStatus>[]];
|
||||||
|
|
||||||
|
export function _members (instanceId: string, api: ApiInterfaceRx): (accountIds: AccountId[]) => Observable<DeriveSocietyMember[]> {
|
||||||
|
return memo(instanceId, (accountIds: AccountId[]): Observable<DeriveSocietyMember[]> =>
|
||||||
|
combineLatest<Result>([
|
||||||
|
of(accountIds),
|
||||||
|
api.query.society.payouts.multi(accountIds),
|
||||||
|
api.query.society.strikes.multi(accountIds),
|
||||||
|
api.query.society.defenderVotes.multi(accountIds),
|
||||||
|
api.query.society.suspendedMembers.multi(accountIds),
|
||||||
|
api.query.society.vouching.multi(accountIds)
|
||||||
|
]).pipe(
|
||||||
|
map(([accountIds, payouts, strikes, defenderVotes, suspended, vouching]) =>
|
||||||
|
accountIds.map((accountId, index) => ({
|
||||||
|
accountId,
|
||||||
|
isDefenderVoter: defenderVotes[index].isSome,
|
||||||
|
isSuspended: suspended[index].isTrue,
|
||||||
|
payouts: payouts[index],
|
||||||
|
strikes: strikes[index],
|
||||||
|
vote: defenderVotes[index].unwrapOr(undefined),
|
||||||
|
vouching: vouching[index].unwrapOr(undefined)
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Get the member info for a society
|
* @description Get the member info for a society
|
||||||
*/
|
*/
|
||||||
export function members (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSocietyMember[]> {
|
export function members (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveSocietyMember[]> {
|
||||||
return memo(instanceId, (): Observable<DeriveSocietyMember[]> =>
|
return memo(instanceId, (): Observable<DeriveSocietyMember[]> =>
|
||||||
api.query.society.members<AccountId[]>().pipe(
|
api.query.society.members<AccountId[]>().pipe(
|
||||||
switchMap((members): Observable<DeriveSocietyMember[]> =>
|
switchMap((members) => api.derive.society._members(members))
|
||||||
combineLatest(
|
|
||||||
members.map((accountId): Observable<DeriveSocietyMember> =>
|
|
||||||
api.derive.society.member(accountId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import type { ApiInterfaceRx } from '@polkadot/api/types';
|
|||||||
import type { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
import type { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||||
import type { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingKeys, DeriveStakingQuery, DeriveUnlocking } from '../types';
|
import type { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingKeys, DeriveStakingQuery, DeriveUnlocking } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN, BN_ZERO } from '@polkadot/util';
|
||||||
|
|
||||||
import { BN_ZERO } from '@polkadot/util';
|
|
||||||
import { combineLatest, Observable } from '@polkadot/x-rxjs';
|
import { combineLatest, Observable } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { StorageKey } from '@polkadot/types';
|
import type { StorageKey } from '@polkadot/types';
|
||||||
import type { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
import type { AccountId, EraIndex, Exposure } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
|
import type { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
|||||||
|
|
||||||
import { deriveCache, memo } from '../util';
|
import { deriveCache, memo } from '../util';
|
||||||
|
|
||||||
type KeysAndExposures = [StorageKey, Exposure][];
|
type KeysAndExposures = [StorageKey<[EraIndex, AccountId]>, Exposure][];
|
||||||
|
|
||||||
const CACHE_KEY = 'eraExposure';
|
const CACHE_KEY = 'eraExposure';
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Option, u32 } from '@polkadot/types';
|
import type { Option, u32 } from '@polkadot/types';
|
||||||
import type { ActiveEraInfo, EraIndex } from '@polkadot/types/interfaces';
|
import type { ActiveEraInfo, EraIndex } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN_ONE, BN_ZERO } from '@polkadot/util';
|
||||||
|
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
@@ -24,12 +24,12 @@ export function erasHistoric (instanceId: string, api: ApiInterfaceRx): (withAct
|
|||||||
const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
|
const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
|
||||||
let lastEra = activeEra;
|
let lastEra = activeEra;
|
||||||
|
|
||||||
while (lastEra.gten(0) && (result.length < max)) {
|
while (lastEra.gte(BN_ZERO) && (result.length < max)) {
|
||||||
if ((lastEra !== activeEra) || (withActive === true)) {
|
if ((lastEra !== activeEra) || (withActive === true)) {
|
||||||
result.push(api.registry.createType('EraIndex', lastEra));
|
result.push(api.registry.createType('EraIndex', lastEra));
|
||||||
}
|
}
|
||||||
|
|
||||||
lastEra = lastEra.subn(1);
|
lastEra = lastEra.sub(BN_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// go from oldest to newest
|
// go from oldest to newest
|
||||||
|
|||||||
@@ -1,55 +1,37 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx, QueryableStorageMultiArg } from '@polkadot/api/types';
|
||||||
import type { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
import type { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveOwnExposure } from '../types';
|
import type { DeriveOwnExposure } from '../types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { deriveCache, memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
const CACHE_KEY = 'ownExposure';
|
export function _ownExposures (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveOwnExposure[]> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export function _ownExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex, withActive: boolean) => Observable<DeriveOwnExposure> {
|
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], _withActive: boolean): Observable<DeriveOwnExposure[]> =>
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex, withActive: boolean): Observable<DeriveOwnExposure> => {
|
eras.length
|
||||||
const cacheKey = `${CACHE_KEY}-${era.toString()}-${accountId.toString()}`;
|
? api.queryMulti<Exposure[]>([
|
||||||
const cached = withActive
|
...eras.map((era): QueryableStorageMultiArg<'rxjs'> => [api.query.staking.erasStakersClipped, [era, accountId]]),
|
||||||
? undefined
|
...eras.map((era): QueryableStorageMultiArg<'rxjs'> => [api.query.staking.erasStakers, [era, accountId]])
|
||||||
: deriveCache.get<DeriveOwnExposure>(cacheKey);
|
|
||||||
|
|
||||||
return cached
|
|
||||||
? of(cached)
|
|
||||||
: api.queryMulti<[Exposure, Exposure]>([
|
|
||||||
[api.query.staking.erasStakersClipped, [era, accountId]],
|
|
||||||
[api.query.staking.erasStakers, [era, accountId]]
|
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([clipped, exposure]): DeriveOwnExposure => {
|
map((all): DeriveOwnExposure[] =>
|
||||||
const value = { clipped, era, exposure };
|
eras.map((era, index) => ({ clipped: all[index], era, exposure: all[eras.length + index] }))
|
||||||
|
)
|
||||||
!withActive && deriveCache.set(cacheKey, value);
|
)
|
||||||
|
: of([])
|
||||||
return value;
|
);
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ownExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex) => Observable<DeriveOwnExposure> {
|
export function ownExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex) => Observable<DeriveOwnExposure> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex): Observable<DeriveOwnExposure> =>
|
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex): Observable<DeriveOwnExposure> =>
|
||||||
api.derive.staking._ownExposure(accountId, era, true)
|
api.derive.staking._ownExposures(accountId, [era], true).pipe(
|
||||||
);
|
map(([first]) => first)
|
||||||
}
|
)
|
||||||
|
|
||||||
export function _ownExposures (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveOwnExposure[]> {
|
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable<DeriveOwnExposure[]> =>
|
|
||||||
eras.length
|
|
||||||
? combineLatest(
|
|
||||||
eras.map((era) => api.derive.staking._ownExposure(accountId, era, withActive))
|
|
||||||
)
|
|
||||||
: of([])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +1,44 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx, QueryableStorageMultiArg } from '@polkadot/api/types';
|
||||||
import type { Option } from '@polkadot/types';
|
import type { Option } from '@polkadot/types';
|
||||||
import type { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
|
import type { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
|
||||||
import type { ITuple } from '@polkadot/types/types';
|
import type { ITuple } from '@polkadot/types/types';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveStakerSlashes } from '../types';
|
import type { DeriveStakerSlashes } from '../types';
|
||||||
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { deriveCache, memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
const CACHE_KEY = 'ownSlash';
|
export function _ownSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerSlashes[]> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export function _ownSlash (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex, withActive: boolean) => Observable<DeriveStakerSlashes> {
|
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], _withActive: boolean): Observable<DeriveStakerSlashes[]> =>
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex, withActive: boolean): Observable<DeriveStakerSlashes> => {
|
eras.length
|
||||||
const cacheKey = `${CACHE_KEY}-${era.toString()}-${accountId.toString()}`;
|
? api.queryMulti<(Option<ITuple<[Perbill, BalanceOf]>> | Option<BalanceOf>)[]>([
|
||||||
const cached = withActive
|
...eras.map((era): QueryableStorageMultiArg<'rxjs'> => [api.query.staking.validatorSlashInEra, [era, accountId]]),
|
||||||
? undefined
|
...eras.map((era): QueryableStorageMultiArg<'rxjs'> => [api.query.staking.nominatorSlashInEra, [era, accountId]])
|
||||||
: deriveCache.get<DeriveStakerSlashes>(cacheKey);
|
|
||||||
|
|
||||||
return cached
|
|
||||||
? of(cached)
|
|
||||||
: api.queryMulti<[Option<BalanceOf>, Option<ITuple<[Perbill, BalanceOf]>>]>([
|
|
||||||
[api.query.staking.nominatorSlashInEra, [era, accountId]],
|
|
||||||
[api.query.staking.validatorSlashInEra, [era, accountId]]
|
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([optNom, optVal]): DeriveStakerSlashes => {
|
map((values): DeriveStakerSlashes[] =>
|
||||||
const value = {
|
eras.map((era, index) => ({
|
||||||
era,
|
era,
|
||||||
total: optVal.isSome
|
total: values[index].isSome
|
||||||
? optVal.unwrap()[1]
|
? (values[index].unwrap() as ITuple<[Perbill, BalanceOf]>)[1]
|
||||||
: optNom.unwrapOrDefault()
|
: (values[index + eras.length].unwrapOrDefault() as BalanceOf)
|
||||||
};
|
}))
|
||||||
|
)
|
||||||
!withActive && deriveCache.set(cacheKey, value);
|
)
|
||||||
|
: of([])
|
||||||
return value;
|
);
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ownSlash (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex) => Observable<DeriveStakerSlashes> {
|
export function ownSlash (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, era: EraIndex) => Observable<DeriveStakerSlashes> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex): Observable<DeriveStakerSlashes> =>
|
return memo(instanceId, (accountId: Uint8Array | string, era: EraIndex): Observable<DeriveStakerSlashes> =>
|
||||||
api.derive.staking._ownSlash(accountId, era, true)
|
api.derive.staking._ownSlashes(accountId, [era], true).pipe(
|
||||||
);
|
map(([first]) => first)
|
||||||
}
|
)
|
||||||
|
|
||||||
export function _ownSlashes (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerSlashes[]> {
|
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable<DeriveStakerSlashes[]> =>
|
|
||||||
eras.length
|
|
||||||
? combineLatest(
|
|
||||||
eras.map((era) => api.derive.staking._ownSlash(accountId, era, withActive))
|
|
||||||
)
|
|
||||||
: of([])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,36 +10,46 @@ import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
|||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function _stakerExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerExposure[]> {
|
export function _stakerExposures (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerExposure[][]> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable<DeriveStakerExposure[]> => {
|
return memo(instanceId, (accountIds: (Uint8Array | string)[], eras: EraIndex[], withActive: boolean): Observable<DeriveStakerExposure[][]> => {
|
||||||
const stakerId = api.registry.createType('AccountId', accountId).toString();
|
const stakerIds = accountIds.map((a) => api.registry.createType('AccountId', a).toString());
|
||||||
|
|
||||||
return api.derive.staking._erasExposure(eras, withActive).pipe(
|
return api.derive.staking._erasExposure(eras, withActive).pipe(
|
||||||
map((exposures): DeriveStakerExposure[] =>
|
map((exposures): DeriveStakerExposure[][] =>
|
||||||
exposures.map(({ era, nominators: allNominators, validators: allValidators }): DeriveStakerExposure => {
|
stakerIds.map((stakerId) =>
|
||||||
const isValidator = !!allValidators[stakerId];
|
exposures.map(({ era, nominators: allNominators, validators: allValidators }): DeriveStakerExposure => {
|
||||||
const validators: DeriveEraValidatorExposure = {};
|
const isValidator = !!allValidators[stakerId];
|
||||||
const nominating = allNominators[stakerId] || [];
|
const validators: DeriveEraValidatorExposure = {};
|
||||||
|
const nominating = allNominators[stakerId] || [];
|
||||||
|
|
||||||
if (isValidator) {
|
if (isValidator) {
|
||||||
validators[stakerId] = allValidators[stakerId];
|
validators[stakerId] = allValidators[stakerId];
|
||||||
} else if (nominating) {
|
} else if (nominating) {
|
||||||
nominating.forEach(({ validatorId }): void => {
|
nominating.forEach(({ validatorId }): void => {
|
||||||
validators[validatorId] = allValidators[validatorId];
|
validators[validatorId] = allValidators[validatorId];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { era, isEmpty: !Object.keys(validators).length, isValidator, nominating, validators };
|
return { era, isEmpty: !Object.keys(validators).length, isValidator, nominating, validators };
|
||||||
})
|
})
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stakerExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerExposure[]> {
|
export function stakerExposures (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], withActive?: boolean) => Observable<DeriveStakerExposure[][]> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable<DeriveStakerExposure[]> =>
|
return memo(instanceId, (accountIds: (Uint8Array | string)[], withActive = false): Observable<DeriveStakerExposure[][]> =>
|
||||||
api.derive.staking.erasHistoric(withActive).pipe(
|
api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras) => api.derive.staking._stakerExposure(accountId, eras, withActive))
|
switchMap((eras) => api.derive.staking._stakerExposures(accountIds, eras, withActive))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stakerExposure (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerExposure[]> {
|
||||||
|
return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable<DeriveStakerExposure[]> =>
|
||||||
|
api.derive.staking.stakerExposures([accountId, withActive]).pipe(
|
||||||
|
map(([first]) => first)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,45 +2,39 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import type { Option } from '@polkadot/types';
|
import type { AccountId, EraIndex, StakingLedger } from '@polkadot/types/interfaces';
|
||||||
import type { AccountId, EraIndex, StakingLedger, StakingLedgerTo240 } from '@polkadot/types/interfaces';
|
import type { BN } from '@polkadot/util';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward, DeriveStakerRewardValidator } from '../types';
|
import type { DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward, DeriveStakerRewardValidator } from '../types';
|
||||||
import type { DeriveStakingQuery } from './types';
|
import type { DeriveStakingQuery } from './types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN_BILLION, BN_ZERO } from '@polkadot/util';
|
||||||
|
|
||||||
import { isFunction } from '@polkadot/util';
|
|
||||||
import { combineLatest, of } from '@polkadot/x-rxjs';
|
import { combineLatest, of } from '@polkadot/x-rxjs';
|
||||||
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
import { map, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
type ErasResult = [{ unwrapOr: (value: BN) => BN }, DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[]];
|
type ErasResult = [DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[]];
|
||||||
|
|
||||||
const ZERO = new BN(0);
|
function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, erasPrefs, erasRewards]: ErasResult, exposures: DeriveStakerExposure[]): DeriveStakerReward[] {
|
||||||
const MIN_ONE = new BN(-1);
|
|
||||||
const COMM_DIV = new BN(1_000_000_000);
|
|
||||||
|
|
||||||
function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [, erasPoints, erasPrefs, erasRewards]: ErasResult, exposures: DeriveStakerExposure[]): DeriveStakerReward[] {
|
|
||||||
return exposures.map(({ era, isEmpty, isValidator, nominating, validators: eraValidators }): DeriveStakerReward => {
|
return exposures.map(({ era, isEmpty, isValidator, nominating, validators: eraValidators }): DeriveStakerReward => {
|
||||||
const { eraPoints, validators: allValPoints } = erasPoints.find((p) => p.era.eq(era)) || { eraPoints: ZERO, validators: {} };
|
const { eraPoints, validators: allValPoints } = erasPoints.find((p) => p.era.eq(era)) || { eraPoints: BN_ZERO, validators: {} };
|
||||||
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: api.registry.createType('Balance') };
|
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: api.registry.createType('Balance') };
|
||||||
const { validators: allValPrefs } = erasPrefs.find((p) => p.era.eq(era)) || { validators: {} as DeriveEraValPrefs };
|
const { validators: allValPrefs } = erasPrefs.find((p) => p.era.eq(era)) || { validators: {} as DeriveEraValPrefs };
|
||||||
const validators: Record<string, DeriveStakerRewardValidator> = {};
|
const validators: Record<string, DeriveStakerRewardValidator> = {};
|
||||||
const stakerId = stashId.toString();
|
const stakerId = stashId.toString();
|
||||||
|
|
||||||
Object.entries(eraValidators).forEach(([validatorId, exposure]): void => {
|
Object.entries(eraValidators).forEach(([validatorId, exposure]): void => {
|
||||||
const valPoints = allValPoints[validatorId] || ZERO;
|
const valPoints = allValPoints[validatorId] || BN_ZERO;
|
||||||
const valComm = allValPrefs[validatorId]?.commission.unwrap() || ZERO;
|
const valComm = allValPrefs[validatorId]?.commission.unwrap() || BN_ZERO;
|
||||||
const expTotal = exposure.total.unwrap();
|
const expTotal = exposure.total?.unwrap() || BN_ZERO;
|
||||||
let avail = ZERO;
|
let avail = BN_ZERO;
|
||||||
let value: BN | undefined;
|
let value: BN | undefined;
|
||||||
|
|
||||||
if (!(expTotal.isZero() || valPoints.isZero() || eraPoints.isZero())) {
|
if (!(expTotal.isZero() || valPoints.isZero() || eraPoints.isZero())) {
|
||||||
avail = eraReward.mul(valPoints).div(eraPoints);
|
avail = eraReward.mul(valPoints).div(eraPoints);
|
||||||
|
|
||||||
const valCut = valComm.mul(avail).div(COMM_DIV);
|
const valCut = valComm.mul(avail).div(BN_BILLION);
|
||||||
let staked: BN;
|
let staked: BN;
|
||||||
|
|
||||||
if (validatorId === stakerId) {
|
if (validatorId === stakerId) {
|
||||||
@@ -50,10 +44,10 @@ function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [, erasPoints, e
|
|||||||
|
|
||||||
staked = stakerExp
|
staked = stakerExp
|
||||||
? stakerExp.value.unwrap()
|
? stakerExp.value.unwrap()
|
||||||
: ZERO;
|
: BN_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = avail.sub(valCut).imul(staked).div(expTotal).iadd(validatorId === stakerId ? valCut : ZERO);
|
value = avail.sub(valCut).imul(staked).div(expTotal).iadd(validatorId === stakerId ? valCut : BN_ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
validators[validatorId] = {
|
validators[validatorId] = {
|
||||||
@@ -73,32 +67,25 @@ function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [, erasPoints, e
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function uniqValidators (rewards: DeriveStakerReward[]): string[] {
|
function allUniqValidators (rewards: DeriveStakerReward[][]): [string[], string[][]] {
|
||||||
const uniq: string[] = [];
|
return rewards.reduce(([all, perStash]: [string[], string[][]], rewards) => {
|
||||||
|
const uniq: string[] = [];
|
||||||
|
|
||||||
rewards.forEach(({ validators }): void => {
|
perStash.push(uniq);
|
||||||
Object.keys(validators).forEach((validatorId): void => {
|
rewards.forEach(({ validators }) =>
|
||||||
if (!uniq.includes(validatorId)) {
|
Object.keys(validators).forEach((validatorId): void => {
|
||||||
uniq.push(validatorId);
|
if (!uniq.includes(validatorId)) {
|
||||||
}
|
uniq.push(validatorId);
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return uniq;
|
if (!all.includes(validatorId)) {
|
||||||
}
|
all.push(validatorId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
function isOldLedger (ledger?: StakingLedger | StakingLedgerTo240): ledger is StakingLedgerTo240 {
|
return [all, perStash];
|
||||||
return !!(ledger as StakingLedgerTo240)?.lastReward;
|
}, [[], []]);
|
||||||
}
|
|
||||||
|
|
||||||
function filterEra (era: EraIndex, stakingLedger: StakingLedger): boolean {
|
|
||||||
return isOldLedger(stakingLedger)
|
|
||||||
? era.gt(stakingLedger.lastReward.unwrapOr(MIN_ONE))
|
|
||||||
: !stakingLedger.claimedRewards.some((e) => e.eq(era));
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterEras (eras: EraIndex[], stakingLedger: StakingLedger): EraIndex[] {
|
|
||||||
return eras.filter((era) => filterEra(era, stakingLedger));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeClaimed (validators: string[], queryValidators: DeriveStakingQuery[], reward: DeriveStakerReward): void {
|
function removeClaimed (validators: string[], queryValidators: DeriveStakingQuery[], reward: DeriveStakerReward): void {
|
||||||
@@ -121,43 +108,32 @@ function removeClaimed (validators: string[], queryValidators: DeriveStakingQuer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], { migrateEra, rewards, stakingLedger }: { migrateEra: BN, rewards: DeriveStakerReward[]; stakingLedger: StakingLedger }): Observable<DeriveStakerReward[]> {
|
function filterRewards (eras: EraIndex[], valInfo: [string, DeriveStakingQuery][], { rewards, stakingLedger }: { rewards: DeriveStakerReward[]; stakingLedger: StakingLedger }): DeriveStakerReward[] {
|
||||||
const validators = uniqValidators(rewards);
|
const filter = eras.filter((era) => !stakingLedger.claimedRewards.some((e) => e.eq(era)));
|
||||||
const filter = filterEras(eras, stakingLedger);
|
const validators = valInfo.map(([v]) => v);
|
||||||
|
const queryValidators = valInfo.map(([, q]) => q);
|
||||||
|
|
||||||
return api.derive.staking.queryMulti(validators, { withLedger: true }).pipe(
|
return rewards
|
||||||
map((queryValidators): DeriveStakerReward[] =>
|
.filter(({ isEmpty }) => !isEmpty)
|
||||||
rewards
|
.filter((reward): boolean => {
|
||||||
.filter(({ isEmpty }) => !isEmpty)
|
if (!filter.some((filter) => reward.era.eq(filter))) {
|
||||||
.filter((reward): boolean => {
|
return false;
|
||||||
if (!filter.some((filter) => reward.era.eq(filter))) {
|
}
|
||||||
return false;
|
|
||||||
} else if (reward.era.lt(migrateEra)) {
|
|
||||||
// we filter again here, the actual ledger may have changed, e.g. something has been claimed
|
|
||||||
return filterEra(reward.era, stakingLedger);
|
|
||||||
}
|
|
||||||
|
|
||||||
reward.isStakerPayout = true;
|
removeClaimed(validators, queryValidators, reward);
|
||||||
|
|
||||||
removeClaimed(validators, queryValidators, reward);
|
return true;
|
||||||
|
})
|
||||||
return true;
|
.filter(({ validators }) => Object.keys(validators).length !== 0)
|
||||||
})
|
.map((reward) => ({
|
||||||
.filter(({ validators }) => Object.keys(validators).length !== 0)
|
...reward,
|
||||||
.map((reward) => ({
|
nominators: reward.nominating.filter((n) => reward.validators[n.validatorId])
|
||||||
...reward,
|
}));
|
||||||
nominators: reward.nominating.filter((n) => reward.validators[n.validatorId])
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _stakerRewardsEras (instanceId: string, api: ApiInterfaceRx): (eras: EraIndex[], withActive: boolean) => Observable<ErasResult> {
|
export function _stakerRewardsEras (instanceId: string, api: ApiInterfaceRx): (eras: EraIndex[], withActive: boolean) => Observable<ErasResult> {
|
||||||
return memo(instanceId, (eras: EraIndex[], withActive: boolean): Observable<ErasResult> =>
|
return memo(instanceId, (eras: EraIndex[], withActive: boolean): Observable<ErasResult> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
isFunction(api.query.staking.migrateEra)
|
|
||||||
? api.query.staking.migrateEra<Option<EraIndex>>()
|
|
||||||
: of(api.registry.createType('Option<EraIndex>')),
|
|
||||||
api.derive.staking._erasPoints(eras, withActive),
|
api.derive.staking._erasPoints(eras, withActive),
|
||||||
api.derive.staking._erasPrefs(eras, withActive),
|
api.derive.staking._erasPrefs(eras, withActive),
|
||||||
api.derive.staking._erasRewards(eras, withActive)
|
api.derive.staking._erasRewards(eras, withActive)
|
||||||
@@ -165,23 +141,43 @@ export function _stakerRewardsEras (instanceId: string, api: ApiInterfaceRx): (e
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _stakerRewards (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerReward[]> {
|
export function _stakerRewards (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], eras: EraIndex[], withActive: boolean) => Observable<DeriveStakerReward[][]> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean): Observable<DeriveStakerReward[]> =>
|
return memo(instanceId, (accountIds: (Uint8Array | string)[], eras: EraIndex[], withActive: boolean): Observable<DeriveStakerReward[][]> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
api.derive.staking.query(accountId, { withLedger: true }),
|
api.derive.staking.queryMulti(accountIds, { withLedger: true }),
|
||||||
api.derive.staking._stakerExposure(accountId, eras, withActive),
|
api.derive.staking._stakerExposures(accountIds, eras, withActive),
|
||||||
api.derive.staking._stakerRewardsEras(eras, withActive)
|
api.derive.staking._stakerRewardsEras(eras, withActive)
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(([{ stakingLedger, stashId }, exposures, erasResult]): Observable<DeriveStakerReward[]> => {
|
switchMap(([queries, exposures, erasResult]): Observable<DeriveStakerReward[][]> => {
|
||||||
if (!stashId || !stakingLedger) {
|
const allRewards = queries.map(({ stakingLedger, stashId }, index): DeriveStakerReward[] =>
|
||||||
return of([]);
|
(!stashId || !stakingLedger)
|
||||||
|
? []
|
||||||
|
: parseRewards(api, stashId, erasResult, exposures[index])
|
||||||
|
);
|
||||||
|
|
||||||
|
if (withActive) {
|
||||||
|
return of(allRewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rewards = parseRewards(api, stashId, erasResult, exposures);
|
const [allValidators, stashValidators] = allUniqValidators(allRewards);
|
||||||
|
|
||||||
return withActive
|
return api.derive.staking.queryMulti(allValidators, { withLedger: true }).pipe(
|
||||||
? of(rewards)
|
map((queriedVals): DeriveStakerReward[][] =>
|
||||||
: filterRewards(api, eras, { migrateEra: erasResult[0].unwrapOr(ZERO), rewards, stakingLedger });
|
queries.map(({ stakingLedger }, index): DeriveStakerReward[] =>
|
||||||
|
filterRewards(
|
||||||
|
eras,
|
||||||
|
stashValidators[index].map((validatorId): [string, DeriveStakingQuery] => [
|
||||||
|
validatorId,
|
||||||
|
queriedVals.find((q) => q.accountId.eq(validatorId)) as DeriveStakingQuery
|
||||||
|
]),
|
||||||
|
{
|
||||||
|
rewards: allRewards[index],
|
||||||
|
stakingLedger
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -190,7 +186,8 @@ export function _stakerRewards (instanceId: string, api: ApiInterfaceRx): (accou
|
|||||||
export function stakerRewards (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerReward[]> {
|
export function stakerRewards (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerReward[]> {
|
||||||
return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable<DeriveStakerReward[]> =>
|
return memo(instanceId, (accountId: Uint8Array | string, withActive = false): Observable<DeriveStakerReward[]> =>
|
||||||
api.derive.staking.erasHistoric(withActive).pipe(
|
api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras) => api.derive.staking._stakerRewards(accountId, eras, withActive))
|
switchMap((eras) => api.derive.staking._stakerRewards([accountId], eras, withActive)),
|
||||||
|
map(([first]) => first)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -198,7 +195,7 @@ export function stakerRewards (instanceId: string, api: ApiInterfaceRx): (accoun
|
|||||||
export function stakerRewardsMultiEras (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], eras: EraIndex[]) => Observable<DeriveStakerReward[][]> {
|
export function stakerRewardsMultiEras (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], eras: EraIndex[]) => Observable<DeriveStakerReward[][]> {
|
||||||
return memo(instanceId, (accountIds: (Uint8Array | string)[], eras: EraIndex[]): Observable<DeriveStakerReward[][]> =>
|
return memo(instanceId, (accountIds: (Uint8Array | string)[], eras: EraIndex[]): Observable<DeriveStakerReward[][]> =>
|
||||||
accountIds.length && eras.length
|
accountIds.length && eras.length
|
||||||
? combineLatest(accountIds.map((acc) => api.derive.staking._stakerRewards(acc, eras, false)))
|
? api.derive.staking._stakerRewards(accountIds, eras, false)
|
||||||
: of([])
|
: of([])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,42 @@ import type { ApiInterfaceRx } from '@polkadot/api/types';
|
|||||||
import type { AccountId } from '@polkadot/types/interfaces';
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
import { map } from '@polkadot/x-rxjs/operators';
|
import { map, startWith, switchMap } from '@polkadot/x-rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { drr, memo } from '../util';
|
||||||
|
|
||||||
|
function onBondedEvent (api: ApiInterfaceRx): Observable<number> {
|
||||||
|
let current = Date.now();
|
||||||
|
|
||||||
|
return api.query.system.events().pipe(
|
||||||
|
map((events): number => {
|
||||||
|
current = events.filter(({ event, phase }): boolean => {
|
||||||
|
try {
|
||||||
|
return phase.isApplyExtrinsic &&
|
||||||
|
event.section === 'staking' &&
|
||||||
|
event.method === 'Bonded';
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
? Date.now()
|
||||||
|
: current;
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}),
|
||||||
|
startWith(current),
|
||||||
|
drr({ skipTimeout: true })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Retrieve the list of all validator stashes
|
* @description Retrieve the list of all validator stashes
|
||||||
*/
|
*/
|
||||||
export function stashes (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId[]> {
|
export function stashes (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId[]> {
|
||||||
return memo(instanceId, (): Observable<AccountId[]> =>
|
return memo(instanceId, (): Observable<AccountId[]> =>
|
||||||
api.query.staking.validators.keys().pipe(
|
onBondedEvent(api).pipe(
|
||||||
map((keys) => keys.map((key) => key.args[0]).filter((a) => a))
|
switchMap(() => api.query.staking.validators.keys()),
|
||||||
|
map((keys) => keys.map(({ args: [validatorId] }) => validatorId).filter((a) => a))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type BN from 'bn.js';
|
|
||||||
import type { AccountId, Balance, EraIndex, Exposure, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
|
import type { AccountId, Balance, EraIndex, Exposure, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||||
|
import type { BN } from '@polkadot/util';
|
||||||
import type { DeriveSessionIndexes } from '../session/types';
|
import type { DeriveSessionIndexes } from '../session/types';
|
||||||
|
|
||||||
export type DeriveEraValPoints = Record<string, RewardPoint>;
|
export type DeriveEraValPoints = Record<string, RewardPoint>;
|
||||||
@@ -81,7 +81,6 @@ export interface DeriveStakerRewardValidator {
|
|||||||
export interface DeriveStakerReward {
|
export interface DeriveStakerReward {
|
||||||
era: EraIndex;
|
era: EraIndex;
|
||||||
eraReward: Balance;
|
eraReward: Balance;
|
||||||
isStakerPayout?: boolean;
|
|
||||||
isEmpty: boolean;
|
isEmpty: boolean;
|
||||||
isValidator: boolean;
|
isValidator: boolean;
|
||||||
nominating: DeriveEraExposureNominating[];
|
nominating: DeriveEraExposureNominating[];
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export function nextElected (instanceId: string, api: ApiInterfaceRx): () => Obs
|
|||||||
// only populate for next era in the last session, so track both here - entries are not
|
// only populate for next era in the last session, so track both here - entries are not
|
||||||
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
|
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
|
||||||
switchMap(({ currentEra }) => api.query.staking.erasStakers.keys(currentEra)),
|
switchMap(({ currentEra }) => api.query.staking.erasStakers.keys(currentEra)),
|
||||||
map((keys) => keys.map((key) => key.args[1]))
|
map((keys) => keys.map(({ args: [, accountId] }) => accountId))
|
||||||
)
|
)
|
||||||
: api.query.staking.currentElected<AccountId[]>()
|
: api.query.staking.currentElected<AccountId[]>()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
export * from './members';
|
||||||
|
export * from './prime';
|
||||||
export * from './proposals';
|
export * from './proposals';
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { members as collectiveMembers } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function members (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId[]> {
|
||||||
|
return memo(instanceId, collectiveMembers(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { AccountId } from '@polkadot/types/interfaces';
|
||||||
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
|
|
||||||
|
import { prime as collectivePrime } from '../collective';
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function prime (instanceId: string, api: ApiInterfaceRx): () => Observable<AccountId | null> {
|
||||||
|
return memo(instanceId, collectivePrime(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
@@ -2,12 +2,30 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
import type { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import type { u32 } from '@polkadot/types';
|
||||||
|
import type { Hash } from '@polkadot/types/interfaces';
|
||||||
import type { Observable } from '@polkadot/x-rxjs';
|
import type { Observable } from '@polkadot/x-rxjs';
|
||||||
import type { DeriveCollectiveProposal } from '../types';
|
import type { DeriveCollectiveProposal } from '../types';
|
||||||
|
|
||||||
import { proposals as collectiveProposals } from '../collective';
|
import { hasProposals as collectiveHasProposals, proposal as collectiveProposal, proposalCount as collectiveProposalCount, proposalHashes as collectiveProposalHashes, proposals as collectiveProposals } from '../collective';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function hasProposals (instanceId: string, api: ApiInterfaceRx): () => Observable<boolean> {
|
||||||
|
return memo(instanceId, collectiveHasProposals(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposal (instanceId: string, api: ApiInterfaceRx): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
|
||||||
|
return memo(instanceId, collectiveProposal(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalCount (instanceId: string, api: ApiInterfaceRx): () => Observable<u32 | null> {
|
||||||
|
return memo(instanceId, collectiveProposalCount(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function proposalHashes (instanceId: string, api: ApiInterfaceRx): () => Observable<Hash[]> {
|
||||||
|
return memo(instanceId, collectiveProposalHashes(instanceId, api, 'technicalCommittee'));
|
||||||
|
}
|
||||||
|
|
||||||
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
|
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
|
||||||
return memo(instanceId, collectiveProposals(instanceId, api, 'technicalCommittee'));
|
return memo(instanceId, collectiveProposals(instanceId, api, 'technicalCommittee'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
|
|||||||
|
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
api.query.treasury.proposals.multi<Option<TreasuryProposal>>(allIds),
|
api.query.treasury.proposals.multi<Option<TreasuryProposal>>(allIds),
|
||||||
api.derive.council.proposals()
|
api.derive.council
|
||||||
|
? api.derive.council.proposals()
|
||||||
|
: of([] as DeriveCollectiveProposal[])
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DeriveCollectiveProposal[]]): DeriveTreasuryProposals =>
|
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DeriveCollectiveProposal[]]): DeriveTreasuryProposals =>
|
||||||
parseResult(api, { allIds, allProposals, approvalIds, councilProposals, proposalCount })
|
parseResult(api, { allIds, allProposals, approvalIds, councilProposals, proposalCount })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
// Copyright 2017-2021 @polkadot/api-derive authors & contributors
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { BN } from '@polkadot/util';
|
||||||
|
|
||||||
export const FALLBACK_MAX_HASH_COUNT = 250;
|
export const FALLBACK_MAX_HASH_COUNT = 250;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user