├── .gitignore ├── README.md ├── build ├── asset-manifest.json ├── eos.min.js ├── favicon.ico ├── ff.js ├── img │ ├── Chevron@2x.png │ ├── check.png │ ├── check_h.png │ ├── chevron.png │ ├── eos_icon.png │ ├── help.png │ └── nodevote.png ├── index.html ├── manifest.json ├── scatter.min.js ├── service-worker.js └── static │ ├── js │ ├── 0.4a16e162.chunk.js │ ├── 0.4a16e162.chunk.js.map │ ├── 1.8200ab96.chunk.js │ ├── 1.8200ab96.chunk.js.map │ ├── 2.592e2146.chunk.js │ ├── 2.592e2146.chunk.js.map │ ├── 3.3b02c771.chunk.js │ ├── 3.3b02c771.chunk.js.map │ ├── 4.0719ea29.chunk.js │ ├── 4.0719ea29.chunk.js.map │ ├── 5.a20c2834.chunk.js │ ├── 5.a20c2834.chunk.js.map │ ├── 6.a18169a3.chunk.js │ ├── 6.a18169a3.chunk.js.map │ ├── main.79d81733.js │ └── main.79d81733.js.map │ └── media │ └── SourceHanSansCN-Light.424662ea.otf ├── config-overrides.js ├── package-lock.json ├── package.json ├── public ├── eos.min.js ├── favicon.ico ├── ff.js ├── img │ ├── Chevron@2x.png │ ├── check.png │ ├── check_h.png │ ├── chevron.png │ ├── eos_icon.png │ ├── help.png │ └── nodevote.png ├── index.html ├── manifest.json └── scatter.min.js ├── rex_abi.md ├── src ├── fonts │ ├── SourceHanSansCN-Light.otf │ ├── SourceHanSansCN-Medium.otf │ └── SourceHanSansCN-Regular.otf ├── index.css ├── index.js ├── locales │ ├── en-US.js │ ├── en.js │ ├── zh-CN.js │ └── zh.js ├── models │ ├── commonModel.js │ ├── index.js │ ├── rexModel.js │ └── voteModel.js ├── registerServiceWorker.js ├── router.js ├── routes │ ├── BuyandSell.js │ ├── DetailsList.js │ ├── GameDescription.js │ ├── Index.js │ ├── MyRexDetails.js │ ├── NodeVoting.js │ └── Withdraw.js └── utils │ ├── Api.js │ ├── Auto.js │ ├── Constants.js │ ├── EosUtil.js │ ├── EventEmitter.js │ ├── FormatUtil.js │ ├── RequestUtil.js │ ├── Utils.js │ ├── eos.min.js │ └── scatter.min.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /.history/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | An open source dapp of rex 2 | 3 | 原型图:https://pro.modao.cc/app/wuCVWCSX3MnmEIuENmMm2hxIW8cShDp
4 | ABI接口:https://github.com/eostoken/eosrex/blob/master/rex_abi.md 5 | 6 | 背景: 7 | rex 开发已经完成 很快就要上线(具体进度:https://eosauthority.com/rex/) ,想必各个钱包将支持。 8 | 9 | 目的: 10 | 1. 我们希望做成一个dapp,可以无缝接入到所有钱包。 11 | 2. 我们会将代码全部开源,开发者可以随意使用,为社区和生态贡献我们的力量。 12 | 3. DAPP内部不包含任何开发方的任何可识别标识,欢迎所有开发者共同维护和使用。 13 | 14 | 15 | 路线图: 16 | 1. 原型图确定 17 | 2. 美术设计 18 | 3. 开发 19 | 1. 前端技术选型 初步定为 react + antd-moblie + scatter 20 | 4. 发布 21 | 22 | 发起方: 23 | XXXXXXXXXXX 24 | XXXXXXXXXXX 25 | 26 | 27 | 接入项目列表: 28 | 29 | ET钱包
30 | 虎符钱包
31 | PocketECO
32 | ONEChain
33 | 块信
34 | Awake钱包
35 | -------------------------------------------------------------------------------- /build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.js": "static/js/main.79d81733.js", 3 | "main.js.map": "static/js/main.79d81733.js.map", 4 | "static/js/0.4a16e162.chunk.js": "static/js/0.4a16e162.chunk.js", 5 | "static/js/0.4a16e162.chunk.js.map": "static/js/0.4a16e162.chunk.js.map", 6 | "static/js/1.8200ab96.chunk.js": "static/js/1.8200ab96.chunk.js", 7 | "static/js/1.8200ab96.chunk.js.map": "static/js/1.8200ab96.chunk.js.map", 8 | "static/js/2.592e2146.chunk.js": "static/js/2.592e2146.chunk.js", 9 | "static/js/2.592e2146.chunk.js.map": "static/js/2.592e2146.chunk.js.map", 10 | "static/js/3.3b02c771.chunk.js": "static/js/3.3b02c771.chunk.js", 11 | "static/js/3.3b02c771.chunk.js.map": "static/js/3.3b02c771.chunk.js.map", 12 | "static/js/4.0719ea29.chunk.js": "static/js/4.0719ea29.chunk.js", 13 | "static/js/4.0719ea29.chunk.js.map": "static/js/4.0719ea29.chunk.js.map", 14 | "static/js/5.a20c2834.chunk.js": "static/js/5.a20c2834.chunk.js", 15 | "static/js/5.a20c2834.chunk.js.map": "static/js/5.a20c2834.chunk.js.map", 16 | "static/js/6.a18169a3.chunk.js": "static/js/6.a18169a3.chunk.js", 17 | "static/js/6.a18169a3.chunk.js.map": "static/js/6.a18169a3.chunk.js.map", 18 | "static/media/SourceHanSansCN-Light.otf": "static/media/SourceHanSansCN-Light.424662ea.otf" 19 | } -------------------------------------------------------------------------------- /build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/favicon.ico -------------------------------------------------------------------------------- /build/ff.js: -------------------------------------------------------------------------------- 1 | !function(){var a="@charset \"utf-8\";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html *{outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}",b=document.createElement("style");if(document.getElementsByTagName("head")[0].appendChild(b),b.styleSheet)b.styleSheet.disabled||(b.styleSheet.cssText=a);else try{b.innerHTML=a}catch(c){b.innerText=a}}();!function(a,b){function c(){var b=f.getBoundingClientRect().width;b/i>540&&(b=540*i);var c=b/10;f.style.fontSize=c+"px",k.rem=a.rem=c}var d,e=a.document,f=e.documentElement,g=e.querySelector('meta[name="viewport"]'),h=e.querySelector('meta[name="flexible"]'),i=0,j=0,k=b.flexible||(b.flexible={});if(g){console.warn("将根据已有的meta标签来设置缩放比例");var l=g.getAttribute("content").match(/initial\-scale=([\d\.]+)/);l&&(j=parseFloat(l[1]),i=parseInt(1/j))}else if(h){var m=h.getAttribute("content");if(m){var n=m.match(/initial\-dpr=([\d\.]+)/),o=m.match(/maximum\-dpr=([\d\.]+)/);n&&(i=parseFloat(n[1]),j=parseFloat((1/i).toFixed(2))),o&&(i=parseFloat(o[1]),j=parseFloat((1/i).toFixed(2)))}}if(!i&&!j){var p=(a.navigator.appVersion.match(/android/gi),a.navigator.appVersion.match(/iphone/gi)),q=a.devicePixelRatio;i=p?q>=3&&(!i||i>=3)?3:q>=2&&(!i||i>=2)?2:1:1,j=1/i}if(f.setAttribute("data-dpr",i),!g)if(g=e.createElement("meta"),g.setAttribute("name","viewport"),g.setAttribute("content","initial-scale="+j+", maximum-scale="+j+", minimum-scale="+j+", user-scalable=no"),f.firstElementChild)f.firstElementChild.appendChild(g);else{var r=e.createElement("div");r.appendChild(g),e.write(r.innerHTML)}a.addEventListener("resize",function(){clearTimeout(d),d=setTimeout(c,300)},!1),a.addEventListener("pageshow",function(a){a.persisted&&(clearTimeout(d),d=setTimeout(c,300))},!1),"complete"===e.readyState?e.body.style.fontSize=12*i+"px":e.addEventListener("DOMContentLoaded",function(){e.body.style.fontSize=12*i+"px"},!1),c(),k.dpr=a.dpr=i,k.refreshRem=c,k.rem2px=function(a){var b=parseFloat(a)*this.rem;return"string"==typeof a&&a.match(/rem$/)&&(b+="px"),b},k.px2rem=function(a){var b=parseFloat(a)/this.rem;return"string"==typeof a&&a.match(/px$/)&&(b+="rem"),b}}(window,window.lib||(window.lib={})); -------------------------------------------------------------------------------- /build/img/Chevron@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/Chevron@2x.png -------------------------------------------------------------------------------- /build/img/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/check.png -------------------------------------------------------------------------------- /build/img/check_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/check_h.png -------------------------------------------------------------------------------- /build/img/chevron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/chevron.png -------------------------------------------------------------------------------- /build/img/eos_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/eos_icon.png -------------------------------------------------------------------------------- /build/img/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/help.png -------------------------------------------------------------------------------- /build/img/nodevote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/img/nodevote.png -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | REX
-------------------------------------------------------------------------------- /build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "ETRobot", 3 | "name": "ETRobot", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#25242B" 15 | } 16 | -------------------------------------------------------------------------------- /build/service-worker.js: -------------------------------------------------------------------------------- 1 | "use strict";var precacheConfig=[["/index.html","2e6651315951cf55cedf8a0ce2ebec64"],["/static/js/0.4a16e162.chunk.js","3f18861545c2c4f29baf23644c87c73e"],["/static/js/1.8200ab96.chunk.js","fbc7e00a6dbc44bae9c0e8232bdc0de3"],["/static/js/2.592e2146.chunk.js","bd1a3971d34e1d5b3a1d08856f8291d6"],["/static/js/3.3b02c771.chunk.js","eb966b97eb1486f49bf06931cfbe2bd2"],["/static/js/4.0719ea29.chunk.js","0a409d5f804301e0585c77db1c688ddf"],["/static/js/5.a20c2834.chunk.js","54587ed1dda671b7c10be8fb5eac1a70"],["/static/js/6.a18169a3.chunk.js","522ff997cdaf4a58a68c526bffa224f5"],["/static/js/main.79d81733.js","d732d536b5bd49fe2cf24d5fc040b225"]],cacheName="sw-precache-v3-sw-precache-webpack-plugin-"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},cleanResponse=function(t){return t.redirected?("body"in t?Promise.resolve(t.body):t.blob()).then(function(e){return new Response(e,{headers:t.headers,status:t.status,statusText:t.statusText})}):Promise.resolve(t)},createCacheKey=function(e,t,n,r){var a=new URL(e);return r&&a.pathname.match(r)||(a.search+=(a.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),a.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,n){var t=new URL(e);return t.hash="",t.search=t.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(t){return n.every(function(e){return!e.test(t[0])})}).map(function(e){return e.join("=")}).join("&"),t.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],r=new URL(t,self.location),a=createCacheKey(r,hashParamName,n,/\.\w{8}\./);return[r.toString(),a]}));function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(r){return setOfCachedUrls(r).then(function(n){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(t){if(!n.has(t)){var e=new Request(t,{credentials:"same-origin"});return fetch(e).then(function(e){if(!e.ok)throw new Error("Request for "+t+" returned a response with status "+e.status);return cleanResponse(e).then(function(e){return r.put(t,e)})})}}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var n=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(t){return t.keys().then(function(e){return Promise.all(e.map(function(e){if(!n.has(e.url))return t.delete(e)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(t){if("GET"===t.request.method){var e,n=stripIgnoredUrlParameters(t.request.url,ignoreUrlParametersMatching),r="index.html";(e=urlsToCacheKeys.has(n))||(n=addDirectoryIndex(n,r),e=urlsToCacheKeys.has(n));var a="/index.html";!e&&"navigate"===t.request.mode&&isPathWhitelisted(["^(?!\\/__).*"],t.request.url)&&(n=new URL(a,self.location).toString(),e=urlsToCacheKeys.has(n)),e&&t.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n)).then(function(e){if(e)return e;throw Error("The cached response that was expected is missing.")})}).catch(function(e){return console.warn('Couldn\'t serve response for "%s" from cache: %O',t.request.url,e),fetch(t.request)}))}}); -------------------------------------------------------------------------------- /build/static/js/6.a18169a3.chunk.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([6],{559:function(e,t,n){"use strict";function i(e){if(null==e)throw new TypeError("Cannot destructure undefined")}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function a(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var o=n(7),u=n.n(o),l=n(244),d=n(243),h=(n.n(d),n(584)),c=n(246),f=(n.n(c),n(247),function(){function e(e,t){for(var n=0;n0)for(n=0;n0?"future":"past"];return Y(n)?n(t):n.replace(/%s/i,t)}function R(e,t){var n=e.toLowerCase();Vi[n]=Vi[n+"s"]=Vi[t]=e}function F(e){return"string"===typeof e?Vi[e]||Vi[e.toLowerCase()]:void 0}function U(e){var t,n,i={};for(n in e)l(e,n)&&(t=F(n))&&(i[t]=e[n]);return i}function E(e,t){ji[e]=t}function N(e){var t=[];for(var n in e)t.push({unit:n,priority:ji[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}function G(e,t,n){var i=""+Math.abs(e),s=t-i.length;return(e>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,s)).toString().substr(1)+i}function V(e,t,n,i){var s=i;"string"===typeof i&&(s=function(){return this[i]()}),e&&(Zi[e]=s),t&&(Zi[t[0]]=function(){return G(s.apply(this,arguments),t[1],t[2])}),n&&(Zi[n]=function(){return this.localeData().ordinal(s.apply(this,arguments),e)})}function j(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function A(e){var t,n,i=e.match(Ai);for(t=0,n=i.length;t=0&&Ii.test(e);)e=e.replace(Ii,n),Ii.lastIndex=0,i-=1;return e}function Z(e,t,n){ds[e]=Y(t)?t:function(e,i){return e&&n?n:t}}function $(e,t){return l(ds,e)?ds[e](t._strict,t._locale):new RegExp(q(e))}function q(e){return J(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,i,s){return t||n||i||s}))}function J(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function B(e,t){var n,i=t;for("string"===typeof e&&(e=[e]),a(t)&&(i=function(e,n){n[t]=v(e)}),n=0;n=0?(o=new Date(e+400,t,n,i,s,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,i,s,r,a),o}function ve(e){var t;if(e<100&&e>=0){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Me(e,t,n){var i=7+t-n;return-(7+ve(e,0,i).getUTCDay()-t)%7+i-1}function ke(e,t,n,i,s){var r,a,o=(7+n-i)%7,u=Me(e,i,s),l=1+7*(t-1)+o+u;return l<=0?(r=e-1,a=K(r)+l):l>K(e)?(r=e+1,a=l-K(e)):(r=e,a=l),{year:r,dayOfYear:a}}function De(e,t,n){var i,s,r=Me(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?(s=e.year()-1,i=a+Se(s,t,n)):a>Se(e.year(),t,n)?(i=a-Se(e.year(),t,n),s=e.year()+1):(s=e.year(),i=a),{week:i,year:s}}function Se(e,t,n){var i=Me(e,t,n),s=Me(e+1,t,n);return(K(e)-i+s)/7}function Ye(e){return De(e,this._week.dow,this._week.doy).week}function Oe(){return this._week.dow}function Te(){return this._week.doy}function be(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")}function xe(e){var t=De(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")}function Pe(e,t){return"string"!==typeof e?e:isNaN(e)?(e=t.weekdaysParse(e),"number"===typeof e?e:null):parseInt(e,10)}function We(e,t){return"string"===typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}function He(e,t){return e.slice(t,7).concat(e.slice(0,t))}function Ce(e,t){var i=n(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?He(i,this._week.dow):e?i[e.day()]:i}function Le(e){return!0===e?He(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Re(e){return!0===e?He(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function Fe(e,t,n){var i,s,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?(s=Ms.call(this._weekdaysParse,a),-1!==s?s:null):"ddd"===t?(s=Ms.call(this._shortWeekdaysParse,a),-1!==s?s:null):(s=Ms.call(this._minWeekdaysParse,a),-1!==s?s:null):"dddd"===t?-1!==(s=Ms.call(this._weekdaysParse,a))?s:-1!==(s=Ms.call(this._shortWeekdaysParse,a))?s:(s=Ms.call(this._minWeekdaysParse,a),-1!==s?s:null):"ddd"===t?-1!==(s=Ms.call(this._shortWeekdaysParse,a))?s:-1!==(s=Ms.call(this._weekdaysParse,a))?s:(s=Ms.call(this._minWeekdaysParse,a),-1!==s?s:null):-1!==(s=Ms.call(this._minWeekdaysParse,a))?s:-1!==(s=Ms.call(this._weekdaysParse,a))?s:(s=Ms.call(this._shortWeekdaysParse,a),-1!==s?s:null)}function Ue(e,t,n){var i,s,r;if(this._weekdaysParseExact)return Fe.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(s=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(s,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(s,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(s,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(s,"")+"|^"+this.weekdaysShort(s,"")+"|^"+this.weekdaysMin(s,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[i].test(e))return i;if(n&&"ddd"===t&&this._shortWeekdaysParse[i].test(e))return i;if(n&&"dd"===t&&this._minWeekdaysParse[i].test(e))return i;if(!n&&this._weekdaysParse[i].test(e))return i}}function Ee(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=Pe(e,this.localeData()),this.add(e-t,"d")):t}function Ne(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")}function Ge(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=We(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7}function Ve(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ie.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=Hs),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function je(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ie.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Cs),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Ae(e){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ie.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Ls),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Ie(){function e(e,t){return t.length-e.length}var t,n,i,s,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=h([2e3,1]).day(t),i=this.weekdaysMin(n,""),s=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(i),o.push(s),u.push(r),l.push(i),l.push(s),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=J(o[t]),u[t]=J(u[t]),l[t]=J(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function ze(){return this.hours()%12||12}function Ze(){return this.hours()||24}function $e(e,t){V(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function qe(e,t){return t._meridiemParse}function Je(e){return"p"===(e+"").toLowerCase().charAt(0)}function Be(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"}function Qe(e){return e?e.toLowerCase().replace("_","-"):e}function Xe(e){for(var t,n,i,s,r=0;r0;){if(i=Ke(s.slice(0,t).join("-")))return i;if(n&&n.length>=t&&M(s,n,!0)>=t-1)break;t--}r++}return Rs}function Ke(t){var n=null;if(!Ns[t]&&"undefined"!==typeof e&&e&&e.exports)try{n=Rs._abbr;!function(){var e=new Error('Cannot find module "./locale"');throw e.code="MODULE_NOT_FOUND",e}(),et(n)}catch(e){}return Ns[t]}function et(e,t){var n;return e&&(n=r(t)?it(e):tt(e,t),n?Rs=n:"undefined"!==typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),Rs._abbr}function tt(e,t){if(null!==t){var n,i=Es;if(t.abbr=e,null!=Ns[e])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=Ns[e]._config;else if(null!=t.parentLocale)if(null!=Ns[t.parentLocale])i=Ns[t.parentLocale]._config;else{if(null==(n=Ke(t.parentLocale)))return Gs[t.parentLocale]||(Gs[t.parentLocale]=[]),Gs[t.parentLocale].push({name:e,config:t}),null;i=n._config}return Ns[e]=new b(T(i,t)),Gs[e]&&Gs[e].forEach(function(e){tt(e.name,e.config)}),et(e),Ns[e]}return delete Ns[e],null}function nt(e,t){if(null!=t){var n,i,s=Es;i=Ke(e),null!=i&&(s=i._config),t=T(s,t),n=new b(t),n.parentLocale=Ns[e],Ns[e]=n,et(e)}else null!=Ns[e]&&(null!=Ns[e].parentLocale?Ns[e]=Ns[e].parentLocale:null!=Ns[e]&&delete Ns[e]);return Ns[e]}function it(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Rs;if(!n(e)){if(t=Ke(e))return t;e=[e]}return Xe(e)}function st(){return Fi(Ns)}function rt(e){var t,n=e._a;return n&&-2===f(e).overflow&&(t=n[fs]<0||n[fs]>11?fs:n[ms]<1||n[ms]>ue(n[cs],n[fs])?ms:n[_s]<0||n[_s]>24||24===n[_s]&&(0!==n[ys]||0!==n[ps]||0!==n[gs])?_s:n[ys]<0||n[ys]>59?ys:n[ps]<0||n[ps]>59?ps:n[gs]<0||n[gs]>999?gs:-1,f(e)._overflowDayOfYear&&(tms)&&(t=ms),f(e)._overflowWeeks&&-1===t&&(t=ws),f(e)._overflowWeekday&&-1===t&&(t=vs),f(e).overflow=t),e}function at(e,t,n){return null!=e?e:null!=t?t:n}function ot(e){var n=new Date(t.now());return e._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}function ut(e){var t,n,i,s,r,a=[];if(!e._d){for(i=ot(e),e._w&&null==e._a[ms]&&null==e._a[fs]&<(e),null!=e._dayOfYear&&(r=at(e._a[cs],i[cs]),(e._dayOfYear>K(r)||0===e._dayOfYear)&&(f(e)._overflowDayOfYear=!0),n=ve(r,0,e._dayOfYear),e._a[fs]=n.getUTCMonth(),e._a[ms]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=i[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[_s]&&0===e._a[ys]&&0===e._a[ps]&&0===e._a[gs]&&(e._nextDay=!0,e._a[_s]=0),e._d=(e._useUTC?ve:we).apply(null,a),s=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[_s]=24),e._w&&"undefined"!==typeof e._w.d&&e._w.d!==s&&(f(e).weekdayMismatch=!0)}}function lt(e){var t,n,i,s,r,a,o,u;if(t=e._w,null!=t.GG||null!=t.W||null!=t.E)r=1,a=4,n=at(t.GG,e._a[cs],De(Ot(),1,4).year),i=at(t.W,1),((s=at(t.E,1))<1||s>7)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=De(Ot(),r,a);n=at(t.gg,e._a[cs],l.year),i=at(t.w,l.week),null!=t.d?((s=t.d)<0||s>6)&&(u=!0):null!=t.e?(s=t.e+r,(t.e<0||t.e>6)&&(u=!0)):s=r}i<1||i>Se(n,r,a)?f(e)._overflowWeeks=!0:null!=u?f(e)._overflowWeekday=!0:(o=ke(n,i,s,r,a),e._a[cs]=o.year,e._dayOfYear=o.dayOfYear)}function dt(e){var t,n,i,s,r,a,o=e._i,u=Vs.exec(o)||js.exec(o);if(u){for(f(e).iso=!0,t=0,n=Is.length;t0&&f(e).unusedInput.push(a),o=o.slice(o.indexOf(i)+i.length),l+=i.length),Zi[r]?(i?f(e).empty=!1:f(e).unusedTokens.push(r),X(r,i,e)):e._strict&&!i&&f(e).unusedTokens.push(r);f(e).charsLeftOver=u-l,o.length>0&&f(e).unusedInput.push(o),e._a[_s]<=12&&!0===f(e).bigHour&&e._a[_s]>0&&(f(e).bigHour=void 0),f(e).parsedDateParts=e._a.slice(0),f(e).meridiem=e._meridiem,e._a[_s]=wt(e._locale,e._a[_s],e._meridiem),ut(e),rt(e)}function wt(e,t,n){var i;return null==n?t:null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?(i=e.isPM(n),i&&t<12&&(t+=12),i||12!==t||(t=0),t):t}function vt(e){var t,n,i,s,r;if(0===e._f.length)return f(e).invalidFormat=!0,void(e._d=new Date(NaN));for(s=0;sthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function $t(){if(!r(this._isDSTShifted))return this._isDSTShifted;var e={};if(y(e,this),e=Dt(e),e._a){var t=e._isUTC?h(e._a):Ot(e._a);this._isDSTShifted=this.isValid()&&M(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function qt(){return!!this.isValid()&&!this._isUTC}function Jt(){return!!this.isValid()&&this._isUTC}function Bt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Qt(e,t){var n,i,s,r=e,o=null;return Lt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:a(e)?(r={},t?r[t]=e:r.milliseconds=e):(o=er.exec(e))?(n="-"===o[1]?-1:1,r={y:0,d:v(o[ms])*n,h:v(o[_s])*n,m:v(o[ys])*n,s:v(o[ps])*n,ms:v(Rt(1e3*o[gs]))*n}):(o=tr.exec(e))?(n="-"===o[1]?-1:1,r={y:Xt(o[2],n),M:Xt(o[3],n),w:Xt(o[4],n),d:Xt(o[5],n),h:Xt(o[6],n),m:Xt(o[7],n),s:Xt(o[8],n)}):null==r?r={}:"object"===typeof r&&("from"in r||"to"in r)&&(s=en(Ot(r.from),Ot(r.to)),r={},r.ms=s.milliseconds,r.M=s.months),i=new Ct(r),Lt(e)&&l(e,"_locale")&&(i._locale=e._locale),i}function Xt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Kt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function en(e,t){var n;return e.isValid()&&t.isValid()?(t=Et(t,e),e.isBefore(t)?n=Kt(e,t):(n=Kt(t,e),n.milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function tn(e,t){return function(n,i){var s,r;return null===i||isNaN(+i)||(S(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=i,i=r),n="string"===typeof n?+n:n,s=Qt(n,i),nn(this,s,e),this}}function nn(e,n,i,s){var r=n._milliseconds,a=Rt(n._days),o=Rt(n._months);e.isValid()&&(s=null==s||s,o&&fe(e,ie(e,"Month")+o*i),a&&se(e,"Date",ie(e,"Date")+a*i),r&&e._d.setTime(e._d.valueOf()+r*i),s&&t.updateOffset(e,a||o))}function sn(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"}function rn(e,n){var i=e||Ot(),s=Et(i,this).startOf("day"),r=t.calendarFormat(this,s)||"sameElse",a=n&&(Y(n[r])?n[r].call(this,i):n[r]);return this.format(a||this.localeData().calendar(r,this,Ot(i)))}function an(){return new p(this)}function on(e,t){var n=g(e)?e:Ot(e);return!(!this.isValid()||!n.isValid())&&(t=F(t)||"millisecond","millisecond"===t?this.valueOf()>n.valueOf():n.valueOf()9999?I(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):Y(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",I(n,"Z")):I(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function pn(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",s=t+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+s)}function gn(e){e||(e=this.isUtc()?t.defaultFormatUtc:t.defaultFormat);var n=I(this,e);return this.localeData().postformat(n)}function wn(e,t){return this.isValid()&&(g(e)&&e.isValid()||Ot(e).isValid())?Qt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function vn(e){return this.from(Ot(),e)}function Mn(e,t){return this.isValid()&&(g(e)&&e.isValid()||Ot(e).isValid())?Qt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function kn(e){return this.to(Ot(),e)}function Dn(e){var t;return void 0===e?this._locale._abbr:(t=it(e),null!=t&&(this._locale=t),this)}function Sn(){return this._locale}function Yn(e,t){return(e%t+t)%t}function On(e,t,n){return e<100&&e>=0?new Date(e+400,t,n)-ur:new Date(e,t,n).valueOf()}function Tn(e,t,n){return e<100&&e>=0?Date.UTC(e+400,t,n)-ur:Date.UTC(e,t,n)}function bn(e){var n;if(void 0===(e=F(e))||"millisecond"===e||!this.isValid())return this;var i=this._isUTC?Tn:On;switch(e){case"year":n=i(this.year(),0,1);break;case"quarter":n=i(this.year(),this.month()-this.month()%3,1);break;case"month":n=i(this.year(),this.month(),1);break;case"week":n=i(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":n=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":n=i(this.year(),this.month(),this.date());break;case"hour":n=this._d.valueOf(),n-=Yn(n+(this._isUTC?0:this.utcOffset()*ar),or);break;case"minute":n=this._d.valueOf(),n-=Yn(n,ar);break;case"second":n=this._d.valueOf(),n-=Yn(n,rr)}return this._d.setTime(n),t.updateOffset(this,!0),this}function xn(e){var n;if(void 0===(e=F(e))||"millisecond"===e||!this.isValid())return this;var i=this._isUTC?Tn:On;switch(e){case"year":n=i(this.year()+1,0,1)-1;break;case"quarter":n=i(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":n=i(this.year(),this.month()+1,1)-1;break;case"week":n=i(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":n=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":n=i(this.year(),this.month(),this.date()+1)-1;break;case"hour":n=this._d.valueOf(),n+=or-Yn(n+(this._isUTC?0:this.utcOffset()*ar),or)-1;break;case"minute":n=this._d.valueOf(),n+=ar-Yn(n,ar)-1;break;case"second":n=this._d.valueOf(),n+=rr-Yn(n,rr)-1}return this._d.setTime(n),t.updateOffset(this,!0),this}function Pn(){return this._d.valueOf()-6e4*(this._offset||0)}function Wn(){return Math.floor(this.valueOf()/1e3)}function Hn(){return new Date(this.valueOf())}function Cn(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function Ln(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function Rn(){return this.isValid()?this.toISOString():null}function Fn(){return m(this)}function Un(){return d({},f(this))}function En(){return f(this).overflow}function Nn(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Gn(e,t){V(0,[e,e.length],0,t)}function Vn(e){return zn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function jn(e){return zn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)}function An(){return Se(this.year(),1,4)}function In(){var e=this.localeData()._week;return Se(this.year(),e.dow,e.doy)}function zn(e,t,n,i,s){var r;return null==e?De(this,i,s).year:(r=Se(e,i,s),t>r&&(t=r),Zn.call(this,e,t,n,i,s))}function Zn(e,t,n,i,s){var r=ke(e,t,n,i,s),a=ve(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}function $n(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)}function qn(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")}function Jn(e,t){t[gs]=v(1e3*("0."+e))}function Bn(){return this._isUTC?"UTC":""}function Qn(){return this._isUTC?"Coordinated Universal Time":""}function Xn(e){return Ot(1e3*e)}function Kn(){return Ot.apply(null,arguments).parseZone()}function ei(e){return e}function ti(e,t,n,i){var s=it(),r=h().set(i,t);return s[n](r,e)}function ni(e,t,n){if(a(e)&&(t=e,e=void 0),e=e||"",null!=t)return ti(e,t,n,"month");var i,s=[];for(i=0;i<12;i++)s[i]=ti(e,i,n,"month");return s}function ii(e,t,n,i){"boolean"===typeof e?(a(t)&&(n=t,t=void 0),t=t||""):(t=e,n=t,e=!1,a(t)&&(n=t,t=void 0),t=t||"");var s=it(),r=e?s._week.dow:0;if(null!=n)return ti(t,(n+r)%7,i,"day");var o,u=[];for(o=0;o<7;o++)u[o]=ti(t,(o+r)%7,i,"day");return u}function si(e,t){return ni(e,t,"months")}function ri(e,t){return ni(e,t,"monthsShort")}function ai(e,t,n){return ii(e,t,n,"weekdays")}function oi(e,t,n){return ii(e,t,n,"weekdaysShort")}function ui(e,t,n){return ii(e,t,n,"weekdaysMin")}function li(){var e=this._data;return this._milliseconds=yr(this._milliseconds),this._days=yr(this._days),this._months=yr(this._months),e.milliseconds=yr(e.milliseconds),e.seconds=yr(e.seconds),e.minutes=yr(e.minutes),e.hours=yr(e.hours),e.months=yr(e.months),e.years=yr(e.years),this}function di(e,t,n,i){var s=Qt(t,n);return e._milliseconds+=i*s._milliseconds,e._days+=i*s._days,e._months+=i*s._months,e._bubble()}function hi(e,t){return di(this,e,t,1)}function ci(e,t){return di(this,e,t,-1)}function fi(e){return e<0?Math.floor(e):Math.ceil(e)}function mi(){var e,t,n,i,s,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*fi(yi(o)+a),a=0,o=0),u.milliseconds=r%1e3,e=w(r/1e3),u.seconds=e%60,t=w(e/60),u.minutes=t%60,n=w(t/60),u.hours=n%24,a+=w(n/24),s=w(_i(a)),o+=s,a-=fi(yi(s)),i=w(o/12),o%=12,u.days=a,u.months=o,u.years=i,this}function _i(e){return 4800*e/146097}function yi(e){return 146097*e/4800}function pi(e){if(!this.isValid())return NaN;var t,n,i=this._milliseconds;if("month"===(e=F(e))||"quarter"===e||"year"===e)switch(t=this._days+i/864e5,n=this._months+_i(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(yi(this._months)),e){case"week":return t/7+i/6048e5;case"day":return t+i/864e5;case"hour":return 24*t+i/36e5;case"minute":return 1440*t+i/6e4;case"second":return 86400*t+i/1e3;case"millisecond":return Math.floor(864e5*t)+i;default:throw new Error("Unknown unit "+e)}}function gi(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*v(this._months/12):NaN}function wi(e){return function(){return this.as(e)}}function vi(){return Qt(this)}function Mi(e){return e=F(e),this.isValid()?this[e+"s"]():NaN}function ki(e){return function(){return this.isValid()?this._data[e]:NaN}}function Di(){return w(this.days()/7)}function Si(e,t,n,i,s){return s.relativeTime(t||1,!!n,e,i)}function Yi(e,t,n){var i=Qt(e).abs(),s=Cr(i.as("s")),r=Cr(i.as("m")),a=Cr(i.as("h")),o=Cr(i.as("d")),u=Cr(i.as("M")),l=Cr(i.as("y")),d=s<=Lr.ss&&["s",s]||s0,d[4]=n,Si.apply(null,d)}function Oi(e){return void 0===e?Cr:"function"===typeof e&&(Cr=e,!0)}function Ti(e,t){return void 0!==Lr[e]&&(void 0===t?Lr[e]:(Lr[e]=t,"s"===e&&(Lr.ss=t-1),!0))}function bi(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=Yi(this,!e,t);return e&&(n=t.pastFuture(+this,n)),t.postformat(n)}function xi(e){return(e>0)-(e<0)||+e}function Pi(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,i=Rr(this._milliseconds)/1e3,s=Rr(this._days),r=Rr(this._months);e=w(i/60),t=w(e/60),i%=60,e%=60,n=w(r/12),r%=12;var a=n,o=r,u=s,l=t,d=e,h=i?i.toFixed(3).replace(/\.?0+$/,""):"",c=this.asSeconds();if(!c)return"P0D";var f=c<0?"-":"",m=xi(this._months)!==xi(c)?"-":"",_=xi(this._days)!==xi(c)?"-":"",y=xi(this._milliseconds)!==xi(c)?"-":"";return f+"P"+(a?m+a+"Y":"")+(o?m+o+"M":"")+(u?_+u+"D":"")+(l||d||h?"T":"")+(l?y+l+"H":"")+(d?y+d+"M":"")+(h?y+h+"S":"")}var Wi,Hi;Hi=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,i=0;i68?1900:2e3)};var Ms,ks=ne("FullYear",!0);Ms=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;tthis?this:e:_()}),Qs=function(){return Date.now?Date.now():+new Date},Xs=["year","quarter","month","week","day","hour","minute","second","millisecond"];Ft("Z",":"),Ft("ZZ",""),Z("Z",os),Z("ZZ",os),B(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Ut(os,e)});var Ks=/([\+\-]|\d\d)/gi;t.updateOffset=function(){};var er=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,tr=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Qt.fn=Ct.prototype,Qt.invalid=Ht;var nr=tn(1,"add"),ir=tn(-1,"subtract");t.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",t.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var sr=D("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)}),rr=1e3,ar=60*rr,or=60*ar,ur=3506328*or;V(0,["gg",2],0,function(){return this.weekYear()%100}),V(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Gn("gggg","weekYear"),Gn("ggggg","weekYear"),Gn("GGGG","isoWeekYear"),Gn("GGGGG","isoWeekYear"),R("weekYear","gg"),R("isoWeekYear","GG"),E("weekYear",1),E("isoWeekYear",1),Z("G",rs),Z("g",rs),Z("GG",Xi,qi),Z("gg",Xi,qi),Z("GGGG",ns,Bi),Z("gggg",ns,Bi),Z("GGGGG",is,Qi),Z("ggggg",is,Qi),Q(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,i){t[i.substr(0,2)]=v(e)}),Q(["gg","GG"],function(e,n,i,s){n[s]=t.parseTwoDigitYear(e)}),V("Q",0,"Qo","quarter"),R("quarter","Q"),E("quarter",7),Z("Q",$i),B("Q",function(e,t){t[fs]=3*(v(e)-1)}),V("D",["DD",2],"Do","date"),R("date","D"),E("date",9),Z("D",Xi),Z("DD",Xi,qi),Z("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),B(["D","DD"],ms),B("Do",function(e,t){t[ms]=v(e.match(Xi)[0])});var lr=ne("Date",!0);V("DDD",["DDDD",3],"DDDo","dayOfYear"),R("dayOfYear","DDD"),E("dayOfYear",4),Z("DDD",ts),Z("DDDD",Ji),B(["DDD","DDDD"],function(e,t,n){n._dayOfYear=v(e)}),V("m",["mm",2],0,"minute"),R("minute","m"),E("minute",14),Z("m",Xi),Z("mm",Xi,qi),B(["m","mm"],ys);var dr=ne("Minutes",!1);V("s",["ss",2],0,"second"),R("second","s"),E("second",15),Z("s",Xi),Z("ss",Xi,qi),B(["s","ss"],ps);var hr=ne("Seconds",!1);V("S",0,0,function(){return~~(this.millisecond()/100)}),V(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),V(0,["SSS",3],0,"millisecond"),V(0,["SSSS",4],0,function(){return 10*this.millisecond()}),V(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),V(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),V(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),V(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),V(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),R("millisecond","ms"),E("millisecond",16),Z("S",ts,$i),Z("SS",ts,qi),Z("SSS",ts,Ji);var cr;for(cr="SSSS";cr.length<=9;cr+="S")Z(cr,ss);for(cr="S";cr.length<=9;cr+="S")B(cr,Jn);var fr=ne("Milliseconds",!1);V("z",0,0,"zoneAbbr"),V("zz",0,0,"zoneName");var mr=p.prototype;mr.add=nr,mr.calendar=rn,mr.clone=an,mr.diff=fn,mr.endOf=xn,mr.format=gn,mr.from=wn,mr.fromNow=vn,mr.to=Mn,mr.toNow=kn,mr.get=re,mr.invalidAt=En,mr.isAfter=on,mr.isBefore=un,mr.isBetween=ln,mr.isSame=dn,mr.isSameOrAfter=hn,mr.isSameOrBefore=cn,mr.isValid=Fn,mr.lang=sr,mr.locale=Dn,mr.localeData=Sn,mr.max=Bs,mr.min=Js,mr.parsingFlags=Un,mr.set=ae,mr.startOf=bn,mr.subtract=ir,mr.toArray=Cn,mr.toObject=Ln,mr.toDate=Hn,mr.toISOString=yn,mr.inspect=pn,mr.toJSON=Rn,mr.toString=_n,mr.unix=Wn,mr.valueOf=Pn,mr.creationData=Nn,mr.year=ks,mr.isLeapYear=te,mr.weekYear=Vn,mr.isoWeekYear=jn,mr.quarter=mr.quarters=$n,mr.month=me,mr.daysInMonth=_e,mr.week=mr.weeks=be,mr.isoWeek=mr.isoWeeks=xe,mr.weeksInYear=In,mr.isoWeeksInYear=An,mr.date=lr,mr.day=mr.days=Ee,mr.weekday=Ne,mr.isoWeekday=Ge,mr.dayOfYear=qn,mr.hour=mr.hours=Us,mr.minute=mr.minutes=dr,mr.second=mr.seconds=hr,mr.millisecond=mr.milliseconds=fr,mr.utcOffset=Gt,mr.utc=jt,mr.local=At,mr.parseZone=It,mr.hasAlignedHourOffset=zt,mr.isDST=Zt,mr.isLocal=qt,mr.isUtcOffset=Jt,mr.isUtc=Bt,mr.isUTC=Bt,mr.zoneAbbr=Bn,mr.zoneName=Qn,mr.dates=D("dates accessor is deprecated. Use date instead.",lr),mr.months=D("months accessor is deprecated. Use month instead",me),mr.years=D("years accessor is deprecated. Use year instead",ks),mr.zone=D("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Vt),mr.isDSTShifted=D("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",$t);var _r=b.prototype;_r.calendar=x,_r.longDateFormat=P,_r.invalidDate=W,_r.ordinal=H,_r.preparse=ei,_r.postformat=ei,_r.relativeTime=C,_r.pastFuture=L,_r.set=O,_r.months=le,_r.monthsShort=de,_r.monthsParse=ce,_r.monthsRegex=pe,_r.monthsShortRegex=ye,_r.week=Ye,_r.firstDayOfYear=Te,_r.firstDayOfWeek=Oe,_r.weekdays=Ce,_r.weekdaysMin=Re,_r.weekdaysShort=Le,_r.weekdaysParse=Ue,_r.weekdaysRegex=Ve,_r.weekdaysShortRegex=je,_r.weekdaysMinRegex=Ae,_r.isPM=Je,_r.meridiem=Be,et("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===v(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),t.lang=D("moment.lang is deprecated. Use moment.locale instead.",et),t.langData=D("moment.langData is deprecated. Use moment.localeData instead.",it);var yr=Math.abs,pr=wi("ms"),gr=wi("s"),wr=wi("m"),vr=wi("h"),Mr=wi("d"),kr=wi("w"),Dr=wi("M"),Sr=wi("Q"),Yr=wi("y"),Or=ki("milliseconds"),Tr=ki("seconds"),br=ki("minutes"),xr=ki("hours"),Pr=ki("days"),Wr=ki("months"),Hr=ki("years"),Cr=Math.round,Lr={ss:44,s:45,m:45,h:22,d:26,M:11},Rr=Math.abs,Fr=Ct.prototype;return Fr.isValid=Wt,Fr.abs=li,Fr.add=hi,Fr.subtract=ci,Fr.as=pi,Fr.asMilliseconds=pr,Fr.asSeconds=gr,Fr.asMinutes=wr,Fr.asHours=vr,Fr.asDays=Mr,Fr.asWeeks=kr,Fr.asMonths=Dr,Fr.asQuarters=Sr,Fr.asYears=Yr,Fr.valueOf=gi,Fr._bubble=mi,Fr.clone=vi,Fr.get=Mi,Fr.milliseconds=Or,Fr.seconds=Tr,Fr.minutes=br,Fr.hours=xr,Fr.days=Pr,Fr.weeks=Di,Fr.months=Wr,Fr.years=Hr,Fr.humanize=bi,Fr.toISOString=Pi,Fr.toString=Pi,Fr.toJSON=Pi,Fr.locale=Dn,Fr.localeData=Sn,Fr.toIsoString=D("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Pi),Fr.lang=sr,V("X",0,0,"unix"),V("x",0,0,"valueOf"),Z("x",rs),Z("X",us),B("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),B("x",function(e,t,n){n._d=new Date(v(e))}),t.version="2.24.0",function(e){Wi=e}(Ot),t.fn=mr,t.min=bt,t.max=xt,t.now=Qs,t.utc=h,t.unix=Xn,t.months=si,t.isDate=o,t.locale=et,t.invalid=_,t.duration=Qt,t.isMoment=g,t.weekdays=ai,t.parseZone=Kn,t.localeData=it,t.isDuration=Lt,t.monthsShort=ri,t.weekdaysMin=ui,t.defineLocale=tt,t.updateLocale=nt,t.locales=st,t.weekdaysShort=oi,t.normalizeUnits=F,t.relativeTimeRounding=Oi,t.relativeTimeThreshold=Ti,t.calendarFormat=sn,t.prototype=mr,t.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},t})}).call(t,n(586)(e))},584:function(e,t,n){"use strict";t.a={WHT:function(e){return(e/75).toExponential(2)+"rem"}}},585:function(e,t,n){!function(e,t){t(n(574))}(0,function(e){"use strict";return e.defineLocale("zh-cn",{months:"\u4e00\u6708_\u4e8c\u6708_\u4e09\u6708_\u56db\u6708_\u4e94\u6708_\u516d\u6708_\u4e03\u6708_\u516b\u6708_\u4e5d\u6708_\u5341\u6708_\u5341\u4e00\u6708_\u5341\u4e8c\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661f\u671f\u65e5_\u661f\u671f\u4e00_\u661f\u671f\u4e8c_\u661f\u671f\u4e09_\u661f\u671f\u56db_\u661f\u671f\u4e94_\u661f\u671f\u516d".split("_"),weekdaysShort:"\u5468\u65e5_\u5468\u4e00_\u5468\u4e8c_\u5468\u4e09_\u5468\u56db_\u5468\u4e94_\u5468\u516d".split("_"),weekdaysMin:"\u65e5_\u4e00_\u4e8c_\u4e09_\u56db_\u4e94_\u516d".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5e74M\u6708D\u65e5",LLL:"YYYY\u5e74M\u6708D\u65e5Ah\u70b9mm\u5206",LLLL:"YYYY\u5e74M\u6708D\u65e5ddddAh\u70b9mm\u5206",l:"YYYY/M/D",ll:"YYYY\u5e74M\u6708D\u65e5",lll:"YYYY\u5e74M\u6708D\u65e5 HH:mm",llll:"YYYY\u5e74M\u6708D\u65e5dddd HH:mm"},meridiemParse:/\u51cc\u6668|\u65e9\u4e0a|\u4e0a\u5348|\u4e2d\u5348|\u4e0b\u5348|\u665a\u4e0a/,meridiemHour:function(e,t){return 12===e&&(e=0),"\u51cc\u6668"===t||"\u65e9\u4e0a"===t||"\u4e0a\u5348"===t?e:"\u4e0b\u5348"===t||"\u665a\u4e0a"===t?e+12:e>=11?e:e+12},meridiem:function(e,t,n){var i=100*e+t;return i<600?"\u51cc\u6668":i<900?"\u65e9\u4e0a":i<1130?"\u4e0a\u5348":i<1230?"\u4e2d\u5348":i<1800?"\u4e0b\u5348":"\u665a\u4e0a"},calendar:{sameDay:"[\u4eca\u5929]LT",nextDay:"[\u660e\u5929]LT",nextWeek:"[\u4e0b]ddddLT",lastDay:"[\u6628\u5929]LT",lastWeek:"[\u4e0a]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(\u65e5|\u6708|\u5468)/,ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"\u65e5";case"M":return e+"\u6708";case"w":case"W":return e+"\u5468";default:return e}},relativeTime:{future:"%s\u5185",past:"%s\u524d",s:"\u51e0\u79d2",ss:"%d \u79d2",m:"1 \u5206\u949f",mm:"%d \u5206\u949f",h:"1 \u5c0f\u65f6",hh:"%d \u5c0f\u65f6",d:"1 \u5929",dd:"%d \u5929",M:"1 \u4e2a\u6708",MM:"%d \u4e2a\u6708",y:"1 \u5e74",yy:"%d \u5e74"},week:{dow:1,doy:4}})})},586:function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}}); 2 | //# sourceMappingURL=6.a18169a3.chunk.js.map -------------------------------------------------------------------------------- /build/static/media/SourceHanSansCN-Light.424662ea.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/build/static/media/SourceHanSansCN-Light.424662ea.otf -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | const { injectBabelPlugin, getLoader } = require('react-app-rewired'); 2 | const fileLoaderMatcher = function (rule) { 3 | return rule.loader && rule.loader.indexOf(`file-loader`) != -1; 4 | } 5 | 6 | module.exports = function override(config, env) { 7 | // babel-plugin-import 8 | config = injectBabelPlugin(['import', { 9 | libraryName: 'antd-mobile', 10 | //style: 'css', 11 | style: true, // use less for customized theme 12 | }], config); 13 | 14 | // customize theme 15 | config.module.rules[1].oneOf.unshift( 16 | { 17 | test: /\.less$/, 18 | use: [ 19 | require.resolve('style-loader'), 20 | require.resolve('css-loader'), 21 | { 22 | loader: require.resolve('postcss-loader'), 23 | options: { 24 | // Necessary for external CSS imports to work 25 | // https://github.com/facebookincubator/create-react-app/issues/2677 26 | ident: 'postcss', 27 | plugins: () => [ 28 | require('postcss-flexbugs-fixes'), 29 | autoprefixer({ 30 | browsers: [ 31 | '>1%', 32 | 'last 4 versions', 33 | 'Firefox ESR', 34 | 'not ie < 9', // React doesn't support IE8 anyway 35 | ], 36 | flexbox: 'no-2009', 37 | }), 38 | ], 39 | }, 40 | }, 41 | { 42 | loader: require.resolve('less-loader'), 43 | options: { 44 | // theme vars, also can use theme.js instead of this. 45 | modifyVars: { 46 | "@hd": "1px", // 基本单位 47 | 48 | "@font-family":"SourceHanSansCN-Light,SourceHanSansCN-Medium,SourceHanSansCN-Regular", 49 | 50 | // 文字色 51 | "@color-text-base":"#323232", // 基本 52 | "@color-text-base-inverse":"#FFFFFF", // 基本 - 反色 53 | "@color-text-secondary": "#a4a9b0", // 辅助色 54 | "@color-text-placeholder": "#bbb", // 文本框提示 55 | "@color-text-disabled": "#bbb", // 失效 56 | "@color-text-caption": "#888", // 辅助描述 57 | "@color-text-paragraph": "#333", // 段落 58 | "@color-link": "@brand-primary", // 链接 59 | 60 | // 背景色 61 | "@fill-base": "#FFFFFF", // 组件默认背景 62 | "@fill-body": "#F8F8F8", // 页面背景 63 | "@fill-tap": "#ddd", // 组件默认背景 - 按下 64 | "@fill-disabled": "#ddd", // 通用失效背景 65 | "@fill-mask": "rgba(0, 0, 0, 0.4)", // 遮罩背景 66 | "@color-icon-base": "#ccc", // 许多小图标的背景,比如一些小圆点,加减号 67 | "@fill-grey": "#f7f7f7", 68 | 69 | // 透明度 70 | "@opacity-disabled": "0.3", // switch checkbox radio 等组件禁用的透明度 71 | 72 | // 全局/品牌色 73 | "@brand-primary": "#108EE9", 74 | "@brand-primary-tap": "#0e80d2", 75 | "@brand-success": "#6abf47", 76 | "@brand-warning": "#ffc600", 77 | "@brand-error": "#f4333c", 78 | "@brand-important": "#ff5b05", // 用于小红点 79 | "@brand-wait": "#108EE9", 80 | 81 | "@border-color-base":"#F4F4F4", // 边框色 82 | 83 | // 字体尺寸 84 | "@font-size-icontext": "10 * @hd", 85 | "@font-size-caption-sm": "12 * @hd", 86 | "@font-size-base": "14 * @hd", 87 | "@font-size-subhead": "15 * @hd", 88 | "@font-size-caption": "16 * @hd", 89 | "@font-size-heading": "17 * @hd", 90 | 91 | // 圆角 92 | "@radius-xs": "2 * @hd", 93 | "@radius-sm": "3 * @hd", 94 | "@radius-md": "5 * @hd", 95 | "@radius-lg": "7 * @hd", 96 | "@radius-circle": "50%", 97 | 98 | // 边框尺寸 99 | "@border-width-sm": "1PX", 100 | "@border-width-md": "1PX", 101 | "@border-width-lg": "2 * @hd", 102 | 103 | // 水平间距 104 | "@h-spacing-sm": "5 * @hd", 105 | "@h-spacing-md": "8 * @hd", 106 | "@h-spacing-lg": "15 * @hd", 107 | 108 | // 垂直间距 109 | "@v-spacing-xs": "3 * @hd", 110 | "@v-spacing-sm": "6 * @hd", 111 | "@v-spacing-md": "9 * @hd", 112 | "@v-spacing-lg": "15 * @hd", 113 | "@v-spacing-xl": "21 * @hd", 114 | 115 | // 高度 116 | "@line-height-base": "1", // 单行行高 117 | "@line-height-paragraph": "1.5", // 多行行高 118 | 119 | // 图标尺寸 导航条上的图标、grid的图标大小 120 | "@icon-size-xxs": "15 * @hd", 121 | "@icon-size-xs": "18 * @hd", 122 | "@icon-size-sm": "21 * @hd", 123 | "@icon-size-md": "22 * @hd", 124 | "@icon-size-lg": "32 * @hd", 125 | 126 | // 动画缓动 127 | "@ease-in-out-quint": "cubic-bezier(.86, 0, .07, 1)", 128 | 129 | // 组件变量 130 | "@actionsheet-item-height": "50 * @hd", 131 | "@actionsheet-item-font-size": "18 * @hd", 132 | 133 | // button 134 | "@button-height":" 47 * @hd", 135 | "@button-font-size":" 18 * @hd", 136 | 137 | "@button-height-sm":" 30 * @hd", 138 | "@button-font-size-sm":" 13 * @hd", 139 | 140 | "@primary-button-fill":" @brand-primary", 141 | "@primary-button-fill-tap":" @brand-primary-tap", 142 | 143 | "@ghost-button-color":" @brand-primary", // 同时应用于背景、文字颜色、边框色 144 | "@ghost-button-fill-tap":" fade(@brand-primary, 60%)", 145 | 146 | "@warning-button-fill":" #e94f4f", 147 | "@warning-button-fill-tap":" #d24747", 148 | 149 | "@link-button-fill-tap":" #ddd", 150 | "@link-button-font-size":" 16 * @hd", 151 | 152 | // menu 153 | "@menu-multi-select-btns-height":" @button-height", 154 | 155 | // modal 156 | "@modal-font-size-heading": "14 * @hd", 157 | "@modal-button-font-size": "14 * @hd", // 按钮字号 158 | "@modal-button-height": "42 * @hd", // 按钮高度 159 | 160 | // list 161 | "@list-title-height":" 30 * @hd", 162 | "@list-item-height-sm":" 35 * @hd", 163 | "@list-item-height":" 40 * @hd", 164 | 165 | // input 166 | "@input-label-width": "15 * @hd", // InputItem、TextareaItem 文字长度基础值 167 | "@input-font-size": "15 * @hd", 168 | "@input-color-icon":" #ccc", // input clear icon 的背景色 169 | "@input-color-icon-tap":" @brand-primary", 170 | 171 | // tabs 172 | "@tabs-color": "#108EE9", 173 | "@tabs-height": "auto", 174 | "@tabs-font-size-heading": "20 * @hd", 175 | "@tabs-ink-bar-height": "5 * @hd", 176 | 177 | // segmented-control 178 | "@segmented-control-color":" @brand-primary", // 同时应用于背景、文字颜色、边框色 179 | "@segmented-control-height":" 27 * @hd", 180 | "@segmented-control-fill-tap":" fade(@brand-primary, 0.1)", 181 | 182 | // tab-bar 183 | "@tab-bar-fill":" #ebeeef", 184 | "@tab-bar-height":" 50 * @hd", 185 | 186 | // toast 187 | "@toast-fill":" rgba(58, 58, 58, 0.9)", // toast, activity-indicator 的背景颜色 188 | 189 | // search-bar 190 | "@search-bar-fill":" #efeff4", 191 | "@search-bar-height":" 44 * @hd", 192 | "@search-bar-input-height":" 28 * @hd", 193 | "@search-bar-font-size":" 15 * @hd", 194 | "@search-color-icon":" #bbb", // input search icon 的背景色 195 | 196 | // notice-bar 197 | "@notice-bar-fill":" #fefcec", 198 | "@notice-bar-height":" 36 * @hd", 199 | "@notice-bar-color":" #f76a24", 200 | 201 | // switch 202 | "@switch-fill":" #4dd865", 203 | "@switch-fill-android":" @brand-primary", 204 | 205 | // tag 206 | "@tag-height":" 25 * @hd", 207 | "@tag-height-sm":" 15 * @hd", 208 | "@tag-color":" @brand-primary", 209 | 210 | // keyboard 211 | "@keyboard-confirm-color":" @brand-primary", 212 | "@keyboard-confirm-tap-color":" @brand-primary-tap", 213 | 214 | // picker 215 | "@option-height":" 42 * @hd", // picker 标题的高度 216 | 217 | // z-index 218 | "@progress-zindex":" 2000", 219 | "@popover-zindex":" 1999", 220 | "@toast-zindex":" 1999", 221 | "@action-sheet-zindex":" 1000", // actonsheet 会放到 popup / modal 中 222 | "@picker-zindex":" 1000", 223 | "@popup-zindex":" 999", 224 | "@modal-zindex":" 999", // modal.alert 应该最大,其他应该较小 225 | "@tabs-pagination-zindex":" 999" 226 | 227 | }, 228 | }, 229 | }, 230 | ] 231 | } 232 | ); 233 | 234 | // css-modules 235 | config.module.rules[1].oneOf.unshift( 236 | { 237 | test: /\.css$/, 238 | exclude: /node_modules|antd-mobile\.css/, 239 | use: [ 240 | require.resolve('style-loader'), 241 | { 242 | loader: require.resolve('css-loader'), 243 | options: { 244 | modules: true, 245 | importLoaders: 1, 246 | localIdentName: '[local]___[hash:base64:5]' 247 | }, 248 | }, 249 | { 250 | loader: require.resolve('postcss-loader'), 251 | options: { 252 | // Necessary for external CSS imports to work 253 | // https://github.com/facebookincubator/create-react-app/issues/2677 254 | ident: 'postcss', 255 | plugins: () => [ 256 | require('postcss-flexbugs-fixes'), 257 | autoprefixer({ 258 | browsers: [ 259 | '>1%', 260 | 'last 4 versions', 261 | 'Firefox ESR', 262 | 'not ie < 9', // React doesn't support IE8 anyway 263 | ], 264 | flexbox: 'no-2009', 265 | }), 266 | ], 267 | }, 268 | }, 269 | ] 270 | } 271 | ); 272 | 273 | // module: { 274 | // rules: [ 275 | // { 276 | // test: /\.js$/, 277 | // use: { 278 | // loader: 'babel-loader', 279 | // options: { 280 | // presets: [ 281 | // ['env',{ 282 | // targets: { 283 | // browsers: ['> 1%', 'last 2 versions'] 284 | // } 285 | // }] 286 | // ] 287 | // } 288 | // }, 289 | // exclude: '/node_modules/' 290 | // } 291 | // ] 292 | // } 293 | // file-loader exclude 294 | let l = getLoader(config.module.rules, fileLoaderMatcher); 295 | l.exclude.push(/\.less$/); 296 | 297 | return config; 298 | }; 299 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ETRobot", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "antd-mobile": "^2.2.6", 7 | "copy-to-clipboard": "^3.0.5", 8 | "dva": "^2.4.0", 9 | "dva-loading": "^2.0.5", 10 | "events": "^3.0.0", 11 | "intl": "^1.2.5", 12 | "moment": "^2.24.0", 13 | "react": "^15.6.1", 14 | "react-dev-utils": "^8.0.0", 15 | "react-dom": "^15.6.1", 16 | "react-intl": "^2.7.2", 17 | "react-moment": "^0.8.4", 18 | "react-native-keyboard-aware-scroll-view": "^0.8.0", 19 | "react-scripts": "1.0.13", 20 | "storejs": "^1.0.20" 21 | }, 22 | "scripts": { 23 | "start": "react-app-rewired start", 24 | "build": "react-app-rewired build", 25 | "test": "react-app-rewired test --env=jsdom", 26 | "eject": "react-scripts eject" 27 | }, 28 | "devDependencies": { 29 | "babel-core": "^6.26.3", 30 | "babel-loader": "^8.0.4", 31 | "babel-plugin-dva-hmr": "^0.3.2", 32 | "babel-plugin-import": "^1.2.0", 33 | "babel-preset-env": "^1.7.0", 34 | "babel-preset-es2015": "^6.24.1", 35 | "babel-preset-react": "^6.24.1", 36 | "babel-preset-stage-0": "^6.24.1", 37 | "less": "^2.7.3", 38 | "less-loader": "^4.0.5", 39 | "react-app-rewired": "^1.2.9" 40 | }, 41 | "theme": { 42 | "primary-color": "#1088ae" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/favicon.ico -------------------------------------------------------------------------------- /public/ff.js: -------------------------------------------------------------------------------- 1 | !function(){var a="@charset \"utf-8\";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html *{outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}",b=document.createElement("style");if(document.getElementsByTagName("head")[0].appendChild(b),b.styleSheet)b.styleSheet.disabled||(b.styleSheet.cssText=a);else try{b.innerHTML=a}catch(c){b.innerText=a}}();!function(a,b){function c(){var b=f.getBoundingClientRect().width;b/i>540&&(b=540*i);var c=b/10;f.style.fontSize=c+"px",k.rem=a.rem=c}var d,e=a.document,f=e.documentElement,g=e.querySelector('meta[name="viewport"]'),h=e.querySelector('meta[name="flexible"]'),i=0,j=0,k=b.flexible||(b.flexible={});if(g){console.warn("将根据已有的meta标签来设置缩放比例");var l=g.getAttribute("content").match(/initial\-scale=([\d\.]+)/);l&&(j=parseFloat(l[1]),i=parseInt(1/j))}else if(h){var m=h.getAttribute("content");if(m){var n=m.match(/initial\-dpr=([\d\.]+)/),o=m.match(/maximum\-dpr=([\d\.]+)/);n&&(i=parseFloat(n[1]),j=parseFloat((1/i).toFixed(2))),o&&(i=parseFloat(o[1]),j=parseFloat((1/i).toFixed(2)))}}if(!i&&!j){var p=(a.navigator.appVersion.match(/android/gi),a.navigator.appVersion.match(/iphone/gi)),q=a.devicePixelRatio;i=p?q>=3&&(!i||i>=3)?3:q>=2&&(!i||i>=2)?2:1:1,j=1/i}if(f.setAttribute("data-dpr",i),!g)if(g=e.createElement("meta"),g.setAttribute("name","viewport"),g.setAttribute("content","initial-scale="+j+", maximum-scale="+j+", minimum-scale="+j+", user-scalable=no"),f.firstElementChild)f.firstElementChild.appendChild(g);else{var r=e.createElement("div");r.appendChild(g),e.write(r.innerHTML)}a.addEventListener("resize",function(){clearTimeout(d),d=setTimeout(c,300)},!1),a.addEventListener("pageshow",function(a){a.persisted&&(clearTimeout(d),d=setTimeout(c,300))},!1),"complete"===e.readyState?e.body.style.fontSize=12*i+"px":e.addEventListener("DOMContentLoaded",function(){e.body.style.fontSize=12*i+"px"},!1),c(),k.dpr=a.dpr=i,k.refreshRem=c,k.rem2px=function(a){var b=parseFloat(a)*this.rem;return"string"==typeof a&&a.match(/rem$/)&&(b+="px"),b},k.px2rem=function(a){var b=parseFloat(a)/this.rem;return"string"==typeof a&&a.match(/px$/)&&(b+="rem"),b}}(window,window.lib||(window.lib={})); -------------------------------------------------------------------------------- /public/img/Chevron@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/Chevron@2x.png -------------------------------------------------------------------------------- /public/img/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/check.png -------------------------------------------------------------------------------- /public/img/check_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/check_h.png -------------------------------------------------------------------------------- /public/img/chevron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/chevron.png -------------------------------------------------------------------------------- /public/img/eos_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/eos_icon.png -------------------------------------------------------------------------------- /public/img/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/help.png -------------------------------------------------------------------------------- /public/img/nodevote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/public/img/nodevote.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | REX 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "ETRobot", 3 | "name": "ETRobot", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#25242B" 15 | } 16 | -------------------------------------------------------------------------------- /rex_abi.md: -------------------------------------------------------------------------------- 1 | ## ABI接口
2 | ### 充值 3 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio deposit '["user11111111","100000.0000 EOS"]' -p user11111111 4 | 5 | actions: [{ 6 | account: 'eosio', 7 | name: 'deposit', 8 | authorization: [{ 9 | actor: 'user11111111', 10 | permission: 'active', 11 | }], 12 | data: { 13 | owner: 'useraaaaaaaa', 14 | amount: '100000.0000 EOS', 15 | }, 16 | }] 17 | 18 | ### 提现 19 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio withdraw '["user22222222","50000.0000 EOS"]' -p user22222222 20 | 21 | actions: [{ 22 | account: 'eosio', 23 | name: 'withdraw', 24 | authorization: [{ 25 | actor: 'user22222222', 26 | permission: 'active', 27 | }], 28 | data: { 29 | owner: 'user22222222', 30 | amount: '50000.0000 EOS', 31 | }, 32 | }] 33 | 34 | ### 购买REX 35 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio buyrex '["user11111111","50000.0000 EOS"]' -p user11111111 36 | 37 | actions: [{ 38 | account: 'eosio', 39 | name: 'buyrex', 40 | authorization: [{ 41 | actor: 'user11111111', 42 | permission: 'active', 43 | }], 44 | data: { 45 | owner: 'user11111111', 46 | amount: '50000.0000 EOS', 47 | }, 48 | }] 49 | 50 | ### 使用抵押资源购买REX 51 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio unstaketorex '["user22222222","user22222222","50.0000 EOS","50.0000 EOS"]' -p user22222222 52 | 53 | actions: [{ 54 | account: 'eosio', 55 | name: 'unstaketorex', 56 | authorization: [{ 57 | actor: 'user22222222', 58 | permission: 'active', 59 | }], 60 | data: { 61 | owner: 'user22222222', 62 | receiver: 'user22222222', 63 | from_net: '50.0000 EOS', 64 | from_cpu: '50.0000 EOS', 65 | }, 66 | }] 67 | 68 | 69 | ### 卖出REX 70 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio sellrex '["user11111111","500000000.0000 REX"]' -p user11111111 71 | 72 | actions: [{ 73 | account: 'eosio', 74 | name: 'sellrex', 75 | authorization: [{ 76 | actor: 'user11111111', 77 | permission: 'active', 78 | }], 79 | data: { 80 | from: 'user11111111', 81 | rex: '500000000.0000 REX', 82 | }, 83 | }] 84 | 85 | ### 取消订单 86 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio cnclrexorder '["user11111111"]' -p user11111111 87 | 88 | actions: [{ 89 | account: 'eosio', 90 | name: 'cnclrexorder', 91 | authorization: [{ 92 | actor: 'user11111111', 93 | permission: 'active', 94 | }], 95 | data: { 96 | owner: 'user11111111', 97 | }, 98 | }] 99 | 100 | 101 | ### 租赁CPU 102 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio rentcpu '["user22222222","user22222222","20.0000 EOS","0.0000 EOS"]' -p user22222222 103 | 104 | actions: [{ 105 | account: 'eosio', 106 | name: 'rentcpu', 107 | authorization: [{ 108 | actor: 'user22222222', 109 | permission: 'active', 110 | }], 111 | data: { 112 | from: 'user22222222', 113 | receiver: 'user22222222', 114 | loan_payment: '20.0000 EOS', 115 | loan_fund: '0.0000 EOS', 116 | }, 117 | }] 118 | 119 | ### 租赁NET 120 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio rentnet '["user22222222","user22222222","20.0000 EOS","0.0000 EOS"]' -p user22222222 121 | 122 | actions: [{ 123 | account: 'eosio', 124 | name: 'rentnet', 125 | authorization: [{ 126 | actor: 'user22222222', 127 | permission: 'active', 128 | }], 129 | data: { 130 | from: 'user22222222', 131 | receiver: 'user22222222', 132 | loan_payment: '20.0000 EOS', 133 | loan_fund: '0.0000 EOS', 134 | }, 135 | }] 136 | 137 | ### 存CPU贷款基金 138 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio fundcpuloan '["user22222222", "1", "20.0000 EOS"]' -p user22222222 139 | 140 | actions: [{ 141 | account: 'eosio', 142 | name: 'fundcpuloan', 143 | authorization: [{ 144 | actor: 'user22222222', 145 | permission: 'active', 146 | }], 147 | data: { 148 | from: 'user22222222', 149 | loan_num: '1', 150 | amount: '20.0000 EOS', 151 | }, 152 | }] 153 | ### 存NET贷款基金 154 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio fundnetloan '["user22222222", "1", "20.0000 EOS"]' -p user22222222 155 | 156 | actions: [{ 157 | account: 'eosio', 158 | name: 'fundnetloan', 159 | authorization: [{ 160 | actor: 'user22222222', 161 | permission: 'active', 162 | }], 163 | data: { 164 | from: 'user22222222', 165 | loan_num: '1', 166 | amount: '20.0000 EOS', 167 | }, 168 | }] 169 | 170 | ### 取回CPU贷款基金 171 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio defcpuloan '["user22222222", "1", "20.0000 EOS"]' -p user22222222 172 | 173 | actions: [{ 174 | account: 'eosio', 175 | name: 'defcpuloan', 176 | authorization: [{ 177 | actor: 'user22222222', 178 | permission: 'active', 179 | }], 180 | data: { 181 | from: 'user22222222', 182 | loan_num: '1', 183 | amount: '20.0000 EOS', 184 | }, 185 | }] 186 | ### 取回NET贷款基金 187 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 push action eosio defnetloan '["user22222222", "1", "20.0000 EOS"]' -p user22222222 188 | 189 | actions: [{ 190 | account: 'eosio', 191 | name: 'defnetloan', 192 | authorization: [{ 193 | actor: 'user22222222', 194 | permission: 'active', 195 | }], 196 | data: { 197 | from: 'user22222222', 198 | loan_num: '1', 199 | amount: '20.0000 EOS', 200 | }, 201 | }] 202 | 203 | 204 | 205 | ### 查看节点: 206 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 system listproducers 207 | 208 | ### 投票 209 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 system voteproducer prods user11111111 producer1111 producer1114 producer111f producer111h producer111p producer111w producer111b producer111c producer111d producer111e producer111g producer111j producer111k producer111l producer111q producer111r producer111z producer1113 producer111u producer111v producer111i 210 | 211 | actions: [{ 212 | account: 'eosio', 213 | name: 'voteproducer', 214 | authorization: [{ 215 | actor: 'user11111111', 216 | permission: 'active', 217 | }], 218 | data: { 219 | voter: 'user11111111', 220 | proxy: '', 221 | producers: [ 222 | "producer1111", 223 | "producer1114", 224 | "producer111f" 225 | ] 226 | }, 227 | }] 228 | 229 | 230 | ### 查看投票结果 231 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 get table eosio eosio voters -L user11111111 -l 1 232 | 233 | ### 购买REX: 价格: 234 | [total_rex*(total_lendable+amount)/total_lendable - total_rex] / amount 235 | ### 租赁CPU: 价格: 236 | [total_unlent*amount / (total_rent + amount)]/ amount 237 | 238 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 get table eosio eosio rexpool 239 | { 240 | "rows": [{ 241 | "version": 0, 242 | "total_lent": "0.0149 EOS", 已租出的EOS总量 243 | "total_unlent": "300.9851 EOS", 可出租的EOS总量 244 | "total_rent": "20001.0000 EOS", 总的租金=20000.0000(初始值) + 1.0000(实际) 245 | "total_lendable": "301.0000 EOS", 总的EOS量=total_lent+total_unlent 246 | "total_rex": "3000000.0000 REX", REX总量 247 | "namebid_proceeds": "0.0000 EOS", 248 | "loan_num": 1 249 | } 250 | ], 251 | "more": false 252 | } 253 | 254 | 255 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 get table eosio eosio rexfund -l 1 -L user11111111 256 | { 257 | "rows": [{ 258 | "version": 0, 259 | "owner": "user11111111", 260 | "balance": "400.0000 EOS" 充值但未花费的EOS量 261 | } 262 | ], 263 | "more": true 264 | } 265 | 266 | 267 | cleos --wallet-url http://localhost:6666 --url http://localhost:8000 get table eosio eosio rexbal -l 1 -L user11111111 268 | { 269 | "rows": [{ 270 | "version": 0, 271 | "owner": "user11111111", 272 | "vote_stake": "200.0000 EOS", 已花费的EOS量 273 | "rex_balance": "2000000.0000 REX", 用户REX持有量 274 | "matured_rex": 0, 275 | "rex_maturities": [{ 276 | "first": "2019-03-31T00:00:00", 解冻时间 277 | "second": "20000000000" 278 | } 279 | ] 280 | } 281 | ], 282 | "more": true 283 | } 284 | 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /src/fonts/SourceHanSansCN-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/src/fonts/SourceHanSansCN-Light.otf -------------------------------------------------------------------------------- /src/fonts/SourceHanSansCN-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/src/fonts/SourceHanSansCN-Medium.otf -------------------------------------------------------------------------------- /src/fonts/SourceHanSansCN-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etwallet/eosrex/f017e24986f36c920fb1184944fe82657136629d/src/fonts/SourceHanSansCN-Regular.otf -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face{ 3 | font-family: 'SourceHanSansCN-Light'; 4 | src:url('./fonts/SourceHanSansCN-Light.otf') format('otf') 5 | } 6 | body,p,span,div { 7 | font-family: "SourceHanSansCN-Light"; 8 | display:"flex"; 9 | background-color: "#F8F8F8" 10 | } 11 | 12 | #root, body, html { 13 | width: 100%; 14 | height: 100%; 15 | margin: 0; 16 | padding: 0; 17 | font-family: "SourceHanSansCN-Light"; 18 | -webkit-text-size-adjust: none; 19 | background-color: "#F8F8F8" 20 | } 21 | body :global(#root) { 22 | width: 100%; 23 | height: 100%; 24 | } 25 | 26 | input:-ms-input-placeholder { 27 | color: #D9D9D9; 28 | opacity: 1; 29 | } 30 | input::-webkit-input-placeholder { 31 | color: #D9D9D9; 32 | opacity: 1; 33 | } 34 | 35 | 36 | /* 列表上下边框 */ 37 | body :global(.am-list-body) { 38 | position: relative; 39 | background-color: #F8F8F8; 40 | border: none; 41 | } 42 | 43 | body :global(.am-list-header) { 44 | padding: 0 45 | } 46 | 47 | body :global(.am-modal-button-group-h .am-modal-button:first-child) { 48 | color: #B5B5B5; 49 | } 50 | 51 | body :global(.am-navbar-left) { 52 | padding-left: 0; 53 | } 54 | body :global(.am-navbar-light) { 55 | color: #323232; 56 | } 57 | 58 | body :global(.am-popover .am-popover-item-container) { 59 | justify-content: center; 60 | } 61 | 62 | 63 | /* 单行输入框 */ 64 | body :global(.am-list-item:not(:last-child) .am-list-line) { 65 | border: none; 66 | } 67 | 68 | /* 图片选择器 */ 69 | body :global(.am-image-picker-list) { 70 | padding: 10px 10px 1px; 71 | margin: 0; 72 | } 73 | 74 | body :global(.am-image-picker-list .am-flexbox .am-flexbox-item) { 75 | margin-left: 5px; 76 | margin-right: 5px; 77 | } 78 | body :global(.am-image-picker-list .am-flexbox) { 79 | margin-bottom: 10px; 80 | } 81 | body :global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-remove) { 82 | width: 20px; 83 | height: 20px; 84 | background-size: 20px auto; 85 | } 86 | 87 | 88 | body :global(.am-list-item .am-list-line .am-list-content) { 89 | display: flex; 90 | flex-direction: row 91 | } 92 | 93 | /* 长输入框 */ 94 | body :global(.am-textarea-has-count) { 95 | min-height: 30px; 96 | border: 1PX solid #D9D9D9; 97 | background: #F8F8F8; 98 | border-radius: 2px; 99 | padding: 0; 100 | } 101 | body :global(.am-textarea-control) { 102 | padding: 2px; 103 | } 104 | body :global(.am-textarea-control textarea) { 105 | font-size: 14px; 106 | } 107 | /* 单选按钮 */ 108 | body :global(.am-radio-item) { 109 | min-height: 30px; 110 | padding: 0; 111 | } 112 | body :global(.am-list .am-list-item.am-radio-item .am-list-line .am-list-extra .am-radio) { 113 | height: 30px; 114 | } 115 | body :global(.am-list .am-list-item.am-radio-item .am-list-line .am-list-extra .am-radio-inner) { 116 | top: 7.5px; 117 | } 118 | 119 | 120 | body :global(.am-list-item .am-input-label) { 121 | margin-right: 15px; 122 | } 123 | body :global(.am-list-item .am-list-line .am-list-extra) { 124 | padding-top: 2px; 125 | padding-bottom: 2px; 126 | } 127 | body :global(.am-list-item .am-list-line .am-list-content) { 128 | color: #888888; 129 | font-size: 15px; 130 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import dva from 'dva'; 2 | import createLoading from 'dva-loading'; 3 | import createHistory from 'history/createBrowserHistory'; 4 | import registerServiceWorker from './registerServiceWorker'; 5 | import './index.css'; 6 | 7 | const app = dva({ 8 | history: createHistory(), 9 | onError(e) { 10 | console.log(e); 11 | }, 12 | }); 13 | 14 | app.use(createLoading()); 15 | 16 | app.router(require('./router').default); 17 | 18 | app.start('#root'); 19 | 20 | registerServiceWorker(); 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/locales/en-US.js: -------------------------------------------------------------------------------- 1 | import enUS from 'antd-mobile/lib/locale-provider/en_US'; 2 | import appLocaleData from 'react-intl/locale-data/en'; 3 | import en from './en'; 4 | 5 | window.appLocale = { 6 | messages: {...en}, 7 | antd: enUS, 8 | locale: 'en-US', 9 | data: appLocaleData, 10 | } 11 | -------------------------------------------------------------------------------- /src/locales/en.js: -------------------------------------------------------------------------------- 1 | const en = { 2 | "index.slogn":"ETRobot" 3 | } 4 | export default en; 5 | -------------------------------------------------------------------------------- /src/locales/zh-CN.js: -------------------------------------------------------------------------------- 1 | import appLocaleData from 'react-intl/locale-data/zh'; 2 | import zh from './zh'; 3 | 4 | window.appLocale = { 5 | messages: {...zh}, 6 | antd: null, 7 | locale: 'zh-Hans-CN', 8 | data: appLocaleData, 9 | }; 10 | -------------------------------------------------------------------------------- /src/locales/zh.js: -------------------------------------------------------------------------------- 1 | const zh = { 2 | "index.slogn":"ET交易所", 3 | "index.intr":"全国首家开源、开放、透明去中心化交易所" 4 | } 5 | export default zh; 6 | -------------------------------------------------------------------------------- /src/models/commonModel.js: -------------------------------------------------------------------------------- 1 | import Request from '../utils/RequestUtil'; 2 | import { noAttentionPage, attentionPage, plazaPage, biggiePage,} from '../utils/Api'; 3 | import { Toast } from 'antd-mobile'; 4 | import Utils from '../utils/Utils' 5 | 6 | export default { 7 | namespace: 'common', 8 | 9 | state: { 10 | account: '', 11 | permission: 'active', 12 | eosBalance: '0.0000', 13 | delegated_eosBalance: '0.0000', 14 | cpuDelegated: '0.0000', 15 | netDelegated: '0.0000', 16 | network: { 17 | blockchain:'eos', 18 | protocol:'http', 19 | host:'api.fn.eosbixin.com', 20 | port:80, 21 | chainId:'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906' 22 | }, 23 | rexpool:{ 24 | total_lent: '0.0000 EOS', // 已出租的EOS总量 25 | total_unlent: '0.0000 EOS', // 可出租的EOS总量 26 | total_rent: '0.0000 EOS', // 总租金 27 | total_lendable: '0.0000', //总的EOS量 28 | total_rex: '0.0000 REX', // REX总量 29 | }, 30 | lent_percent: 0, //出租百分比 31 | isVoted: false, 32 | myVotes: [], 33 | }, 34 | 35 | effects: { 36 | // 登录 37 | *login({ payload, callback }, { select, call, put }) { 38 | try { 39 | const requiredFields={ 40 | accounts:[{protocol:"https", 41 | blockchain:"eos", 42 | host:"eosapi.big.game", 43 | port:8889, 44 | chainId:"aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906"}] 45 | }; 46 | let identity = yield window.scatter.getIdentity(requiredFields); 47 | if(window.scatter.identity && window.scatter.identity.accounts && window.scatter.identity.accounts.length>0){ 48 | let account = window.scatter.identity.accounts[0]; 49 | if(account.blockchain=="eos"){ 50 | 51 | 52 | yield put({ type: 'update', payload: {account: account.name, permission: account.authority}}); 53 | 54 | yield put({ type: 'getAccountInfo', payload: {account: account.name}}); 55 | 56 | yield put({ type: 'getRexInfo', payload: {}}); 57 | 58 | if(callback) callback(account); 59 | } 60 | }else{ 61 | // Toast.info("登录失败,请重新登录", 1); 62 | } 63 | } catch (error) { 64 | // Toast.info("登录失败,请重新登录", 1); 65 | console.log("+++++app/models/commonModel.js++++login:",JSON.stringify(error)); 66 | } 67 | }, 68 | 69 | // 获取账户信息 70 | *getAccountInfo({ payload, callback }, { select, call, put }) { 71 | try { 72 | let network = yield select(state => state.common.network) 73 | var eos = window.scatter.eos(network, window.Eos); 74 | 75 | let eosBalance = '0.0000'; 76 | let delegated_eosBalance = '0.0000'; 77 | let cpu_weight = '0.0000'; 78 | let net_weight = '0.0000'; 79 | 80 | let accountInfo = yield eos.getAccount(payload.account); 81 | if(accountInfo){ 82 | if(accountInfo.core_liquid_balance){ 83 | eosBalance = accountInfo.core_liquid_balance.replace("EOS", "").replace(" ", ""); 84 | } 85 | if(accountInfo.self_delegated_bandwidth){ 86 | if(accountInfo.self_delegated_bandwidth.cpu_weight) 87 | { 88 | cpu_weight = accountInfo.self_delegated_bandwidth.cpu_weight.replace("EOS", "").replace(" ", ""); 89 | } 90 | if(accountInfo.self_delegated_bandwidth.net_weight) 91 | { 92 | net_weight = accountInfo.self_delegated_bandwidth.net_weight.replace("EOS", "").replace(" ", ""); 93 | } 94 | delegated_eosBalance = (parseFloat(cpu_weight) + parseFloat(net_weight)).toFixed(4); 95 | } 96 | } 97 | 98 | let isVoted = false; // 是否已经投票过 99 | let myVotes = []; 100 | if(accountInfo && accountInfo.voter_info && accountInfo.voter_info.producers){ 101 | myVotes = accountInfo.voter_info.producers; 102 | if(myVotes && myVotes.length >= 21){ 103 | isVoted = true; 104 | } 105 | } 106 | yield put({ type: 'update', payload: {myVotes: myVotes, isVoted: isVoted, eosBalance: eosBalance,delegated_eosBalance:delegated_eosBalance, cpuDelegated: cpu_weight, netDelegated: net_weight}}); 107 | 108 | } catch (error) { 109 | console.log("+++++app/models/commonModel.js++++getAccountInfo-error:",JSON.stringify(error)); 110 | } 111 | }, 112 | 113 | // 获取REX信息 114 | *getRexInfo({ payload, callback }, { select, call, put }) { 115 | try { 116 | let network = yield select(state => state.common.network); 117 | var eos = window.scatter.eos(network, window.Eos); 118 | var obj = new Object(); 119 | obj.json = true; 120 | obj.code = 'eosio'; 121 | obj.scope = 'eosio'; 122 | obj.table = 'rexpool'; 123 | obj.limit = 1; 124 | let info = yield eos.getTableRows(obj); 125 | 126 | let rexpoolRemote = info.rows[0]; 127 | let rexpoolLocal = yield select(state => state.common.rexpool); 128 | let rexpool = {...rexpoolLocal, ...rexpoolRemote}; 129 | 130 | let lent_percent = 0; 131 | if(rexpool && rexpool.total_lent && rexpool.total_lendable) 132 | { 133 | let total_lent = Utils.sliceUnit(rexpool.total_lent); 134 | let total_lendable = Utils.sliceUnit(rexpool.total_lendable); 135 | // alert('total_lent = ' + total_lent + ' total_lendable = ' + total_lendable); 136 | let float_total_lent = parseFloat(total_lent).toFixed(4); 137 | let float_total_lendable = parseFloat(total_lendable).toFixed(4); 138 | lent_percent = (float_total_lent * 100 / float_total_lendable).toFixed(2); 139 | } 140 | yield put({ type: 'update', payload: {rexpool: rexpool,lent_percent: lent_percent} }); 141 | if(callback) callback(true); 142 | } catch (error) { 143 | console.log("+++++app/models/commonModel.js++++getRexInfo-error:",JSON.stringify(error)); 144 | if(callback) callback(false); 145 | } 146 | }, 147 | // 发送eos交易 148 | *sendEosAction({ payload, callback }, { select, call, put }) { 149 | try { 150 | let network = yield select(state => state.common.network); 151 | var eos = window.scatter.eos(network, window.Eos); 152 | let resp = yield eos.transaction({actions: payload.actions}); 153 | if(resp.transaction_id){ 154 | let account = yield select(state => state.common.account); 155 | yield put({ type: 'getAccountInfo', payload: {account: account}}); 156 | yield put({ type: 'getRexInfo', payload: {}}); 157 | } 158 | if(callback) callback(resp); 159 | } catch (error) { 160 | console.log("+++++app/models/commonModel.js++++sendEosAction-error:",JSON.stringify(error)); 161 | if(callback) callback(null); 162 | } 163 | }, 164 | //查询卖单 165 | *querySellRexInfo({ payload, callback }, { select, call, put }) { 166 | try { 167 | if(!payload.account){ 168 | if(callback) callback(null); 169 | return; 170 | } 171 | 172 | let network = yield select(state => state.common.network); 173 | var eos = window.scatter.eos(network, window.Eos); 174 | var obj = new Object(); 175 | obj.json = true; 176 | obj.code = 'eosio'; 177 | obj.scope = 'eosio'; 178 | obj.table = 'rexqueue'; 179 | obj.limit = 1; 180 | obj.lower_bound = payload.account; 181 | // obj.table_key = 'owner'; 182 | let resp = yield eos.getTableRows(obj); 183 | 184 | if(callback) callback(resp); 185 | } catch (error) { 186 | console.log("+++++app/models/common.js++++querySellRexInfo-error:",JSON.stringify(error)); 187 | if(callback) callback(null); 188 | } 189 | }, 190 | //查询可提币余额 191 | *queryWithdrawInfo({ payload, callback }, { select, call, put }) { 192 | try { 193 | if(!payload.account){ 194 | if(callback) callback(null); 195 | return; 196 | } 197 | 198 | let network = yield select(state => state.common.network); 199 | var eos = window.scatter.eos(network, window.Eos); 200 | var obj = new Object(); 201 | obj.json = true; 202 | obj.code = 'eosio'; 203 | obj.scope = 'eosio'; 204 | obj.table = 'rexfund'; 205 | obj.limit = 1; 206 | obj.lower_bound = payload.account; 207 | // obj.table_key = 'owner'; 208 | let resp = yield eos.getTableRows(obj); 209 | 210 | if(callback) callback(resp); 211 | } catch (error) { 212 | console.log("+++++app/models/common.js++++queryWithdrawInfo-error:",JSON.stringify(error)); 213 | if(callback) callback(null); 214 | } 215 | }, 216 | 217 | }, 218 | 219 | reducers: { 220 | update(state, action) { 221 | return { ...state, ...action.payload }; 222 | }, 223 | 224 | }, 225 | 226 | subscriptions: { 227 | 228 | } 229 | }; 230 | -------------------------------------------------------------------------------- /src/models/index.js: -------------------------------------------------------------------------------- 1 | import commonModel from './commonModel'; 2 | import rexModel from './rexModel'; 3 | import voteModel from './voteModel'; 4 | 5 | const models = [ 6 | commonModel, 7 | rexModel, 8 | voteModel, 9 | ] 10 | export default models; -------------------------------------------------------------------------------- /src/models/rexModel.js: -------------------------------------------------------------------------------- 1 | import Request from '../utils/RequestUtil'; 2 | import { noAttentionPage, attentionPage, plazaPage, biggiePage,} from '../utils/Api'; 3 | import { Toast } from 'antd-mobile'; 4 | import Utils from '../utils/Utils' 5 | 6 | export default { 7 | namespace: 'rex', 8 | 9 | state: { 10 | myRexInfo:{ 11 | total_rex: 0, // 总rex 12 | sell_available_rex: 0, // 可卖的rex 13 | }, 14 | 15 | }, 16 | 17 | effects: { 18 | // 获取REX信息 19 | *getMyRexInfo({ payload, callback }, { select, call, put }) { 20 | try { 21 | if(!payload.account){ 22 | return; 23 | } 24 | let network = yield select(state => state.common.network); 25 | var eos = window.scatter.eos(network, window.Eos); 26 | var obj = new Object(); 27 | obj.json = true; 28 | obj.code = 'eosio'; 29 | obj.scope = 'eosio'; 30 | obj.table = 'rexbal'; 31 | obj.limit = 1; 32 | obj.lower_bound = payload.account; 33 | let info = yield eos.getTableRows(obj); 34 | 35 | let rexInfo = info.rows[0]; 36 | if(rexInfo && rexInfo.owner != payload.account){ 37 | return; 38 | } 39 | 40 | rexInfo.sell_available_rex = 0; 41 | rexInfo.total_rex = 0; 42 | if(rexInfo.rex_balance){ 43 | rexInfo.total_rex = Utils.sliceUnit(rexInfo.rex_balance); 44 | rexInfo.sell_available_rex = rexInfo.total_rex; 45 | } 46 | 47 | if(rexInfo.rex_maturities){ 48 | rexInfo.rex_maturities.forEach(item => { 49 | try { 50 | if(Utils.isTimeExpire(new Date(item.first).valueOf())){ 51 | return; 52 | } 53 | rexInfo.sell_available_rex = (parseFloat(rexInfo.sell_available_rex) - (item.second/10000).toFixed(4)).toFixed(4); 54 | } catch (error) { 55 | 56 | } 57 | }); 58 | } 59 | 60 | yield put({ type: 'update', payload: {myRexInfo: rexInfo} }); 61 | } catch (error) { 62 | console.log("+++++app/models/rexModel.js++++getMyRexInfo-error:",JSON.stringify(error)); 63 | } 64 | }, 65 | }, 66 | 67 | reducers: { 68 | update(state, action) { 69 | return { ...state, ...action.payload }; 70 | }, 71 | 72 | }, 73 | 74 | subscriptions: { 75 | 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /src/models/voteModel.js: -------------------------------------------------------------------------------- 1 | import Request from '../utils/RequestUtil'; 2 | import { noAttentionPage, attentionPage, plazaPage, biggiePage,} from '../utils/Api'; 3 | import { Toast } from 'antd-mobile'; 4 | import Utils from '../utils/Utils' 5 | 6 | export default { 7 | namespace: 'vote', 8 | 9 | state: { 10 | myVoteInfo:[], 11 | isVoted: false, // 是否进行投票过 12 | producers: [], // 节点列表 13 | }, 14 | 15 | effects: { 16 | // 获取投票信息 17 | *getMyVoteInfo({ payload, callback }, { select, call, put }) { 18 | try { 19 | if(!payload.account){ 20 | return; 21 | } 22 | let network = yield select(state => state.common.network); 23 | var eos = window.scatter.eos(network, window.Eos); 24 | var obj = new Object(); 25 | obj.json = true; 26 | obj.code = 'eosio'; 27 | obj.scope = 'eosio'; 28 | obj.table = 'voters'; 29 | obj.limit = 1; 30 | obj.lower_bound = payload.account; 31 | obj.table_key = 'owner'; 32 | let info = yield eos.getTableRows(obj); 33 | 34 | let voteInfo = info.rows; 35 | yield put({ type: 'update', payload: {myVoteInfo: voteInfo, isVoted:true} }); 36 | } catch (error) { 37 | console.log("+++++app/models/voteModel.js++++getMyVoteInfo-error:",JSON.stringify(error)); 38 | } 39 | }, 40 | 41 | /** 42 | * 根据排名获取投票列表 43 | */ 44 | *listProducers({ payload, callback }, { select, call, put }) { 45 | try { 46 | let network = yield select(state => state.common.network); 47 | var eos = window.scatter.eos(network, window.Eos); 48 | var obj = new Object(); 49 | obj.json = true; 50 | obj.code = 'eosio'; 51 | obj.scope = 'eosio'; 52 | obj.table = 'producers'; 53 | obj.limit = 100; 54 | obj.index_position = 2; 55 | obj.key_type = 'float64' 56 | let info = yield eos.getTableRows(obj); 57 | 58 | let producers = info.rows; 59 | 60 | let myVotes = yield select(state => state.common.myVotes); 61 | producers.forEach((p) => { 62 | p.isSelect = false; 63 | if(myVotes && myVotes.includes(p.owner)){ 64 | p.isSelect = true; 65 | } 66 | }); 67 | 68 | // alert("listProducers: " + JSON.stringify(producers)); 69 | 70 | yield put({ type: 'update', payload: {producers: producers} }); 71 | if(callback) callback(producers); 72 | } catch (error) { 73 | console.log("+++++app/models/voteModel.js++++listProducers-error:",JSON.stringify(error)); 74 | if(callback) callback([]); 75 | } 76 | }, 77 | }, 78 | 79 | reducers: { 80 | update(state, action) { 81 | return { ...state, ...action.payload }; 82 | }, 83 | 84 | }, 85 | 86 | subscriptions: { 87 | 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | const isLocalhost = Boolean( 12 | window.location.hostname === 'localhost' || 13 | // [::1] is the IPv6 localhost address. 14 | window.location.hostname === '[::1]' || 15 | // 127.0.0.1/8 is considered localhost for IPv4. 16 | window.location.hostname.match( 17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 18 | ) 19 | ); 20 | 21 | export default function register() { 22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 23 | // The URL constructor is available in all browsers that support SW. 24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 25 | if (publicUrl.origin !== window.location.origin) { 26 | // Our service worker won't work if PUBLIC_URL is on a different origin 27 | // from what our page is served on. This might happen if a CDN is used to 28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 29 | return; 30 | } 31 | 32 | window.addEventListener('load', () => { 33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 34 | 35 | if (!isLocalhost) { 36 | // Is not local host. Just register service worker 37 | registerValidSW(swUrl); 38 | } else { 39 | // This is running on localhost. Lets check if a service worker still exists or not. 40 | checkValidServiceWorker(swUrl); 41 | } 42 | }); 43 | } 44 | } 45 | 46 | function registerValidSW(swUrl) { 47 | navigator.serviceWorker 48 | .register(swUrl) 49 | .then(registration => { 50 | registration.onupdatefound = () => { 51 | const installingWorker = registration.installing; 52 | installingWorker.onstatechange = () => { 53 | if (installingWorker.state === 'installed') { 54 | if (navigator.serviceWorker.controller) { 55 | // At this point, the old content will have been purged and 56 | // the fresh content will have been added to the cache. 57 | // It's the perfect time to display a "New content is 58 | // available; please refresh." message in your web app. 59 | console.log('New content is available; please refresh.'); 60 | } else { 61 | // At this point, everything has been precached. 62 | // It's the perfect time to display a 63 | // "Content is cached for offline use." message. 64 | console.log('Content is cached for offline use.'); 65 | } 66 | } 67 | }; 68 | }; 69 | }) 70 | .catch(error => { 71 | console.error('Error during service worker registration:', error); 72 | }); 73 | } 74 | 75 | function checkValidServiceWorker(swUrl) { 76 | // Check if the service worker can be found. If it can't reload the page. 77 | fetch(swUrl) 78 | .then(response => { 79 | // Ensure service worker exists, and that we really are getting a JS file. 80 | if ( 81 | response.status === 404 || 82 | response.headers.get('content-type').indexOf('javascript') === -1 83 | ) { 84 | // No service worker found. Probably a different app. Reload the page. 85 | navigator.serviceWorker.ready.then(registration => { 86 | registration.unregister().then(() => { 87 | window.location.reload(); 88 | }); 89 | }); 90 | } else { 91 | // Service worker found. Proceed as normal. 92 | registerValidSW(swUrl); 93 | } 94 | }) 95 | .catch(() => { 96 | console.log( 97 | 'No internet connection found. App is running in offline mode.' 98 | ); 99 | }); 100 | } 101 | 102 | export function unregister() { 103 | if ('serviceWorker' in navigator) { 104 | navigator.serviceWorker.ready.then(registration => { 105 | registration.unregister(); 106 | }); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Router, Route, Switch } from 'dva/router'; 3 | import Dynamic from 'dva/dynamic'; 4 | import { LocaleProvider } from 'antd-mobile'; 5 | import { addLocaleData, IntlProvider } from 'react-intl'; 6 | import store from 'storejs'; 7 | 8 | let lan = store.get("language"); 9 | if(!lan){ 10 | let language = navigator.language; 11 | if(language){ 12 | lan = language.split('-')[0]; 13 | }else{ 14 | lan="en"; 15 | } 16 | } 17 | switch(lan){ 18 | case 'en': 19 | require("./locales/en-US"); 20 | break; 21 | case 'zh': 22 | require("./locales/zh-CN"); 23 | break; 24 | default: 25 | require("./locales/en-US"); 26 | break; 27 | } 28 | const appLocale = window.appLocale; 29 | addLocaleData(appLocale.data); 30 | 31 | export default function RouterConfig({history,app}) { 32 | const Index = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/Index')}); 33 | const GameDescription = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/GameDescription')}); 34 | const BuyandSell = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/BuyandSell')}); 35 | const DetailsList = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/DetailsList')}); 36 | const Withdraw = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/Withdraw')}); 37 | const NodeVoting = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/NodeVoting')}); 38 | const MyRexDetails = Dynamic({app,models:()=>[require("./models/")],component:()=>import('./routes/MyRexDetails')}); 39 | 40 | return ( 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/routes/BuyandSell.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Toast, PullToRefresh, ListView, Button, Modal, InputItem, List, WhiteSpace, SegmentedControl} from 'antd-mobile'; 3 | import { injectIntl } from 'react-intl'; 4 | import { connect } from 'dva'; 5 | import Auto from '../utils/Auto' 6 | import {routerRedux} from 'dva/router'; 7 | import Utils from '../utils/Utils' 8 | import {formatEosQua} from '../utils/FormatUtil'; 9 | 10 | require('moment/locale/zh-cn'); 11 | var ScreenWidth = window.screen.width 12 | var ScreenHeight = window.screen.height 13 | const alert = Modal.alert; 14 | 15 | var TransType = { 16 | BUY: 0, 17 | SELL: 1, 18 | }; 19 | 20 | class BuyandSell extends React.Component { 21 | constructor(props) { 22 | super(props); 23 | const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 }); 24 | this.state = { 25 | dataSource, 26 | isSwitch: true, 27 | values: ['购买', '出售'], 28 | netQuantity: '0.0000', 29 | cpuQuantity: '0.0000', 30 | quantity: '0.0000', 31 | quantity_rex: '0.0000', 32 | transType: TransType.BUY, 33 | actionsList: [ 34 | {actions: this.getBuyActions}, 35 | {actions: this.getSellActions}, 36 | ], 37 | defaultProducers:[ 38 | 'argentinaeos', 39 | 'atticlabeosb', 40 | 'bitfinexeos1', 41 | 'cochainworld', 42 | 'eos42freedom', 43 | 'eosauthority', 44 | 'eosbeijingbp', 45 | 'eosbixinboot', 46 | 'eoscannonchn', 47 | 'eosflytomars', 48 | 'eoshuobipool', 49 | 'eosiosg11111', 50 | 'eoslaomaocom', 51 | 'eosliquideos', 52 | 'eosnewyorkio', 53 | 'eosriobrazil', 54 | 'eosswedenorg', 55 | 'helloeoscnbp', 56 | 'jedaaaaaaaaa', 57 | 'starteosiobp', 58 | 'zbeosbp11111', 59 | // "producer1111", 60 | // "producer1114", 61 | // "producer111f" 62 | ], 63 | exchangeradio: 0, //兑换比例 64 | selectedIndex: 0, 65 | }; 66 | } 67 | 68 | componentDidMount() { 69 | Utils.dispatchActiionData(this, { type: 'rex/getMyRexInfo', payload:{account: this.props.account}}); 70 | this.calcExchangRadio(); 71 | } 72 | 73 | onlease = () => { 74 | this.props.dispatch(routerRedux.push({pathname: '/', query: { }})) 75 | } 76 | 77 | description = () => { 78 | this.props.dispatch(routerRedux.push({pathname: '/GameDescription', query: {lease:false}})) 79 | } 80 | 81 | onChange = (e) => { 82 | this.setState({selectedIndex: e.nativeEvent.selectedSegmentIndex}) 83 | } 84 | 85 | onValueChange = (value) => { 86 | if(value == this.state.values[1]){ 87 | this.setState({transType: TransType.SELL}) 88 | }else{ 89 | this.setState({transType: TransType.BUY}) 90 | } 91 | } 92 | 93 | onBuySellList = () => { 94 | let isBuySell = (this.state.transType == TransType.BUY) ? true : false; 95 | localStorage.setItem('buy_sell', isBuySell); 96 | this.props.dispatch(routerRedux.push({pathname: '/DetailsList', query: { isBuySell: isBuySell }})) 97 | } 98 | 99 | onNodeVoting = () => { 100 | this.props.dispatch(routerRedux.push({pathname: '/NodeVoting', query: { }})) 101 | } 102 | 103 | calcExchangRadio(){ 104 | let val_price = 0; 105 | try { 106 | let total_rex = Utils.sliceUnit(this.props.rexpool.total_rex); 107 | let total_lendable = Utils.sliceUnit(this.props.rexpool.total_lendable); 108 | let float_total_rex = parseFloat(total_rex); 109 | let float_total_lendable = parseFloat(total_lendable); 110 | let amount = 1.0000; 111 | let val = (float_total_lendable + amount).toFixed(4); 112 | 113 | let tmp = (float_total_rex * val).toFixed(4); 114 | let tmp1 = (tmp/float_total_lendable).toFixed(4); 115 | let tmp2 = (tmp1 - float_total_rex).toFixed(4); 116 | val_price = (tmp2/amount).toFixed(4); 117 | } catch (error) { 118 | val_price = 0; 119 | } 120 | this.setState({exchangeradio:val_price}); 121 | } 122 | //查询冻结的 EOS 123 | queryWithdrawAmount = async () => { 124 | let tmp_amount = 0.0000; 125 | let resp = await Utils.dispatchActiionData(this, { type: 'common/queryWithdrawInfo', payload:{account: this.props.account}}); 126 | if(resp && resp.rows){ 127 | resp.rows.forEach(function(val,index){ 128 | if(val.balance){ 129 | let amount = 0.0000; 130 | try { 131 | let s3 = Utils.sliceUnit(val.balance); 132 | amount = parseFloat(s3).toFixed(4); 133 | } catch (error) { 134 | amount = 0.0000; 135 | } 136 | tmp_amount = amount; 137 | return ; 138 | } 139 | }); 140 | } 141 | console.log('resp tmp_amount',tmp_amount); 142 | return tmp_amount; 143 | } 144 | withdraw = async () => { 145 | let tmp_amount = await this.queryWithdrawAmount(); 146 | if(tmp_amount < 0.0001){ 147 | Toast.info("没有冻结的币,无需提币"); 148 | return ; 149 | } 150 | this.props.dispatch(routerRedux.push({pathname: '/Withdraw', query: {balance: tmp_amount}})) 151 | } 152 | auto_sendWithdraw = async (amount) => { 153 | try { 154 | let actions = [{ 155 | account: 'eosio', 156 | name: 'withdraw', 157 | authorization: [{ 158 | actor: this.props.account, 159 | permission: this.props.permission, 160 | }], 161 | data: { 162 | owner: this.props.account, 163 | amount: formatEosQua(amount + ' EOS'), 164 | }, 165 | }]; 166 | console.log('actions=',JSON.stringify(actions)); 167 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 168 | console.log('resp =',JSON.stringify(resp)); 169 | if(resp){ 170 | Utils.dispatchActiionData(this, { type: 'common/getAccountInfo', payload:{account: this.props.account}}); 171 | Toast.info("交易成功"); 172 | }else{ 173 | Toast.info("提币失败"); 174 | } 175 | } catch (error) { 176 | console.log('err=',JSON.stringify(error)); 177 | } 178 | } 179 | 180 | 181 | doTrans = async (transType) => { 182 | try { 183 | let quantity; 184 | let banlance; 185 | if(transType == TransType.BUY){ 186 | quantity = parseFloat(this.state.quantity); 187 | let cpuQuantity = parseFloat(this.state.cpuQuantity); 188 | let netQuantity = parseFloat(this.state.netQuantity); 189 | banlance = parseFloat(this.state.isSwitch ? this.props.eosBalance :this.props.delegated_eosBalance); 190 | if(this.state.isSwitch){ 191 | if(quantity < 0.0001){ 192 | Toast.info('购买数量错误'); 193 | return ; 194 | } 195 | }else{ 196 | if(cpuQuantity < 0.0001 && netQuantity < 0.0001){ 197 | Toast.info('购买数量错误'); 198 | return ; 199 | } 200 | } 201 | 202 | }else{ 203 | quantity = parseFloat(this.state.quantity_rex); 204 | banlance = parseFloat(this.props.myRexInfo.total_rex); 205 | if(quantity < 0.0001){ 206 | Toast.info('出售数量错误'); 207 | return ; 208 | } 209 | } 210 | if(quantity > banlance){ 211 | Toast.info('余额不足'); 212 | return ; 213 | } 214 | 215 | if(this.props.isVoted){ // 投过票了 216 | let rexTransActions = this.getRexTransActions(); 217 | let resp = await this.doEosTransact(rexTransActions); 218 | if(resp){ 219 | console.log('doEosTransact+++++'); 220 | // if(this.state.transType == TransType.SELL){ 221 | //卖了REX,自动发起提币 222 | // setTimeout(async () => { 223 | // let tmp_amount = await this.queryWithdrawAmount(); 224 | // console.log('tmp_amount 11',tmp_amount); 225 | // if(tmp_amount >= 0.0001){ 226 | // console.log('tmp_amount 22'); 227 | // // resp = await this.auto_sendWithdraw('' + tmp_amount); 228 | // resp = await this.auto_sendWithdraw('0.1000'); 229 | // } 230 | // }, 1000); 231 | // } 232 | Toast.info('交易成功'); 233 | }else{ 234 | Toast.info('交易失败'); 235 | } 236 | return; 237 | } 238 | 239 | // 还没投过票 240 | Modal.alert('温馨提示',
在进行买卖REX之前,您必须要对至少21个节点投过票或代理投票,我们已经帮您进行了默认的节点投票。
, [ 241 | { text: '高级设置 >', onPress: () => {this.onNodeVoting()}}, 242 | { text: '确定', onPress: () => this.doVoteAndRexTrans() }, 243 | ]) 244 | } catch (error) { 245 | 246 | } 247 | } 248 | 249 | getdefaultVoteActions = () => { 250 | let actions = [{ 251 | account: 'eosio', 252 | name: 'voteproducer', 253 | authorization: [{ 254 | actor: this.props.account, 255 | permission: this.props.permission, 256 | }], 257 | data: { 258 | voter: this.props.account, 259 | proxy: '', 260 | producers: this.state.defaultProducers, 261 | }, 262 | }]; 263 | 264 | return actions; 265 | } 266 | 267 | // 使用抵押资源购买rex 268 | getBuyByStakeActions(){ 269 | let actions = [{ 270 | account: 'eosio', 271 | name: 'unstaketorex', 272 | authorization: [{ 273 | actor: this.props.account, 274 | permission: this.props.permission, 275 | }], 276 | data: { 277 | owner: this.props.account, 278 | receiver: this.props.account, 279 | from_net: formatEosQua(this.state.netQuantity + ' EOS'), 280 | from_cpu: formatEosQua(this.state.cpuQuantity + ' EOS'), 281 | }, 282 | }]; 283 | 284 | return actions; 285 | } 286 | 287 | // 使用余额购买rex 288 | getBuyByBalanceActions(){ 289 | let actions = [{ 290 | account: 'eosio', 291 | name: 'deposit', 292 | authorization: [{ 293 | actor: this.props.account, 294 | permission: this.props.permission, 295 | }], 296 | data: { 297 | owner: this.props.account, 298 | amount: formatEosQua(this.state.quantity + ' EOS'), 299 | }, 300 | }, 301 | { 302 | account: 'eosio', 303 | name: 'buyrex', 304 | authorization: [{ 305 | actor: this.props.account, 306 | permission: this.props.permission, 307 | }], 308 | data: { 309 | from: this.props.account, 310 | amount: formatEosQua(this.state.quantity + ' EOS'), 311 | }, 312 | }]; 313 | 314 | return actions; 315 | } 316 | 317 | /** 318 | * 买rex 319 | */ 320 | getBuyActions = () => { 321 | if(this.state.isSwitch){ // 使用余额购买rex 322 | return this.getBuyByBalanceActions(); 323 | } 324 | 325 | return this.getBuyByStakeActions(); 326 | } 327 | 328 | /** 329 | * 卖rex 330 | */ 331 | getSellActions = () => { 332 | let actions = [{ 333 | account: 'eosio', 334 | name: 'sellrex', 335 | authorization: [{ 336 | actor: this.props.account, 337 | permission: this.props.permission, 338 | }], 339 | data: { 340 | from: this.props.account, 341 | rex: formatEosQua(this.state.quantity_rex + ' REX'), 342 | }, 343 | }, 344 | ] 345 | 346 | return actions; 347 | } 348 | 349 | onQuantityRex = () => { 350 | this.setState({quantity_rex: this.props.myRexInfo.sell_available_rex}) 351 | } 352 | 353 | getRexTransActions = () => { 354 | let actions = this.state.actionsList[this.state.transType].actions(); 355 | return actions; 356 | } 357 | 358 | doVoteAndRexTrans = () => { 359 | let voteActions = this.getdefaultVoteActions(); 360 | let rexTransActions = this.getRexTransActions(); 361 | let actions = voteActions.concat(rexTransActions); 362 | this.doEosTransact(actions); 363 | } 364 | 365 | async doEosTransact(actions){ 366 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 367 | return resp; 368 | } 369 | 370 | showMyRexDetails = () => { 371 | if(!this.props.myRexInfo.rex_maturities || this.props.myRexInfo.rex_maturities.length == 0){ 372 | Modal.alert('温馨提示',
您没有冻结的REX
, [ 373 | { text: '关闭', onPress: () => {}}, 374 | ]); 375 | return; 376 | } 377 | this.props.dispatch(routerRedux.push({pathname: '/MyRexDetails', query: { }})) 378 | } 379 | 380 | render() { 381 | return (
382 |
383 |
384 |

总量(REX)

385 | 386 |
387 |
388 |

{Utils.sliceUnit(this.props.rexpool.total_rex)}

389 |
390 |

REX趋势

391 | 392 |
393 |
394 |
395 | 396 | 397 |
398 |
399 |

账户信息:{this.props.account}

400 |
403 | 404 | 405 | 兑换比例: 406 | 1 EOS ≈ {this.state.exchangeradio} REX 407 | 408 | 409 | 我的REX: 410 | {this.props.myRexInfo.total_rex} REX 411 | 详情 412 | 413 | 414 |
415 | 416 | 417 |
418 |
419 |
420 | 421 | 422 |
423 | {this.state.transType == TransType.BUY ? 424 |
425 |
426 | {this.state.isSwitch ? 427 |

我的余额:{this.props.eosBalance} EOS

428 | : 429 |
430 |

抵押资源:{this.props.delegated_eosBalance} EOS

431 |

{'(net:' + this.props.netDelegated + ' cpu:' + this.props.cpuDelegated + ')'}

432 |
433 | } 434 | 435 |
436 | {this.state.isSwitch ? 437 |
438 |
439 |
440 | this.setState({ quantity: Utils.chkEosQuantity(quantity)})} >购买数量: 441 | 442 |
443 |
444 | : 445 |
446 |
447 |
448 | this.setState({ netQuantity: Utils.chkEosQuantity(quantity)})} >使用net: 449 | 450 |
451 | 452 |
453 |
454 | this.setState({ cpuQuantity: Utils.chkEosQuantity(quantity)})} >使用cpu: 455 | 456 |
457 |
458 | } 459 | 460 |
461 |
462 | : 463 |
464 |
465 | this.setState({ quantity_rex: Utils.chkEosQuantity(quantity_rex)})} >出售数量: 466 | 467 |
468 |
469 |
470 |

可卖数量:{this.props.myRexInfo.sell_available_rex} REX

471 |
472 |
473 |
474 | } 475 |
476 | 477 | {(this.state.transType == TransType.BUY) && 478 |
479 |

订单确认:

480 |
花费{this.state.isSwitch ? this.state.quantity : parseFloat(this.state.netQuantity) + parseFloat(this.state.cpuQuantity)} EOS,为您兑换{((this.state.isSwitch ? parseFloat(this.state.quantity) : parseFloat(this.state.netQuantity) + parseFloat(this.state.cpuQuantity)) * this.state.exchangeradio).toFixed(4)} REX
481 |
} 482 | 483 |
484 | 486 |
487 | 488 |
489 | 491 |
492 |
) 493 | } 494 | } 495 | 496 | export default connect(({ common, rex }) => ({ ...common, ...rex }))(injectIntl(BuyandSell)); 497 | 498 | const styles = { 499 | rootDiv:{ 500 | width: ScreenWidth, 501 | height: ScreenHeight, 502 | background:"#F8F8F8", 503 | boxSizing: 'border-box', 504 | }, 505 | 506 | headtopout: { 507 | display:"flex", 508 | flexDirection: 'row', 509 | alignItems: 'center', 510 | height: Auto.WHT(88), 511 | paddingLeft: Auto.WHT(30), 512 | paddingRight: Auto.WHT(30), 513 | }, 514 | headtoptext: { 515 | flex: 1, 516 | color: '#000000', 517 | fontSize: Auto.WHT(34), 518 | lineHeight: Auto.WHT(42), 519 | }, 520 | headtopbtn: { 521 | width: Auto.WHT(164), 522 | height: Auto.WHT(60), 523 | lineHeight: Auto.WHT(60), 524 | background: '#FFFFFF', 525 | border: '1px #108EE9 solid', 526 | textDecoration: 'none', 527 | borderRadius: Auto.WHT(6), 528 | fontSize: Auto.WHT(26), 529 | color: '#108EE9', 530 | }, 531 | headbottomout: { 532 | display: 'flex', 533 | flexDirection: 'row', 534 | alignItems: 'center', 535 | justifyContent: 'space-between', 536 | padding: Auto.WHT(30), 537 | }, 538 | headbottomleft: { 539 | color: '#000000', 540 | fontSize: Auto.WHT(48), 541 | lineHeight: Auto.WHT(67), 542 | paddingBottom: Auto.WHT(22), 543 | }, 544 | headbottomright: { 545 | display: 'flex', 546 | flexDirection: 'row', 547 | alignItems: 'center', 548 | }, 549 | headbottomtext: { 550 | color: '#888888', 551 | fontSize: Auto.WHT(32), 552 | lineHeight: Auto.WHT(45), 553 | }, 554 | headbottomimg: { 555 | width: Auto.WHT(16), 556 | height: Auto.WHT(26), 557 | marginLeft: Auto.WHT(30) 558 | }, 559 | 560 | centerDiv: { 561 | display: 'flex', 562 | flexDirection: 'column', 563 | background: '#FFFFFF', 564 | }, 565 | centertopout:{ 566 | height: Auto.WHT(110), 567 | display:"flex", 568 | flexDirection: 'row', 569 | alignItems: 'center', 570 | justifyContent: 'space-between', 571 | borderBottom: '1px solid #DDDDDD', 572 | }, 573 | centertoptext: { 574 | flex: 1, 575 | color: '#000000', 576 | fontSize: Auto.WHT(34), 577 | lineHeight: Auto.WHT(42), 578 | paddingLeft: Auto.WHT(30), 579 | }, 580 | graytext: { 581 | flex: 1, 582 | color: 'gray', 583 | fontSize: Auto.WHT(30), 584 | lineHeight: Auto.WHT(42), 585 | paddingLeft: Auto.WHT(30), 586 | }, 587 | centertopbtn: { 588 | border: 'none', 589 | borderRadius: 0, 590 | color: '#D9D9D9', 591 | padding: '0 0.4rem', 592 | height: Auto.WHT(36), 593 | textDecoration: 'none', 594 | }, 595 | reportimg: { 596 | width: Auto.WHT(30), 597 | height: Auto.WHT(30), 598 | margin: 0, 599 | }, 600 | centerbottom: { 601 | color: '#888888', 602 | fontSize: Auto.WHT(28), 603 | }, 604 | centerbottom1: { 605 | display: 'flex', 606 | flex: 1, 607 | color: '#888888', 608 | fontSize: Auto.WHT(28), 609 | }, 610 | rexDetail: { 611 | 612 | color: '#108EE9', 613 | fontSize: Auto.WHT(28), 614 | }, 615 | listDiv: { 616 | display: 'flex', 617 | flexDirection: 'column', 618 | background: '#FFFFFF', 619 | }, 620 | sellbtn: { 621 | flex: 1, 622 | background: 'transparent', 623 | border: 'none', 624 | textDecoration: 'none', 625 | borderRadius: 0, 626 | fontSize: Auto.WHT(28), 627 | color: '#BBBBBB', 628 | }, 629 | listitemout: { 630 | display: 'flex', 631 | flexDirection: 'row', 632 | alignItems: 'center', 633 | height: Auto.WHT(110), 634 | paddingRight: Auto.WHT(30), 635 | }, 636 | listbtn: { 637 | width: Auto.WHT(112), 638 | height: Auto.WHT(60), 639 | lineHeight: Auto.WHT(60), 640 | background: '#108EE9', 641 | border: 'none', 642 | textDecoration: 'none', 643 | borderRadius: Auto.WHT(6), 644 | fontSize: Auto.WHT(26), 645 | color: '#FFFFFF', 646 | 647 | }, 648 | ordertext: { 649 | color: '#000000', 650 | fontSize: Auto.WHT(28), 651 | paddingTop: Auto.WHT(10), 652 | paddingBottom: Auto.WHT(10), 653 | }, 654 | orderout: { 655 | color: '#888888', 656 | fontSize: Auto.WHT(28), 657 | lineHeight: Auto.WHT(40), 658 | }, 659 | 660 | footDiv: { 661 | width: ScreenWidth, 662 | boxSizing: 'border-box', 663 | paddingTop: Auto.WHT(40), 664 | paddingLeft: Auto.WHT(30), 665 | paddingRight: Auto.WHT(30), 666 | paddingBottom: Auto.WHT(40), 667 | }, 668 | footbtn: { 669 | width: '100%', 670 | border: 'none', 671 | color: '#FFFFFF', 672 | height: Auto.WHT(94), 673 | background: '#108EE9', 674 | textDecoration: 'none', 675 | fontSize: Auto.WHT(36), 676 | lineHeight: Auto.WHT(94), 677 | borderRadius: Auto.WHT(10), 678 | }, 679 | 680 | footDivWithdraw: { 681 | width: ScreenWidth, 682 | boxSizing: 'border-box', 683 | paddingTop: Auto.WHT(15), 684 | paddingLeft: Auto.WHT(30), 685 | paddingRight: Auto.WHT(30), 686 | paddingBottom: Auto.WHT(40), 687 | }, 688 | footbtnWithdraw: { 689 | width: '100%', 690 | border: '1px #108EE9 solid', 691 | color: '#108EE9', 692 | height: Auto.WHT(94), 693 | background: '#FFFFFF', 694 | textDecoration: 'none', 695 | fontSize: Auto.WHT(36), 696 | lineHeight: Auto.WHT(94), 697 | borderRadius: Auto.WHT(10), 698 | }, 699 | 700 | listitemout11: { 701 | display: 'flex', 702 | flexDirection: 'row', 703 | alignItems: 'center', 704 | justifyContent: 'center', 705 | height: Auto.WHT(88), 706 | // paddingRight: Auto.WHT(30), 707 | }, 708 | centertoptext11: { 709 | flex: 1, 710 | textAlign: 'center', 711 | color: '#888888', 712 | fontSize: Auto.WHT(26), 713 | lineHeight: Auto.WHT(37), 714 | // paddingLeft: Auto.WHT(30), 715 | }, 716 | 717 | } 718 | -------------------------------------------------------------------------------- /src/routes/DetailsList.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react' 2 | import { connect } from 'dva'; 3 | import {routerRedux} from 'dva/router'; 4 | import { injectIntl } from 'react-intl'; 5 | import moment from "moment"; 6 | import PropTypes from 'prop-types'; 7 | import Auto from '../utils/Auto' 8 | import Utils from '../utils/Utils' 9 | import Constants from '../utils/Constants' 10 | import { Toast, PullToRefresh, ListView, Button, WhiteSpace, List, Modal} from 'antd-mobile'; 11 | var ScreenWidth = document.documentElement.clientWidth; 12 | var ScreenHeight = document.documentElement.clientHeight; 13 | require('moment/locale/zh-cn'); 14 | 15 | class DetailsList extends Component{ 16 | constructor(props) { 17 | super(props); 18 | const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 }); 19 | this.state = { 20 | dataSource, 21 | isbuysell: this.props.location.query ? this.props.location.query.isBuySell : localStorage.getItem('buy_sell'), 22 | data: [] 23 | } 24 | } 25 | componentWillMount(){ 26 | this.getListData(); 27 | } 28 | componentDidMount() { 29 | 30 | } 31 | async getListData(){ 32 | // alert(JSON.stringify(this.props.rexpool)); 33 | let total_rex = 0.0000; 34 | let total_lendable = 0.0000; 35 | try { 36 | let s1 = Utils.sliceUnit(this.props.rexpool.total_rex); 37 | let s2 = Utils.sliceUnit(this.props.rexpool.total_lendable); 38 | total_rex = parseFloat(s1); 39 | total_lendable = parseFloat(s2); 40 | } catch (error) { 41 | total_rex = 0.0000; 42 | total_lendable = 0.0000; 43 | } 44 | // alert("total_rex="+total_rex+" total_lendable=" + total_lendable); 45 | let resp = await Utils.dispatchActiionData(this, { type: 'common/querySellRexInfo', payload:{account: this.props.account}}); 46 | // let resp = [ 47 | // {transaction: false, quantity: '9 REX', conversionratio: '1 EOS ≈ 500 REX', createdate: 1520840297000, }, 48 | // ]; 49 | // alert("resp"+JSON.stringify(resp)); 50 | if(resp && resp.rows){ 51 | let retArray = new Array(); 52 | resp.rows.forEach(function(val,index){ 53 | let price = 0; 54 | try { 55 | let s3 = Utils.sliceUnit(val.rex_requested); 56 | let amount = parseFloat(s3); 57 | let tmp1 = (total_lendable+amount).toFixed(4); 58 | let tmp2 = (total_rex*tmp1/total_lendable).toFixed(4); 59 | let tmp3 = (tmp2 - total_rex).toFixed(4); 60 | price = (tmp3/amount).toFixed(4); 61 | // alert("tmp1="+tmp1 + " tmp2=" + tmp2 + " tmp3=" + tmp3 +" price="+price); 62 | } catch (error) { 63 | price = 0; 64 | } 65 | retArray[index] = { 66 | transaction: false, quantity: val.rex_requested, conversionratio: '1 EOS ≈ '+price+' REX', createdate: val.order_time, 67 | }; 68 | }); 69 | this.setState({data: retArray}); 70 | }else{ 71 | Toast.info("暂无更多数据"); 72 | } 73 | } 74 | onRefresh() { 75 | 76 | } 77 | 78 | onEndReached() { 79 | 80 | } 81 | async refundTransaction(){ 82 | let actions = [{ 83 | account: 'eosio', 84 | name: 'cnclrexorder', 85 | authorization: [{ 86 | actor: this.props.account, 87 | permission: this.props.permission, 88 | }], 89 | data: { 90 | owner: this.props.account, 91 | }, 92 | }]; 93 | // alert('refundTransaction='+JSON.stringify(actions)); 94 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 95 | // alert("resp="+JSON.stringify(resp)); 96 | if(resp){ 97 | Toast.info("撤单成功"); 98 | }else{ 99 | Toast.info("撤单失败"); 100 | } 101 | } 102 | onWithdraw = () => { 103 | Modal.alert('', '您是否撤回这次交易?', [ 104 | { text: '取消', onPress: () => console.log('取消'), style: 'default' }, 105 | { text: '确定', onPress: () => this.refundTransaction() }, 106 | ]); 107 | } 108 | 109 | render() { 110 | return
111 | this.lv = el} 115 | dataSource={this.state.dataSource.cloneWithRows(this.state.data)} 116 | pullToRefresh={ 119 | } 120 | onEndReached={this.onEndReached} 121 | renderRow={this._renderRow} 122 | /> 123 |
124 | } 125 | 126 | _renderRow= (rowData, sectionID, rowID) => { 127 | return (
128 |
129 |

{this.state.isbuysell ? '卖' : '买'}

130 |

{moment(rowData.createdate).format('MM-DD')}

131 |

{rowData.transaction ? '已成交' : '待成交'}

132 |
133 | {!rowData.transaction && } 134 |
135 | 136 | 出售数量:{rowData.quantity} 137 | 兑换比例:{rowData.conversionratio} 138 | 成交时间:{moment(rowData.createdate).format('HH:mm:ss')} 139 | 140 | 141 |
) 142 | } 143 | 144 | } 145 | 146 | export default connect(({ common,}) => ({ ...common,}))(injectIntl(DetailsList)); 147 | 148 | const styles = { 149 | rootDiv: { 150 | width: ScreenWidth, 151 | height: ScreenHeight, 152 | background: '#F5F5F9', 153 | boxSizing: 'border-box', 154 | }, 155 | rowDiv: { 156 | background: '#F5F5F9', 157 | }, 158 | listTopout: { 159 | display:"flex", 160 | flexDirection: 'row', 161 | alignItems: 'center', 162 | height: Auto.WHT(88), 163 | paddingLeft: Auto.WHT(30), 164 | paddingRight: Auto.WHT(30), 165 | backgroundColor: '#FFFFFF', 166 | borderBottom: '1px #DDDDDD solid', 167 | }, 168 | buyselltext: { 169 | color: '#000000', 170 | fontSize: Auto.WHT(34), 171 | lineHeight: Auto.WHT(48), 172 | }, 173 | datetext: { 174 | color: '#BBBBBB', 175 | fontSize: Auto.WHT(34), 176 | lineHeight: Auto.WHT(48), 177 | paddingLeft: Auto.WHT(30), 178 | paddingRight: Auto.WHT(30), 179 | }, 180 | clinchtext: { 181 | color: '#108EE9', 182 | textAlign: 'center', 183 | width: Auto.WHT(110), 184 | fontSize: Auto.WHT(28), 185 | lineHeight: Auto.WHT(42), 186 | border: '1px #108EE9 solid', 187 | }, 188 | listTopbtn: { 189 | width: Auto.WHT(112), 190 | height: Auto.WHT(60), 191 | lineHeight: Auto.WHT(60), 192 | background: '#108EE9', 193 | border: 'none', 194 | textDecoration: 'none', 195 | borderRadius: Auto.WHT(6), 196 | fontSize: Auto.WHT(26), 197 | color: '#FFFFFF', 198 | }, 199 | } -------------------------------------------------------------------------------- /src/routes/GameDescription.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ListView, Button, InputItem, } from 'antd-mobile'; 3 | import { injectIntl } from 'react-intl'; 4 | import { connect } from 'dva'; 5 | import Auto from '../utils/Auto' 6 | import {routerRedux} from 'dva/router'; 7 | import Constants from '../utils/Constants' 8 | require('moment/locale/zh-cn'); 9 | var ScreenWidth = window.screen.width 10 | var ScreenHeight = window.screen.height 11 | 12 | class GameDescription extends React.Component { 13 | constructor(props) { 14 | super(props); 15 | this.state = { 16 | lease: this.props.location.query ? this.props.location.query.lease : false, 17 | }; 18 | } 19 | 20 | componentDidMount() { 21 | 22 | } 23 | 24 | render() { 25 | return (
26 |

REX玩法说明

27 |

1、在进行买卖REX之前,用户必须要对至少21个节点投过票或代理投票,并且买入4天后方可卖出,之后就不需要进行节点投票。

28 |

2、如果REX里面没有足够的EOS,则排入队列,等到EOS足够再卖出,并且卖出时才计算REX价格,用户是可以取消尚未成交的卖出订单。

29 | {this.state.lease && 30 |
31 |

租赁介绍

32 |

1、您可以根据自己的需要填写足量的CPU,NET,租用时长,默认接收账户是您当前使用的账户,可给当前账户租赁,还可以帮助朋友租赁, 33 | 默认接收账户是您当前使用账户,您可以修改为朋友账户,填写完成后,在订单确认里您可以看到当前可以租用的EOS金额,确认无误后,点击一键租赁完成资源租赁。

34 |
35 | } 36 |
37 | ) 38 | } 39 | } 40 | 41 | export default connect(({ }) => ({ }))(injectIntl(GameDescription)); 42 | 43 | const styles = { 44 | rootDiv:{ 45 | width: ScreenWidth, 46 | height: ScreenHeight, 47 | background:"#F5F5F9", 48 | boxSizing: 'border-box', 49 | padding: Auto.WHT(30), 50 | }, 51 | description: { 52 | color: '#000000', 53 | fontSize: Auto.WHT(48), 54 | lineHeight: Auto.WHT(67), 55 | paddingTop: Auto.WHT(10), 56 | }, 57 | explaintext: { 58 | color: '#333333', 59 | fontSize: Auto.WHT(28), 60 | lineHeight: Auto.WHT(36), 61 | paddingTop: Auto.WHT(30), 62 | }, 63 | descriptiontitle: { 64 | color: '#000000', 65 | fontSize: Auto.WHT(48), 66 | lineHeight: Auto.WHT(67), 67 | paddingTop: Auto.WHT(70), 68 | }, 69 | } 70 | -------------------------------------------------------------------------------- /src/routes/Index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Toast, ListView, Button, Progress, InputItem, List, WhiteSpace,Stepper} from 'antd-mobile'; 3 | import { injectIntl } from 'react-intl'; 4 | import { connect } from 'dva'; 5 | import {routerRedux} from 'dva/router'; 6 | import Auto from '../utils/Auto' 7 | import Utils from '../utils/Utils' 8 | import {formatEosQua} from '../utils/FormatUtil'; 9 | 10 | require('moment/locale/zh-cn'); 11 | var ScreenWidth = window.screen.width 12 | var ScreenHeight = window.screen.height 13 | 14 | class Index extends React.Component { 15 | constructor(props) { 16 | super(props); 17 | const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 }); 18 | this.state = { 19 | dataSource, 20 | cpuval: 0.1, 21 | netval: 0.1, 22 | timeval: 30, 23 | cpuval_price: 0, 24 | netval_price: 0, 25 | toAccount: this.props.account, 26 | }; 27 | } 28 | 29 | componentDidMount() { 30 | document.addEventListener('scatterLoaded', scatterExtension => { 31 | this.login(); 32 | }); 33 | 34 | setTimeout(()=>{ 35 | this.login(); 36 | }, 10); 37 | } 38 | 39 | async login() { 40 | let accountInfo = await Utils.dispatchActiionData(this, { type: 'common/login', payload:{}}); 41 | if(!accountInfo){ 42 | return; 43 | } 44 | this.setState({toAccount: accountInfo.name}); 45 | let resp = await Utils.dispatchActiionData(this, { type: 'common/getRexInfo', payload:{}}); 46 | if(resp){ 47 | this.update_costval_cpu(this.state.cpuval); 48 | this.update_costval_net(this.state.netval); 49 | } 50 | } 51 | 52 | calc_costval(tmp_val){ 53 | let val_price = 0; 54 | try { 55 | let total_rent = Utils.sliceUnit(this.props.rexpool.total_rent); 56 | let total_unlent = Utils.sliceUnit(this.props.rexpool.total_unlent); 57 | let float_total_rent = parseFloat(total_rent); 58 | let float_total_unlent = parseFloat(total_unlent); 59 | let val = parseFloat(tmp_val); 60 | 61 | let tmp = (float_total_rent + val).toFixed(4); 62 | let tmp1 = ((float_total_unlent*val)/tmp).toFixed(4); 63 | val_price = (tmp1/val).toFixed(4); 64 | 65 | // alert("tmp="+tmp + "tmp1="+tmp1 + " val_price="+val_price); 66 | } catch (error) { 67 | val_price = 0; 68 | } 69 | return val_price; 70 | } 71 | //计算 租赁 CPU价格 72 | update_costval_cpu(tmp_cpuval){ 73 | let cpuval_price = this.calc_costval(tmp_cpuval); 74 | this.setState({cpuval_price: cpuval_price}); 75 | } 76 | //计算 租赁 NET价格 77 | update_costval_net(tmp_netval){ 78 | let netval_price = this.calc_costval(tmp_netval); 79 | this.setState({netval_price: netval_price}); 80 | } 81 | 82 | onCpuChange = (cpuval) => { 83 | // console.log(val); 84 | this.setState({ cpuval }); 85 | this.update_costval_cpu(cpuval); 86 | } 87 | 88 | onNetChange = (netval) => { 89 | // console.log(val); 90 | this.setState({ netval }); 91 | this.update_costval_net(netval); 92 | } 93 | 94 | onTimeChange = (timeval) => { 95 | // console.log(val); 96 | this.setState({ timeval }); 97 | } 98 | 99 | onbuysell = () => { 100 | this.props.dispatch(routerRedux.push({pathname: '/BuyandSell', query: { }})) 101 | } 102 | 103 | description = () => { 104 | this.props.dispatch(routerRedux.push({pathname: '/GameDescription', query: {lease:true}})) 105 | } 106 | 107 | doRent = async () => { 108 | if(!this.props.account){ 109 | Toast.info("请先登录", 1); 110 | return; 111 | } 112 | try { 113 | let tmp_cpuval = parseFloat(this.state.cpuval); 114 | let cpu_loan_fund = ((this.state.timeval/30 -1) * tmp_cpuval).toFixed(4); 115 | 116 | let tmp_netval = parseFloat(this.state.netval); 117 | let net_loan_fund = ((this.state.timeval/30 -1) * tmp_netval).toFixed(4); 118 | 119 | let actions = [ 120 | { 121 | account: 'eosio', 122 | name: 'deposit', 123 | authorization: [{ 124 | actor: this.props.account, 125 | permission: this.props.permission, 126 | }], 127 | data: { 128 | owner: this.props.account, 129 | amount: formatEosQua( (this.state.cpuval + this.state.netval).toFixed(4) + ' EOS'), 130 | }, 131 | }, 132 | { 133 | account: 'eosio', 134 | name: 'rentcpu', 135 | authorization: [{ 136 | actor: this.props.account, 137 | permission: this.props.permission, 138 | }], 139 | data: { 140 | from: this.props.account, 141 | receiver: this.state.toAccount, 142 | loan_payment: formatEosQua(this.state.cpuval + ' EOS'), 143 | loan_fund: cpu_loan_fund + ' EOS', 144 | }, 145 | }, 146 | { 147 | account: 'eosio', 148 | name: 'rentnet', 149 | authorization: [{ 150 | actor: this.props.account, 151 | permission: this.props.permission, 152 | }], 153 | data: { 154 | from: this.props.account, 155 | receiver: this.state.toAccount, 156 | loan_payment: formatEosQua(this.state.netval + ' EOS'), 157 | loan_fund: net_loan_fund + ' EOS', 158 | }, 159 | } 160 | ]; 161 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 162 | if(resp){ 163 | Toast.info('交易成功'); 164 | }else{ 165 | Toast.info('交易失败'); 166 | } 167 | } catch (error) { 168 | 169 | } 170 | } 171 | 172 | render() { 173 | return (
174 |
175 |
176 |

可出租资源:(EOS)

177 | 178 |
179 |
180 |

{Utils.sliceUnit(this.props.rexpool.total_unlent)}

181 | 182 |
183 |

已出租:{Utils.sliceUnit(this.props.rexpool.total_lent)}

184 |

总量:{Utils.sliceUnit(this.props.rexpool.total_lendable)}

185 |
186 |
187 |
188 | 189 | 190 |
191 |
192 |

租用资源

193 |

我的余额:{this.props.eosBalance} EOS

194 |
195 |

{'付款账户: ' + this.props.account}

196 | this.setState({ toAccount })} 199 | ref={el => this.autoFocusInst = el}>接收账户: 200 |
201 | 202 | 203 |
204 |
205 |

租赁费用

206 |
209 | 210 | {this.onCpuChange(cpuval)}}/>} 213 | >CPU 214 | {this.onNetChange(netval)}}/>} 217 | >NET 218 | {this.onTimeChange(timeval)}}/>} 221 | >租用时长(天) 222 | 223 |
224 | 225 |
226 |

订单确认:

227 |
{this.props.account}为{this.state.toAccount}租赁抵押{this.state.timeval}天,花费{(this.state.cpuval + this.state.netval).toFixed(1)} EOS租赁CPU {this.state.cpuval_price},租赁NET {this.state.netval_price}。
228 | 229 |
230 |
) 231 | } 232 | } 233 | 234 | export default connect(({common, vote }) => ({...common, ...vote }))(injectIntl(Index)); 235 | 236 | const styles = { 237 | rootDiv:{ 238 | width: ScreenWidth, 239 | height: ScreenHeight, 240 | background:"#F8F8F8", 241 | boxSizing: 'border-box', 242 | }, 243 | 244 | headtopout: { 245 | height: Auto.WHT(88), 246 | paddingLeft: Auto.WHT(30), 247 | paddingRight: Auto.WHT(30), 248 | display:"flex", 249 | flexDirection: 'row', 250 | alignItems: 'center', 251 | }, 252 | headtoptext: { 253 | flex: 1, 254 | color: '#000000', 255 | fontSize: Auto.WHT(34), 256 | lineHeight: Auto.WHT(42), 257 | }, 258 | headtopbtn: { 259 | width: Auto.WHT(164), 260 | height: Auto.WHT(60), 261 | lineHeight: Auto.WHT(60), 262 | background: '#FFFFFF', 263 | border: '1px #108EE9 solid', 264 | textDecoration: 'none', 265 | borderRadius: Auto.WHT(10), 266 | fontSize: Auto.WHT(26), 267 | color: '#108EE9', 268 | }, 269 | headbottomout: { 270 | display: 'flex', 271 | flexDirection: 'column', 272 | padding: Auto.WHT(30), 273 | paddingTop: Auto.WHT(10), 274 | }, 275 | headbottomtext: { 276 | color: '#000000', 277 | fontSize: Auto.WHT(48), 278 | lineHeight: Auto.WHT(67), 279 | paddingBottom: Auto.WHT(22), 280 | }, 281 | progress: { 282 | height: Auto.WHT(34), 283 | background: '#FFFFFF', 284 | border: '1PX solid #E9E9E9', 285 | borderRadius: Auto.WHT(17) 286 | }, 287 | barout: { 288 | background: '#108EE9', 289 | borderWidth: Auto.WHT(17), 290 | borderStyle: 'solid', 291 | borderColor: '#108EE9', 292 | borderRadius: Auto.WHT(17) 293 | }, 294 | rentout: { 295 | width: '100%', 296 | display:"flex", 297 | flexDirection: 'row', 298 | alignItems: 'center', 299 | justifyContent: 'space-between', 300 | paddingTop: Auto.WHT(30), 301 | }, 302 | renttext: { 303 | color: '#888888', 304 | fontSize: Auto.WHT(30), 305 | lineHeight: Auto.WHT(34), 306 | }, 307 | 308 | centerDiv: { 309 | display: 'flex', 310 | flexDirection: 'column', 311 | background: '#FFFFFF', 312 | }, 313 | centertop: { 314 | height: Auto.WHT(88), 315 | display:"flex", 316 | flexDirection: 'row', 317 | alignItems: 'center', 318 | justifyContent: 'space-between', 319 | borderBottom: '1px solid #DDDDDD', 320 | }, 321 | centertoptitle: { 322 | color: '#000000', 323 | fontSize: Auto.WHT(30), 324 | lineHeight: Auto.WHT(84), 325 | paddingLeft: Auto.WHT(30), 326 | }, 327 | centertoptext: { 328 | color: '#888888', 329 | fontSize: Auto.WHT(30), 330 | lineHeight: Auto.WHT(34), 331 | paddingRight: Auto.WHT(30), 332 | }, 333 | centertopbtn: { 334 | border: 'none', 335 | borderRadius: 0, 336 | color: '#D9D9D9', 337 | padding: '0 0.4rem', 338 | height: Auto.WHT(36), 339 | textDecoration: 'none', 340 | }, 341 | reportimg: { 342 | width: Auto.WHT(30), 343 | height: Auto.WHT(30), 344 | margin: 0, 345 | }, 346 | 347 | footDiv: { 348 | flex: 1, 349 | padding: Auto.WHT(30), 350 | }, 351 | description: { 352 | color: '#000000', 353 | fontSize: Auto.WHT(28), 354 | paddingTop: Auto.WHT(10), 355 | paddingBottom: Auto.WHT(10), 356 | }, 357 | explaintext: { 358 | color: '#888888', 359 | fontSize: Auto.WHT(28), 360 | lineHeight: Auto.WHT(40), 361 | }, 362 | footbtn: { 363 | width: '100%', 364 | height: Auto.WHT(94), 365 | lineHeight: Auto.WHT(94), 366 | background: '#108EE9', 367 | border: 'none', 368 | textDecoration: 'none', 369 | borderRadius: Auto.WHT(10), 370 | fontSize: Auto.WHT(36), 371 | color: '#FFFFFF', 372 | marginTop: Auto.WHT(40), 373 | marginBottom: Auto.WHT(40), 374 | }, 375 | } 376 | -------------------------------------------------------------------------------- /src/routes/MyRexDetails.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react' 2 | import { connect } from 'dva'; 3 | import {routerRedux} from 'dva/router'; 4 | import { injectIntl } from 'react-intl'; 5 | import moment from "moment"; 6 | import PropTypes from 'prop-types'; 7 | import Auto from '../utils/Auto' 8 | import Utils from '../utils/Utils' 9 | import Constants from '../utils/Constants' 10 | import { Toast, PullToRefresh, ListView, Button, WhiteSpace, List, Modal} from 'antd-mobile'; 11 | var ScreenWidth = document.documentElement.clientWidth; 12 | var ScreenHeight = document.documentElement.clientHeight; 13 | require('moment/locale/zh-cn'); 14 | 15 | class MyRexDetails extends Component{ 16 | constructor(props) { 17 | super(props); 18 | const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 }); 19 | this.state = { 20 | dataSource, 21 | } 22 | } 23 | componentWillMount(){ 24 | 25 | } 26 | componentDidMount() { 27 | 28 | } 29 | 30 | render() { 31 | return
32 | {/* 33 | 总量:{this.props.myRexInfo.total_rex + ' REX'} 34 | 可卖:{this.props.myRexInfo.sell_available_rex + ' REX'} 35 | */} 36 |

我的REX

37 |

总量:{this.props.myRexInfo.total_rex + ' REX'}

38 |

可卖:{this.props.myRexInfo.sell_available_rex + ' REX'}

39 | this.lv = el} 43 | dataSource={this.state.dataSource.cloneWithRows(this.props.myRexInfo.rex_maturities)} 44 | renderRow={this._renderRow} 45 | /> 46 |
47 | } 48 | 49 | _renderRow= (rowData, sectionID, rowID) => { 50 | return (
51 | 52 |
53 |

{(rowData.second/10000).toFixed(4)+ ' REX'}

54 |

{rowData.first + ' 解冻'}

55 |
56 |
) 57 | } 58 | 59 | } 60 | 61 | export default connect(({ rex,}) => ({ ...rex,}))(injectIntl(MyRexDetails)); 62 | 63 | const styles = { 64 | rootDiv: { 65 | width: ScreenWidth, 66 | height: ScreenHeight, 67 | background: '#F5F5F9', 68 | boxSizing: 'border-box', 69 | }, 70 | rowDiv: { 71 | background: '#F5F5F9', 72 | }, 73 | listTopout: { 74 | display:"flex", 75 | flexDirection: 'row', 76 | alignItems: 'center', 77 | height: Auto.WHT(88), 78 | paddingLeft: Auto.WHT(30), 79 | paddingRight: Auto.WHT(30), 80 | backgroundColor: '#FFFFFF', 81 | borderBottom: '1px #DDDDDD solid', 82 | }, 83 | datetext: { 84 | color: '#BBBBBB', 85 | fontSize: Auto.WHT(28), 86 | lineHeight: Auto.WHT(48), 87 | paddingLeft: Auto.WHT(30), 88 | paddingRight: Auto.WHT(30), 89 | }, 90 | titletext: { 91 | background: '#FFFFFF', 92 | textAlign: 'center', 93 | fontSize: Auto.WHT(40), 94 | lineHeight: Auto.WHT(50), 95 | }, 96 | headtext: { 97 | background: '#FFFFFF', 98 | fontSize: Auto.WHT(28), 99 | lineHeight: Auto.WHT(42), 100 | paddingLeft: Auto.WHT(30), 101 | paddingRight: Auto.WHT(30), 102 | paddingTop: Auto.WHT(10), 103 | }, 104 | clinchtext: { 105 | background: '#FFFFFF', 106 | // color: '#108EE9', 107 | // textAlign: 'center', 108 | // width: Auto.WHT(110), 109 | fontSize: Auto.WHT(28), 110 | lineHeight: Auto.WHT(42), 111 | // border: '1px #108EE9 solid', 112 | }, 113 | listTopbtn: { 114 | width: Auto.WHT(112), 115 | height: Auto.WHT(60), 116 | lineHeight: Auto.WHT(60), 117 | background: '#108EE9', 118 | border: 'none', 119 | textDecoration: 'none', 120 | borderRadius: Auto.WHT(6), 121 | fontSize: Auto.WHT(26), 122 | color: '#FFFFFF', 123 | }, 124 | } -------------------------------------------------------------------------------- /src/routes/NodeVoting.js: -------------------------------------------------------------------------------- 1 | import React,{Component} from 'react' 2 | import { connect } from 'dva'; 3 | import {routerRedux} from 'dva/router'; 4 | import { injectIntl } from 'react-intl'; 5 | import moment from "moment"; 6 | import PropTypes from 'prop-types'; 7 | import Auto from '../utils/Auto' 8 | import Utils from '../utils/Utils' 9 | import { Toast, PullToRefresh, ListView, Button, WhiteSpace, List, Modal, Checkbox} from 'antd-mobile'; 10 | var ScreenWidth = document.documentElement.clientWidth; 11 | var ScreenHeight = document.documentElement.clientHeight; 12 | const CheckboxItem = Checkbox.CheckboxItem; 13 | require('moment/locale/zh-cn'); 14 | 15 | class NodeVoting extends Component{ 16 | constructor(props) { 17 | super(props); 18 | const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2 }); 19 | this.state = { 20 | dataSource, 21 | selected: 0, 22 | producers: [] 23 | } 24 | } 25 | 26 | componentDidMount() { 27 | this.onRefresh(); 28 | } 29 | 30 | onRefresh() { 31 | this.getVoteInfo(); 32 | } 33 | 34 | onEndReached() { 35 | 36 | } 37 | 38 | async getVoteInfo(){ 39 | try { 40 | let producers = await Utils.dispatchActiionData(this, { type: 'vote/listProducers', payload:{}}); 41 | let selected = 0; 42 | producers.forEach((item) => { 43 | if(item.isSelect){ 44 | selected++; 45 | } 46 | }) 47 | this.setState({producers: producers, selected: selected}); 48 | } catch (error) { 49 | 50 | } 51 | } 52 | 53 | getVoteActions = () => { 54 | let producers = []; 55 | this.state.producers.forEach((p) => { 56 | if(p.isSelect){ 57 | producers.push(p.owner); 58 | } 59 | }); 60 | producers.sort(); 61 | 62 | let actions = [{ 63 | account: 'eosio', 64 | name: 'voteproducer', 65 | authorization: [{ 66 | actor: this.props.account, 67 | permission: this.props.permission, 68 | }], 69 | data: { 70 | voter: this.props.account, 71 | proxy: '', 72 | producers: producers, 73 | }, 74 | }]; 75 | 76 | return actions; 77 | } 78 | 79 | async doVote (){ 80 | let actions = this.getVoteActions(); 81 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 82 | if(resp && resp.transaction_id){ 83 | Toast.info("投票成功"); 84 | return; 85 | } 86 | 87 | Toast.info("投票失败"); 88 | } 89 | 90 | voteProc = () =>{ 91 | if(this.state.selected < 21){ 92 | let dialog = Modal.alert('温馨提示',
您的选择少于21个节点,交易REX必须要对至少21个节点投过票或代理投票,确定进行投票?
, [ 93 | { text: '重新选择', onPress: () => {}}, 94 | { text: '确定', onPress: () =>{dialog.close(); this.doVote()}}, 95 | ]) 96 | return; 97 | } 98 | 99 | this.doVote(); 100 | } 101 | 102 | selectItem = (rowData) => { 103 | let newdata = new Array(); 104 | let quantity = 0; 105 | this.state.producers.forEach((item) => { 106 | if(item.owner == rowData.owner){ 107 | item.isSelect = !item.isSelect; 108 | } 109 | 110 | if(item.isSelect){ 111 | quantity++; 112 | } 113 | newdata.push(item); 114 | }) 115 | 116 | this.setState({producers: newdata, selected: quantity}); 117 | } 118 | render() { 119 | return
120 |
121 | 122 |

节点投票

123 |

1、在进行买卖REX之前,用户必须要对至少21个节点投过票或代理投票。

124 |

2、在进行投票前,用户需要进行EOS抵押换取投票权。

125 |
126 | 127 | this.lv = el} 131 | style={{paddingLeft: Auto.WHT(30), backgroundColor: '#FFFFFF', paddingBottom: Auto.WHT(100), }} 132 | dataSource={this.state.dataSource.cloneWithRows(this.state.producers)} 133 | pullToRefresh={ 136 | } 137 | onEndReached={this.onEndReached} 138 | renderRow={this._renderRow} 139 | /> 140 |
141 |

已选节点:{this.state.selected}/21

142 | 143 |
144 |
145 | } 146 | 147 | _renderRow = (rowData, sectionID, rowID) => { 148 | return (
149 | 150 |
151 |

{rowData.owner}

152 | {/*

{rowData.region}

*/} 153 |
154 |
) 157 | } 158 | 159 | } 160 | 161 | export default connect(({ common, rex, vote }) => ({ ...common, ...rex, ...vote }))(injectIntl(NodeVoting)); 162 | 163 | const styles = { 164 | rootDiv: { 165 | width: ScreenWidth, 166 | height: ScreenHeight, 167 | background: '#F5F5F9', 168 | boxSizing: 'border-box', 169 | 170 | }, 171 | headerDiv: { 172 | display:"flex", 173 | alignItems: 'center', 174 | background: '#FFFFFF', 175 | flexDirection: 'column', 176 | paddingTop: Auto.WHT(40), 177 | paddingLeft: Auto.WHT(30), 178 | paddingRight: Auto.WHT(30), 179 | }, 180 | headerimg: { 181 | width: Auto.WHT(133), 182 | height: Auto.WHT(133), 183 | }, 184 | headertitle: { 185 | color: '#333333', 186 | padding: Auto.WHT(20), 187 | fontSize: Auto.WHT(28), 188 | lineHeight: Auto.WHT(36), 189 | }, 190 | headertext: { 191 | color: '#333333', 192 | fontSize: Auto.WHT(28), 193 | lineHeight: Auto.WHT(36), 194 | paddingBottom: Auto.WHT(30), 195 | }, 196 | 197 | rowDiv: { 198 | display:"flex", 199 | flexDirection: 'row', 200 | alignItems: 'center', 201 | paddingTop: Auto.WHT(18), 202 | paddingBottom: Auto.WHT(18), 203 | background: '#FFFFFF', 204 | borderBottom: '1px #DDDDDD solid', 205 | }, 206 | nodeimg: { 207 | width: Auto.WHT(100), 208 | height: Auto.WHT(100), 209 | }, 210 | rownodeout: { 211 | flex: 1, 212 | paddingLeft: Auto.WHT(30), 213 | }, 214 | nodename: { 215 | color: '#000000', 216 | fontSize: Auto.WHT(34), 217 | lineHeight: Auto.WHT(48), 218 | }, 219 | regiontext: { 220 | color: '#888888', 221 | fontSize: Auto.WHT(28), 222 | lineHeight: Auto.WHT(40), 223 | }, 224 | buyselltext: { 225 | color: '#000000', 226 | fontSize: Auto.WHT(34), 227 | lineHeight: Auto.WHT(48), 228 | }, 229 | datetext: { 230 | color: '#BBBBBB', 231 | fontSize: Auto.WHT(34), 232 | lineHeight: Auto.WHT(48), 233 | paddingLeft: Auto.WHT(30), 234 | paddingRight: Auto.WHT(30), 235 | }, 236 | clinchtext: { 237 | color: '#108EE9', 238 | textAlign: 'center', 239 | width: Auto.WHT(110), 240 | fontSize: Auto.WHT(28), 241 | lineHeight: Auto.WHT(42), 242 | border: '1px #108EE9 solid', 243 | }, 244 | listbtn: { 245 | border: 'none', 246 | borderRadius: 0, 247 | color: '#FFFFFF', 248 | textDecoration: 'none', 249 | fontSize: Auto.WHT(26), 250 | }, 251 | listbtnimg: { 252 | width: Auto.WHT(42), 253 | height: Auto.WHT(42), 254 | margin: Auto.WHT(30), 255 | }, 256 | 257 | footDiv: { 258 | width: ScreenWidth, 259 | bottom: 0, 260 | display:"flex", 261 | position: 'fixed', 262 | flexDirection: 'row', 263 | alignItems: 'center', 264 | backgroundColor: '#FFFFFF', 265 | borderTop: '1px #DDDDDD solid', 266 | }, 267 | foottext: { 268 | flex: 1, 269 | color: '#000000', 270 | fontSize: Auto.WHT(28), 271 | lineHeight: Auto.WHT(40), 272 | paddingLeft: Auto.WHT(20), 273 | }, 274 | footbtn: { 275 | width: Auto.WHT(230), 276 | height: Auto.WHT(100), 277 | lineHeight: Auto.WHT(100), 278 | background: '#108EE9', 279 | border: 'none', 280 | textDecoration: 'none', 281 | borderRadius: 0, 282 | fontSize: Auto.WHT(36), 283 | color: '#FFFFFF', 284 | }, 285 | } -------------------------------------------------------------------------------- /src/routes/Withdraw.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Toast, Button, Modal, InputItem,} from 'antd-mobile'; 3 | import { injectIntl } from 'react-intl'; 4 | import { connect } from 'dva'; 5 | import Auto from '../utils/Auto'; 6 | import Utils from '../utils/Utils'; 7 | import {formatEosQua} from '../utils/FormatUtil'; 8 | 9 | require('moment/locale/zh-cn'); 10 | var ScreenWidth = window.screen.width 11 | var ScreenHeight = window.screen.height 12 | const alert = Modal.alert; 13 | 14 | 15 | class Withdraw extends React.Component { 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | balance: this.props.location.query ? this.props.location.query.balance : '0.0000', 20 | quantity: '', 21 | }; 22 | } 23 | 24 | componentDidMount() { 25 | // Utils.dispatchActiionData(this, { type: 'rex/getMyRexInfo', payload:{account: this.props.account}}); 26 | } 27 | 28 | 29 | sendWithdraw = async () => { 30 | try { 31 | let quantity = parseFloat(this.state.quantity).toFixed(4); 32 | let banlance = parseFloat(this.state.balance).toFixed(4); 33 | if(quantity < 0.0001){ 34 | Toast.info('请输入提现数量'); 35 | return ; 36 | } 37 | if(quantity > banlance){ 38 | Toast.info('余额不足'); 39 | return ; 40 | } 41 | let actions = [{ 42 | account: 'eosio', 43 | name: 'withdraw', 44 | authorization: [{ 45 | actor: this.props.account, 46 | permission: this.props.permission, 47 | }], 48 | data: { 49 | owner: this.props.account, 50 | amount: formatEosQua(this.state.quantity + ' EOS'), 51 | }, 52 | }]; 53 | console.log('sendWithdraw actions=',JSON.stringify(actions)); 54 | let resp = await Utils.dispatchActiionData(this, { type: 'common/sendEosAction', payload:{actions: actions}}); 55 | console.log('sendWithdraw resp=',JSON.stringify(resp)); 56 | if(resp){ 57 | //更新EOS 余额 58 | Utils.dispatchActiionData(this, { type: 'common/getAccountInfo', payload:{account: this.props.account}}); 59 | Toast.info("成功"); 60 | window.history.go(-1); 61 | }else{ 62 | Toast.info("失败"); 63 | } 64 | } catch (error) { 65 | 66 | } 67 | } 68 | 69 | 70 | render() { 71 | return (
72 |
73 |
74 | 75 |

余额: {this.state.balance} EOS

76 |

收款账户:{ this.props.account}

77 |
78 |
79 | this.autoFocusInst = el} onChange={(quantity) => this.setState({ quantity: Utils.chkEosQuantity(quantity) })} >提现数量: 80 |
81 |
82 |
83 | 84 |
85 |
) 86 | } 87 | } 88 | 89 | export default connect(({ common, rex }) => ({ ...common, ...rex }))(injectIntl(Withdraw)); 90 | 91 | const styles = { 92 | rootDiv:{ 93 | width: ScreenWidth, 94 | height: ScreenHeight, 95 | background:"#F8F8F8", 96 | boxSizing: 'border-box', 97 | }, 98 | 99 | headtopout: { 100 | display:"flex", 101 | flexDirection: 'column', 102 | alignItems: 'center', 103 | justifyContent: 'center', 104 | paddingTop: Auto.WHT(61), 105 | paddingBottom: Auto.WHT(75), 106 | }, 107 | 108 | headbottomleft: { 109 | color: '#333333', 110 | fontSize: Auto.WHT(34), 111 | lineHeight: Auto.WHT(42), 112 | paddingTop: Auto.WHT(25), 113 | }, 114 | centertoptext: { 115 | color: '#888888', 116 | fontSize: Auto.WHT(30), 117 | lineHeight: Auto.WHT(34), 118 | paddingTop: Auto.WHT(18), 119 | }, 120 | reportimg: { 121 | width: Auto.WHT(120), 122 | height: Auto.WHT(120), 123 | margin: 0, 124 | }, 125 | listitemout: { 126 | display: 'flex', 127 | flexDirection: 'row', 128 | alignItems: 'center', 129 | height: Auto.WHT(90), 130 | boxSizing: 'border-box', 131 | borderTop: '1px #DDDDDD solid', 132 | borderBottom: '1px #DDDDDD solid', 133 | }, 134 | footDiv: { 135 | width: ScreenWidth, 136 | boxSizing: 'border-box', 137 | paddingTop: Auto.WHT(40), 138 | paddingLeft: Auto.WHT(30), 139 | paddingRight: Auto.WHT(30), 140 | paddingBottom: Auto.WHT(40), 141 | 142 | }, 143 | footbtn: { 144 | width: '100%', 145 | border: 'none', 146 | color: '#FFFFFF', 147 | height: Auto.WHT(94), 148 | background: '#108EE9', 149 | textDecoration: 'none', 150 | fontSize: Auto.WHT(36), 151 | lineHeight: Auto.WHT(94), 152 | borderRadius: Auto.WHT(10), 153 | }, 154 | } 155 | -------------------------------------------------------------------------------- /src/utils/Api.js: -------------------------------------------------------------------------------- 1 | 2 | var rootaddr = ""; 3 | export const getBigRamRank = rootaddr + '/ramprice/getLargeRamRank'; -------------------------------------------------------------------------------- /src/utils/Auto.js: -------------------------------------------------------------------------------- 1 | export default { 2 | WHT: function (value) { 3 | return (value/75).toExponential(2) + 'rem'; 4 | }, 5 | } -------------------------------------------------------------------------------- /src/utils/Constants.js: -------------------------------------------------------------------------------- 1 | export default { 2 | loginUser:null, 3 | token:null, 4 | uid: '', 5 | PWD_MIN_LENGTH:4, //密码最小长度 6 | PWD_MAX_LENGTH:18, //密码最大长度 7 | isNetWorkOffline:false, 8 | FitPhone: 20, 9 | }; -------------------------------------------------------------------------------- /src/utils/EosUtil.js: -------------------------------------------------------------------------------- 1 | import '../shim.js' 2 | import eos from 'eosjs' 3 | var ecc = require('eosjs-ecc'); 4 | 5 | const RPC_API_URL = "http://47.52.250.41:8001"; 6 | 7 | export class Eos { 8 | static respSucc(e){ 9 | return {isSuccess:!0,msg:"success",data:e}; 10 | } 11 | 12 | static respErr(e){ 13 | return {isSuccess:!1,msg:"error",data:e}; 14 | } 15 | 16 | static getEos(){ 17 | config = { 18 | httpEndpoint: RPC_API_URL, 19 | chainId: "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906", 20 | } 21 | 22 | var eoss = eos(config); 23 | return eoss; 24 | } 25 | 26 | 27 | static getInfo(){ 28 | let eos = Eos.getEos(); 29 | return eos.getInfo({}).then(info => { 30 | return info; 31 | }); 32 | } 33 | 34 | static checkPrivateKey(privatekey,callback){ 35 | try{ 36 | if(ecc.isValidPrivate(privatekey)){ 37 | callback(Eos.respSucc(!0)); 38 | }else{ 39 | callback(Eos.respErr({code:500,msg:"私钥格式错误"})); 40 | } 41 | }catch(t){ 42 | callback(Eos.respErr({code:500,msg:"校验私钥失败"})); 43 | } 44 | } 45 | 46 | static privateToPublic(privateKey,callback){ 47 | try{ 48 | var publicKey=ecc.privateToPublic(privateKey); 49 | callback(Eos.respSucc({publicKey:publicKey})); 50 | }catch(t){ 51 | callback(Eos.respErr({code:500,msg:"生成公钥失败"})); 52 | } 53 | } 54 | 55 | /** 56 | * 生成随机私钥 57 | * @param {回调函数} callback 58 | */ 59 | static randomPrivateKey(callback){ 60 | try{ 61 | ecc.randomKey().then(privateKey => { 62 | alert('Private Key:\t', privateKey) // wif 63 | alert('Public Key:\t', ecc.privateToPublic(privateKey)) // EOSkey... 64 | }) 65 | // ecc.randomKey().then(t =>{ 66 | // alert(t) 67 | // if(t){ 68 | // var e=t; 69 | // var r=ecc.privateToPublic(e); 70 | // callback(Eos.respSucc({ownerPrivate:e,ownerPublic:r})); 71 | // }else{ 72 | // callback(Eos.respErr({code:500,msg:"生成私钥失败"})); 73 | // } 74 | // }).catch(function(t){ 75 | // alert("222"); 76 | // callback(Eos.respErr({code:500,msg:"生成私钥失败"})); 77 | // }) 78 | }catch(t){ 79 | callback(Eos.respErr({code:500,msg:"生成私钥失败"})); 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/utils/EventEmitter.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | export default new EventEmitter(); 3 | -------------------------------------------------------------------------------- /src/utils/FormatUtil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright 2016-present reading 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | export const formatDateString = (timestamp) => { 19 | if (timestamp === undefined) { 20 | return ''; 21 | } 22 | const date = new Date(parseInt(timestamp) * 1000); 23 | const year = date.getFullYear(); 24 | const month = parseInt(date.getMonth()) + 1; 25 | const day = date.getDate(); 26 | return `${year}-${month}-${day}`; 27 | }; 28 | 29 | export const formatStringWithHtml = (originString) => { 30 | if (originString === undefined) { 31 | return ''; 32 | } 33 | const newString = originString 34 | .replace(/ /g, ' ') 35 | .replace(/"/g, '"') 36 | .replace(/&/g, '&') 37 | .replace(/</g, '<') 38 | .replace(/>/g, '>'); 39 | return newString; 40 | }; 41 | 42 | export const formatterNumber = (number) =>{ 43 | return (number || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,'); 44 | } 45 | export const formatterUnit = (number) =>{ 46 | if(number>100000000){ 47 | let f = number/100000000; 48 | let value = Math.floor(f * 100) / 100; 49 | return value+"亿" 50 | }else if(number>10000){ 51 | let f = number/10000; 52 | let value = Math.floor(f * 100) / 100; 53 | return value+"万" 54 | }else{ 55 | return number; 56 | } 57 | } 58 | 59 | export const formatEosQua = (amount, precision = 4) =>{ 60 | var e = amount.split(" "); 61 | // if(e.length > 1 && e[1] == "IQ"){ 62 | // precision = 3; 63 | // } 64 | // if(e.length > 1 && e[1] == "QB"){ 65 | // return amount; // QB精度为1,这里不做精度转换 66 | // } 67 | if(precision === 0){ 68 | return amount; 69 | } 70 | let r=e[0].split("."); 71 | if(r.length>1){ 72 | if(r[1].length <= precision){ 73 | var n=precision-r[1].length; 74 | amount=e[0]; 75 | for(var i=0;i { 4 | const request1 = new Promise((resolve, reject) => { 5 | fetch(url,{ 6 | method: method, 7 | headers: { 8 | 'Content-Type': 'application/json;charset=utf-8', 9 | // "uid":Constants.uid|'', 10 | // "token":Constants.token, 11 | // "version":Constants.version, 12 | // "os":Constants.os, 13 | // "osVersion":Constants.osVersion, 14 | // "model":Constants.model, 15 | // "deviceId":Constants.deviceId 16 | }, 17 | body:JSON.stringify(body) 18 | }).then((response) => { 19 | return response.json(); 20 | }).then((responseData) => { 21 | resolve(responseData); 22 | }).catch((error) => { 23 | reject(error); 24 | }); 25 | }); 26 | 27 | // 定义一个延时函数 28 | const timeoutRequest = new Promise((resolve, reject) => { 29 | setTimeout(reject, timeout, 'Request timed out'); 30 | }); 31 | 32 | // 竞时函数,谁先完成调用谁 33 | return Promise.race([request1, timeoutRequest]).then(res => { 34 | return res 35 | }, m => { 36 | throw new Error(m); 37 | }); 38 | }; 39 | 40 | const request = (url,method,body, timeout = 30000)=>{ 41 | if(Constants.isNetWorkOffline){ 42 | return { code: 500, msg: '网络繁忙,请稍后再试' }; 43 | } 44 | return getRootaddr().then(res=>{ 45 | let okUrl = url 46 | let rootaddr = res 47 | if(okUrl.indexOf("/")==0){ 48 | okUrl = rootaddr+url 49 | } 50 | return requestO(okUrl, method, body, timeout) 51 | }).catch(e=>{ 52 | console.log(e); 53 | return { code: 500, msg: '网络繁忙,请稍后再试' }; 54 | }) 55 | }; 56 | 57 | const getRootaddr = ()=>{ 58 | return requestO(Constants.gateurl, 'post',{}).then(res => { 59 | Constants.rootaddr = res.url 60 | return Constants.rootaddr; 61 | }).catch(e=>{ 62 | console.log(e); 63 | Constants.rootaddr = Constants.defaultrootaddr 64 | return Constants.rootaddr; 65 | }) 66 | } 67 | 68 | export default { 69 | request, 70 | requestO, 71 | getRootaddr 72 | }; 73 | -------------------------------------------------------------------------------- /src/utils/Utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright 2016-present reading 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | export default class Utils { 20 | 21 | static async sendActionToModel(context,action) { 22 | let pthis = context; 23 | var p = new Promise(function (resolve, reject) { 24 | action.callback=(ret) => { 25 | // 只要回调 有调用 就返回 不管是返回对 26 | resolve(ret); 27 | } 28 | pthis.props.dispatch(action); 29 | }); 30 | return p; 31 | } 32 | 33 | static async dispatchActiionData(context, action) { 34 | if(!action.hasOwnProperty("type")) 35 | { 36 | console.error("action hava not type"); 37 | return; 38 | } 39 | if(action.hasOwnProperty("callback")) 40 | { 41 | console.error("callback action is not allowed"); 42 | } 43 | return await Utils.sendActionToModel(context,action); 44 | } 45 | 46 | static sliceUnit(val){ 47 | try { 48 | var e = val.split(" "); 49 | return e[0]; 50 | } catch (error) { 51 | return '0.0000'; 52 | } 53 | } 54 | 55 | static chkEosQuantity(obj) { 56 | obj = obj.replace(/[^\d.]/g, ""); //清除 "数字"和 "."以外的字符 57 | obj = obj.replace(/^\./g, ""); //验证第一个字符是否为数字 58 | obj = obj.replace(/\.{2,}/g, "."); //只保留第一个小数点,清除多余的 59 | obj = obj 60 | .replace(".", "$#$") 61 | .replace(/\./g, "") 62 | .replace("$#$", "."); 63 | obj = obj.replace(/^(\-)*(\d+)\.(\d\d\d\d).*$/,'$1$2.$3'); //只能输入四个小数 64 | // var max = 9999999999.9999; // 100亿 -1 65 | // var min = 0.0000; 66 | // var value = 0.0000; 67 | // var floatbalance; 68 | // try { 69 | // value = parseFloat(obj); 70 | // floatbalance = parseFloat(this.state.balance); 71 | // } catch (error) { 72 | // value = 0.0000; 73 | // floatbalance = 0.0000; 74 | // } 75 | // if(value < min|| value > max){ 76 | // EasyToast.show(Translate.getT("输入错误")); 77 | // obj = ""; 78 | // } 79 | // if (value > floatbalance) { 80 | // EasyToast.show(Translate.getT('账户余额不足,请重输')); 81 | // obj = ""; 82 | // } 83 | return obj; 84 | } 85 | 86 | static async isTimeExpire(tUs){ 87 | var myDate = new Date(); 88 | var now = myDate.valueOf(); 89 | var time = new Date(tUs).valueOf(); 90 | if(now <= time){ 91 | return true; 92 | }else{ 93 | return false; 94 | } 95 | } 96 | } --------------------------------------------------------------------------------