diff --git a/src/assets/App.css b/src/assets/App.css index 1419fcc..d79dac8 100644 --- a/src/assets/App.css +++ b/src/assets/App.css @@ -1 +1 @@ -.footer{left:0;right:0}.new-form,.settings,.ballots-i{background-color:#fff;border-radius:6px;border:1px solid #e4e4e4;margin-bottom:30px;padding:30px;transition:0.15s box-shadow}@media screen and (max-width: 768px){.new-form,.settings,.ballots-i{margin-bottom:15px;padding:15px}}input,textarea,select{transition:0.3s background-color, 0.3s border-color;background-color:#fff;border-radius:3px;border:1px solid #e4e4e4;box-sizing:border-box;color:#444;font-size:14px;height:40px;outline:none;padding:0 10px;width:100%}input:hover,textarea:hover,select:hover{border-color:#8e959d;color:#202d3c}input:focus,textarea:focus,select:focus{border-color:#5c34a2;color:#202d3c}.sokol input:focus,.sokol textarea:focus,.sokol select:focus{border-color:#6ac9b9}button,.ballots-i--vote,.ballots-footer-finalize{cursor:pointer;display:inline-block;transition:0.3s opacity;box-sizing:border-box;border:0;outline:none;padding:0 15px;text-transform:uppercase;line-height:36px;font-size:13px;font-weight:bold}button:hover,.ballots-i--vote:hover,.ballots-footer-finalize:hover{opacity:0.9;text-decoration:none}html,body,p,h1,h2,h3{margin:0;padding:0;font-weight:normal}html{display:flex;min-height:100%}body{-webkit-font-smoothing:antialiased;background-color:#ffffff;box-sizing:border-box;color:#333;font-family:'Nunito', sans-serif;font-size:14px;padding-bottom:66px;position:relative;width:100%}@media screen and (max-width: 768px){body{padding-bottom:132px}}@media screen and (max-width: 767px){body{padding-bottom:132px}}a{color:#5c34a2;text-decoration:none}a:hover{text-decoration:underline}a .sokol{color:#6ac9b9}hr{display:block;width:100%;height:1px;margin:10px 0 30px;border:0;background-color:#e4e4e4}.center{text-align:center}.left{float:left;width:48%}.right{float:right;width:48%}@media screen and (max-width: 767px){.left,.right{float:none;width:100%}}.hidden{overflow:hidden}.display-none{display:none}.container{width:960px;margin:0 auto;box-sizing:border-box}@media screen and (max-width: 960px){.container{width:100%;padding:0 10px}}.title{margin-top:30px;margin-bottom:30px;color:#38454f;font-size:30px;font-weight:normal}@media screen and (max-width: 768px){.title{font-size:28px}}@media screen and (max-width: 767px){.title{font-size:26px}}button,input,textarea{outline:none}.btn{background-position:calc(100% - 15px) 50%;background-repeat:no-repeat;border-radius:5px;border:0;color:#fff;cursor:pointer;font-weight:bold;font-size:14px;line-height:42px;outline:none;padding:0 15px;text-decoration:none;text-transform:uppercase;transition:0.15s background-color}.btn.btn-primary{background-color:#5c34a2;box-shadow:0px 5px 10px 0 rgba(92,52,162,0.3)}.btn.btn-primary:hover{background-color:#46287b}.btn.btn-success{background-color:#60db97;box-shadow:0px 5px 10px 0 rgba(96,219,151,0.3)}.btn.btn-success:hover{background-color:#36d27c}.btn.btn-danger{background-color:#f21b57;box-shadow:0px 5px 10px 0 rgba(242,27,87,0.3)}.btn.btn-danger:hover{background-color:#ce0c42}.btn.btn-freeze{background-color:#50bbda;box-shadow:0px 5px 10px 0 rgba(80,187,218,0.3)}.btn.btn-freeze:hover{background-color:#2ba8cc}.sokol .btn.btn-primary{background-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(106,201,185,0.3)}.sokol .btn.btn-primary:hover{background-color:#45bba7}.sokol .btn.btn-success{background-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(96,219,151,0.3)}.sokol .btn.btn-success:hover{background-color:#45bba7}.sokol .btn.btn-danger{background-color:#f24c67;box-shadow:0px 5px 10px 0 rgba(242,76,103,0.33)}.sokol .btn.btn-danger:hover{background-color:#ef1c3f}.sokol .btn.btn-freeze{background-color:#50bbda;box-shadow:0px 5px 10px 0 rgba(80,187,218,0.3)}.sokol .btn.btn-freeze:hover{background-color:#2ba8cc}.btn.btn-new{background-image:url("../assets/images/icons/icon-add.svg");background-size:14px 14px;padding-right:45px}.btn.btn-load-more{background-image:url("../assets/images/icons/icon-load-more.svg");border-radius:5px;border:2px solid #5c34a2;font-size:17px;font-weight:400;background-size:14px 14px;padding-right:45px}.sokol .btn.btn-load-more{background-image:url("../assets/images/icons/icon-load-more-sokol.svg");border-color:#6ac9b9}.btn.btn-transparent{color:#5c34a2;background-color:transparent}.btn.btn-transparent:hover{opacity:0.8}.sokol .btn.btn-transparent{color:#6ac9b9}.btn[disabled],.sokol .btn[disabled],.btn.disabled,.sokol .btn.disabled{color:#333333;cursor:default;background-color:#f0f0f0;box-shadow:none}.btn[disabled]:hover,.sokol .btn[disabled]:hover,.btn.disabled:hover,.sokol .btn.disabled:hover{background-color:#f0f0f0}.btn.btn-finalize{background-image:url("../assets/images/icons/icon-finalize-white.svg");background-size:14px 14px;padding-right:45px}.btn.btn-finalize[disabled],.btn.btn-finalize.disabled{background-image:url("../assets/images/icons/icon-finalize-black.svg")}.btn.no-shadow{box-shadow:none}.btn.text-lowercase{text-transform:lowercase}.btn.text-uppercase{text-transform:uppercase}.btn.text-capitalize{text-transform:capitalize}label{color:#333;display:inline-block;font-size:13px;line-height:1.2;margin-bottom:15px}input:focus,textarea:focus{border-color:#fff}input[type='radio'],textarea[type='radio']{display:none}textarea{width:100%;padding-top:10px;padding-bottom:10px;height:70px;resize:none}select{appearance:none;background-image:url(./images/select.png);background-position:right 13px center;background-repeat:no-repeat;padding-right:30px}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){select{background-image:url("./images/select@2x.png");background-size:8px 4px}}button{background-color:rgba(92,52,162,0.1);color:#5c34a2}button.load-more{margin-bottom:50px}@media screen and (max-width: 960px){button.load-more{margin-bottom:80px}}@media screen and (max-width: 768px){button.load-more{margin-top:80px}}.radio-button{position:relative}.radio-button-label{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;border-radius:3px;border:1px solid #e4e4e4;color:#333;cursor:pointer;font-size:14px;font-weight:400;line-height:50px;margin:0;outline:none;padding:0 15px;text-decoration:none;text-transform:capitalize;text-align:center;transition:0.25s background-color;position:relative;z-index:1}.radio-button input[type='radio']{height:100%;position:absolute;visibility:hidden;width:100%;z-index:12}input[type='radio']:checked+.radio-button-label{background-color:#5c34a2;border-color:#5c34a2;box-shadow:0px 5px 10px 0 rgba(92,52,162,0.3);color:#fff}.sokol input[type='radio']:checked+.radio-button-label{background-color:#6ac9b9;border-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(106,201,185,0.3)}.keys-radio-button-tr{display:flex;margin-bottom:30px}@media screen and (max-width: 768px){.keys-radio-button-tr{flex-direction:column}}.keys-radio-button-td{min-width:30%;margin-right:5%}.keys-radio-button-td:last-child{margin-right:0}.keys-radio-button-td .radio-button-label{display:flex;justify-content:center}@media screen and (max-width: 768px){.keys-radio-button-td{margin-bottom:15px;margin-right:0;min-width:100%}}.form-el{margin-bottom:30px}.hint{color:#777;font-size:13px;font-weight:400;line-height:1.38;padding-top:12px;margin:0;word-break:break-word}.footer{background-color:#5c34a2;bottom:0;padding:18px 0;position:absolute}.footer.sokol{background-color:#6ac9b9}.footer .container{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}@media screen and (max-width: 768px){.footer .container{flex-direction:column}}.footer .socials{order:2}@media screen and (max-width: 768px){.footer .socials{margin-top:15px;order:1}}.footer-logo{background-image:url("../assets/images/logos/logo-poa.svg");background-repeat:no-repeat;background-size:contain;display:block;height:18px;left:0;order:0;width:139px}.footer-logo.sokol{background-image:url("../assets/images/logos/logo-sokol.svg");width:144px}.footer-rights{color:#fff;font-size:12px;order:1;text-align:center}@media screen and (max-width: 768px){.footer-rights{line-height:normal;margin-top:15px;order:2;width:100%}}.header{background-color:#5c34a2;position:relative;width:100%;z-index:9999}@media screen and (max-width: 767px){.header{left:0;right:0;position:fixed;top:0;z-index:124}}.header .container{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}@media screen and (max-width: 767px){.header .container{width:93%;padding:22px 0}}.header.sokol{background-color:#6ac9b9}.header-logo{display:block;height:26px}.header .links-container{align-items:center;display:flex;justify-content:space-between;height:70px;margin-left:auto}@media screen and (max-width: 767px){.header .links-container{display:none}}@media screen and (max-width: 768px){.header .links-container{justify-content:flex-end;width:auto}}.header .links-container-mobile{display:none}@media screen and (max-width: 767px){.header .links-container-mobile{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:space-evenly}}.header .link{color:#fff;font-size:14px;font-weight:700;line-height:18px;margin-left:34px;opacity:0.8;text-decoration:none;transition:opacity linear 0.1s}.header .link:hover,.header .link.active{opacity:1}@media screen and (max-width: 767px){.header .link{margin-left:0}}.header .link-icon{height:18px;width:18px;margin-right:10px;float:left;background-position:50% 50%;background-repeat:no-repeat}.header .link-icon-all{background-image:url("../assets/images/icons/icon-all.svg")}.header .link-icon-active{background-image:url("../assets/images/icons/icon-active.svg")}.header .link-icon-to-finalize{background-image:url("../assets/images/icons/icon-to-finalize.svg")}.header.sokol .link-icon-all{background-image:url("../assets/images/icons/icon-all-sokol.svg")}.header.sokol .link-icon-active{background-image:url("../assets/images/icons/icon-active-sokol.svg")}.header.sokol .link-icon-to-finalize{background-image:url("../assets/images/icons/icon-to-finalize-sokol.svg")}.header .mobile-menu{display:none}@media screen and (max-width: 767px){.header .mobile-menu{display:block;order:3}}.header .mobile-menu .mobile-menu-icon{width:18px;height:14px}.header .mobile-menu .mobile-menu-open-icon{width:18px;height:18px}@media screen and (max-width: 767px){.header .header-mobile-menu-container{background-color:#45277a;height:220px}}@media screen and (max-width: 767px){.header.sokol .header-mobile-menu-container{background-color:#41b19e}}.header .Select{margin-left:25px}@media screen and (max-width: 767px){.header .Select{margin-left:0;max-width:125px;order:2}.header .Select .Select-control{max-width:125px}}.header .btn.btn-new-ballot{height:36px;line-height:36px;opacity:1}.header .btn.btn-new-ballot .link-icon{display:none}.header.sokol .btn.btn-new-ballot{background-color:#fff;background-image:url("../assets/images/icons/icon-add-sokol.svg");color:#6ac9b9}.header.sokol .btn.btn-new-ballot:hover{opacity:0.9}.select-network-id{background:#fff;width:40px}.info-container{background-color:#f8f8f8;margin-bottom:30px;margin-left:-30px;margin-right:-30px;padding-bottom:30px;padding-left:30px;padding-right:30px;padding-top:30px}@media screen and (max-width: 768px){.info-container{margin-left:-15px;margin-right:-15px;padding-left:15px;padding-right:15px}}.info{color:#000}.ballots .info{background-position:0 2px;background-repeat:no-repeat;color:#333333;font-size:14px;font-weight:normal;letter-spacing:normal;line-height:1.71;margin-bottom:20px;max-width:100%;min-height:32px;padding-left:30px;text-align:left;word-break:break-word}.ballots .info:last-child{margin-bottom:0}.ballots .info-minimum{background-image:url("../assets/images/icons/icon-min.svg");background-size:18px 18px}.ballots .info-details{background-image:url("../assets/images/icons/icon-info.svg");background-size:10px 18px;position:relative}.ballots .info-details.collapsed{height:90px;overflow:hidden}.ballots .info-details .toggle-show{color:#5c34a2;cursor:pointer;display:inline-block;margin-left:5px}.sokol .ballots .info-details .toggle-show{color:#6ac9b9}.new-form .info{padding:30px}.info-title{color:#333;font-size:16px;font-weight:400;margin-bottom:30px;padding-left:25px;position:relative}.info-title:before{background-image:url("../assets/images/icons/icon-info.svg");background-position:50% 50%;background-repeat:no-repeat;background-size:10px 18px;content:'';height:32px;left:0;position:absolute;top:50%;transform:translateY(-50%);width:10px}.info-i{color:#777;font-size:14px;line-height:1.71;margin-bottom:20px;padding-left:25px;position:relative}.info-i:before{background-color:#333;border-radius:50%;content:'';height:6px;left:0;position:absolute;top:8px;width:6px}.app-container{padding-bottom:30px;padding-top:40px;position:relative}.app-container.app-container-open-mobile-menu:before{background-color:rgba(78,44,137,0.8);bottom:0;content:'';display:none;left:0;position:fixed;right:0;top:290px;z-index:1234}@media screen and (max-width: 767px){.app-container.app-container-open-mobile-menu:before{display:block}}.app-container.app-container-open-mobile-menu.sokol:before{background-color:rgba(106,201,185,0.8)}@media screen and (max-width: 767px){#root,.app-container{height:100%}.app-container{padding-left:10px;padding-right:10px}}@media screen and (max-width: 767px){.content{padding-top:120px}}.content.content-menu-open{padding-top:290px}.clearfix::after{content:"";clear:both;display:table}@keyframes fadeOut{0%{opacity:.2}20%{opacity:1;transform:scale(1)}100%{opacity:.2;transform:scale(0.3)}}.loading{display:flex;justify-content:space-between;left:50%;margin:-30px 0 0 -111.5px;padding-top:50px;position:absolute;top:50%;width:206px}.loading:before{background-image:url("../assets/images/logos/logo_loader.svg");background-position:0 0;background-repeat:no-repeat;content:'';left:0;position:absolute;top:0;height:100px;width:206px}.loading-container{bottom:0;left:0;position:fixed;right:0;top:0;z-index:1000000}.loading-i{animation-duration:2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:fadeOut;animation-timing-function:linear;background-color:#fff;border-radius:50%;height:9px;opacity:.2;width:9px}.loading-i:nth-child(2){animation-delay:.1s}.loading-i:nth-child(3){animation-delay:.2s}.loading-i:nth-child(4){animation-delay:.3s}.loading-i:nth-child(5){animation-delay:.4s}.loading-i:nth-child(6){animation-delay:.5s}.main-title-container{-ms-flex-pack:justify;display:-ms-flexbox;display:flex;justify-content:space-between;margin-bottom:40px}.main-title-container .main-title{font-size:24px;color:#333;line-height:38px}@media screen and (max-width: 767px){.main-title-container{-ms-flex-direction:column;flex-direction:column}.main-title-container .search-input{width:100%}}.new-form{display:flex;overflow:hidden;padding:0}@media screen and (max-width: 768px){.new-form{display:block}}.new-form-side{box-sizing:border-box;padding-bottom:30px;padding-top:30px}@media screen and (max-width: 768px){.new-form-side{width:100% !important}}.new-form-side_left{background-color:#f8f8f8;padding-top:0;width:30%}@media screen and (max-width: 768px){.new-form-side_left{margin-bottom:30px;padding-bottom:0}}.new-form-side_right{border-left:1px solid #e4e4e4;padding-left:30px;padding-right:30px;width:70%}@media screen and (max-width: 768px){.new-form-side_right{border:0;padding-top:0}}.new .add-ballot{white-space:nowrap}@media screen and (max-width: 767px){.new .add-ballot{margin-top:20px}}.search-container{background-color:#502d8d;box-sizing:border-box;height:50px;padding:10px 0 0 0}.search-container.sokol{background-color:#41b19e}@media screen and (max-width: 767px){.search-container{left:0;position:fixed;right:0;top:70px;z-index:123}}input.search-input{background-color:transparent;background-image:url("../assets/images/icons/icon-search.svg");background-position:0 50%;background-repeat:no-repeat;background-size:16px 16px;border-radius:0;border:none;box-sizing:border-box;display:block;font-size:14px;font-weight:400;height:30px;outline:none;padding-left:30px;width:100%}input.search-input,input.search-input:focus input.search-input:hover,input.search-input:active{color:#fff}.sokol input.search-input{background-image:url("../assets/images/icons/icon-search-sokol.svg")}input.search-input::-webkit-input-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important}input.search-input:-moz-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important;opacity:1}input.search-input::-moz-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important;opacity:1}input.search-input:-ms-input-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important}.settings{max-width:600px;margin:0 auto}.settings-title{margin-bottom:20px;color:#38454f;text-align:center;font-size:24px}.socials-item:not(:first-child){margin-left:10px}.socials-i{background-color:#ffffff;border-radius:3px;display:inline-block;font-size:0;height:30px;position:relative;transition:0.3s background-color;vertical-align:top;width:30px}.socials-i:not(:first-child){margin-left:10px}.socials-i:hover{background-color:rgba(255,255,255,0.4)}.socials-i:before{background-position:50% 50%;background-repeat:no-repeat;background-size:contain;content:'';height:16px;left:50%;position:absolute;top:50%;transform:translate(-50%, -50%);width:16px}.socials-i_github:before{background-image:url("../assets/images/socials/git.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_github:before{background-image:url("../assets/images/socials/git@2x.png");background-size:100% 100%}}.socials-i_telegram:before{background-image:url("../assets/images/socials/telegram.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_telegram:before{background-image:url("../assets/images/socials/telegram@2x.png");background-size:100% 100%}}.socials-i_twitter:before{background-image:url("../assets/images/socials/tw.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_twitter:before{background-image:url("../assets/images/socials/tw@2x.png");background-size:100% 100%}}.socials-i_poa:before{background-image:url("../assets/images/socials/poa.png");height:20px;width:20px}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_poa:before{background-image:url("../assets/images/socials/poa@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_github:before{background-image:url("../assets/images/socials/git-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_github:before{background-image:url("../assets/images/socials/git-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_telegram:before{background-image:url("../assets/images/socials/telegram-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_telegram:before{background-image:url("../assets/images/socials/telegram-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_twitter:before{background-image:url("../assets/images/socials/tw-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_twitter:before{background-image:url("../assets/images/socials/tw-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_poa:before{background-image:url("../assets/images/socials/poa-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_poa:before{background-image:url("../assets/images/socials/poa-sokol@2x.png");background-size:100% 100%}}.vote-scale{background-color:#f0f0f0;border-radius:5px;clear:left;height:10px;margin-top:34px;overflow:hidden}.vote-scale-not-finalized{background-color:#ffffff}.vote-scale--fill{height:100%;border-radius:3px}.vote-scale--fill_no{background-color:#f21b57}.sokol .vote-scale--fill_no{background-color:#f24c67}.vote-scale--fill_yes{background-color:#60db97}.sokol .vote-scale--fill_yes{background-color:#6ac9b9}.vote-scale--fill_send{background-color:#60db97}.sokol .vote-scale--fill_send{background-color:#6ac9b9}.vote-scale--fill_burn{background-color:#f21b57}.sokol .vote-scale--fill_burn{background-color:#f24c67}.vote-scale--fill_freeze{background-color:#50bbda}.sokol .vote-scale--fill_freeze{background-color:#50bbda}.vote-scale--container{width:100%}.vote-scale--value{float:left;font-size:12px}.vote-scale--votes,.vote-scale--percentage{float:right;font-size:13px}.vote-scale--votes{color:#333;margin-left:10px}.vote-scale--percentage{color:#000;font-weight:700}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}}.Select{position:relative}.Select input::-webkit-contacts-auto-fill-button,.Select input::-webkit-credentials-auto-fill-button{display:none !important}.Select input::-ms-clear{display:none !important}.Select input::-ms-reveal{display:none !important}.Select,.Select div,.Select input,.Select span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.Select.is-disabled .Select-arrow-zone{cursor:default;pointer-events:none}.Select.is-disabled>.Select-control{background-color:#f9f9f9}.Select.is-disabled>.Select-control:hover{box-shadow:none}.Select.is-searchable.is-open>.Select-control{cursor:text}.Select.is-searchable.is-focused:not(.is-open)>.Select-control{cursor:text}.Select.is-open>.Select-control{border-bottom-right-radius:0;border-bottom-left-radius:0;background:#fff;border-color:#cbcbcb #e4e4e4 #f1f1f1}.Select.is-open>.Select-control .Select-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}.Select.is-focused>.Select-control{background:#fff}.Select.is-focused:not(.is-open)>.Select-control{border-color:#5c34a2 #673ab5 #673ab5;box-shadow:none}.Select.has-value.is-clearable.Select--single>.Select-control .Select-value{padding-right:44px}.Select.has-value.Select--single>.Select-control .Select-value .Select-value-label,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value .Select-value-label{color:#333}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label{cursor:pointer;text-decoration:none}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:hover,.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:hover,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus{color:#8e959d;outline:none;text-decoration:underline}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus{background:#fff}.Select.has-value.is-pseudo-focused .Select-input{opacity:0}.Select.is-open .Select-arrow,.Select .Select-arrow-zone:hover>.Select-arrow{border-top-color:#666}.Select.Select--rtl{direction:rtl;text-align:right}.Select-control{background-color:#fff;border-collapse:separate;border-color:#f1f1f1 #e4e4e4 #cbcbcb;border-radius:3px;border-spacing:0;border:1px solid #e4e4e4;color:#333;cursor:default;display:table;height:40px;outline:none;overflow:hidden;position:relative;width:100%}.Select-control:hover{box-shadow:none}.Select-control .Select-input:focus{outline:none;background:#fff}.Select-placeholder,.Select--single>.Select-control .Select-value{bottom:0;color:#333;left:0;line-height:38px;padding-left:15px;padding-right:15px;position:absolute;right:0;top:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.Select-input{height:38px;padding-left:15px;padding-right:15px;vertical-align:middle}.Select-input>input{background:none transparent;border:0 none;box-shadow:none;cursor:default;display:inline-block;font-family:inherit;font-size:inherit;margin:0;outline:none;line-height:17px;padding:10px 0 14px;-webkit-appearance:none}.is-focused .Select-input>input{cursor:text}.Select-control:not(.is-searchable)>.Select-input{outline:none}.Select-loading-zone{cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:16px}.Select-loading{-webkit-animation:Select-animation-spin 400ms infinite linear;-o-animation:Select-animation-spin 400ms infinite linear;animation:Select-animation-spin 400ms infinite linear;width:16px;height:16px;box-sizing:border-box;border-radius:50%;border:2px solid #e4e4e4;border-right-color:#333;display:inline-block;position:relative;vertical-align:middle}.Select-clear-zone{-webkit-animation:Select-animation-fadeIn 200ms;-o-animation:Select-animation-fadeIn 200ms;animation:Select-animation-fadeIn 200ms;color:#999;cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:19px}.Select-clear-zone:hover{color:#D0021B}.Select-clear{display:inline-block;font-size:20px;line-height:1}.Select--multi .Select-clear-zone{width:19px}.Select--multi .Select-multi-value-wrapper{display:inline-block}.Select .Select-aria-only{position:absolute;display:inline-block;height:1px;width:1px;margin:-1px;clip:rect(0, 0, 0, 0);overflow:hidden;float:left}.Select-arrow-zone{cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:25px;padding-right:5px}.Select--rtl .Select-arrow-zone{padding-right:0;padding-left:5px}.Select-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px;display:inline-block;height:0;width:0;position:relative}@-webkit-keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}@keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}.Select-menu-outer{border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:#fff;border:1px solid #e4e4e4;border-top-color:#f2f2f2;box-shadow:none;box-sizing:border-box;margin-top:-1px;max-height:200px;position:absolute;top:100%;width:100%;z-index:1000;-webkit-overflow-scrolling:touch}.Select-menu{max-height:198px;overflow-y:auto}.Select-option{box-sizing:border-box;background-color:#fff;color:#666;cursor:pointer;display:block;padding:8px 15px}.Select-option:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.Select-option.is-selected{background-color:#f5faff;color:#333}.Select-option.is-focused{background-color:#f2f9fc;color:#333}.Select-option.is-disabled{color:#ccc;cursor:default}.Select-noresults{box-sizing:border-box;color:#999;cursor:default;display:block;padding:8px 15px}.Select--multi .Select-input{vertical-align:middle;margin-left:15px;padding:0}.Select--multi.Select--rtl .Select-input{margin-left:0;margin-right:15px}.Select--multi.has-value .Select-input{margin-left:5px}.Select--multi .Select-value{background-color:#f2f9fc;border-radius:3px;border:1px solid #e5eef9;color:#08c;display:inline-block;font-size:.9em;margin-left:5px;margin-top:5px;vertical-align:top}.Select--multi .Select-value-icon,.Select--multi .Select-value-label{display:inline-block;vertical-align:middle}.Select--multi .Select-value-label{border-bottom-right-radius:3px;border-top-right-radius:3px;cursor:default;padding:2px 5px}.Select--multi a.Select-value-label{color:#08c;cursor:pointer;text-decoration:none}.Select--multi a.Select-value-label:hover{text-decoration:underline}.Select--multi .Select-value-icon{cursor:pointer;border-bottom-left-radius:3px;border-top-left-radius:3px;border-right:1px solid #e5eef9;padding:1px 5px 3px}.Select--multi .Select-value-icon:hover,.Select--multi .Select-value-icon:focus{background-color:#ddeff7;color:#0077b3}.Select--multi .Select-value-icon:active{background-color:#e5eef9}.Select--multi.Select--rtl .Select-value{margin-left:0;margin-right:5px}.Select--multi.Select--rtl .Select-value-icon{border-right:none;border-left:1px solid #e5eef9}.Select--multi.is-disabled .Select-value{background-color:#fcfcfc;border:1px solid #e3e3e3;color:#333}.Select--multi.is-disabled .Select-value-icon{cursor:not-allowed;border-right:1px solid #e3e3e3}.Select--multi.is-disabled .Select-value-icon:hover,.Select--multi.is-disabled .Select-value-icon:focus,.Select--multi.is-disabled .Select-value-icon:active{background-color:#fcfcfc}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}}.ballot-types{background-color:#fff;border-bottom:1px solid #e4e4e4;padding:20px 30px 10px}.ballot-types-i{color:#333;cursor:pointer;font-size:16px;font-weight:400;margin-bottom:10px;position:relative;line-height:30px}.ballot-types-i:before{background-color:#5c34a2;border-bottom-right-radius:5px;border-top-right-radius:5px;content:'';height:30px;left:-30px;opacity:0;position:absolute;top:50%;transform:translateY(-50%);width:4px}.sokol .ballot-types-i:before{background-color:#6ac9b9}.ballot-types-i_active{color:#5c34a2}.ballot-types-i_active:before{opacity:1}.sokol .ballot-types-i_active{color:#6ac9b9}.ballots-i--vote,.ballots-footer-finalize{border-radius:2px;padding:0 13px;font-size:13px;font-weight:bold}.ballots .title{margin-bottom:50px}@media screen and (max-width: 768px){.ballots .title{margin-bottom:15px}}@media screen and (max-width: 767px){.ballots .title{margin-bottom:10px}}.ballots-about{margin-top:-8px}.ballots-i{background-color:#fff}.ballots-i-scale{border-top:1px solid #e4e4e4;display:flex;margin-bottom:30px;margin-top:30px;padding:30px 0 0 0}@media screen and (max-width: 768px){.ballots-i-scale{display:block;margin-top:15px;padding:15px 0 0 0}}@media screen and (max-width: 767px){.ballots-i-scale{margin-top:10px;padding:10px 0 0 0}}.ballots-i-scale-column{display:flex;flex-grow:1;justify-content:space-between;margin-right:40px}@media screen and (max-width: 768px){.ballots-i-scale-column{margin-bottom:30px;margin-right:0;overflow:hidden;width:100%}}.ballots-i-scale-column:last-child{margin-right:0}@media screen and (max-width: 768px){.ballots-i-scale-column.reverse-responsive{flex-direction:row-reverse}}.ballots-i--name{overflow:hidden;text-overflow:ellipsis}.ballots-i--see-all-proposal{display:inline-block;margin-top:5px}.ballots-i--vote-label{color:#333;cursor:default;font-size:14px;font-weight:700;line-height:1.2}@media screen and (max-width: 767px){.ballots-i--vote-label{margin-bottom:25px}}.ballots-i--vote-label-right{margin-left:auto !important}.ballots-i--vote_btn{line-height:44px;min-width:55px;text-transform:capitalize}.ballots-i--vote_btn.xl{min-width:78px}.ballots-i--vote_btn.m-r-20{margin-right:20px}.ballots-i--vote_btn.m-l-20{margin-left:20px}@media screen and (max-width: 768px){.ballots-i--vote_btn.m-r-20,.ballots-i--vote_btn.m-l-20{margin-left:0;margin-right:20px}}textarea{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;overflow:auto;outline:none;border-radius:3px;width:100%}.color-primary{color:#5c34a2}.sokol .color-primary{color:#6ac9b9}.color-danger{color:#f21b57}.sokol .color-danger{color:#f24c67}.color-success{color:#60db97}.sokol .color-success{color:#6ac9b9}@media screen and (max-width: 768px){.ballots-about{display:table;width:100%}}.ballots-about p{line-height:28px}.ballots-about-i{position:relative;display:inline-block;vertical-align:top;box-sizing:border-box}@media screen and (max-width: 768px){.ballots-about-i{display:table-row;width:100% !important}}.ballots-about-i .ballots-about-td-value{padding-right:12px}.ballots-about-i_name{width:12%}.ballots-about-i_action{width:8%}.ballots-about-i_type{width:8%}.ballots-about-i_proposal{width:30%}.ballots-about-i_key{width:26%;word-break:break-all}.ballots-about-i_key_wide{width:50%;word-break:break-all}.ballots-about-i_proposed_receiver{width:45%;word-break:break-all}.ballots-about-i_funds_amount{width:23%;word-break:break-all}.ballots-about-i_proposed-min-threshold{width:30%;word-break:break-all}.ballots-about-i_contract-type{width:25%;word-break:break-all}.ballots-about-i_proposed-address{width:30%;word-break:break-all}.ballots-about-i_time{width:20%}.ballots-about-i--title{color:#777;font-size:13px;font-weight:400;text-align:left}.ballots-about-i:first-child .ballots-about-td-value{border-left:none;padding-left:0}.ballots-about-i:last-child .ballots-about-td-value{border-right:none;padding-right:0}.ballots-about-td.ballots-about-td-value{color:#333;font-size:14px}.ballots-about-i_action .ballots-about-td.ballots-about-td-value,.ballots-about-i_type .ballots-about-td.ballots-about-td-value{text-transform:capitalize}@media screen and (max-width: 768px){.ballots-about-td.ballots-about-td-value{padding-left:0;padding-right:0}}@media screen and (max-width: 768px){.ballots-about-td{display:table-cell;vertical-align:top}}@media screen and (max-width: 768px){.ballots-about-td:first-child{padding-right:10px}}@media screen and (max-width: 768px){.ballots-about-i:not(:last-child) .ballots-about-td{padding-bottom:10px}}.ballots-footer{display:flex;align-items:center;justify-content:space-between}.ballots-footer-left{display:inline-flex;align-items:center}@media screen and (max-width: 767px){.ballots-footer-left{display:block}.ballots-footer-left .btn{display:block;margin:0 0 15px;width:100%}}@media screen and (max-width: 768px){.ballots-footer{padding-top:15px}}@media screen and (max-width: 767px){.ballots-footer{flex-direction:column-reverse;padding-top:0}}.ballots-footer p{color:#777;font-size:14px;font-stretch:normal;font-style:normal;font-weight:normal;line-height:18px;max-width:340px;padding-left:15px}.ballots-footer-finalize{margin-right:20px;background-color:rgba(8,179,242,0.1);white-space:nowrap}.ballots-footer-finalize-finalized{background-color:rgba(109,46,174,0.1);color:#6d2eae;cursor:default}@media screen and (max-width: 767px){.ballots-footer-finalize{width:100%;margin-right:0;margin-top:10px;text-align:center}} +.footer{left:0;right:0}.new-form,.settings,.ballots-i{background-color:#fff;border-radius:6px;border:1px solid #e4e4e4;margin-bottom:30px;padding:30px;transition:0.15s box-shadow}@media screen and (max-width: 768px){.new-form,.settings,.ballots-i{margin-bottom:15px;padding:15px}}input,textarea,select{transition:0.3s background-color, 0.3s border-color;background-color:#fff;border-radius:3px;border:1px solid #e4e4e4;box-sizing:border-box;color:#444;font-size:14px;height:40px;outline:none;padding:0 10px;width:100%}input:hover,textarea:hover,select:hover{border-color:#8e959d;color:#202d3c}input:focus,textarea:focus,select:focus{border-color:#5c34a2;color:#202d3c}.sokol input:focus,.sokol textarea:focus,.sokol select:focus{border-color:#6ac9b9}button,.ballots-i--vote,.ballots-footer-finalize{cursor:pointer;display:inline-block;transition:0.3s opacity;box-sizing:border-box;border:0;outline:none;padding:0 15px;text-transform:uppercase;line-height:36px;font-size:13px;font-weight:bold}button:hover,.ballots-i--vote:hover,.ballots-footer-finalize:hover{opacity:0.9;text-decoration:none}html,body,p,h1,h2,h3{margin:0;padding:0;font-weight:normal}html{display:flex;min-height:100%}body{-webkit-font-smoothing:antialiased;background-color:#ffffff;box-sizing:border-box;color:#333;font-family:'Nunito', sans-serif;font-size:14px;padding-bottom:66px;position:relative;width:100%}@media screen and (max-width: 768px){body{padding-bottom:132px}}@media screen and (max-width: 767px){body{padding-bottom:132px}}a{color:#5c34a2;text-decoration:none}a:hover{text-decoration:underline}a .sokol{color:#6ac9b9}hr{display:block;width:100%;height:1px;margin:10px 0 30px;border:0;background-color:#e4e4e4}.center{text-align:center}.left{float:left;width:48%}.right{float:right;width:48%}@media screen and (max-width: 767px){.left,.right{float:none;width:100%}}.hidden{overflow:hidden}.display-none{display:none}.container{width:960px;margin:0 auto;box-sizing:border-box}@media screen and (max-width: 960px){.container{width:100%;padding:0 10px}}.title{margin-top:30px;margin-bottom:30px;color:#38454f;font-size:30px;font-weight:normal}@media screen and (max-width: 768px){.title{font-size:28px}}@media screen and (max-width: 767px){.title{font-size:26px}}button,input,textarea{outline:none}.btn{background-position:calc(100% - 15px) 50%;background-repeat:no-repeat;border-radius:5px;border:0;color:#fff;cursor:pointer;font-weight:bold;font-size:14px;line-height:42px;outline:none;padding:0 15px;text-decoration:none;text-transform:uppercase;transition:0.15s background-color}.btn.btn-primary{background-color:#5c34a2;box-shadow:0px 5px 10px 0 rgba(92,52,162,0.3)}.btn.btn-primary:hover{background-color:#46287b}.btn.btn-success{background-color:#60db97;box-shadow:0px 5px 10px 0 rgba(96,219,151,0.3)}.btn.btn-success:hover{background-color:#36d27c}.btn.btn-danger{background-color:#f21b57;box-shadow:0px 5px 10px 0 rgba(242,27,87,0.3)}.btn.btn-danger:hover{background-color:#ce0c42}.btn.btn-freeze{background-color:#50bbda;box-shadow:0px 5px 10px 0 rgba(80,187,218,0.3)}.btn.btn-freeze:hover{background-color:#2ba8cc}.sokol .btn.btn-primary{background-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(106,201,185,0.3)}.sokol .btn.btn-primary:hover{background-color:#45bba7}.sokol .btn.btn-success{background-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(96,219,151,0.3)}.sokol .btn.btn-success:hover{background-color:#45bba7}.sokol .btn.btn-danger{background-color:#f24c67;box-shadow:0px 5px 10px 0 rgba(242,76,103,0.33)}.sokol .btn.btn-danger:hover{background-color:#ef1c3f}.sokol .btn.btn-freeze{background-color:#50bbda;box-shadow:0px 5px 10px 0 rgba(80,187,218,0.3)}.sokol .btn.btn-freeze:hover{background-color:#2ba8cc}.btn.btn-new{background-image:url("../assets/images/icons/icon-add.svg");background-size:14px 14px;padding-right:45px}.btn.btn-load-more{background-image:url("../assets/images/icons/icon-load-more.svg");border-radius:5px;border:2px solid #5c34a2;font-size:17px;font-weight:400;background-size:14px 14px;padding-right:45px}.sokol .btn.btn-load-more{background-image:url("../assets/images/icons/icon-load-more-sokol.svg");border-color:#6ac9b9}.btn.btn-transparent{color:#5c34a2;background-color:transparent}.btn.btn-transparent:hover{opacity:0.8}.sokol .btn.btn-transparent{color:#6ac9b9}.btn[disabled],.sokol .btn[disabled],.btn.disabled,.sokol .btn.disabled{color:#333333;cursor:default;background-color:#f0f0f0;box-shadow:none}.btn[disabled]:hover,.sokol .btn[disabled]:hover,.btn.disabled:hover,.sokol .btn.disabled:hover{background-color:#f0f0f0}.btn.btn-finalize{background-image:url("../assets/images/icons/icon-finalize-white.svg");background-size:14px 14px;padding-right:45px}.btn.btn-finalize[disabled],.btn.btn-finalize.disabled{background-image:url("../assets/images/icons/icon-finalize-black.svg")}.btn.no-shadow{box-shadow:none}.btn.text-lowercase{text-transform:lowercase}.btn.text-uppercase{text-transform:uppercase}.btn.text-capitalize{text-transform:capitalize}label{color:#333;display:inline-block;font-size:13px;line-height:1.2;margin-bottom:15px}input:focus,textarea:focus{border-color:#fff}input[type='radio'],textarea[type='radio']{display:none}textarea{width:100%;padding-top:10px;padding-bottom:10px;height:70px;resize:none}select{appearance:none;background-image:url(./images/select.png);background-position:right 13px center;background-repeat:no-repeat;padding-right:30px}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){select{background-image:url("./images/select@2x.png");background-size:8px 4px}}button{background-color:rgba(92,52,162,0.1);color:#5c34a2}button.load-more{margin-bottom:50px}@media screen and (max-width: 960px){button.load-more{margin-bottom:80px}}@media screen and (max-width: 768px){button.load-more{margin-top:80px}}.radio-button{position:relative}.radio-button-label{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;border-radius:3px;border:1px solid #e4e4e4;color:#333;cursor:pointer;font-size:14px;font-weight:400;line-height:50px;margin:0;outline:none;padding:0 15px;text-decoration:none;text-transform:capitalize;text-align:center;transition:0.25s background-color;position:relative;z-index:1}.radio-button input[type='radio']{height:100%;position:absolute;visibility:hidden;width:100%;z-index:12}input[type='radio']:checked+.radio-button-label{background-color:#5c34a2;border-color:#5c34a2;box-shadow:0px 5px 10px 0 rgba(92,52,162,0.3);color:#fff}.sokol input[type='radio']:checked+.radio-button-label{background-color:#6ac9b9;border-color:#6ac9b9;box-shadow:0px 5px 10px 0 rgba(106,201,185,0.3)}.keys-radio-button-tr{display:flex;margin-bottom:30px}@media screen and (max-width: 768px){.keys-radio-button-tr{flex-direction:column}}.keys-radio-button-td{min-width:30%;margin-right:5%}.keys-radio-button-td:last-child{margin-right:0}.keys-radio-button-td .radio-button-label{display:flex;justify-content:center}@media screen and (max-width: 768px){.keys-radio-button-td{margin-bottom:15px;margin-right:0;min-width:100%}}.form-el{margin-bottom:30px}.hint{color:#777;font-size:13px;font-weight:400;line-height:1.38;padding-top:12px;margin:0;word-break:break-word}.hint a{color:#5c34a2}.sokol .hint a{color:#6ac9b9}.footer{background-color:#5c34a2;bottom:0;padding:18px 0;position:absolute}.footer.sokol{background-color:#6ac9b9}.footer .container{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}@media screen and (max-width: 768px){.footer .container{flex-direction:column}}.footer .socials{order:2}@media screen and (max-width: 768px){.footer .socials{margin-top:15px;order:1}}.footer-logo{background-image:url("../assets/images/logos/logo-poa.svg");background-repeat:no-repeat;background-size:contain;display:block;height:18px;left:0;order:0;width:139px}.footer-logo.sokol{background-image:url("../assets/images/logos/logo-sokol.svg");width:144px}.footer-rights{color:#fff;font-size:12px;order:1;text-align:center}@media screen and (max-width: 768px){.footer-rights{line-height:normal;margin-top:15px;order:2;width:100%}}.header{background-color:#5c34a2;position:relative;width:100%;z-index:9999}@media screen and (max-width: 767px){.header{left:0;right:0;position:fixed;top:0;z-index:124}}.header .container{align-items:center;display:flex;flex-wrap:wrap;justify-content:space-between}@media screen and (max-width: 767px){.header .container{width:93%;padding:22px 0}}.header.sokol{background-color:#6ac9b9}.header-logo{display:block;height:26px}.header .links-container{align-items:center;display:flex;justify-content:space-between;height:70px;margin-left:auto}@media screen and (max-width: 767px){.header .links-container{display:none}}@media screen and (max-width: 768px){.header .links-container{justify-content:flex-end;width:auto}}.header .links-container-mobile{display:none}@media screen and (max-width: 767px){.header .links-container-mobile{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:space-evenly}}.header .link{color:#fff;font-size:14px;font-weight:700;line-height:18px;margin-left:34px;opacity:0.8;text-decoration:none;transition:opacity linear 0.1s}.header .link:hover,.header .link.active{opacity:1}@media screen and (max-width: 767px){.header .link{margin-left:0}}.header .link-icon{height:18px;width:18px;margin-right:10px;float:left;background-position:50% 50%;background-repeat:no-repeat}.header .link-icon-all{background-image:url("../assets/images/icons/icon-all.svg")}.header .link-icon-active{background-image:url("../assets/images/icons/icon-active.svg")}.header .link-icon-to-finalize{background-image:url("../assets/images/icons/icon-to-finalize.svg")}.header.sokol .link-icon-all{background-image:url("../assets/images/icons/icon-all-sokol.svg")}.header.sokol .link-icon-active{background-image:url("../assets/images/icons/icon-active-sokol.svg")}.header.sokol .link-icon-to-finalize{background-image:url("../assets/images/icons/icon-to-finalize-sokol.svg")}.header .mobile-menu{display:none}@media screen and (max-width: 767px){.header .mobile-menu{display:block;order:3}}.header .mobile-menu .mobile-menu-icon{width:18px;height:14px}.header .mobile-menu .mobile-menu-open-icon{width:18px;height:18px}@media screen and (max-width: 767px){.header .header-mobile-menu-container{background-color:#45277a;height:220px}}@media screen and (max-width: 767px){.header.sokol .header-mobile-menu-container{background-color:#41b19e}}.header .Select{margin-left:25px}@media screen and (max-width: 767px){.header .Select{margin-left:0;max-width:125px;order:2}.header .Select .Select-control{max-width:125px}}.header .btn.btn-new-ballot{height:36px;line-height:36px;opacity:1}.header .btn.btn-new-ballot .link-icon{display:none}.header.sokol .btn.btn-new-ballot{background-color:#fff;background-image:url("../assets/images/icons/icon-add-sokol.svg");color:#6ac9b9}.header.sokol .btn.btn-new-ballot:hover{opacity:0.9}.select-network-id{background:#fff;width:40px}.info-container{background-color:#f8f8f8;margin-bottom:30px;margin-left:-30px;margin-right:-30px;padding-bottom:30px;padding-left:30px;padding-right:30px;padding-top:30px}@media screen and (max-width: 768px){.info-container{margin-left:-15px;margin-right:-15px;padding-left:15px;padding-right:15px}}.info{color:#000}.ballots .info{background-position:0 2px;background-repeat:no-repeat;color:#333333;font-size:14px;font-weight:normal;letter-spacing:normal;line-height:1.71;margin-bottom:20px;max-width:100%;min-height:32px;padding-left:30px;text-align:left;word-break:break-word}.ballots .info:last-child{margin-bottom:0}.ballots .info-minimum{background-image:url("../assets/images/icons/icon-min.svg");background-size:18px 18px}.ballots .info-details{background-image:url("../assets/images/icons/icon-info.svg");background-size:10px 18px;position:relative}.ballots .info-details.collapsed{height:90px;overflow:hidden}.ballots .info-details .toggle-show{color:#5c34a2;cursor:pointer;display:inline-block;margin-left:5px}.sokol .ballots .info-details .toggle-show{color:#6ac9b9}.new-form .info{padding:30px}.info-title{color:#333;font-size:16px;font-weight:400;margin-bottom:30px;padding-left:25px;position:relative}.info-title:before{background-image:url("../assets/images/icons/icon-info.svg");background-position:50% 50%;background-repeat:no-repeat;background-size:10px 18px;content:'';height:32px;left:0;position:absolute;top:50%;transform:translateY(-50%);width:10px}.info-i{color:#777;font-size:14px;line-height:1.71;margin-bottom:20px;padding-left:25px;position:relative}.info-i:before{background-color:#333;border-radius:50%;content:'';height:6px;left:0;position:absolute;top:8px;width:6px}.app-container{padding-bottom:30px;padding-top:40px;position:relative}.app-container.app-container-open-mobile-menu:before{background-color:rgba(78,44,137,0.8);bottom:0;content:'';display:none;left:0;position:fixed;right:0;top:290px;z-index:1234}@media screen and (max-width: 767px){.app-container.app-container-open-mobile-menu:before{display:block}}.app-container.app-container-open-mobile-menu.sokol:before{background-color:rgba(106,201,185,0.8)}@media screen and (max-width: 767px){#root,.app-container{height:100%}.app-container{padding-left:10px;padding-right:10px}}@media screen and (max-width: 767px){.content{padding-top:120px}}.content.content-menu-open{padding-top:290px}.clearfix::after{content:"";clear:both;display:table}@keyframes fadeOut{0%{opacity:.2}20%{opacity:1;transform:scale(1)}100%{opacity:.2;transform:scale(0.3)}}.loading{display:flex;justify-content:space-between;left:50%;margin:-30px 0 0 -111.5px;padding-top:50px;position:absolute;top:50%;width:206px}.loading:before{background-image:url("../assets/images/logos/logo_loader.svg");background-position:0 0;background-repeat:no-repeat;content:'';left:0;position:absolute;top:0;height:100px;width:206px}.loading-container{bottom:0;left:0;position:fixed;right:0;top:0;z-index:1000000}.loading-i{animation-duration:2s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:fadeOut;animation-timing-function:linear;background-color:#fff;border-radius:50%;height:9px;opacity:.2;width:9px}.loading-i:nth-child(2){animation-delay:.1s}.loading-i:nth-child(3){animation-delay:.2s}.loading-i:nth-child(4){animation-delay:.3s}.loading-i:nth-child(5){animation-delay:.4s}.loading-i:nth-child(6){animation-delay:.5s}.main-title-container{-ms-flex-pack:justify;display:-ms-flexbox;display:flex;justify-content:space-between;margin-bottom:40px}.main-title-container .main-title{font-size:24px;color:#333;line-height:38px}@media screen and (max-width: 767px){.main-title-container{-ms-flex-direction:column;flex-direction:column}.main-title-container .search-input{width:100%}}.new-form{display:flex;overflow:hidden;padding:0}@media screen and (max-width: 768px){.new-form{display:block}}.new-form-side{box-sizing:border-box;padding-bottom:30px;padding-top:30px}@media screen and (max-width: 768px){.new-form-side{width:100% !important}}.new-form-side_left{background-color:#f8f8f8;padding-top:0;width:30%}@media screen and (max-width: 768px){.new-form-side_left{margin-bottom:30px;padding-bottom:0}}.new-form-side_right{border-left:1px solid #e4e4e4;padding-left:30px;padding-right:30px;width:70%}@media screen and (max-width: 768px){.new-form-side_right{border:0;padding-top:0}}.new .add-ballot{white-space:nowrap}@media screen and (max-width: 767px){.new .add-ballot{margin-top:20px}}.search-container{background-color:#502d8d;box-sizing:border-box;height:50px;padding:10px 0 0 0}.search-container.sokol{background-color:#41b19e}@media screen and (max-width: 767px){.search-container{left:0;position:fixed;right:0;top:70px;z-index:123}}input.search-input{background-color:transparent;background-image:url("../assets/images/icons/icon-search.svg");background-position:0 50%;background-repeat:no-repeat;background-size:16px 16px;border-radius:0;border:none;box-sizing:border-box;display:block;font-size:14px;font-weight:400;height:30px;outline:none;padding-left:30px;width:100%}input.search-input,input.search-input:focus input.search-input:hover,input.search-input:active{color:#fff}.sokol input.search-input{background-image:url("../assets/images/icons/icon-search-sokol.svg")}input.search-input::-webkit-input-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important}input.search-input:-moz-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important;opacity:1}input.search-input::-moz-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important;opacity:1}input.search-input:-ms-input-placeholder{color:rgba(255,255,255,0.5) !important;font-size:14px !important}.settings{max-width:600px;margin:0 auto}.settings-title{margin-bottom:20px;color:#38454f;text-align:center;font-size:24px}.socials-item:not(:first-child){margin-left:10px}.socials-i{background-color:#ffffff;border-radius:3px;display:inline-block;font-size:0;height:30px;position:relative;transition:0.3s background-color;vertical-align:top;width:30px}.socials-i:not(:first-child){margin-left:10px}.socials-i:hover{background-color:rgba(255,255,255,0.4)}.socials-i:before{background-position:50% 50%;background-repeat:no-repeat;background-size:contain;content:'';height:16px;left:50%;position:absolute;top:50%;transform:translate(-50%, -50%);width:16px}.socials-i_github:before{background-image:url("../assets/images/socials/git.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_github:before{background-image:url("../assets/images/socials/git@2x.png");background-size:100% 100%}}.socials-i_telegram:before{background-image:url("../assets/images/socials/telegram.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_telegram:before{background-image:url("../assets/images/socials/telegram@2x.png");background-size:100% 100%}}.socials-i_twitter:before{background-image:url("../assets/images/socials/tw.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_twitter:before{background-image:url("../assets/images/socials/tw@2x.png");background-size:100% 100%}}.socials-i_poa:before{background-image:url("../assets/images/socials/poa.png");height:20px;width:20px}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.socials-i_poa:before{background-image:url("../assets/images/socials/poa@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_github:before{background-image:url("../assets/images/socials/git-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_github:before{background-image:url("../assets/images/socials/git-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_telegram:before{background-image:url("../assets/images/socials/telegram-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_telegram:before{background-image:url("../assets/images/socials/telegram-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_twitter:before{background-image:url("../assets/images/socials/tw-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_twitter:before{background-image:url("../assets/images/socials/tw-sokol@2x.png");background-size:100% 100%}}.sokol .socials .socials-i_poa:before{background-image:url("../assets/images/socials/poa-sokol.png")}@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx){.sokol .socials .socials-i_poa:before{background-image:url("../assets/images/socials/poa-sokol@2x.png");background-size:100% 100%}}.vote-scale{background-color:#f0f0f0;border-radius:5px;clear:left;height:10px;margin-top:34px;overflow:hidden}.vote-scale-not-finalized{background-color:#ffffff}.vote-scale--fill{height:100%;border-radius:3px}.vote-scale--fill_no{background-color:#f21b57}.sokol .vote-scale--fill_no{background-color:#f24c67}.vote-scale--fill_yes{background-color:#60db97}.sokol .vote-scale--fill_yes{background-color:#6ac9b9}.vote-scale--fill_send{background-color:#60db97}.sokol .vote-scale--fill_send{background-color:#6ac9b9}.vote-scale--fill_burn{background-color:#f21b57}.sokol .vote-scale--fill_burn{background-color:#f24c67}.vote-scale--fill_freeze{background-color:#50bbda}.sokol .vote-scale--fill_freeze{background-color:#50bbda}.vote-scale--container{width:100%}.vote-scale--value{float:left;font-size:12px}.vote-scale--votes,.vote-scale--percentage{float:right;font-size:13px}.vote-scale--votes{color:#333;margin-left:10px}.vote-scale--percentage{color:#000;font-weight:700}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}}.Select{position:relative}.Select input::-webkit-contacts-auto-fill-button,.Select input::-webkit-credentials-auto-fill-button{display:none !important}.Select input::-ms-clear{display:none !important}.Select input::-ms-reveal{display:none !important}.Select,.Select div,.Select input,.Select span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.Select.is-disabled .Select-arrow-zone{cursor:default;pointer-events:none}.Select.is-disabled>.Select-control{background-color:#f9f9f9}.Select.is-disabled>.Select-control:hover{box-shadow:none}.Select.is-searchable.is-open>.Select-control{cursor:text}.Select.is-searchable.is-focused:not(.is-open)>.Select-control{cursor:text}.Select.is-open>.Select-control{border-bottom-right-radius:0;border-bottom-left-radius:0;background:#fff;border-color:#cbcbcb #e4e4e4 #f1f1f1}.Select.is-open>.Select-control .Select-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}.Select.is-focused>.Select-control{background:#fff}.Select.is-focused:not(.is-open)>.Select-control{border-color:#5c34a2 #673ab5 #673ab5;box-shadow:none}.Select.has-value.is-clearable.Select--single>.Select-control .Select-value{padding-right:44px}.Select.has-value.Select--single>.Select-control .Select-value .Select-value-label,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value .Select-value-label{color:#333}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label{cursor:pointer;text-decoration:none}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:hover,.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:hover,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus{color:#8e959d;outline:none;text-decoration:underline}.Select.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.Select.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus{background:#fff}.Select.has-value.is-pseudo-focused .Select-input{opacity:0}.Select.is-open .Select-arrow,.Select .Select-arrow-zone:hover>.Select-arrow{border-top-color:#666}.Select.Select--rtl{direction:rtl;text-align:right}.Select-control{background-color:#fff;border-collapse:separate;border-color:#f1f1f1 #e4e4e4 #cbcbcb;border-radius:3px;border-spacing:0;border:1px solid #e4e4e4;color:#333;cursor:default;display:table;height:40px;outline:none;overflow:hidden;position:relative;width:100%}.Select-control:hover{box-shadow:none}.Select-control .Select-input:focus{outline:none;background:#fff}.Select-placeholder,.Select--single>.Select-control .Select-value{bottom:0;color:#333;left:0;line-height:38px;padding-left:15px;padding-right:15px;position:absolute;right:0;top:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.Select-input{height:38px;padding-left:15px;padding-right:15px;vertical-align:middle}.Select-input>input{background:none transparent;border:0 none;box-shadow:none;cursor:default;display:inline-block;font-family:inherit;font-size:inherit;margin:0;outline:none;line-height:17px;padding:10px 0 14px;-webkit-appearance:none}.is-focused .Select-input>input{cursor:text}.Select-control:not(.is-searchable)>.Select-input{outline:none}.Select-loading-zone{cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:16px}.Select-loading{-webkit-animation:Select-animation-spin 400ms infinite linear;-o-animation:Select-animation-spin 400ms infinite linear;animation:Select-animation-spin 400ms infinite linear;width:16px;height:16px;box-sizing:border-box;border-radius:50%;border:2px solid #e4e4e4;border-right-color:#333;display:inline-block;position:relative;vertical-align:middle}.Select-clear-zone{-webkit-animation:Select-animation-fadeIn 200ms;-o-animation:Select-animation-fadeIn 200ms;animation:Select-animation-fadeIn 200ms;color:#999;cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:19px}.Select-clear-zone:hover{color:#D0021B}.Select-clear{display:inline-block;font-size:20px;line-height:1}.Select--multi .Select-clear-zone{width:19px}.Select--multi .Select-multi-value-wrapper{display:inline-block}.Select .Select-aria-only{position:absolute;display:inline-block;height:1px;width:1px;margin:-1px;clip:rect(0, 0, 0, 0);overflow:hidden;float:left}.Select-arrow-zone{cursor:pointer;display:table-cell;position:relative;text-align:center;vertical-align:middle;width:25px;padding-right:5px}.Select--rtl .Select-arrow-zone{padding-right:0;padding-left:5px}.Select-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px;display:inline-block;height:0;width:0;position:relative}@-webkit-keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}@keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}.Select-menu-outer{border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:#fff;border:1px solid #e4e4e4;border-top-color:#f2f2f2;box-shadow:none;box-sizing:border-box;margin-top:-1px;max-height:200px;position:absolute;top:100%;width:100%;z-index:1000;-webkit-overflow-scrolling:touch}.Select-menu{max-height:198px;overflow-y:auto}.Select-option{box-sizing:border-box;background-color:#fff;color:#666;cursor:pointer;display:block;padding:8px 15px}.Select-option:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.Select-option.is-selected{background-color:#f5faff;color:#333}.Select-option.is-focused{background-color:#f2f9fc;color:#333}.Select-option.is-disabled{color:#ccc;cursor:default}.Select-noresults{box-sizing:border-box;color:#999;cursor:default;display:block;padding:8px 15px}.Select--multi .Select-input{vertical-align:middle;margin-left:15px;padding:0}.Select--multi.Select--rtl .Select-input{margin-left:0;margin-right:15px}.Select--multi.has-value .Select-input{margin-left:5px}.Select--multi .Select-value{background-color:#f2f9fc;border-radius:3px;border:1px solid #e5eef9;color:#08c;display:inline-block;font-size:.9em;margin-left:5px;margin-top:5px;vertical-align:top}.Select--multi .Select-value-icon,.Select--multi .Select-value-label{display:inline-block;vertical-align:middle}.Select--multi .Select-value-label{border-bottom-right-radius:3px;border-top-right-radius:3px;cursor:default;padding:2px 5px}.Select--multi a.Select-value-label{color:#08c;cursor:pointer;text-decoration:none}.Select--multi a.Select-value-label:hover{text-decoration:underline}.Select--multi .Select-value-icon{cursor:pointer;border-bottom-left-radius:3px;border-top-left-radius:3px;border-right:1px solid #e5eef9;padding:1px 5px 3px}.Select--multi .Select-value-icon:hover,.Select--multi .Select-value-icon:focus{background-color:#ddeff7;color:#0077b3}.Select--multi .Select-value-icon:active{background-color:#e5eef9}.Select--multi.Select--rtl .Select-value{margin-left:0;margin-right:5px}.Select--multi.Select--rtl .Select-value-icon{border-right:none;border-left:1px solid #e5eef9}.Select--multi.is-disabled .Select-value{background-color:#fcfcfc;border:1px solid #e3e3e3;color:#333}.Select--multi.is-disabled .Select-value-icon{cursor:not-allowed;border-right:1px solid #e3e3e3}.Select--multi.is-disabled .Select-value-icon:hover,.Select--multi.is-disabled .Select-value-icon:focus,.Select--multi.is-disabled .Select-value-icon:active{background-color:#fcfcfc}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}}.ballot-types{background-color:#fff;border-bottom:1px solid #e4e4e4;padding:20px 30px 10px}.ballot-types-i{color:#333;cursor:pointer;font-size:16px;font-weight:400;margin-bottom:10px;position:relative;line-height:30px}.ballot-types-i:before{background-color:#5c34a2;border-bottom-right-radius:5px;border-top-right-radius:5px;content:'';height:30px;left:-30px;opacity:0;position:absolute;top:50%;transform:translateY(-50%);width:4px}.sokol .ballot-types-i:before{background-color:#6ac9b9}.ballot-types-i_active{color:#5c34a2}.ballot-types-i_active:before{opacity:1}.sokol .ballot-types-i_active{color:#6ac9b9}.ballots-i--vote,.ballots-footer-finalize{border-radius:2px;padding:0 13px;font-size:13px;font-weight:bold}.ballots .title{margin-bottom:50px}@media screen and (max-width: 768px){.ballots .title{margin-bottom:15px}}@media screen and (max-width: 767px){.ballots .title{margin-bottom:10px}}.ballots-about{margin-top:-8px}.ballots-i{background-color:#fff}.ballots-i-scale{border-top:1px solid #e4e4e4;display:flex;margin-bottom:30px;margin-top:30px;padding:30px 0 0 0}@media screen and (max-width: 768px){.ballots-i-scale{display:block;margin-top:15px;padding:15px 0 0 0}}@media screen and (max-width: 767px){.ballots-i-scale{margin-top:10px;padding:10px 0 0 0}}.ballots-i-scale-column{display:flex;flex-grow:1;justify-content:space-between;margin-right:40px}@media screen and (max-width: 768px){.ballots-i-scale-column{margin-bottom:30px;margin-right:0;overflow:hidden;width:100%}}.ballots-i-scale-column:last-child{margin-right:0}@media screen and (max-width: 768px){.ballots-i-scale-column.reverse-responsive{flex-direction:row-reverse}}.ballots-i--name{overflow:hidden;text-overflow:ellipsis}.ballots-i--see-all-proposal{display:inline-block;margin-top:5px}.ballots-i--vote-label{color:#333;cursor:default;font-size:14px;font-weight:700;line-height:1.2}@media screen and (max-width: 767px){.ballots-i--vote-label{margin-bottom:25px}}.ballots-i--vote-label-right{margin-left:auto !important}.ballots-i--vote_btn{line-height:44px;min-width:55px;text-transform:capitalize}.ballots-i--vote_btn.xl{min-width:78px}.ballots-i--vote_btn.m-r-20{margin-right:20px}.ballots-i--vote_btn.m-l-20{margin-left:20px}@media screen and (max-width: 768px){.ballots-i--vote_btn.m-r-20,.ballots-i--vote_btn.m-l-20{margin-left:0;margin-right:20px}}textarea{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;overflow:auto;outline:none;border-radius:3px;width:100%}.color-primary{color:#5c34a2}.sokol .color-primary{color:#6ac9b9}.color-danger{color:#f21b57}.sokol .color-danger{color:#f24c67}.color-success{color:#60db97}.sokol .color-success{color:#6ac9b9}@media screen and (max-width: 768px){.ballots-about{display:table;width:100%}}.ballots-about p{line-height:28px}.ballots-about-i{position:relative;display:inline-block;vertical-align:top;box-sizing:border-box}@media screen and (max-width: 768px){.ballots-about-i{display:table-row;width:100% !important}}.ballots-about-i .ballots-about-td-value{padding-right:12px}.ballots-about-i_name{width:12%}.ballots-about-i_action{width:8%}.ballots-about-i_type{width:8%}.ballots-about-i_proposal{width:30%}.ballots-about-i_key{width:26%;word-break:break-all}.ballots-about-i_key_wide{width:50%;word-break:break-all}.ballots-about-i_proposed_receiver{width:45%;word-break:break-all}.ballots-about-i_funds_amount{width:23%;word-break:break-all}.ballots-about-i_proposed-min-threshold{width:30%;word-break:break-all}.ballots-about-i_contract-type{width:25%;word-break:break-all}.ballots-about-i_proposed-address{width:30%;word-break:break-all}.ballots-about-i_time{width:20%}.ballots-about-i--title{color:#777;font-size:13px;font-weight:400;text-align:left}.ballots-about-i:first-child .ballots-about-td-value{border-left:none;padding-left:0}.ballots-about-i:last-child .ballots-about-td-value{border-right:none;padding-right:0}.ballots-about-td.ballots-about-td-value{color:#333;font-size:14px}.ballots-about-i_action .ballots-about-td.ballots-about-td-value,.ballots-about-i_type .ballots-about-td.ballots-about-td-value{text-transform:capitalize}@media screen and (max-width: 768px){.ballots-about-td.ballots-about-td-value{padding-left:0;padding-right:0}}@media screen and (max-width: 768px){.ballots-about-td{display:table-cell;vertical-align:top}}@media screen and (max-width: 768px){.ballots-about-td:first-child{padding-right:10px}}@media screen and (max-width: 768px){.ballots-about-i:not(:last-child) .ballots-about-td{padding-bottom:10px}}.ballots-footer{display:flex;align-items:center;justify-content:space-between}.ballots-footer-left{display:inline-flex;align-items:center}@media screen and (max-width: 767px){.ballots-footer-left{display:block}.ballots-footer-left .btn{display:block;margin:0 0 15px;width:100%}}@media screen and (max-width: 768px){.ballots-footer{padding-top:15px}}@media screen and (max-width: 767px){.ballots-footer{flex-direction:column-reverse;padding-top:0}}.ballots-footer p{color:#777;font-size:14px;font-stretch:normal;font-style:normal;font-weight:normal;line-height:18px;max-width:340px;padding-left:15px}.ballots-footer-finalize{margin-right:20px;background-color:rgba(8,179,242,0.1);white-space:nowrap}.ballots-footer-finalize-finalized{background-color:rgba(109,46,174,0.1);color:#6d2eae;cursor:default}@media screen and (max-width: 767px){.ballots-footer-finalize{width:100%;margin-right:0;margin-top:10px;text-align:center}} diff --git a/src/assets/stylesheets/application/_controls.scss b/src/assets/stylesheets/application/_controls.scss index 765f492..c832a2b 100644 --- a/src/assets/stylesheets/application/_controls.scss +++ b/src/assets/stylesheets/application/_controls.scss @@ -136,4 +136,12 @@ button { padding-top: 12px; margin: 0; word-break: break-word; + + a { + color: $primary-color; + + .sokol & { + color: $primary-color-sokol; + } + } } diff --git a/src/components/BallotCard.jsx b/src/components/BallotCard.jsx index ddf54cf..d602cd1 100644 --- a/src/components/BallotCard.jsx +++ b/src/components/BallotCard.jsx @@ -8,6 +8,9 @@ import swal from 'sweetalert2' const ACCEPT = 1 const REJECT = 2 +const SEND = 1 +const BURN = 2 +const FREEZE = 3 const USDateTimeFormat = 'MM/DD/YYYY h:mm:ss A' const maxDetailsLength = 500 @@ -16,6 +19,7 @@ const zeroTimeTo = '00:00' @inject('commonStore', 'contractsStore', 'routing', 'ballotsStore') @observer export class BallotCard extends React.Component { + @observable cancelDeadline = 0 @observable startTime @observable endTime @observable timeTo = {} @@ -31,39 +35,63 @@ export class BallotCard extends React.Component { displayValue: zeroTimeTo, title: 'To close' } + @observable + timeToCancel = { + val: 0, + displayValue: zeroTimeTo + } @observable creatorMiningKey @observable creator @observable progress @observable totalVoters + @observable burnVotes + @observable freezeVotes + @observable sendVotes @observable isFinalized + @observable isCanceled = false @observable canBeFinalized @observable hasAlreadyVoted @observable memo @computed - get finalizeButtonDisplayName() { - const displayName = this.isFinalized ? 'Finalized' : 'Finalize ballot' - return displayName + get cancelOrFinalizeButtonDisplayName() { + if (this.isFinalized) { + return 'Finalized' + } else if (this.isCanceled) { + return 'Canceled' + } else if (this.timeToCancel.val > 0) { + return 'Cancel ballot' + } else { + return 'Finalize ballot' + } } @computed - get finalizeButtonClass() { - const cls = this.isFinalized - ? 'btn btn-primary btn-finalize disabled text-capitalize' - : 'btn btn-primary btn-finalize text-capitalize' - return cls + get cancelOrFinalizeButtonClass() { + if (this.isFinalized) { + return 'btn btn-primary btn-finalize disabled text-capitalize' + } else if (this.isCanceled) { + return 'btn btn-primary disabled text-capitalize' + } else if (this.timeToCancel.val > 0) { + return 'btn btn-danger text-capitalize' + } else { + return 'btn btn-primary btn-finalize text-capitalize' + } } @computed - get finalizeDescription() { - if (this.isFinalized) { + get cancelOrFinalizeDescription() { + if (this.isFinalized || this.isCanceled) { return '' + } else if (this.timeToCancel.val > 0) { + return `You can cancel this ballot within ${this.timeToCancel.displayValue}` + } else { + let description = 'Finalization is available after ballot time is finished' + if (this.canBeFinalized !== null) { + description += ' or all validators are voted' + } + return description } - let description = 'Finalization is available after ballot time is finished' - if (this.canBeFinalized !== null) { - description += ' or all validators are voted' - } - return description } @computed @@ -102,21 +130,85 @@ export class BallotCard extends React.Component { return votesPercents } + @computed + get votesBurnNumber() { + let votes = this.burnVotes + if (isNaN(votes)) votes = 0 + return votes + } + + @computed + get votesBurnPercents() { + if (this.totalVoters <= 0) { + return 0 + } + + let votesPercents = Math.round((this.votesBurnNumber / this.totalVoters) * 100) + if (isNaN(votesPercents)) votesPercents = 0 + return votesPercents + } + + @computed + get votesFreezeNumber() { + let votes = this.freezeVotes + if (isNaN(votes)) votes = 0 + return votes + } + + @computed + get votesFreezePercents() { + if (this.totalVoters <= 0) { + return 0 + } + + let votesPercents = Math.round((this.votesFreezeNumber / this.totalVoters) * 100) + if (isNaN(votesPercents)) votesPercents = 0 + return votesPercents + } + + @computed + get votesSendNumber() { + let votes = this.sendVotes + if (isNaN(votes)) votes = 0 + return votes + } + + @computed + get votesSendPercents() { + if (this.totalVoters <= 0) { + return 0 + } + + let votesPercents = Math.round((this.votesSendNumber / this.totalVoters) * 100) + if (isNaN(votesPercents)) votesPercents = 0 + return votesPercents + } + @action('Calculate time to start/finish') calcTimeTo = () => { const _now = moment() + const cancel = moment.utc(this.cancelDeadline, USDateTimeFormat) const start = moment.utc(this.startTime, USDateTimeFormat) const finish = moment.utc(this.endTime, USDateTimeFormat) - let msStart = start.diff(_now) - let msFinish = finish.diff(_now) + const msCancel = cancel.diff(_now) + const msStart = start.diff(_now) + const msFinish = finish.diff(_now) + + if (msCancel > 0 && !this.isCanceled) { + this.timeToCancel.val = msCancel + this.timeToCancel.displayValue = this.formatMs(msCancel, ':mm:ss') + } else { + this.timeToCancel.val = 0 + this.timeToCancel.displayValue = zeroTimeTo + } - if (msStart > 0) { + if (msStart > 0 && !this.isCanceled) { this.timeToStart.val = msStart + 5000 this.timeToStart.displayValue = this.formatMs(msStart, ':mm:ss') return (this.timeTo = this.timeToStart) } - if (msFinish > 0) { + if (msFinish > 0 && !this.isCanceled) { this.timeToStart.val = 0 this.timeToFinish.val = msFinish this.timeToFinish.displayValue = this.formatMs(msFinish, ':mm:ss') @@ -175,6 +267,10 @@ export class BallotCard extends React.Component { } vote = async ({ choice }) => { + if (this.isCanceled) { + swal('Warning!', messages.INVALID_VOTE_MSG, 'warning') + return + } if (this.timeToStart.val > 0) { swal('Warning!', messages.ballotIsNotActiveMsg(this.timeTo.displayValue), 'warning') return @@ -202,9 +298,22 @@ export class BallotCard extends React.Component { async tx => { const ballotInfo = await contract.getBallotInfo(id, contractsStore.votingKey) - this.totalVoters = Number(ballotInfo.totalVoters) - this.progress = Number(ballotInfo.progress) + if (ballotInfo.hasOwnProperty('totalVoters')) { + this.totalVoters = Number(ballotInfo.totalVoters) + } else { + this.burnVotes = ballotInfo.burnVotes + this.freezeVotes = ballotInfo.freezeVotes + this.sendVotes = ballotInfo.sendVotes + this.totalVoters = + Number(ballotInfo.burnVotes) + Number(ballotInfo.freezeVotes) + Number(ballotInfo.sendVotes) + } + if (ballotInfo.hasOwnProperty('progress')) { + this.progress = Number(ballotInfo.progress) + } this.isFinalized = Boolean(ballotInfo.isFinalized) + if (ballotInfo.hasOwnProperty('isCanceled')) { + this.isCanceled = Boolean(ballotInfo.isCanceled) + } if (ballotInfo.hasOwnProperty('canBeFinalizedNow')) { this.canBeFinalized = Boolean(ballotInfo.canBeFinalizedNow) } else { @@ -212,9 +321,18 @@ export class BallotCard extends React.Component { } this.hasAlreadyVoted = true - ballotsStore.ballotCards[pos].props.votingState.totalVoters = this.totalVoters - ballotsStore.ballotCards[pos].props.votingState.progress = this.progress + if (ballotInfo.hasOwnProperty('totalVoters')) { + ballotsStore.ballotCards[pos].props.votingState.totalVoters = this.totalVoters + } else { + ballotsStore.ballotCards[pos].props.votingState.burnVotes = this.burnVotes + ballotsStore.ballotCards[pos].props.votingState.freezeVotes = this.freezeVotes + ballotsStore.ballotCards[pos].props.votingState.sendVotes = this.sendVotes + } + if (ballotInfo.hasOwnProperty('progress')) { + ballotsStore.ballotCards[pos].props.votingState.progress = this.progress + } ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized + ballotsStore.ballotCards[pos].props.votingState.isCanceled = this.isCanceled ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized ballotsStore.ballotCards[pos].props.votingState.hasAlreadyVoted = this.hasAlreadyVoted @@ -226,11 +344,69 @@ export class BallotCard extends React.Component { ) } - finalize = async e => { - if (this.isFinalized) { + cancelOrFinalize = e => { + if (this.isFinalized || this.isCanceled) { + return + } + if (this.timeToCancel.val > 0) { + this.cancel(e) + } else { + this.finalize(e) + } + } + + cancel = async e => { + console.log('cancel function called') + const { votingState, contractsStore, commonStore, ballotsStore, votingType, id, pos } = this.props + const { push } = this.props.routing + const contract = this.getContract(contractsStore, votingType) + let canCancel = true + + if (!this.timeToCancel.val) { + canCancel = false + } + if (votingState.creatorMiningKey.toLowerCase() !== contractsStore.miningKey.toLowerCase()) { + canCancel = false + } + commonStore.showLoading() + if (!votingState.creationTime) { + canCancel = false + } else { + const currentTime = Number(await contract.getTime()) + if (currentTime - votingState.creationTime > contractsStore.ballotCancelingThreshold) { + canCancel = false + } + } + + if (!canCancel) { + commonStore.hideLoading() + swal('Warning!', messages.INVALID_CANCEL_MSG, 'warning') return } + sendTransactionByVotingKey( + this.props, + contract.address, + contract.cancelBallot(id), + async tx => { + this.isFinalized = false + this.isCanceled = true + ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized + ballotsStore.ballotCards[pos].props.votingState.isCanceled = this.isCanceled + if (this.canBeFinalized !== null) { + this.canBeFinalized = false + ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized + } + swal('Congratulations!', messages.CANCELED_SUCCESS_MSG, 'success').then(result => { + push(`${commonStore.rootPath}`) + }) + }, + messages.CANCEL_BALLOT_FAILED_TX + ) + } + + finalize = async e => { + console.log('finalize function called') if (this.timeToStart.val > 0) { swal('Warning!', messages.ballotIsNotActiveMsg(this.timeTo.displayValue), 'warning') return @@ -271,7 +447,9 @@ export class BallotCard extends React.Component { }) if (events.length > 0) { this.isFinalized = true + this.isCanceled = false ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized + ballotsStore.ballotCards[pos].props.votingState.isCanceled = this.isCanceled if (this.canBeFinalized !== null) { this.canBeFinalized = false ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized @@ -315,6 +493,8 @@ export class BallotCard extends React.Component { return contractsStore.votingToChangeMinThreshold case 'votingToChangeProxy': return contractsStore.votingToChangeProxy + case 'votingToManageEmissionFunds': + return contractsStore.votingToManageEmissionFunds case 'validatorMetadata': return contractsStore.validatorMetadata default: @@ -330,6 +510,8 @@ export class BallotCard extends React.Component { return contractsStore.minThresholdBallotThreshold case 'votingToChangeProxy': return contractsStore.proxyBallotThreshold + case 'votingToManageEmissionFunds': + return contractsStore.emissionFundsBallotThreshold default: return contractsStore.keysBallotThreshold } @@ -337,22 +519,49 @@ export class BallotCard extends React.Component { constructor(props) { super(props) - const { votingState } = this.props + const { votingState, contractsStore } = this.props // getTimes + if ( + votingState.hasOwnProperty('creationTime') && + contractsStore.ballotCancelingThreshold > 0 && + votingState.creatorMiningKey === contractsStore.miningKey + ) { + votingState.creationTime = Number(votingState.creationTime) + this.cancelDeadline = moment + .utc((votingState.creationTime + contractsStore.ballotCancelingThreshold) * 1000) + .format(USDateTimeFormat) + } this.startTime = moment.utc(votingState.startTime * 1000).format(USDateTimeFormat) this.endTime = moment.utc(votingState.endTime * 1000).format(USDateTimeFormat) - this.calcTimeTo() // getCreator this.creator = votingState.creator this.creatorMiningKey = votingState.creatorMiningKey // getTotalVoters - this.totalVoters = Number(votingState.totalVoters) + if (votingState.hasOwnProperty('totalVoters')) { + this.totalVoters = Number(votingState.totalVoters) + } else { + this.burnVotes = Number(votingState.burnVotes) + this.freezeVotes = Number(votingState.freezeVotes) + this.sendVotes = Number(votingState.sendVotes) + this.totalVoters = this.burnVotes + this.freezeVotes + this.sendVotes + } // getProgress - this.progress = Number(votingState.progress) + if (votingState.hasOwnProperty('progress')) { + this.progress = Number(votingState.progress) + } // getIsFinalized this.isFinalized = votingState.isFinalized + // getIsCanceled + if (votingState.hasOwnProperty('isCanceled')) { + this.isCanceled = votingState.isCanceled + } + this.calcTimeTo() // canBeFinalizedNow - this.canBeFinalized = votingState.hasOwnProperty('canBeFinalizedNow') ? votingState.canBeFinalizedNow : null + if (votingState.hasOwnProperty('canBeFinalizedNow')) { + this.canBeFinalized = votingState.canBeFinalizedNow + } else { + this.canBeFinalizedNow() + } // getMemo this.memo = votingState.memo // hasAlreadyVoted @@ -383,9 +592,12 @@ export class BallotCard extends React.Component { showCard = () => { let { commonStore } = this.props let checkToFinalizeFilter = commonStore.isToFinalizeFilter - ? !this.isFinalized && (this.timeToFinish.val === 0 || this.canBeFinalized) && this.timeToStart.val === 0 + ? !this.isFinalized && + !this.isCanceled && + (this.timeToFinish.val === 0 || this.canBeFinalized) && + this.timeToStart.val === 0 : true - let show = commonStore.isActiveFilter ? !this.isFinalized : checkToFinalizeFilter + let show = commonStore.isActiveFilter ? !this.isFinalized && !this.isCanceled : checkToFinalizeFilter return show } @@ -397,6 +609,8 @@ export class BallotCard extends React.Component { return 'Keys' case 'votingToChangeProxy': return 'Proxy' + case 'votingToManageEmissionFunds': + return 'EmissionFunds' default: return '' } @@ -425,47 +639,25 @@ export class BallotCard extends React.Component { ) : ( '' ) - return ( -
-
-
-
-

Proposer

-
-
-

{this.creator}

-
-
- {children} -
-
-

Ballot Time

-
-
-

{this.startTime}

-

- {this.timeTo.displayValue} ({this.timeTo.title}) -

-
-
-
- {/* TODO: Send / Burn / Freeze */} - {/*
+ let votingScale + if (votingType === 'votingToManageEmissionFunds') { + votingScale = ( +
-

{this.votesForNumber} Votes

-

{this.votesForPercents}%

+

{this.votesBurnNumber} Votes

+

{this.votesBurnPercents}%

@@ -473,43 +665,45 @@ export class BallotCard extends React.Component {
-

{this.votesAgainstNumber} Votes

-

{this.votesAgainstPercents}%

+

{this.votesFreezeNumber} Votes

+

{this.votesFreezePercents}%

-

{this.votesAgainstNumber} Votes

-

{this.votesAgainstPercents}%

+

{this.votesSendNumber} Votes

+

{this.votesSendPercents}%

-
*/} - {/* No / yes */} +
+ ) + } else { + votingScale = (
+ ) + } + return ( +
+
+
+
+

Proposer

+
+
+

{this.creator}

+
+
+ {children} +
+
+

Ballot Time

+
+
+

{this.startTime}

+

+ {this.timeTo.displayValue} ({this.timeTo.title}) +

+
+
+
+ {votingScale}
Minimum {threshold} from {contractsStore.validatorsLength} validators are required to pass the proposal @@ -560,10 +781,10 @@ export class BallotCard extends React.Component {
- -

{this.finalizeDescription}

+

{this.cancelOrFinalizeDescription}

{showHasAlreadyVotedLabel}
diff --git a/src/components/BallotEmissionFundsCard.jsx b/src/components/BallotEmissionFundsCard.jsx new file mode 100644 index 0000000..c6862d6 --- /dev/null +++ b/src/components/BallotEmissionFundsCard.jsx @@ -0,0 +1,32 @@ +import React from 'react' +import { inject, observer } from 'mobx-react' +import { BallotCard } from './BallotCard.jsx' + +@inject('contractsStore') +@observer +export class BallotEmissionFundsCard extends React.Component { + render() { + const { id, votingState, pos, contractsStore } = this.props + const amount = contractsStore.web3Instance.fromWei(votingState.amount, 'ether') + return ( + +
+
+

Proposed Receiver

+
+
+

{votingState.receiver}

+
+
+
+
+

Funds Amount

+
+
+

{amount} POA

+
+
+
+ ) + } +} diff --git a/src/components/BallotEmissionFundsMetadata.jsx b/src/components/BallotEmissionFundsMetadata.jsx new file mode 100644 index 0000000..f75229c --- /dev/null +++ b/src/components/BallotEmissionFundsMetadata.jsx @@ -0,0 +1,117 @@ +import React from 'react' +import { observable, action } from 'mobx' +import { inject, observer } from 'mobx-react' +import moment from 'moment' + +@inject('ballotStore', 'contractsStore') +@observer +export class BallotEmissionFundsMetadata extends React.Component { + @observable emissionFundsBalance + @observable noActiveBallotExists + @observable beginDateTime + @observable endDateTime + + @action('Get EmissionFunds balance') + getEmissionFundsBalance = async () => { + const { contractsStore } = this.props + this.emissionFundsBalance = 'Loading...' + this.emissionFundsBalance = contractsStore.web3Instance.fromWei( + await contractsStore.emissionFunds.balance(), + 'ether' + ) + } + + @action('Get VotingToManageEmissionFunds.noActiveBallotExists') + getNoActiveBallotExists = async () => { + this.noActiveBallotExists = await this.props.contractsStore.votingToManageEmissionFunds.noActiveBallotExists() + } + + @action('Get beginDateTime and endDateTime') + getDateTimeLimits = async () => { + const { votingToManageEmissionFunds } = this.props.contractsStore + const dateTimeFormat = 'MM/DD/YYYY HH:mm' + + this.beginDateTime = '...loading date...' + this.endDateTime = '...loading date...' + + let emissionReleaseTime = Number(await votingToManageEmissionFunds.emissionReleaseTime()) + const emissionReleaseThreshold = Number(await votingToManageEmissionFunds.emissionReleaseThreshold()) + const currentTime = Number(await votingToManageEmissionFunds.getTime()) + const distributionThreshold = Number(await votingToManageEmissionFunds.distributionThreshold()) + emissionReleaseTime = votingToManageEmissionFunds.refreshEmissionReleaseTime( + emissionReleaseTime, + emissionReleaseThreshold, + currentTime + ) + + const releasePlusDistribution = emissionReleaseTime + distributionThreshold + + if (currentTime < releasePlusDistribution) { + this.beginDateTime = moment.unix(emissionReleaseTime).format(dateTimeFormat) + this.endDateTime = moment.unix(releasePlusDistribution).format(dateTimeFormat) + } else { + const futureEmissionReleaseTime = emissionReleaseTime + emissionReleaseThreshold + this.beginDateTime = moment.unix(futureEmissionReleaseTime).format(dateTimeFormat) + this.endDateTime = moment.unix(futureEmissionReleaseTime + distributionThreshold).format(dateTimeFormat) + } + } + + constructor(props) { + super(props) + this.getEmissionFundsBalance() + this.getNoActiveBallotExists() + this.getDateTimeLimits() + } + + render() { + const { ballotStore, contractsStore } = this.props + let note, explorerLink + if (this.noActiveBallotExists === true) { + note = ( +

+ The ballot can be created starting from {this.beginDateTime} and will end on {this.endDateTime}. +

+ ) + } else if (this.noActiveBallotExists !== true) { + note =

To be able to create a new ballot, the previous ballot of this type must be finalized.

+ } + if (contractsStore.netId === '77') { + explorerLink = `https://sokol.poaexplorer.com/address/search/${contractsStore.emissionFunds.address}` + } else { + explorerLink = `https://poaexplorer.com/address/${contractsStore.emissionFunds.address}` + } + return ( +
+
+
+
+ + ballotStore.changeBallotMetadata(e, 'receiver', 'ballotEmissionFunds')} + /> +

The address which the funds will be sent to, in case of the majority of votes.

+
+
+
+
+ + +

+ Current balance of  + + EmissionFunds contract + . +

+
+
+
+
+ {note} +
+
+ ) + } +} diff --git a/src/components/BallotKeysCard.jsx b/src/components/BallotKeysCard.jsx index 07e485e..8978d9a 100644 --- a/src/components/BallotKeysCard.jsx +++ b/src/components/BallotKeysCard.jsx @@ -63,23 +63,6 @@ export class BallotKeysCard extends React.Component {
{miningKeyDiv} - {/* TODO: New ballot type */} - {/*
-
-

Proposed Receiver

-
-
-

0x4432c441EE96ef387CEC496709967Be6E27f57C8

-
-
-
-
-

Funds Amount

-
-
-

10000 POA

-
-
*/} ) } diff --git a/src/components/Ballots.jsx b/src/components/Ballots.jsx index 580637b..1af9cc0 100644 --- a/src/components/Ballots.jsx +++ b/src/components/Ballots.jsx @@ -116,6 +116,14 @@ export class Ballots extends React.Component { ) { continue } + } else if (contractType === ballotStore.BallotType.emissionFunds) { + if ( + String(votingState.receiver) + .toLowerCase() + .includes(searchTerm) + ) { + continue + } } ballotCards.splice(i--, 1) diff --git a/src/components/NewBallot.jsx b/src/components/NewBallot.jsx index 9acf9cb..45fffdd 100644 --- a/src/components/NewBallot.jsx +++ b/src/components/NewBallot.jsx @@ -7,6 +7,7 @@ import { KeysTypes } from './KeysTypes.jsx' import { BallotKeysMetadata } from './BallotKeysMetadata.jsx' import { BallotMinThresholdMetadata } from './BallotMinThresholdMetadata.jsx' import { BallotProxyMetadata } from './BallotProxyMetadata.jsx' +import { BallotEmissionFundsMetadata } from './BallotEmissionFundsMetadata.jsx' import { messages } from '../messages' import { constants } from '../constants' import { sendTransactionByVotingKey } from '../helpers' @@ -44,40 +45,42 @@ export class NewBallot extends React.Component { return false } - const minBallotDurationInHours = constants.minBallotDurationInDays * 24 - const startTime = this.getStartTimeUnix() - const minEndTime = moment - .utc() - .add(minBallotDurationInHours, 'hours') - .format() - let neededMinutes = moment(minEndTime).diff(moment(ballotStore.endTime), 'minutes') - let neededHours = Math.floor(neededMinutes / 60) - let duration = moment.unix(ballotStore.endTimeUnix).diff(moment.unix(startTime), 'hours') - - if (duration < 0) { - duration = 0 - } + if (!ballotStore.isBallotForEmissionFunds) { + const minBallotDurationInHours = constants.minBallotDurationInDays * 24 + const startTime = this.getStartTimeUnix() + const minEndTime = moment + .utc() + .add(minBallotDurationInHours, 'hours') + .format() + let neededMinutes = moment(minEndTime).diff(moment(ballotStore.endTime), 'minutes') + const neededHours = Math.floor(neededMinutes / 60) + let duration = moment.unix(ballotStore.endTimeUnix).diff(moment.unix(startTime), 'hours') - if (neededMinutes > 0) { - neededMinutes = Math.abs(neededHours * 60 - neededMinutes) - swal( - 'Warning!', - messages.SHOULD_BE_MORE_THAN_MIN_DURATION(minBallotDurationInHours, duration, neededHours, neededMinutes), - 'warning' - ) - commonStore.hideLoading() - return false - } + if (duration < 0) { + duration = 0 + } - const twoWeeks = moment - .utc() - .add(14, 'days') - .format() - let exceededMinutes = moment(ballotStore.endTime).diff(moment(twoWeeks), 'minutes') - if (exceededMinutes > 0) { - swal('Warning!', messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS(duration), 'warning') - commonStore.hideLoading() - return false + if (neededMinutes > 0) { + neededMinutes = Math.abs(neededHours * 60 - neededMinutes) + swal( + 'Warning!', + messages.SHOULD_BE_MORE_THAN_MIN_DURATION(minBallotDurationInHours, duration, neededHours, neededMinutes), + 'warning' + ) + commonStore.hideLoading() + return false + } + + const twoWeeks = moment + .utc() + .add(14, 'days') + .format() + const exceededMinutes = moment(ballotStore.endTime).diff(moment(twoWeeks), 'minutes') + if (exceededMinutes > 0) { + swal('Warning!', messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS(duration), 'warning') + commonStore.hideLoading() + return false + } } if (ballotStore.isBallotForKey) { @@ -132,7 +135,7 @@ export class NewBallot extends React.Component { } } - let isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotProxy.proposedAddress) + const isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotProxy.proposedAddress) if (!isAddress) { swal('Warning!', messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG, 'warning') @@ -141,7 +144,28 @@ export class NewBallot extends React.Component { } } - if (!ballotStore.isBallotForKey && !ballotStore.isBallotForMinThreshold && !ballotStore.isBallotForProxy) { + if (ballotStore.isBallotForEmissionFunds) { + if (ballotStore.ballotEmissionFunds.receiver.length === 0) { + swal('Warning!', `Address of funds receiver is empty`, 'warning') + commonStore.hideLoading() + return false + } + + const isAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotEmissionFunds.receiver) + + if (!isAddress) { + swal('Warning!', messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG, 'warning') + commonStore.hideLoading() + return false + } + } + + if ( + !ballotStore.isBallotForKey && + !ballotStore.isBallotForMinThreshold && + !ballotStore.isBallotForProxy && + !ballotStore.isBallotForEmissionFunds + ) { swal('Warning!', messages.BALLOT_TYPE_IS_EMPTY_MSG, 'warning') commonStore.hideLoading() return false @@ -150,11 +174,11 @@ export class NewBallot extends React.Component { return true } - createBallotForKeys = startTime => { + createBallotForKeys = (startTime, endTime) => { const { ballotStore, contractsStore } = this.props const inputToMethod = { - startTime: startTime, - endTime: ballotStore.endTimeUnix, + startTime, + endTime, affectedKey: ballotStore.ballotKeys.affectedKey, affectedKeyType: ballotStore.ballotKeys.keyType, newVotingKey: ballotStore.ballotKeys.newVotingKey, @@ -176,22 +200,22 @@ export class NewBallot extends React.Component { return data } - createBallotForMinThreshold = startTime => { + createBallotForMinThreshold = (startTime, endTime) => { const { ballotStore, contractsStore } = this.props const inputToMethod = { - startTime: startTime, - endTime: ballotStore.endTimeUnix, + startTime, + endTime, proposedValue: ballotStore.ballotMinThreshold.proposedValue, memo: ballotStore.memo } return contractsStore.votingToChangeMinThreshold.createBallot(inputToMethod) } - createBallotForProxy = startTime => { + createBallotForProxy = (startTime, endTime) => { const { ballotStore, contractsStore } = this.props const inputToMethod = { - startTime: startTime, - endTime: ballotStore.endTimeUnix, + startTime, + endTime, proposedValue: ballotStore.ballotProxy.proposedAddress, contractType: ballotStore.ballotProxy.contractType, memo: ballotStore.memo @@ -199,6 +223,17 @@ export class NewBallot extends React.Component { return contractsStore.votingToChangeProxy.createBallot(inputToMethod) } + createBallotForEmissionFunds = (startTime, endTime) => { + const { ballotStore, contractsStore } = this.props + const inputToMethod = { + startTime, + endTime, + receiver: ballotStore.ballotEmissionFunds.receiver, + memo: ballotStore.memo + } + return contractsStore.votingToManageEmissionFunds.createBallot(inputToMethod) + } + onClick = async () => { const { commonStore, contractsStore, ballotStore, ballotsStore } = this.props const { push } = this.props.routing @@ -240,6 +275,44 @@ export class NewBallot extends React.Component { } } + let startTime = this.getStartTimeUnix() + let endTime = ballotStore.endTimeUnix + + if (ballotStore.ballotType === ballotStore.BallotType.emissionFunds) { + const votingContract = contractsStore.votingToManageEmissionFunds + + let emissionReleaseTime = Number(await votingContract.emissionReleaseTime()) + const emissionReleaseThreshold = Number(await votingContract.emissionReleaseThreshold()) + const currentTime = Number(await votingContract.getTime()) + emissionReleaseTime = votingContract.refreshEmissionReleaseTime( + emissionReleaseTime, + emissionReleaseThreshold, + currentTime + ) + + if (currentTime < emissionReleaseTime) { + commonStore.hideLoading() + const emissionReleaseTimeString = moment + .unix(emissionReleaseTime) + .utc() + .format('MMM Do YYYY, h:mm:ss a') + swal('Warning!', messages.EMISSION_RELEASE_TIME_IN_FUTURE(emissionReleaseTimeString), 'warning') + return + } + + const noActiveBallotExists = await votingContract.noActiveBallotExists() + if (!noActiveBallotExists) { + commonStore.hideLoading() + swal('Warning!', messages.PREVIOUS_BALLOT_NOT_FINALIZED, 'warning') + return + } + + const distributionThreshold = Number(await votingContract.distributionThreshold()) + + startTime = currentTime + constants.startTimeOffsetInMinutes * 60 + endTime = emissionReleaseTime + distributionThreshold + } + let methodToCreateBallot let contractType let contractInstance @@ -259,16 +332,19 @@ export class NewBallot extends React.Component { contractType = 'votingToChangeProxy' contractInstance = contractsStore.votingToChangeProxy.votingToChangeProxyInstance break + case ballotStore.BallotType.emissionFunds: + methodToCreateBallot = this.createBallotForEmissionFunds + contractType = 'votingToManageEmissionFunds' + contractInstance = contractsStore.votingToManageEmissionFunds.instance + break default: break } - const startTime = this.getStartTimeUnix() - sendTransactionByVotingKey( this.props, contractInstance.options.address, - methodToCreateBallot(startTime), + methodToCreateBallot(startTime, endTime), async tx => { const events = await contractInstance.getPastEvents('BallotCreated', { fromBlock: tx.blockNumber, @@ -322,9 +398,23 @@ export class NewBallot extends React.Component { metadata = minThreshold = contractsStore.proxyBallotThreshold break + case ballotStore.BallotType.emissionFunds: + metadata = + minThreshold = contractsStore.emissionFundsBallotThreshold + break default: break } + const emissionFundsManagementBallot = contractsStore.votingToManageEmissionFunds ? ( +
ballotStore.changeBallotType(e, ballotStore.BallotType.emissionFunds)} + > + Emission Funds Ballot +
+ ) : ( + '' + ) return (
@@ -348,12 +438,13 @@ export class NewBallot extends React.Component { > Modify Proxy Contract Ballot
+ {emissionFundsManagementBallot}
-

Information of the ballot

+

Limits of the ballot

- Minimum {minThreshold} from {contractsStore.validatorsLength} - validators are required to pass the proposal
+ Minimum {minThreshold} from {contractsStore.validatorsLength} validators are required to pass the  + proposal
You can create {contractsStore.validatorLimits.keys} ballot(s) for keys
diff --git a/src/constants.js b/src/constants.js index eaef903..8f7a7b1 100644 --- a/src/constants.js +++ b/src/constants.js @@ -6,11 +6,13 @@ constants.ABIsSources = { KeysManager: 'KeysManager.abi.json', PoaNetworkConsensus: 'PoaNetworkConsensus.abi.json', BallotStorage: 'BallotsStorage.abi.json', + EmissionFunds: 'EmissionFunds.abi.json', ProxyStorage: 'ProxyStorage.abi.json', ValidatorMetadata: 'ValidatorMetadata.abi.json', VotingToChangeKeys: 'VotingToChangeKeys.abi.json', VotingToChangeMinThreshold: 'VotingToChangeMinThreshold.abi.json', - VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json' + VotingToChangeProxyAddress: 'VotingToChangeProxyAddress.abi.json', + VotingToManageEmissionFunds: 'VotingToManageEmissionFunds.abi.json' } constants.NEW_MINING_KEY = { label: 'New Mining Key', diff --git a/src/contracts/EmissionFunds.contract.js b/src/contracts/EmissionFunds.contract.js new file mode 100644 index 0000000..57160d2 --- /dev/null +++ b/src/contracts/EmissionFunds.contract.js @@ -0,0 +1,15 @@ +import Web3 from 'web3' +import { networkAddresses } from './addresses' + +export default class EmissionFunds { + async init({ web3, netId }) { + const { EMISSION_FUNDS_ADDRESS } = networkAddresses(netId) + console.log('EmissionFunds address', EMISSION_FUNDS_ADDRESS) + this.web3_10 = new Web3(web3.currentProvider) + this.address = EMISSION_FUNDS_ADDRESS + } + + balance() { + return this.web3_10.eth.getBalance(this.address) + } +} diff --git a/src/contracts/VotingToManageEmissionFunds.contract.js b/src/contracts/VotingToManageEmissionFunds.contract.js new file mode 100644 index 0000000..de69b43 --- /dev/null +++ b/src/contracts/VotingToManageEmissionFunds.contract.js @@ -0,0 +1,95 @@ +import Web3 from 'web3' +import { networkAddresses } from './addresses' +import helpers from './helpers' + +export default class VotingToManageEmissionFunds { + async init({ web3, netId }) { + const { VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS } = networkAddresses(netId) + console.log('VotingToManageEmissionFunds address', VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS) + const web3_10 = new Web3(web3.currentProvider) + + const branch = helpers.getBranch(netId) + + const votingToManageEmissionFundsABI = await helpers.getABI(branch, 'VotingToManageEmissionFunds') + + this.instance = new web3_10.eth.Contract(votingToManageEmissionFundsABI, VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS) + this.address = VOTING_TO_MANAGE_EMISSION_FUNDS_ADDRESS + } + + // setters + cancelBallot(_id) { + return this.instance.methods.cancelNewBallot().encodeABI() + } + + createBallot({ startTime, endTime, receiver, memo }) { + return this.instance.methods.createBallot(startTime, endTime, receiver, memo).encodeABI() + } + + finalize(_id) { + return this.instance.methods.finalize(_id).encodeABI() + } + + vote(_id, choice) { + return this.instance.methods.vote(_id, choice).encodeABI() + } + + // getters + ballotCancelingThreshold() { + return this.instance.methods.ballotCancelingThreshold().call() + } + + canBeFinalizedNow(_id) { + return this.instance.methods.canBeFinalizedNow(_id).call() + } + + distributionThreshold() { + return this.instance.methods.distributionThreshold().call() + } + + emissionReleaseThreshold() { + return this.instance.methods.emissionReleaseThreshold().call() + } + + emissionReleaseTime() { + return this.instance.methods.emissionReleaseTime().call() + } + + refreshEmissionReleaseTime(emissionReleaseTime, emissionReleaseThreshold, currentTime) { + let emissionReleaseTimeRefreshed = emissionReleaseTime + if (currentTime > emissionReleaseTime) { + const diff = Math.floor((currentTime - emissionReleaseTime) / emissionReleaseThreshold) + if (diff > 0) { + emissionReleaseTimeRefreshed += emissionReleaseThreshold * diff + } + } + return emissionReleaseTimeRefreshed + } + + getBallotInfo(_id, _votingKey) { + return this.instance.methods.getBallotInfo(_id).call() + } + + getTime() { + return this.instance.methods.getTime().call() + } + + hasAlreadyVoted(_id, _votingKey) { + return this.instance.methods.hasAlreadyVoted(_id, _votingKey).call() + } + + isActive(_id) { + return this.instance.methods.isActive(_id).call() + } + + isValidVote(_id, _votingKey) { + return this.instance.methods.isValidVote(_id, _votingKey).call() + } + + nextBallotId() { + return this.instance.methods.nextBallotId().call() + } + + noActiveBallotExists() { + return this.instance.methods.noActiveBallotExists().call() + } +} diff --git a/src/index.js b/src/index.js index a2f4603..55b18e2 100644 --- a/src/index.js +++ b/src/index.js @@ -49,7 +49,7 @@ class AppMainRouter extends Component { let setVotingToChangeProxy = contractsStore.setVotingToChangeProxy(web3Config) let setValidatorMetadata = contractsStore.setValidatorMetadata(web3Config) - await Promise.all([ + let promises = [ setPoaConsensus, setBallotsStorage, setKeysManager, @@ -58,20 +58,30 @@ class AppMainRouter extends Component { setVotingToChangeMinThreshold, setVotingToChangeProxy, setValidatorMetadata - ]) + ] + + if (web3Config.netId === '77') { + // if we're in Sokol + promises.push(contractsStore.setEmissionFunds(web3Config)) + promises.push(contractsStore.setVotingToManageEmissionFunds(web3Config)) + } + + await Promise.all(promises) await contractsStore.setMiningKey(web3Config) await contractsStore.setVotingKey(web3Config) - await contractsStore.getAllValidatorMetadata() - await contractsStore.getAllBallots() - contractsStore.getKeysBallotThreshold() - contractsStore.getMinThresholdBallotThreshold() contractsStore.getProxyBallotThreshold() + contractsStore.getBallotCancelingThreshold() contractsStore.getBallotsLimits() + + await contractsStore.getAllValidatorMetadata() + await contractsStore.getAllBallots() + console.log('votingKey', contractsStore.votingKey) console.log('miningKey', contractsStore.miningKey) + commonStore.hideLoading() }) .catch(error => { diff --git a/src/messages.js b/src/messages.js index 66bf507..eb1ab03 100644 --- a/src/messages.js +++ b/src/messages.js @@ -5,12 +5,14 @@ messages.invalidVotingKeyMsg = key => { messages.VOTED_SUCCESS_MSG = 'You successfully voted' messages.BALLOT_CREATED_SUCCESS_MSG = 'You successfully created a new ballot' messages.FINALIZED_SUCCESS_MSG = 'You successfully finalized' +messages.CANCELED_SUCCESS_MSG = 'You successfully canceled' messages.ALREADY_FINALIZED_MSG = 'This ballot is already finalized' messages.INVALID_VOTE_MSG = "You can't vote on this ballot" messages.INVALID_FINALIZE_MSG = "You can't finalize this ballot" +messages.INVALID_CANCEL_MSG = "You can't cancel this ballot" messages.AFFECTED_KEY_IS_NOT_ADDRESS_MSG = "Ballot affectedKey isn't address" messages.MINING_KEY_IS_NOT_ADDRESS_MSG = "Ballot miningKey isn't address" -messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Ballot proposedAddress isn't address" +messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Proposed address isn't address" messages.END_TIME_SHOULD_BE_GREATER_THAN_NOW_MSG = 'Ballot end time should be greater than now' messages.BALLOT_TYPE_IS_EMPTY_MSG = 'Ballot type is empty' messages.NO_METAMASK_MSG = `You haven't chosen any account in MetaMask. @@ -30,12 +32,18 @@ messages.SHOULD_BE_MORE_THAN_MIN_DURATION = (minDuration, duration, neededHours, messages.SHOULD_BE_LESS_OR_EQUAL_14_DAYS = duration => { return `Ballot end time should not be more than 14 days from now in UTC time. Current duration is ${duration} hours.` } +messages.EMISSION_RELEASE_TIME_IN_FUTURE = emissionReleaseTime => { + return `You cannot create ballot right now. You'll be able to do that after ${emissionReleaseTime} UTC.` +} +messages.PREVIOUS_BALLOT_NOT_FINALIZED = 'Previous ballot should be finalized first.' messages.BALLOT_CREATE_FAILED_TX = `Your transaction was failed. Please make sure you set correct parameters for ballot creation. Make sure you don't have Transaction Error. Exception thrown in contract code message in Metamask before you sign it.` messages.VOTE_FAILED_TX = `Your transaction was failed. Please make sure you haven't already voted for this ballot. Make sure you don't have Transaction Error. Exception thrown in contract code message in Metamask before you sign it.` messages.FINALIZE_FAILED_TX = `Your transaction was failed. Make sure you don't have Transaction Error. Exception thrown in contract code message in Metamask before you sign it.` +messages.CANCEL_BALLOT_FAILED_TX = `Your transaction was failed. Make sure you don't have Transaction Error. +Exception thrown in contract code message in Metamask before you sign it.` messages.DESCRIPTION_IS_EMPTY = 'Description cannot be empty' messages.wrongRepo = repo => { return `There is no contracts.json in configured repo ${repo}` diff --git a/src/stores/BallotStore.js b/src/stores/BallotStore.js index a4141ae..bbf316a 100644 --- a/src/stores/BallotStore.js +++ b/src/stores/BallotStore.js @@ -6,7 +6,8 @@ class BallotStore { BallotType = { keys: 1, minThreshold: 2, - proxy: 3 + proxy: 3, + emissionFunds: 4 } KeysBallotType = { add: 1, @@ -34,6 +35,8 @@ class BallotStore { @observable ballotKeys @observable ballotMinThreshold @observable ballotProxy + @observable ballotEmissionFunds + @observable memo constructor() { @@ -59,6 +62,11 @@ class BallotStore { proposedAddress: '', contractType: '' } + + this.ballotEmissionFunds = { + receiver: '' + } + this.memo = '' } @@ -83,6 +91,11 @@ class BallotStore { return this.ballotType === this.BallotType.proxy } + @computed + get isBallotForEmissionFunds() { + return this.ballotType === this.BallotType.emissionFunds + } + @computed get isAddKeysBallotType() { return this.ballotKeys.keysBallotType === this.KeysBallotType.add diff --git a/src/stores/BallotsStore.js b/src/stores/BallotsStore.js index 16daf83..a6ba107 100644 --- a/src/stores/BallotsStore.js +++ b/src/stores/BallotsStore.js @@ -1,21 +1,9 @@ import { observable } from 'mobx' class BallotsStore { - @observable activeKeysBallotsLength - @observable activeMinThresholdBallotsLength - @observable activeProxyBallotsLength @observable ballotCards - @observable activeMinThresholdBallotsIDs - @observable activeProxyBallotsIDs - constructor() { - this.activeKeysBallotsLength = 0 - this.activeMinThresholdBallotsLength = 0 - this.activeProxyBallotsLength = 0 - - this.activeMinThresholdBallotsIDs = [] - this.activeProxyBallotsIDs = [] this.ballotCards = [] } } diff --git a/src/stores/ContractsStore.js b/src/stores/ContractsStore.js index b7b9a82..19a9c4f 100644 --- a/src/stores/ContractsStore.js +++ b/src/stores/ContractsStore.js @@ -3,11 +3,13 @@ import React from 'react' import PoaConsensus from '../contracts/PoaConsensus.contract' import BallotsStorage from '../contracts/BallotsStorage.contract' +import EmissionFunds from '../contracts/EmissionFunds.contract' import KeysManager from '../contracts/KeysManager.contract' import ProxyStorage from '../contracts/ProxyStorage.contract' import VotingToChangeKeys from '../contracts/VotingToChangeKeys.contract' import VotingToChangeMinThreshold from '../contracts/VotingToChangeMinThreshold.contract' import VotingToChangeProxy from '../contracts/VotingToChangeProxy.contract' +import VotingToManageEmissionFunds from '../contracts/VotingToManageEmissionFunds.contract' import ValidatorMetadata from '../contracts/ValidatorMetadata.contract' import ballotStore from './BallotStore' import ballotsStore from './BallotsStore' @@ -15,6 +17,7 @@ import commonStore from './CommonStore' import { BallotKeysCard } from '../components/BallotKeysCard.jsx' import { BallotMinThresholdCard } from '../components/BallotMinThresholdCard.jsx' import { BallotProxyCard } from '../components/BallotProxyCard.jsx' +import { BallotEmissionFundsCard } from '../components/BallotEmissionFundsCard.jsx' import { constants } from '../constants' import 'babel-polyfill' @@ -22,11 +25,13 @@ import 'babel-polyfill' class ContractsStore { @observable poaConsensus @observable ballotsStorage + @observable emissionFunds @observable keysManager @observable proxyStorage @observable votingToChangeKeys @observable votingToChangeMinThreshold @observable votingToChangeProxy + @observable votingToManageEmissionFunds @observable validatorMetadata @observable votingKey @observable miningKey @@ -35,6 +40,8 @@ class ContractsStore { @observable keysBallotThreshold @observable minThresholdBallotThreshold @observable proxyBallotThreshold + @observable emissionFundsBallotThreshold + @observable ballotCancelingThreshold @observable validatorLimits @observable validatorsMetadata @observable netId @@ -55,18 +62,20 @@ class ContractsStore { @action('Get keys ballot threshold') getKeysBallotThreshold = async () => { this.keysBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getBallotThreshold(1).call() - } - - @action('Get min threshold ballot threshold') - async getMinThresholdBallotThreshold() { - this.minThresholdBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods - .getBallotThreshold(1) - .call() + this.minThresholdBallotThreshold = this.keysBallotThreshold } @action('Get proxy ballot threshold') getProxyBallotThreshold = async () => { this.proxyBallotThreshold = await this.ballotsStorage.ballotsStorageInstance.methods.getProxyThreshold().call() + this.emissionFundsBallotThreshold = this.proxyBallotThreshold + } + + @action('Get ballot canceling threshold') + getBallotCancelingThreshold = async () => { + this.ballotCancelingThreshold = this.votingToManageEmissionFunds + ? Number(await this.votingToManageEmissionFunds.ballotCancelingThreshold()) + : 0 } @action('Set web3Instance') @@ -93,6 +102,15 @@ class ContractsStore { }) } + @action('Set EmissionFunds contract') + setEmissionFunds = async web3Config => { + this.emissionFunds = new EmissionFunds() + await this.emissionFunds.init({ + web3: web3Config.web3Instance, + netId: web3Config.netId + }) + } + @action('Set KeysManager contract') setKeysManager = async web3Config => { this.keysManager = new KeysManager() @@ -138,6 +156,15 @@ class ContractsStore { }) } + @action('Set VotingToManageEmissionFunds contract') + setVotingToManageEmissionFunds = async web3Config => { + this.votingToManageEmissionFunds = new VotingToManageEmissionFunds() + await this.votingToManageEmissionFunds.init({ + web3: web3Config.web3Instance, + netId: web3Config.netId + }) + } + @action('Set ValidatorMetadata contract') setValidatorMetadata = async web3Config => { this.validatorMetadata = new ValidatorMetadata() @@ -171,12 +198,19 @@ class ContractsStore { getAllBallots = async () => { let keysNextBallotId = 0, minThresholdNextBallotId = 0, - proxyNextBallotId = 0 + proxyNextBallotId = 0, + emissionFundsNextBallotId = 0 try { - ;[keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId] = await this.getAllBallotsNextIDs() + ;[ + keysNextBallotId, + minThresholdNextBallotId, + proxyNextBallotId, + emissionFundsNextBallotId + ] = await this.getAllBallotsNextIDs() keysNextBallotId = Number(keysNextBallotId) minThresholdNextBallotId = Number(minThresholdNextBallotId) proxyNextBallotId = Number(proxyNextBallotId) + emissionFundsNextBallotId = Number(emissionFundsNextBallotId) } catch (e) { console.log(e.message) } @@ -184,10 +218,12 @@ class ContractsStore { const allKeysPromise = this.getCards(keysNextBallotId, 'votingToChangeKeys') const allMinThresholdPromise = this.getCards(minThresholdNextBallotId, 'votingToChangeMinThreshold') const allProxyPromise = this.getCards(proxyNextBallotId, 'votingToChangeProxy') + const allEmissionFundsPromise = this.getCards(emissionFundsNextBallotId, 'votingToManageEmissionFunds') - await Promise.all([allKeysPromise, allMinThresholdPromise, allProxyPromise]) + await Promise.all([allKeysPromise, allMinThresholdPromise, allProxyPromise, allEmissionFundsPromise]) - const allBallotsIDsLength = keysNextBallotId + minThresholdNextBallotId + proxyNextBallotId + const allBallotsIDsLength = + keysNextBallotId + minThresholdNextBallotId + proxyNextBallotId + emissionFundsNextBallotId if (allBallotsIDsLength === 0) { commonStore.hideLoading() @@ -315,6 +351,17 @@ class ContractsStore { /> ) break + case 'votingToManageEmissionFunds': + card = ( + + ) + break default: break } @@ -333,7 +380,10 @@ class ContractsStore { const keysNextBallotId = this.votingToChangeKeys.nextBallotId() const minThresholdNextBallotId = this.votingToChangeMinThreshold.nextBallotId() const proxyNextBallotId = this.votingToChangeProxy.nextBallotId() - return Promise.all([keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId]) + const emissionFundsNextBallotId = this.votingToManageEmissionFunds + ? this.votingToManageEmissionFunds.nextBallotId() + : 0 + return Promise.all([keysNextBallotId, minThresholdNextBallotId, proxyNextBallotId, emissionFundsNextBallotId]) } @action