open source
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
package-lock.json
|
7
Dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
FROM index.docker.io/keymetrics/pm2:12-alpine
|
||||
RUN mkdir -p ~/look-web
|
||||
ADD server/ ~/look-web
|
||||
WORKDIR ~/look-web
|
||||
RUN npm set registry https://registry.npm.taobao.org
|
||||
RUN npm install
|
||||
ENTRYPOINT npm run start;sleep 100000000
|
72
README.md
Normal file
@ -0,0 +1,72 @@
|
||||
# LOOK Explorer
|
||||
|
||||
Look is a light explorer for Cosmos-based Blockchains. https://look.ping.pub .
|
||||
|
||||
## What is the difference between Look and other explorers?
|
||||
|
||||
Look is designed to explore blockchain data as real as possible, therefore there is no cache, no analysis. Look does not cache/save blockchain data on its server. Look only fetch data from Cosmos full node via LCD/RPC endpoints. We call it "Light Explorer".
|
||||
|
||||
## Do you want Look to explore your blockchain?
|
||||
|
||||
If you want Look to explore your blockchain, pull a request [here](https://github.com/liangping/look/issues), We will explore your chains as soon as possibe. And the most important thing is that Look is free for all public cosmos-based blockchains.
|
||||
|
||||
## Why LOOK explorer use official/trusted third party public LCD/rpc server?
|
||||
|
||||
We have two considerations: 1, Trust, In decentralize system, everything controled by one single team/orgnization could be risks. So we decided to co-build LOOK explorer with the community. 2. Look explorer will explose handreds and thousands cosmos-based blockchains in the future, it's impossible for our team to run validators or fullnodes for all of those chains.
|
||||
|
||||
## Contributors
|
||||
|
||||
Developers: @liangping @dingyiming
|
||||
|
||||
Data providers: [full list](https://github.com/ping-pub/look/blob/master/hosts.json)
|
||||
|
||||
* irisnet.org,
|
||||
* nylira.net,
|
||||
* 01node.com,
|
||||
* kava.io
|
||||
|
||||
*If you don't want to provide data services for LOOK exporer, let us know.*
|
||||
|
||||
## Blockchains on LOOK explorer:
|
||||
* https://cosmos.ping.pub
|
||||
* https://iris.ping.pub
|
||||
* https://kava.ping.pub
|
||||
* https://sentinel.ping.pub
|
||||
|
||||
# LOOK 浏览器
|
||||
|
||||
Look是一个轻浏览器,免费为所有的基于Cosmos-SDK开发的区块链提供浏览服务
|
||||
|
||||
## Look 和其他区块链浏览器有什么不同?
|
||||
|
||||
Look的设计理念是尽可能的保持数据的真实性,所以,他不会在服务器端缓存或者保存任何数据,也不会增加任何分析处理。它仅仅通过LCD/RPC来获取他所需要的所有数据。因此我们叫它“轻浏览器”。
|
||||
|
||||
## 你希望Look来浏览你的区块链吗?
|
||||
|
||||
如果你需要Look来浏览你的区块链,请在[这里](https://github.com/liangping/look/issues) 提交申请,我们会尽快开通。而且是免费的。
|
||||
|
||||
## 为什么LOOK要使用官方或者可信赖的第三方的LCD/RPC服务器?
|
||||
|
||||
我们主要是基于以下两个考虑:1,可信,在去中心化的系统里,任何有一个由单个团队或者实体控制的事情都是有风险的,所以我们选择和社区一起来共建LOOK浏览器。2,LOOK浏览器计划在未来支持成百上千条区块链,因此对我们团队来说,不可能为所有这些链去提供一个验证人节点或者全节点。
|
||||
|
||||
## 项目贡献者
|
||||
|
||||
开发者: @liangping @dingyiming
|
||||
|
||||
数据服务方: [列表](https://github.com/ping-pub/look/blob/master/hosts.json)
|
||||
|
||||
* irisnet.org,
|
||||
* nylira.net,
|
||||
* 01node.com,
|
||||
* kava.io
|
||||
|
||||
*如果你觉得我们滥用了你的服务器资源,请告知我们。*
|
||||
|
||||
## LOOK explorer 上的区块链:
|
||||
* https://cosmos.ping.pub
|
||||
* https://iris.ping.pub
|
||||
* https://kava.ping.pub
|
||||
* https://sentinel.ping.pub
|
||||
|
||||
# Contact Us
|
||||
Email:18786721#qq.com
|
5
babel.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
43
package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "look",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"start": "pm2 delete all && git pull origin dev && cd server && npm run start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmostation/cosmosjs": "^0.5.2",
|
||||
"@lunie/cosmos-api": "^0.2.5",
|
||||
"@lunie/cosmos-ledger": "^0.1.7",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"core-js": "^3.6.4",
|
||||
"cosmos-lib": "^1.1.0",
|
||||
"dayjs": "^1.8.21",
|
||||
"element-ui": "^2.13.0",
|
||||
"fingerprintjs2": "^2.1.0",
|
||||
"hash.js": "^1.1.7",
|
||||
"js-base64": "^3.6.0",
|
||||
"localforage": "^1.7.3",
|
||||
"vant": "^2.6.1",
|
||||
"vue": "^2.6.11",
|
||||
"vue-i18n": "^8.15.1",
|
||||
"vue-router": "^3.1.5",
|
||||
"vue-worker": "^1.2.1",
|
||||
"vuex": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.2.0",
|
||||
"@vue/cli-plugin-router": "~4.2.0",
|
||||
"@vue/cli-plugin-vuex": "~4.2.0",
|
||||
"@vue/cli-service": "~4.2.0",
|
||||
"sass": "^1.25.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
]
|
||||
}
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
38
public/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<title>
|
||||
LOOK Explorer - A light explorer for Cosmos based blockchains, Powered by
|
||||
ping.pub.
|
||||
</title>
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<link rel="stylesheet" href="/static/css/font_1354695_lrb2z8iklqe.css" />
|
||||
<script src="/static/cdn/vue@2.6.11.min.js"></script>
|
||||
<script src="/static/cdn/element-ui@2.13.0.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||
properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?612cb1567ca1cb640c7e9ee55b748c8c";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
3
public/static/cdn/axios@0.19.2.min.js
vendored
Normal file
10
public/static/cdn/core@2.6.11.min.js
vendored
Normal file
1
public/static/cdn/element-ui@2.13.0.js
Normal file
6
public/static/cdn/vue-router@3.1.6.min.js
vendored
Normal file
6
public/static/cdn/vue@2.6.11.min.js
vendored
Normal file
6
public/static/cdn/vuex@3.1.3.min.js
vendored
Normal file
BIN
public/static/cdp/risk.png
Normal file
After Width: | Height: | Size: 73 KiB |
109
public/static/chains/cosmoshub.svg
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
public/static/chains/default.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
29
public/static/chains/irishub.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 319.97 320">
|
||||
<defs>
|
||||
<style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill:url(#linear-gradient-2);}.cls-3{fill:url(#linear-gradient-3);}.cls-4{fill:url(#linear-gradient-4);}.cls-5{fill:url(#linear-gradient-5);}.cls-6{fill:url(#linear-gradient-6);}.cls-7{fill:url(#linear-gradient-7);}</style>
|
||||
<linearGradient id="linear-gradient" x1="36.16" y1="24.77" x2="285.75" y2="274.37" gradientTransform="matrix(1, 0, 0, -1, -5.41, 313.57)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#189dd8"/>
|
||||
<stop offset="0.5" stop-color="#694ea0"/>
|
||||
<stop offset="1" stop-color="#ed3855"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="63.4" y1="-2.47" x2="312.99" y2="247.13" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-3" x1="134.61" y1="-73.68" x2="384.2" y2="175.91" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-4" x1="109.22" y1="-48.29" x2="358.82" y2="201.3" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-5" x1="-36.5" y1="97.43" x2="213.1" y2="347.02" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-6" x1="-61.81" y1="122.74" x2="187.78" y2="372.33" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-7" x1="9.4" y1="51.53" x2="258.99" y2="301.12" xlink:href="#linear-gradient"/>
|
||||
</defs>
|
||||
<title>Asset 1</title>
|
||||
<g id="Layer_2">
|
||||
<g id="Layer_1-2">
|
||||
<path class="cls-1" d="M97.11,231.9l-73.39,8.26,43.09-99.45L22.68,80.5,130,68.3l29.16-67L223,88.1l73.41-8.26-42.9,99,43.81,59.74L190.59,250.72l-29.6,68Zm30.48-6.6a51.53,51.53,0,0,1-8.91,3.38l-2.8.78,41.39,56.26L172,251.94l-2.65-.34a52.91,52.91,0,0,1-36.1-21.36l-4.12-5.68Zm-14.39-51,33.39,46.2a36.31,36.31,0,0,0,29.33,15,35.61,35.61,0,0,0,4-.22L267,225.36l-34.69-47.31a35.77,35.77,0,0,0-5.91-6.32l-2-1.7-24.82,56-43.19-57.2Zm1.46-56.25A36.28,36.28,0,0,0,85.29,139.7l-35,80.74,58.12-6.53a35.22,35.22,0,0,0,8.4-2l2.48-.92L83.37,161.34l70.92-9,16.85-40.28Zm54.86,40.74,26.29,34.81,16-36.2,7.09-15.9a36.52,36.52,0,0,0-4-36.37L162.83,34.28,139.41,88.11a36,36,0,0,0-2.49,8.31L136.47,99l60.76-6.43Zm63.84-55.14,1,2.47a53.49,53.49,0,0,1-.39,42.1l-2.83,6.42,1.39.94a51,51,0,0,1,7.37,6.07l2.08,2,27.8-64.15ZM53,93.8,75.11,124l1.62-2.1a53,53,0,0,1,36.2-20.39l7-.73.12-1.69a52,52,0,0,1,1.75-10.37l.79-2.87Z"/>
|
||||
<path class="cls-2" d="M144.51,320A158.79,158.79,0,0,1,29.93,253.61l18.54-2.11c3.08,3.77,6.34,7.39,9.71,10.77a142.87,142.87,0,0,0,72.93,39.48Z"/>
|
||||
<path class="cls-3" d="M183.17,302.82a142.36,142.36,0,0,0,78.65-40.52c1.93-1.94,3.89-4,5.82-6.2l22.51-2.6A158.89,158.89,0,0,1,175.7,320Z"/>
|
||||
<path class="cls-4" d="M294.72,211.3a146.54,146.54,0,0,0,2-96.94l9-20.8a161.83,161.83,0,0,1,0,132.8Z"/>
|
||||
<path class="cls-5" d="M14.33,226.58a161.85,161.85,0,0,1,.16-133.51l11,15a146.46,146.46,0,0,0-2.17,97.7Z"/>
|
||||
<path class="cls-6" d="M30.59,65.5A159,159,0,0,1,144.42,0L137,17.16A142.34,142.34,0,0,0,58.18,57.7c-1.63,1.63-3.28,3.38-4.92,5.19Z"/>
|
||||
<path class="cls-7" d="M271.59,68.5c-3.08-3.78-6.34-7.4-9.72-10.79a142.81,142.81,0,0,0-72.8-39.45L175.59,0A158.89,158.89,0,0,1,290.08,66.4Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
16
public/static/chains/kava.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 193.63 213">
|
||||
<defs>
|
||||
<style>.cls-1{opacity:0.2;}.cls-2{fill:#ff564f;}</style>
|
||||
</defs>
|
||||
<title>Kava Logo</title>
|
||||
<g id="Layer_2">
|
||||
<g id="Layer_1-2">
|
||||
<g class="cls-1">
|
||||
<polygon class="cls-2" points="30 213 111.63 106.85 30 0 20.25 38.34 72.81 106.85 22.66 171.3 30 213"/>
|
||||
</g>
|
||||
<polygon class="cls-2" points="154.34 213 72.21 106.85 154.13 0 193 0 111.03 106.85 193.63 213 154.34 213"/>
|
||||
<rect class="cls-2" width="30" height="213"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 537 B |
84
public/static/css/font_1354695_lrb2z8iklqe.css
Normal file
BIN
public/static/icon/chromefeature.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
public/static/icon/empty.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
public/static/icon/empty2.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
public/static/icon/empty3.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
public/static/wallet/asset1.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/static/wallet/asset2.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/static/wallet/asset3.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
public/static/wallet/bg.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
public/static/wallet/bg2.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
public/static/wallet/link.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
public/static/wallet/usb.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
public/static/wallet/wafe.gif
Normal file
After Width: | Height: | Size: 956 KiB |
13
server/.env
Normal file
@ -0,0 +1,13 @@
|
||||
PORT=80
|
||||
|
||||
# local
|
||||
# Mongodb_url=127.0.0.1:27017/look
|
||||
# Mongodb_user=
|
||||
# Mongodb_pwd=
|
||||
|
||||
# look
|
||||
Mongodb_url=127.0.0.1:37777/look
|
||||
Mongodb_user=look_20200415
|
||||
Mongodb_pwd=@@look@@dingyi
|
||||
|
||||
# MONGODB_URL=mongodb://127.0.0.1:27017/look
|
BIN
server/dist/favicon.ico
vendored
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
server/dist/fonts/element-icons.535877f5.woff
vendored
Normal file
BIN
server/dist/fonts/element-icons.732389de.ttf
vendored
Normal file
7
server/dist/index.html
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>LOOK Explorer - A light explorer for Cosmos based blockchains, Powered by ping.pub.</title><link rel=icon href=/favicon.ico><link rel=stylesheet href=/static/css/font_1354695_lrb2z8iklqe.css><script src=/static/cdn/vue@2.6.11.min.js></script><script src=/static/cdn/element-ui@2.13.0.js></script><link href=/js/chunk-dee43a6e.fa2f824d.js rel=prefetch><link href=/js/pc.3b9cf088.js rel=prefetch><link href=/js/index.9398c703.js rel=preload as=script></head><body><noscript><strong>We're sorry but look doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?612cb1567ca1cb640c7e9ee55b748c8c";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();</script><script src=/js/index.9398c703.js></script></body></html>
|
3
server/dist/js/chunk-dee43a6e.fa2f824d.js
vendored
Normal file
1
server/dist/js/h5.2e45d230.js
vendored
Normal file
21
server/dist/js/index.9398c703.js
vendored
Normal file
21
server/dist/js/m.6108a2ad.js
vendored
Normal file
8
server/dist/js/pc.3b9cf088.js
vendored
Normal file
7
server/dist/m.html
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=apple-mobile-web-app-status-bar-style content=black><meta name=format-detection content="telephone=no"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=/favicon.ico><link rel=stylesheet href=/static/css/font_1354695_lrb2z8iklqe.css><script src=https://unpkg.com/vue@2.6.11/dist/vue.min.js></script><script src=https://unpkg.com/element-ui@2.13.0/lib/index.js></script><title>LOOK Explorer - A light explorer for Cosmos based blockchains, Powered by ping.pub.</title><link href=/js/h5.2e45d230.js rel=prefetch><link href=/js/m.6108a2ad.js rel=preload as=script></head><body><noscript><strong>We're sorry but look doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?612cb1567ca1cb640c7e9ee55b748c8c";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();</script><script src=/js/m.6108a2ad.js></script></body></html>
|
3
server/dist/static/cdn/axios@0.19.2.min.js
vendored
Normal file
10
server/dist/static/cdn/core@2.6.11.min.js
vendored
Normal file
1
server/dist/static/cdn/element-ui@2.13.0.js
vendored
Normal file
6
server/dist/static/cdn/vue-router@3.1.6.min.js
vendored
Normal file
6
server/dist/static/cdn/vue@2.6.11.min.js
vendored
Normal file
6
server/dist/static/cdn/vuex@3.1.3.min.js
vendored
Normal file
BIN
server/dist/static/cdp/risk.png
vendored
Normal file
After Width: | Height: | Size: 73 KiB |
109
server/dist/static/chains/cosmoshub.svg
vendored
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
server/dist/static/chains/default.png
vendored
Normal file
After Width: | Height: | Size: 8.5 KiB |
29
server/dist/static/chains/irishub.svg
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 319.97 320">
|
||||
<defs>
|
||||
<style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill:url(#linear-gradient-2);}.cls-3{fill:url(#linear-gradient-3);}.cls-4{fill:url(#linear-gradient-4);}.cls-5{fill:url(#linear-gradient-5);}.cls-6{fill:url(#linear-gradient-6);}.cls-7{fill:url(#linear-gradient-7);}</style>
|
||||
<linearGradient id="linear-gradient" x1="36.16" y1="24.77" x2="285.75" y2="274.37" gradientTransform="matrix(1, 0, 0, -1, -5.41, 313.57)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#189dd8"/>
|
||||
<stop offset="0.5" stop-color="#694ea0"/>
|
||||
<stop offset="1" stop-color="#ed3855"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="63.4" y1="-2.47" x2="312.99" y2="247.13" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-3" x1="134.61" y1="-73.68" x2="384.2" y2="175.91" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-4" x1="109.22" y1="-48.29" x2="358.82" y2="201.3" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-5" x1="-36.5" y1="97.43" x2="213.1" y2="347.02" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-6" x1="-61.81" y1="122.74" x2="187.78" y2="372.33" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-7" x1="9.4" y1="51.53" x2="258.99" y2="301.12" xlink:href="#linear-gradient"/>
|
||||
</defs>
|
||||
<title>Asset 1</title>
|
||||
<g id="Layer_2">
|
||||
<g id="Layer_1-2">
|
||||
<path class="cls-1" d="M97.11,231.9l-73.39,8.26,43.09-99.45L22.68,80.5,130,68.3l29.16-67L223,88.1l73.41-8.26-42.9,99,43.81,59.74L190.59,250.72l-29.6,68Zm30.48-6.6a51.53,51.53,0,0,1-8.91,3.38l-2.8.78,41.39,56.26L172,251.94l-2.65-.34a52.91,52.91,0,0,1-36.1-21.36l-4.12-5.68Zm-14.39-51,33.39,46.2a36.31,36.31,0,0,0,29.33,15,35.61,35.61,0,0,0,4-.22L267,225.36l-34.69-47.31a35.77,35.77,0,0,0-5.91-6.32l-2-1.7-24.82,56-43.19-57.2Zm1.46-56.25A36.28,36.28,0,0,0,85.29,139.7l-35,80.74,58.12-6.53a35.22,35.22,0,0,0,8.4-2l2.48-.92L83.37,161.34l70.92-9,16.85-40.28Zm54.86,40.74,26.29,34.81,16-36.2,7.09-15.9a36.52,36.52,0,0,0-4-36.37L162.83,34.28,139.41,88.11a36,36,0,0,0-2.49,8.31L136.47,99l60.76-6.43Zm63.84-55.14,1,2.47a53.49,53.49,0,0,1-.39,42.1l-2.83,6.42,1.39.94a51,51,0,0,1,7.37,6.07l2.08,2,27.8-64.15ZM53,93.8,75.11,124l1.62-2.1a53,53,0,0,1,36.2-20.39l7-.73.12-1.69a52,52,0,0,1,1.75-10.37l.79-2.87Z"/>
|
||||
<path class="cls-2" d="M144.51,320A158.79,158.79,0,0,1,29.93,253.61l18.54-2.11c3.08,3.77,6.34,7.39,9.71,10.77a142.87,142.87,0,0,0,72.93,39.48Z"/>
|
||||
<path class="cls-3" d="M183.17,302.82a142.36,142.36,0,0,0,78.65-40.52c1.93-1.94,3.89-4,5.82-6.2l22.51-2.6A158.89,158.89,0,0,1,175.7,320Z"/>
|
||||
<path class="cls-4" d="M294.72,211.3a146.54,146.54,0,0,0,2-96.94l9-20.8a161.83,161.83,0,0,1,0,132.8Z"/>
|
||||
<path class="cls-5" d="M14.33,226.58a161.85,161.85,0,0,1,.16-133.51l11,15a146.46,146.46,0,0,0-2.17,97.7Z"/>
|
||||
<path class="cls-6" d="M30.59,65.5A159,159,0,0,1,144.42,0L137,17.16A142.34,142.34,0,0,0,58.18,57.7c-1.63,1.63-3.28,3.38-4.92,5.19Z"/>
|
||||
<path class="cls-7" d="M271.59,68.5c-3.08-3.78-6.34-7.4-9.72-10.79a142.81,142.81,0,0,0-72.8-39.45L175.59,0A158.89,158.89,0,0,1,290.08,66.4Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
16
server/dist/static/chains/kava.svg
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 193.63 213">
|
||||
<defs>
|
||||
<style>.cls-1{opacity:0.2;}.cls-2{fill:#ff564f;}</style>
|
||||
</defs>
|
||||
<title>Kava Logo</title>
|
||||
<g id="Layer_2">
|
||||
<g id="Layer_1-2">
|
||||
<g class="cls-1">
|
||||
<polygon class="cls-2" points="30 213 111.63 106.85 30 0 20.25 38.34 72.81 106.85 22.66 171.3 30 213"/>
|
||||
</g>
|
||||
<polygon class="cls-2" points="154.34 213 72.21 106.85 154.13 0 193 0 111.03 106.85 193.63 213 154.34 213"/>
|
||||
<rect class="cls-2" width="30" height="213"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 537 B |
84
server/dist/static/css/font_1354695_lrb2z8iklqe.css
vendored
Normal file
BIN
server/dist/static/icon/chromefeature.png
vendored
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
server/dist/static/icon/empty.png
vendored
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
server/dist/static/icon/empty2.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
server/dist/static/icon/empty3.png
vendored
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
server/dist/static/wallet/asset1.png
vendored
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
server/dist/static/wallet/asset2.png
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
server/dist/static/wallet/asset3.png
vendored
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
server/dist/static/wallet/bg.png
vendored
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
server/dist/static/wallet/bg2.png
vendored
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
server/dist/static/wallet/link.png
vendored
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
server/dist/static/wallet/usb.png
vendored
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
server/dist/static/wallet/wafe.gif
vendored
Normal file
After Width: | Height: | Size: 956 KiB |
28
server/package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "look",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "pm2 start pm2.json",
|
||||
"dev": "nodemon src/main.js",
|
||||
"test": "node app.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "dingyiming",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"compression": "^1.7.4",
|
||||
"dayjs": "^1.8.23",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.16.3",
|
||||
"express-useragent": "^1.0.13",
|
||||
"express-validator": "^6.4.0",
|
||||
"http-proxy-middleware": "^0.19.0",
|
||||
"mongoose": "^5.9.7",
|
||||
"nunjucks": "^3.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.3"
|
||||
}
|
||||
}
|
10
server/pm2.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"apps": [{
|
||||
"name": "look",
|
||||
"script": "./src/main.js",
|
||||
"out_fil": "~/look.log",
|
||||
"watch": true,
|
||||
"instances" : "1",
|
||||
"exec_mode" : "cluster"
|
||||
}]
|
||||
}
|
12
server/src/base/mongodb.js
Normal file
@ -0,0 +1,12 @@
|
||||
const mongoose = require("mongoose");
|
||||
mongoose.set("useCreateIndex", true);
|
||||
mongoose.connect(`mongodb://${process.env.Mongodb_url}?authSource=admin`, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
user: process.env.Mongodb_user,
|
||||
pass: process.env.Mongodb_pwd,
|
||||
});
|
||||
const db = mongoose.connection;
|
||||
db.once("open", () => {
|
||||
console.log("[dingyi]小芒果连上了~~");
|
||||
});
|
15
server/src/base/router.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-10 12:40:50
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-13 11:39:02
|
||||
* @FilePath: /look-web/server/src/base/router.js
|
||||
*/
|
||||
|
||||
const api = require('../routes/index.js')
|
||||
|
||||
module.exports = (app) => {
|
||||
app.use('/look', api)
|
||||
app.use('/look', (req, res) => { res.send('look.ping.pub') })
|
||||
}
|
57
server/src/base/utils.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:21:32
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-13 14:50:25
|
||||
* @FilePath: /look-web/server/src/base/utils.js
|
||||
*/
|
||||
const { validationResult } = require("express-validator");
|
||||
|
||||
exports.ok = ok
|
||||
function ok(res, data, other) {
|
||||
let obj = {
|
||||
code: 1,
|
||||
msg: "ok",
|
||||
data,
|
||||
};
|
||||
if (other) {
|
||||
obj = {
|
||||
...obj,
|
||||
...other,
|
||||
};
|
||||
}
|
||||
res.json(obj);
|
||||
}
|
||||
|
||||
function routerGet(router, uri, valid, logic) {
|
||||
router.get(uri, valid(), (req, res) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty())
|
||||
return ok(res, null, {
|
||||
code: 2,
|
||||
msg: errors.array()[0].msg,
|
||||
data: errors.array(),
|
||||
});
|
||||
logic(req, res);
|
||||
});
|
||||
}
|
||||
|
||||
function routerPost(router, uri, valid, logic) {
|
||||
router.post(uri, valid(), (req, res) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty())
|
||||
return ok(res, null, {
|
||||
code: 2,
|
||||
msg: errors.array()[0].msg,
|
||||
data: errors.array(),
|
||||
});
|
||||
logic(req, res);
|
||||
});
|
||||
}
|
||||
|
||||
exports.routerRun = {
|
||||
get: routerGet,
|
||||
post: routerPost
|
||||
}
|
||||
|
123
server/src/initChains.js
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 23:03:22
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-13 23:53:51
|
||||
* @FilePath: \look-web\server\src\initChains.js
|
||||
*/
|
||||
module.exports = {
|
||||
Mainnet: [
|
||||
{
|
||||
"chainId": "cosmoshub-3",
|
||||
"lcd": "https://lcd.nylira.net",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "Cosmos Hub",
|
||||
"rpc": "https://rpc.nylira.net",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"unit": 'ATOM',
|
||||
"prefix": 'cosmos',
|
||||
"host": 'cosmos.ping.pub',
|
||||
},
|
||||
{
|
||||
"chainId": "kava-2",
|
||||
"lcd": "https://kava-relay.01node.com",
|
||||
"logo": "/static/chains/kava.svg",
|
||||
"name": "Kava",
|
||||
"rpc": "http://13.125.71.131:26657",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"unit": 'KAVA',
|
||||
"prefix": 'kava',
|
||||
"host": 'kava.ping.pub'
|
||||
},
|
||||
{
|
||||
"chainId": "irishub",
|
||||
"lcd": "https://rpc.irisnet.org",
|
||||
"logo": "/static/chains/irishub.svg",
|
||||
"name": "IRISnet",
|
||||
"rpc": "http://seed-1.mainnet.irisnet.org:26657",
|
||||
"version": "0.32.1",
|
||||
"api": 'V2',
|
||||
"unit": 'IRIS',
|
||||
"prefix": 'iaa',
|
||||
"host": 'iris.ping.pub'
|
||||
},
|
||||
{
|
||||
"chainId": "e-money",
|
||||
"lcd": "http://emoney.validator.network/light",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "e-money",
|
||||
"rpc": "https://emoney.validator.network",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"unit": '',
|
||||
"prefix": '', // 地址前缀
|
||||
"host": 'e-money.ping.pub'
|
||||
}
|
||||
],
|
||||
Testnet: [
|
||||
{
|
||||
"chainId": "sentinelhub-test",
|
||||
"lcd": "https://lcd.turing.sentinel.co",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "Sentinel Network",
|
||||
"rpc": "https://rpc.turing.sentinel.co",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"prefix": '',
|
||||
"unit": '',
|
||||
"host": 'sentinel-test.ping.pub'
|
||||
},
|
||||
{
|
||||
"chainId": "cell-test-01",
|
||||
"lcd": "http://sz1.icell.one:1317",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "Cell Network",
|
||||
"rpc": "http://sz1.icell.one:26657",
|
||||
"version": "0.32.7",
|
||||
"prefix": 'cosmos',
|
||||
"api": 'V1',
|
||||
"unit": '',
|
||||
"host": 'cell-test.ping.pub'
|
||||
},
|
||||
{
|
||||
"chainId": "cyber-test",
|
||||
"lcd": "https://titan.cybernode.ai/lcd",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "cyber",
|
||||
"rpc": "https://titan.cybernode.ai/api",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"prefix": '',
|
||||
"unit": '',
|
||||
"host": 'cyber-test.ping.pub'
|
||||
},
|
||||
{
|
||||
"chainId": "e-money-test",
|
||||
"lcd": "https://lilmermaid.validator.network/light",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "e-money",
|
||||
"rpc": "https://lilmermaid.validator.network",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"unit": '',
|
||||
"prefix": '', // 地址前缀
|
||||
"host": 'e-money-test.ping.pub'
|
||||
},
|
||||
// {
|
||||
// "chainId": "new-test",
|
||||
// "lcd": "https://lcd.nylira.net",
|
||||
// "logo": "/static/chains/cosmoshub.svg",
|
||||
// "name": "Genesis Test",
|
||||
// "rpc": "https://rpc.nylira.net",
|
||||
// "version": "0.32.7",
|
||||
// "api": 'V1',
|
||||
// "unit": 'ATOM',
|
||||
// "prefix": 'cosmos',
|
||||
// "host": '',
|
||||
// "genesis_time": '2020-05-01'
|
||||
// },
|
||||
]
|
||||
}
|
92
server/src/main.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-03-27 11:41:45
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @LastEditTime: 2020-04-16 00:20:19
|
||||
* @FilePath: \look-web\server\src\main.js
|
||||
*/
|
||||
// 环境配置
|
||||
require('dotenv').config()
|
||||
// 数据库
|
||||
require('./base/mongodb.js')
|
||||
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
app.use(express.json());
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
// gzip
|
||||
const compression = require('compression')
|
||||
app.use(compression())
|
||||
|
||||
// ua
|
||||
var useragent = require('express-useragent');
|
||||
app.use(useragent.express());
|
||||
|
||||
// proxy
|
||||
var proxy = require('http-proxy-middleware');
|
||||
// 根据请求转发
|
||||
app.use('/api*', proxy({
|
||||
target: 'https://lcd.nylira.net',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
['^/api']: ''
|
||||
},
|
||||
router: function (req) {
|
||||
return req.headers.server || 'https://lcd.nylira.net';
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
router.get('/', function (req, res, next) {
|
||||
var isMobile = req.useragent.isMobile
|
||||
console.log('移动端', isMobile)
|
||||
let render = isMobile ? 'm.html' : 'index.html'
|
||||
res.render(render);
|
||||
});
|
||||
|
||||
router.get('/validator', function (req, res, next) {
|
||||
res.redirect('/#/validator');
|
||||
});
|
||||
router.get('/uptime', function (req, res, next) {
|
||||
res.redirect('/#/uptime');
|
||||
});
|
||||
router.get('/block', function (req, res, next) {
|
||||
res.redirect('/#/block');
|
||||
});
|
||||
router.get('/proposal', function (req, res, next) {
|
||||
res.redirect('/#/governance');
|
||||
});
|
||||
|
||||
router.get('/parameter', function (req, res, next) {
|
||||
res.redirect('/#/parameter');
|
||||
});
|
||||
|
||||
app.use('/', router);
|
||||
|
||||
// 路由
|
||||
require('./base/router.js')(app)
|
||||
|
||||
var nunjucks = require('nunjucks')
|
||||
nunjucks.configure('dist', {
|
||||
autoescape: true,
|
||||
express: app
|
||||
});
|
||||
|
||||
// static cache
|
||||
var path = require('path');
|
||||
app.use(express.static(path.join(__dirname, '../dist'), {
|
||||
maxAge: '1y',
|
||||
expires: '1y',
|
||||
Etag: false,
|
||||
lastModified: false
|
||||
}));
|
||||
|
||||
var server = app.listen(process.env.PORT, function () {
|
||||
var host = server.address().address;
|
||||
var port = server.address().port;
|
||||
|
||||
console.log('app listening at http://%s:%s', host, port);
|
||||
});
|
60
server/src/models/chain.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* @Description:
|
||||
{
|
||||
"chainId": "cosmoshub-3",
|
||||
"lcd": "https://lcd.nylira.net",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"name": "Cosmos Hub",
|
||||
"rpc": "https://rpc.nylira.net",
|
||||
"version": "0.32.7",
|
||||
"api": 'V1',
|
||||
"unit": 'ATOM',
|
||||
"prefix": 'cosmos',
|
||||
"host": isDev ? '' : 'cosmos.ping.pub'
|
||||
},
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:13:34
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-13 23:16:37
|
||||
* @FilePath: \look-web\server\src\models\chain.js
|
||||
*/
|
||||
var mongoose = require('mongoose');
|
||||
const dayjs = require('dayjs')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
const tableSchema = new Schema({
|
||||
// 分类 Mainnet Testnet GOZ
|
||||
type: {
|
||||
type: String, index: true
|
||||
},
|
||||
// 显示名称
|
||||
name: String,
|
||||
logo: String,
|
||||
chainId: String,
|
||||
desc: String,
|
||||
lcd: String,
|
||||
rpc: String,
|
||||
version: String,
|
||||
// 接口版本 V1 类 cosmoshub V2 类 irishub
|
||||
api: String,
|
||||
unit: String,
|
||||
prefix: String,
|
||||
host: String,
|
||||
genesis_time: Date,
|
||||
// 创建时间
|
||||
created: { type: Date, default: Date.now },
|
||||
// 更新时间
|
||||
updated: { type: Date, default: Date.now }
|
||||
})
|
||||
|
||||
tableSchema.methods.toJSONObject = function () {
|
||||
return {
|
||||
name: this.name,
|
||||
logo: this.logo,
|
||||
code: this.code,
|
||||
created: dayjs(this.created).format('YYY MM DD HH:MM:ss'),
|
||||
updated: dayjs(this.updated).format('YYY MM DD HH:MM:ss')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mongoose.model("look_chain", tableSchema);
|
36
server/src/routes/chain_create.js
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Description: 创建链
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:20:07
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-25 21:59:43
|
||||
* @FilePath: \look-web\server\src\routes\chain_create.js
|
||||
*/
|
||||
|
||||
const { ok, routerRun } = require("../base/utils.js");
|
||||
const { body } = require("express-validator");
|
||||
|
||||
const Chain = require("../models/chain");
|
||||
|
||||
module.exports = (router) => {
|
||||
// 路由
|
||||
const uri = "/chain/create";
|
||||
// 验证
|
||||
const valid = () => {
|
||||
return [
|
||||
body("name").notEmpty(),
|
||||
body("lcd").notEmpty(),
|
||||
body("rpc").notEmpty(),
|
||||
body("api").notEmpty(),
|
||||
body("type").notEmpty()
|
||||
];
|
||||
};
|
||||
// 逻辑
|
||||
const logic = async (req, res) => {
|
||||
const row = new Chain({ ...req.body });
|
||||
await row.save();
|
||||
ok(res);
|
||||
};
|
||||
// 封装
|
||||
routerRun.post(router, uri, valid, logic)
|
||||
};
|
42
server/src/routes/chain_delete.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* @Description: 创建链
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:20:07
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-15 22:26:50
|
||||
* @FilePath: /look-web/server/src/routes/chain_delete.js
|
||||
*/
|
||||
|
||||
const { ok, routerRun } = require("../base/utils.js");
|
||||
const { body } = require("express-validator");
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const Chain = require("../models/chain");
|
||||
|
||||
module.exports = (router) => {
|
||||
// 路由
|
||||
const uri = "/chain/delete";
|
||||
// 验证
|
||||
const valid = () => {
|
||||
return [
|
||||
body("lookpwd").notEmpty(),
|
||||
body("ids").notEmpty(),
|
||||
body("lookpwd").custom(async (value, { req }) => {
|
||||
if (value !== "@ping@dddd")
|
||||
throw new Error("密码错误");
|
||||
return true;
|
||||
}),
|
||||
];
|
||||
};
|
||||
// 逻辑
|
||||
const logic = async (req, res) => {
|
||||
const ids = req.body.ids
|
||||
for (let id of ids) {
|
||||
id = mongoose.Types.ObjectId(id);
|
||||
}
|
||||
const row = await Chain.deleteMany({ _id: { $in: ids } });
|
||||
ok(res, row);
|
||||
};
|
||||
// 封装
|
||||
routerRun.post(router, uri, valid, logic)
|
||||
};
|
38
server/src/routes/chain_init.js
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 22:38:46
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-13 23:10:45
|
||||
* @FilePath: \look-web\server\src\routes\chain_init.js
|
||||
*/
|
||||
|
||||
const { ok, routerRun } = require("../base/utils.js");
|
||||
|
||||
const Chain = require("../models/chain");
|
||||
const initChains = require('../initChains')
|
||||
|
||||
module.exports = (router) => {
|
||||
// 路由
|
||||
const uri = "/chain/init";
|
||||
// 验证
|
||||
const valid = () => {
|
||||
return [];
|
||||
};
|
||||
// 逻辑
|
||||
const logic = async (req, res) => {
|
||||
const Mainnet = initChains.Mainnet
|
||||
for (const item of Mainnet) {
|
||||
const row = new Chain({ ...item, type: 'Mainnet' });
|
||||
await row.save();
|
||||
}
|
||||
const Testnet = initChains.Testnet
|
||||
for (const item of Testnet) {
|
||||
const row = new Chain({ ...item, type: 'Testnet' });
|
||||
await row.save();
|
||||
}
|
||||
ok(res);
|
||||
};
|
||||
// 封装
|
||||
routerRun.post(router, uri, valid, logic)
|
||||
};
|
29
server/src/routes/chain_list.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @Description: 查询链
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:20:07
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-15 22:34:02
|
||||
* @FilePath: /look-web/server/src/routes/chain.js
|
||||
*/
|
||||
|
||||
const { ok, routerRun } = require("../base/utils.js");
|
||||
|
||||
const Chain = require("../models/chain");
|
||||
|
||||
module.exports = (router) => {
|
||||
// 路由
|
||||
const uri = "/chain/list";
|
||||
// 验证
|
||||
const valid = () => {
|
||||
return [
|
||||
];
|
||||
};
|
||||
// 逻辑
|
||||
const logic = async (req, res) => {
|
||||
const rows = await Chain.find().exec()
|
||||
ok(res, rows);
|
||||
};
|
||||
// 封装
|
||||
routerRun.post(router, uri, valid, logic)
|
||||
};
|
68
server/src/routes/chain_type.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* @Description: 查询链
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-13 11:20:07
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-25 21:55:10
|
||||
* @FilePath: \look-web\server\src\routes\chain_type.js
|
||||
*/
|
||||
|
||||
const { ok, routerRun } = require("../base/utils.js");
|
||||
const { query } = require("express-validator");
|
||||
|
||||
const Chain = require("../models/chain");
|
||||
|
||||
module.exports = (router) => {
|
||||
// 路由
|
||||
const uri = "/chain/type";
|
||||
// 验证
|
||||
const valid = () => {
|
||||
return [
|
||||
];
|
||||
};
|
||||
// 逻辑
|
||||
const logic = async (req, res) => {
|
||||
const rows = await Chain.aggregate([
|
||||
{
|
||||
$group: {
|
||||
_id: "$type",
|
||||
chains: {
|
||||
$push: {
|
||||
hash: '$_id',
|
||||
api: '$api',
|
||||
chainId: '$chainId',
|
||||
name: '$name',
|
||||
lcd: '$lcd',
|
||||
rpc: '$rpc',
|
||||
logo: '$logo',
|
||||
prefix: '$prefix',
|
||||
unit: '$unit',
|
||||
genesis_time: '$genesis_time',
|
||||
host: '$host',
|
||||
// version: '$version',
|
||||
// type: '$type',
|
||||
// created: '$created',
|
||||
// updated: '$updated'
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
created: 1
|
||||
}
|
||||
}
|
||||
]).exec()
|
||||
const obj = {}
|
||||
for (const item of rows) {
|
||||
obj[item._id] = item.chains
|
||||
}
|
||||
ok(res, {
|
||||
Mainnet: obj['Mainnet'],
|
||||
Testnet: obj['Testnet'],
|
||||
GoZ: obj['GoZ'],
|
||||
});
|
||||
};
|
||||
// 封装
|
||||
routerRun.get(router, uri, valid, logic)
|
||||
};
|
25
server/src/routes/index.js
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Description: routes list
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-08 16:30:15
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-15 22:27:07
|
||||
* @FilePath: /look-web/server/src/routes/index.js
|
||||
*/
|
||||
|
||||
const routes = [
|
||||
'chain_create',
|
||||
'chain_type',
|
||||
'chain_init',
|
||||
'chain_delete',
|
||||
'chain_list'
|
||||
]
|
||||
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
|
||||
for (const item of routes) {
|
||||
require(`./${item}`)(router)
|
||||
}
|
||||
|
||||
module.exports = router
|
128
src/api/V1/request.js
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2020-12-11 15:29:37
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /look-web/src/api/V1/request.js
|
||||
*/
|
||||
const get = (url) => ({ method: 'get', url, headers: { server: window.chain.lcd } })
|
||||
const getRpc = (url) => ({ method: 'get', url, headers: { server: window.chain.rpc } })
|
||||
|
||||
export const getKavaCdpParameters = () => (get('/cdp/parameters'))
|
||||
export const getKavaPricefeed = () => (get('/pricefeed/parameters'))
|
||||
export const getKavaIncentive = () => (get('/incentive/parameters'))
|
||||
export const getKavaBep3 = () => (get('/bep3/parameters'))
|
||||
export const getKavaAuction = () => (get('/auction/parameters'))
|
||||
|
||||
// RPC ===
|
||||
export const getRpcCommitHeight = ({ height }) => (getRpc(`/commit?height=${height}`))
|
||||
export const getRpcBlockchain = ({ minHeight, maxHeight }) => (getRpc(`/blockchain?minHeight=${minHeight}&maxHeight=${maxHeight}`))
|
||||
export const getRpcValidators = ({ height }) => (getRpc(`/validators?height=${height}`))
|
||||
export const getRpcGenesis = () => (getRpc('/genesis'))
|
||||
export const getRpcConsensus_state = () => (getRpc('/consensus_state'))
|
||||
// 获取最新高度
|
||||
export const getRpcAbciInfo = () => (getRpc('/abci_info'))
|
||||
// LCD ===
|
||||
// node info
|
||||
// Auth
|
||||
export const getAuthAccounts = ({ address }) => (get(`/auth/accounts/${address}`))
|
||||
// Blocks
|
||||
export const getBlocksLatest = () => (get('/blocks/latest'))
|
||||
export const getBlocksHeight = ({ height }) => (get(`/blocks/${height}`))
|
||||
// Distribution
|
||||
export const getDistributionParameters = () => (get('/distribution/parameters'))
|
||||
export const getDistributionDelegatorsRewards = ({ delegatorAddress }) => (get(`/distribution/delegators/${delegatorAddress}/rewards`))
|
||||
// Gov
|
||||
export const getGovParametersDeposit = () => (get('/gov/parameters/deposit'))
|
||||
export const getGovParametersVoting = () => (get('/gov/parameters/voting'))
|
||||
export const getGovParametersTallying = () => (get('/gov/parameters/tallying'))
|
||||
// goverance
|
||||
export const getGovProposals = () => (get('/gov/proposals'))
|
||||
export const getGovProposalsId = ({ id }) => (get(`/gov/proposals/${id}`))
|
||||
export const getGovProposalsDeposits = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/deposits`))
|
||||
export const getGovProposalsVotes = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/votes`))
|
||||
// committee
|
||||
export const getCommitteeCommittees = () => {}
|
||||
export const getCommitteeCommitteesId = ({ id }) => (get(`/committee/committees/${id}`))
|
||||
// Slashing
|
||||
export const getSlashingParameters = () => (get('/slashing/parameters'))
|
||||
export const getSlashingValidatorsSigningInfo = ({ validatorAddress }) => (get(`/slashing/validators/${validatorAddress}/signing_info`))
|
||||
export const getSupplyTotal = () => (get('/supply/total'))
|
||||
export const getStakingPool = () => (get('/staking/pool'))
|
||||
export const getStakingParameters = () => (get('/staking/parameters'))
|
||||
export const getStakingValidators = ({ status }) => (get(`/staking/validators?status=${status || 'bonded'}`))
|
||||
export const getStakingValidatorsObj = ({ status }) => (get(`/staking/validators?status=${status || 'bonded'}`))
|
||||
export const getStakingValidatorsValidatorAddress = ({ validatorAddress }) => (get(`/staking/validators/${validatorAddress}`))
|
||||
export const getStakingDelegatorsDelegations = ({ delegatorAddress }) => (get(`/staking/delegators/${delegatorAddress}/delegations`))
|
||||
export const getStakingValidatorsDelegations = ({ validatorAddress }) => (get(`/staking/validators/${validatorAddress}/delegations`))
|
||||
// Minting
|
||||
export const getMintingParameters = () => (get('/minting/parameters'))
|
||||
export const getMintingInflation = () => (get('/minting/inflation'))
|
||||
export const getMintingAnnualProvisionsn = () => (get('/minting/annual-provisions'))
|
||||
// Node
|
||||
export const getNodeInfo = () => (get('/node_info'))
|
||||
export const getNodeInfoRes = () => (get('/node_info'))
|
||||
// Tx
|
||||
export const getTxs = ({ height }) => {
|
||||
const config = get('/txs')
|
||||
config.params = {
|
||||
'tx.height': height
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHistory = ({ address, page, }) => {
|
||||
const config = get('/txs')
|
||||
config.params = {
|
||||
page,
|
||||
limit: 10,
|
||||
'message.sender': address
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHash = ({ hash }) => (get(`/txs/${hash}`))
|
||||
// Validators
|
||||
export const getValidatorsetsHeight = ({ height }) => (get(`/validatorsets/${height}`))
|
||||
|
||||
// POST ===
|
||||
// post Send coins from one account to another
|
||||
export function postBankAccountsTransfers({ address, chain_id, account_number, sequence, amount, denom, memo, simulate }) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/bank/accounts/${address}/transfers`,
|
||||
data: {
|
||||
base_req: {
|
||||
"from": address,
|
||||
"memo": memo || "Sent via look.ping.pub",
|
||||
chain_id,
|
||||
account_number,
|
||||
sequence,
|
||||
"gas": "200000",
|
||||
"gas_adjustment": "2.3",
|
||||
"fees": [
|
||||
Coin({ amount, denom })
|
||||
],
|
||||
simulate
|
||||
},
|
||||
"amount": [
|
||||
Coin({ amount, denom })
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// post Broadcast a signed tx
|
||||
export function postTxs({ txBroadcast }) {
|
||||
const config = get('/txs')
|
||||
config.method = 'post'
|
||||
config.data = { ...txBroadcast }
|
||||
return config
|
||||
}
|
||||
|
||||
function Coin({ amount, denom }) {
|
||||
return {
|
||||
amount: String(amount),
|
||||
denom
|
||||
};
|
||||
}
|
||||
|
466
src/api/V1/response.js
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2020-12-11 15:09:36
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: \look-web\src\api\V1\response.js
|
||||
*/
|
||||
import { timeToDay, toDenom, toTimestamp, formatTime } from '../../utils/format'
|
||||
import { createDisplayCoin, percent, twoDecimals, uatoms, atoms } from '../../utils/num'
|
||||
import { addressToHex, validatorAddressToAccount } from '../../utils/b32'
|
||||
import dayjs from 'dayjs'
|
||||
import store from '../../store'
|
||||
|
||||
const commonResult = (res) => res.result
|
||||
|
||||
export function getNodeInfo(res) {
|
||||
const { network, version } = res.node_info || {}
|
||||
return {
|
||||
network,
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
export function getNodeInfoRes(res) {
|
||||
return res
|
||||
}
|
||||
|
||||
export function getKavaCdpParameters(res) {
|
||||
let result = commonResult(res);
|
||||
result.debt_auction_lot = timeToDay(result.debt_auction_lot)
|
||||
result.surplus_auction_lot = timeToDay(result.surplus_auction_lot)
|
||||
result.debt_auction_threshold = timeToDay(result.debt_auction_threshold)
|
||||
result.surplus_auction_threshold = timeToDay(result.surplus_auction_threshold)
|
||||
result.savings_distribution_frequency = timeToDay(result.savings_distribution_frequency)
|
||||
result.debt_param.savings_rate = percent(result.debt_param.savings_rate)
|
||||
return result
|
||||
}
|
||||
export function getKavaPricefeed(res) { let result = commonResult(res); return result }
|
||||
export function getKavaIncentive(res) {
|
||||
let result = commonResult(res);
|
||||
for (const item of result.rewards) {
|
||||
item.duration = timeToDay(item.duration)
|
||||
item.claim_duration = timeToDay(item.claim_duration)
|
||||
item.time_lock = timeToDay(item.time_lock)
|
||||
}
|
||||
return result }
|
||||
export function getKavaBep3(res) { let result = commonResult(res); return result }
|
||||
export function getKavaAuction(res) {
|
||||
let result = commonResult(res);
|
||||
result.max_auction_duration = timeToDay(result.max_auction_duration)
|
||||
result.bid_duration = timeToDay(result.bid_duration)
|
||||
result.increment_collateral = percent(result.increment_collateral)
|
||||
result.increment_surplus = percent(result.increment_surplus)
|
||||
result.increment_debt = percent(result.increment_debt)
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getAuthAccounts(res) {
|
||||
const result = commonResult(res)
|
||||
const { type, value } = result
|
||||
let coins = value.coins[0]
|
||||
coins = createDisplayCoin(coins)
|
||||
return {
|
||||
type,
|
||||
available: coins.amount,
|
||||
...value
|
||||
}
|
||||
}
|
||||
|
||||
export const postBankAccountsTransfers = (res) => Math.round(res.gas_estimate * 2.3)
|
||||
export const getStakingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_entries, max_validators, unbonding_time, bond_denom } = data
|
||||
return {
|
||||
max_entries,
|
||||
max_validators,
|
||||
unbonding_time: timeToDay(unbonding_time),
|
||||
bond_denom: toDenom(bond_denom)
|
||||
}
|
||||
}
|
||||
export const postTxs = (res) => (res)
|
||||
function formatValidator(item) {
|
||||
item.dailyChange = '--'
|
||||
item.rewards = '--'
|
||||
const { identity, moniker, website, details } = item.description
|
||||
item.moniker = moniker
|
||||
item.identity = identity
|
||||
item.website = website
|
||||
item.details = details
|
||||
item.voting_power = atoms(Number(item.tokens)).toFixed(2) + ' ' + window.chain.unit // TODO: 单位问题
|
||||
item.userAddress = validatorAddressToAccount(item.operator_address)
|
||||
item.hexAddress = addressToHex(item.consensus_pubkey)
|
||||
item.commission_rate = Number(item.commission.commission_rates.rate)
|
||||
item.commission_rate_percent = percent(item.commission_rate)
|
||||
item.commission_rate_max = Number(item.commission.commission_rates.max_rate)
|
||||
item.commission_rate_max_percent = percent(item.commission_rate_max)
|
||||
item.commission_rate_max_change = Number(item.commission.commission_rates.max_change_rate)
|
||||
item.commission_rate_max_change_percent = percent(item.commission_rate_max_change)
|
||||
if (item.unbonding_time) {
|
||||
item.unbonding_time = formatTime(item.unbonding_time)
|
||||
}
|
||||
}
|
||||
export const getStakingValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.sort((current, next) => {
|
||||
formatValidator(current)
|
||||
formatValidator(next)
|
||||
return Number(next.tokens) - Number(current.tokens);
|
||||
})
|
||||
if (data.length === 1) formatValidator(data[0])
|
||||
return res
|
||||
}
|
||||
|
||||
export const getStakingValidatorsObj = (res) => {
|
||||
const data = commonResult(res)
|
||||
const hexObj = {}
|
||||
const addressObj = {}
|
||||
const validatorObj = {}
|
||||
for (const item of data) {
|
||||
formatValidator(item)
|
||||
hexObj[item.hexAddress] = item
|
||||
addressObj[item.userAddress] = item
|
||||
validatorObj[item.operator_address] = item
|
||||
}
|
||||
return {
|
||||
hexObj,
|
||||
addressObj,
|
||||
validatorObj
|
||||
}
|
||||
}
|
||||
|
||||
export const getGovParametersDeposit = (res) => {
|
||||
const data = commonResult(res)
|
||||
const coin = createDisplayCoin(data.min_deposit[0])
|
||||
return {
|
||||
min_deposit: coin.amount + coin.denom,
|
||||
max_deposit_period: timeToDay(data.max_deposit_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersVoting = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
voting_period: timeToDay(data.voting_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersTallying = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { quorum, threshold, veto } = data
|
||||
return {
|
||||
quorum: percent(quorum),
|
||||
threshold: percent(threshold),
|
||||
veto: percent(veto)
|
||||
}
|
||||
}
|
||||
export const getSlashingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_evidence_age, slash_fraction_downtime, downtime_jail_duration, signed_blocks_window, min_signed_per_window, slash_fraction_double_sign } = data
|
||||
return {
|
||||
max_evidence_age: timeToDay(max_evidence_age),
|
||||
downtime_jail_duration: timeToDay(downtime_jail_duration),
|
||||
signed_blocks_window: Number(signed_blocks_window),
|
||||
min_signed_per_window: percent(min_signed_per_window),
|
||||
slash_fraction_double_sign: percent(slash_fraction_double_sign),
|
||||
slash_fraction_downtime: percent(slash_fraction_downtime)
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { community_tax, base_proposer_reward, bonus_proposer_reward, withdraw_addr_enabled } = data
|
||||
return {
|
||||
community_tax: percent(community_tax),
|
||||
base_proposer_reward: percent(base_proposer_reward),
|
||||
bonus_proposer_reward: percent(bonus_proposer_reward),
|
||||
withdraw_addr_enabled: withdraw_addr_enabled ? "Enabled" : "Disabled"
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let total = 0
|
||||
for (const item of data) {
|
||||
total += Number(item.shares)
|
||||
item.shares_str = atoms(Number(item.shares)) + ' ' + window.chain.unit
|
||||
}
|
||||
data.sort((now, next) => {
|
||||
now.shares_percent = percent(Number(now.shares) / total)
|
||||
next.shares_percent = percent(Number(next.shares) / total)
|
||||
return Number(next.shares) - Number(now.shares)
|
||||
})
|
||||
if (data.length === 1) {
|
||||
data[0].shares_percent = percent(Number(data[0].shares) / total)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const getSlashingValidatorsSigningInfo = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
missed_blocks_counter: data.missed_blocks_counter
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingParameters = (result) => {
|
||||
const data = commonResult(result)
|
||||
const { blocks_per_year, inflation_rate_change } = data
|
||||
return {
|
||||
blocks_per_year,
|
||||
mint_denom: toDenom(data.mint_denom),
|
||||
inflation_rate_change: percent(inflation_rate_change),
|
||||
inflation_max: percent(data.inflation_max),
|
||||
inflation_min: percent(data.inflation_min),
|
||||
goal_bonded: percent(data.goal_bonded),
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingInflation = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
inflation: percent(data),
|
||||
inflation_val: Number(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingAnnualProvisionsn = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
annual_provisions: (Number(data) / 1000000).toFixed(0)
|
||||
}
|
||||
}
|
||||
// /gov/proposals 方法
|
||||
function dataFormat(item) {
|
||||
const content = item.proposal_content || item.content
|
||||
item.title = content.value.title;
|
||||
item.description = content.value.description
|
||||
item.description_sub = item.description.length > 200 ? (item.description).substr(0, 200) : item.description
|
||||
|
||||
const { voting_start_time, voting_end_time, deposit_end_time, submit_time, total_deposit } = item
|
||||
item.total_deposit_str = total_deposit && total_deposit[0] && createDisplayCoin(total_deposit[0]) || '--'
|
||||
item.submit_time = formatTime(submit_time)
|
||||
item.voting_start_time = formatTime(voting_start_time)
|
||||
item.voting_end_time = formatTime(voting_end_time)
|
||||
item.deposit_end_time = formatTime(deposit_end_time)
|
||||
|
||||
// item.final_tally_result
|
||||
const { yes, abstain, no, no_with_veto } = item.final_tally_result
|
||||
// 参与总数
|
||||
const total = yes && (Number(yes) + Number(abstain) + Number(no) + Number(no_with_veto)) || 1
|
||||
item.yes = yes && twoDecimals(yes / total) || '--'
|
||||
item.yes_percent = yes && percent(yes / total) || '--'
|
||||
item.abstain = abstain && twoDecimals(abstain / total) || '--'
|
||||
item.abstain_percent = abstain && percent(abstain / total) || '--'
|
||||
item.no = no && twoDecimals(no / total) || '--'
|
||||
item.no_percent = no && percent(no / total) || '--'
|
||||
item.no_with_veto = no_with_veto && twoDecimals(no_with_veto / total) || '--'
|
||||
item.no_with_veto_percent = no_with_veto && percent(no_with_veto / total) || '--'
|
||||
item.type = content.type
|
||||
|
||||
// 质押总数
|
||||
const bondedTokens = store.state.bondedTokens
|
||||
if (bondedTokens) {
|
||||
item.join = twoDecimals(total / bondedTokens)
|
||||
item.join_percent = percent(total / bondedTokens)
|
||||
}
|
||||
}
|
||||
|
||||
// kava 投票接口
|
||||
function formateCommitee(data) {
|
||||
for (const item of data) {
|
||||
item.vote_threshold_str = Number(item.vote_threshold).toFixed(2)
|
||||
item.proposal_duration_str = item.proposal_duration
|
||||
}
|
||||
}
|
||||
export function getCommitteeCommittees(res) {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getCommitteeCommitteesId = (res) => {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getGovProposals = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.sort((now, next) => {
|
||||
dataFormat(now)
|
||||
dataFormat(next)
|
||||
return (
|
||||
toTimestamp(next.submit_time) - toTimestamp(now.submit_time)
|
||||
);
|
||||
});
|
||||
if (data.length === 1) dataFormat(data[0])
|
||||
return data
|
||||
}
|
||||
|
||||
export const getGovProposalsId = (res) => {
|
||||
const data = commonResult(res)
|
||||
dataFormat(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksLatest = (res) => {
|
||||
const { block } = res
|
||||
return {
|
||||
height: Number(block.header.height)
|
||||
}
|
||||
}
|
||||
export const getSupplyTotal = (res) => {
|
||||
const data = commonResult(res)
|
||||
const amount = Number(data[0].amount)
|
||||
const amount_str = amount > 1000000
|
||||
? (amount / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (amount / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
amount,
|
||||
amount_str
|
||||
}
|
||||
}
|
||||
export const getStakingPool = (res) => {
|
||||
const data = commonResult(res)
|
||||
let { bonded_tokens } = data
|
||||
const bonded_tokens_val = Number(bonded_tokens)
|
||||
bonded_tokens = bonded_tokens_val > 1000000
|
||||
? (bonded_tokens_val / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (bonded_tokens_val / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
bonded_tokens_val,
|
||||
bonded_tokens
|
||||
}
|
||||
}
|
||||
|
||||
export const getValidatorsetsHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data.validators
|
||||
}
|
||||
|
||||
|
||||
export const getTxs = (res) => (res)
|
||||
|
||||
export const getTxsHistory = (res) => {
|
||||
res.txs.sort((current, next) => {
|
||||
const dayCurrent = dayjs(current.timestap).valueOf()
|
||||
const dayNext = dayjs(next.timestap).valueOf()
|
||||
return dayCurrent - dayNext
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
export const getGovProposalsDeposits = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
for (const item of data) {
|
||||
item.amountCoin = createDisplayCoin(item.amount[0])
|
||||
item.amountCoin_str = item.amountCoin.amount + ' ' + item.amountCoin.denom
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// getGovProposalsVotes
|
||||
export const getGovProposalsVotes = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksHeight = (res) => {
|
||||
return res
|
||||
}
|
||||
|
||||
export const getTxsHash = (res) => (res)
|
||||
export const getStakingValidatorsValidatorAddress = (res) => {
|
||||
const data = (commonResult(res))
|
||||
formatValidator(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getStakingDelegatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let delegated = 0
|
||||
for (const item of data) {
|
||||
item.shares = atoms(Number(item.shares))
|
||||
delegated += Number(item.shares)
|
||||
}
|
||||
delegated += ''
|
||||
return {
|
||||
delegated,
|
||||
delegations: data
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionDelegatorsRewards = (res) => {
|
||||
const data = commonResult(res)
|
||||
const rewards = data.rewards || []
|
||||
const obj = {}
|
||||
for (const item of rewards) {
|
||||
const coin = createDisplayCoin(item.reward[0])
|
||||
item.amount = coin.amount
|
||||
obj[item.validator_address] = {
|
||||
amount: item.amount
|
||||
}
|
||||
}
|
||||
const total = data.total[0] ? createDisplayCoin(data.total[0]) : { amount: '0' }
|
||||
return {
|
||||
rewardObj: obj,
|
||||
reward: total.amount,
|
||||
rewards
|
||||
}
|
||||
}
|
||||
|
||||
// RPC ===
|
||||
export const getRpcAbciInfo = (res) => {
|
||||
return {
|
||||
last_block_height: res.response.last_block_height
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcCommitHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
const precommits = (data.signed_header && data.signed_header.commit && data.signed_header.commit.precommits) || (data.signed_header && data.signed_header.commit && data.signed_header.commit.signatures)
|
||||
const obj = {}
|
||||
for (const item of precommits) {
|
||||
if (item) {
|
||||
const { validator_address } = item
|
||||
obj[validator_address] = true
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
export const getRpcValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data
|
||||
}
|
||||
|
||||
// 创世节点
|
||||
export const getRpcGenesis = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.genesis_time = data.genesis.genesis_time
|
||||
return data
|
||||
}
|
||||
|
||||
export const getRpcConsensus_state = (res) => {
|
||||
const data = commonResult(res)
|
||||
const height_vote_set = data.round_state.height_vote_set
|
||||
return {
|
||||
height_vote_set
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcBlockchain = (res) => {
|
||||
const data = commonResult(res)
|
||||
const last_height = Number(data.last_height)
|
||||
const block_metas = []
|
||||
for (const item of data.block_metas) {
|
||||
const { header, block_id } = item
|
||||
const { num_txs, height, last_block_id, time } = header
|
||||
header.block_hash = block_id.hash
|
||||
header.num_txs = num_txs && Number(num_txs) || (item.num_txs && Number(item.num_txs))
|
||||
header.last_block_hash = last_block_id.hash
|
||||
header.time = formatTime(time)
|
||||
block_metas.push(header)
|
||||
}
|
||||
return {
|
||||
last_height,
|
||||
block_metas
|
||||
}
|
||||
}
|
130
src/api/V2/request.js
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2021-03-10 16:46:43
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: \look-web\src\api\V2\request.js
|
||||
*/
|
||||
const get = (url) => ({ method: 'get', url, headers: { server: window.chain.lcd } })
|
||||
const getRpc = (url) => ({ method: 'get', url, headers: { server: window.chain.rpc } })
|
||||
|
||||
// RPC ===
|
||||
export const getRpcCommitHeight = ({ height }) => (getRpc(`/commit?height=${height}`))
|
||||
export const getRpcBlockchain = ({ minHeight, maxHeight }) => (getRpc(`/blockchain?minHeight=${minHeight}&maxHeight=${maxHeight}`))
|
||||
export const getRpcValidators = ({ height }) => (getRpc(`/validators?height=${height}`))
|
||||
// 获取最新高度
|
||||
export const getRpcAbciInfo = () => (getRpc('/abci_info'))
|
||||
// LCD ===
|
||||
// node info
|
||||
// Auth
|
||||
export const getAuthAccounts = ({ address }) => (get(`/auth/accounts/${address}`))
|
||||
export const getValidatorsetsLatest = () => (get('/validatorsets/latest'))
|
||||
// Blocks
|
||||
export const getBlocksLatest = () => (get('/blocks/latest'))
|
||||
export const getBlocksHeight = ({ height }) => (get(`/blocks/${height}`))
|
||||
// Distribution
|
||||
export const getDistributionParameters = () => (get('/params?module=distr'))
|
||||
// Gov
|
||||
export const getGovParametersDeposit = () => (false) //(get('/gov/parameters/deposit'))
|
||||
export const getGovParametersVoting = () => (false)// (get('/gov/parameters/voting'))
|
||||
export const getGovParametersTallying = () => (false) //(get('/gov/parameters/tallying'))
|
||||
export const getGovProposals = () => (get('/gov/proposals'))
|
||||
export const getGovProposalsId = ({ id }) => (get(`/gov/proposals/${id}`))
|
||||
export const getGovProposalsDeposits = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/deposits`))
|
||||
export const getGovProposalsVotes = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/votes`))
|
||||
// Slashing
|
||||
export const getSlashingParameters = () => (get('/params?module=slashing'))
|
||||
export const getSlashingValidatorsSigningInfo = ({ validatorAddress }) => (get(`/slashing/validators/${validatorAddress}/signing-info`))
|
||||
export const getSupplyTotal = () => (get('/supply/total'))
|
||||
export const getStakingPool = () => (get('/stake/pool'))
|
||||
export const getStakingParameters = () => (get('/stake/parameters'))
|
||||
export const getStakingValidators = ({ status }) => {
|
||||
const requests = [
|
||||
get(`/stake/validators?page=1&size=100`),
|
||||
get(`/stake/validators?page=2&size=100`),
|
||||
get(`/validatorsets/latest`)
|
||||
]
|
||||
if (!status) {
|
||||
status = 'bonded'
|
||||
}
|
||||
return {
|
||||
type: 'array',
|
||||
params: {
|
||||
status
|
||||
},
|
||||
requests
|
||||
}
|
||||
}
|
||||
export const getStakingValidatorsObj = ({ status }) => {
|
||||
return {
|
||||
type: 'array',
|
||||
requests: [
|
||||
get(`/stake/validators?page=1&size=100`),
|
||||
get(`/stake/validators?page=2&size=100`),
|
||||
]
|
||||
}
|
||||
}
|
||||
export const getStakingValidatorsValidatorAddress = ({ validatorAddress }) => (get(`/stake/validators/${validatorAddress}`))
|
||||
export const getStakingValidatorsDelegations = ({ validatorAddress }) => (get(`/stake/validators/${validatorAddress}/delegations`))
|
||||
// Minting
|
||||
export const getMintingParameters = () => (get('/params?module=mint'))
|
||||
export const getMintingInflation = () => (get('/params?module=mint'))
|
||||
export const getMintingAnnualProvisionsn = () => (false)// (get('/minting/annual-provisions'))
|
||||
// Node
|
||||
export const getNodeInfo = () => (get('/node_info'))
|
||||
export const getNodeInfoRes = () => (get('/node-info'))
|
||||
// Tx
|
||||
export const getTxs = ({ height }) => {
|
||||
const config = get('/txs')
|
||||
config.params = {
|
||||
'tx.height': height
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHash = ({ hash }) => (get(`/txs/${hash}`))
|
||||
// Validators
|
||||
export const getValidatorsetsHeight = ({ height }) => (get(`/validatorsets/${height}`))
|
||||
|
||||
// POST ===
|
||||
// post Send coins from one account to another
|
||||
export function postBankAccountsTransfers({ address, chain_id, account_number, sequence, amount, denom, memo, simulate }) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/bank/accounts/${address}/transfers`,
|
||||
data: {
|
||||
base_req: {
|
||||
"from": address,
|
||||
"memo": memo || "Sent via look.ping.pub",
|
||||
chain_id,
|
||||
account_number,
|
||||
sequence,
|
||||
"gas": "200000",
|
||||
"gas_adjustment": "2.3",
|
||||
"fees": [
|
||||
Coin({ amount, denom })
|
||||
],
|
||||
simulate
|
||||
},
|
||||
"amount": [
|
||||
Coin({ amount, denom })
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// post Broadcast a signed tx
|
||||
export function postTxs({ txBroadcast }) {
|
||||
const config = get('/txs')
|
||||
config.method = 'post'
|
||||
config.data = { ...txBroadcast }
|
||||
return config
|
||||
}
|
||||
|
||||
function Coin({ amount, denom }) {
|
||||
return {
|
||||
amount: String(amount),
|
||||
denom
|
||||
};
|
||||
}
|
||||
|
370
src/api/V2/response.js
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2021-03-10 17:00:40
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /look-web/src/api/V2/response.js
|
||||
*/
|
||||
import { timeToDay, toDenom, toTimestamp, formatTime } from '../../utils/format'
|
||||
import { createDisplayCoin, percent, twoDecimals, uatoms, toIris, atoms } from '../../utils/num'
|
||||
import { addressToHex, validatorAddressToAccount } from '../../utils/b32'
|
||||
import store from '../../store'
|
||||
|
||||
const commonResult = (res) => res
|
||||
|
||||
export function getNodeInfo(res) {
|
||||
const { network, version } = res.node_info || {}
|
||||
return {
|
||||
network,
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
export function getNodeInfoRes(res) {
|
||||
return res
|
||||
}
|
||||
|
||||
export function getAuthAccounts(res) {
|
||||
const result = commonResult(res)
|
||||
const { type, value } = result
|
||||
return {
|
||||
type,
|
||||
...value
|
||||
}
|
||||
}
|
||||
|
||||
export const postBankAccountsTransfers = (res) => Math.round(res.gas_estimate * 2.3)
|
||||
export const getStakingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_validators, unbonding_time } = data.value
|
||||
return {
|
||||
max_validators,
|
||||
unbonding_time: timeToDay(unbonding_time)
|
||||
}
|
||||
}
|
||||
export const postTxs = (res) => (res)
|
||||
function formatValidator(item) {
|
||||
item.dailyChange = '--'
|
||||
item.rewards = '--'
|
||||
const { identity, moniker, website, details } = item.description
|
||||
item.moniker = moniker
|
||||
item.identity = identity
|
||||
item.website = website
|
||||
item.details = details
|
||||
item.tokens = Number(item.tokens).toFixed(2)
|
||||
item.voting_power = Number(item.tokens).toFixed(2) // TODO: 单位问题
|
||||
item.userAddress = validatorAddressToAccount(item.operator_address)
|
||||
item.hexAddress = addressToHex(item.consensus_pubkey)
|
||||
item.commission_rate = Number(item.commission.rate)
|
||||
item.commission_rate_percent = percent(item.commission_rate)
|
||||
item.commission_rate_max = Number(item.commission.max_rate)
|
||||
item.commission_rate_max_percent = percent(item.commission_rate_max)
|
||||
item.commission_rate_max_change = Number(item.commission.max_change_rate)
|
||||
item.commission_rate_max_change_percent = percent(item.commission_rate_max_change)
|
||||
if (item.unbonding_time) {
|
||||
item.unbonding_time = formatTime(item.unbonding_time)
|
||||
}
|
||||
}
|
||||
export const getStakingValidators = (res) => {
|
||||
let [arr1, arr2, validatorsBonded, params] = res
|
||||
const validatorsAll = [...arr1, ...arr2]
|
||||
const height = Number(validatorsBonded.block_height)
|
||||
const validators = []
|
||||
const status = params.status === 'bonded' ? 2 : 0
|
||||
for (const item of validatorsAll) {
|
||||
if (item.status === status) {
|
||||
formatValidator(item)
|
||||
validators.push(item)
|
||||
}
|
||||
}
|
||||
validators.sort((current, next) => {
|
||||
return Number(next.tokens) - Number(current.tokens);
|
||||
})
|
||||
return {
|
||||
height,
|
||||
result: validators
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsObj = (res) => {
|
||||
const [arr1, arr2] = res
|
||||
const data = [...arr1, ...arr2]
|
||||
const hexObj = {}
|
||||
const addressObj = {}
|
||||
const validatorObj = {}
|
||||
for (const item of data) {
|
||||
formatValidator(item)
|
||||
hexObj[item.hexAddress] = item
|
||||
addressObj[item.userAddress] = item
|
||||
validatorObj[item.operator_address] = item
|
||||
}
|
||||
return {
|
||||
hexObj,
|
||||
addressObj,
|
||||
validatorObj
|
||||
}
|
||||
}
|
||||
|
||||
export const getGovParametersDeposit = (res) => {
|
||||
const data = commonResult(res)
|
||||
const coin = createDisplayCoin(data.min_deposit[0])
|
||||
return {
|
||||
min_deposit: coin.amount + coin.denom,
|
||||
max_deposit_period: timeToDay(data.max_deposit_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersVoting = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
voting_period: timeToDay(data.voting_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersTallying = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { quorum, threshold, veto } = data
|
||||
return {
|
||||
quorum: percent(quorum),
|
||||
threshold: percent(threshold),
|
||||
veto: percent(veto)
|
||||
}
|
||||
}
|
||||
export const getSlashingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_evidence_age, slash_fraction_downtime, downtime_jail_duration, signed_blocks_window, min_signed_per_window, slash_fraction_double_sign } = data.value
|
||||
return {
|
||||
max_evidence_age: timeToDay(max_evidence_age, true),
|
||||
downtime_jail_duration: timeToDay(downtime_jail_duration),
|
||||
signed_blocks_window: Number(signed_blocks_window),
|
||||
min_signed_per_window: percent(min_signed_per_window),
|
||||
slash_fraction_double_sign: percent(slash_fraction_double_sign),
|
||||
slash_fraction_downtime: percent(slash_fraction_downtime)
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { community_tax, base_proposer_reward, bonus_proposer_reward, withdraw_addr_enabled } = data.value
|
||||
return {
|
||||
community_tax: percent(community_tax),
|
||||
base_proposer_reward: percent(base_proposer_reward),
|
||||
bonus_proposer_reward: percent(bonus_proposer_reward),
|
||||
// withdraw_addr_enabled: withdraw_addr_enabled ? "Enabled" : "Disabled"
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let total = 0
|
||||
for (const item of data) {
|
||||
total += Number(item.shares)
|
||||
item.delegator_address = item.delegator_addr
|
||||
item.shares_str = atoms(Number(item.shares)) + ' ' + window.chain.unit
|
||||
}
|
||||
data.sort((now, next) => {
|
||||
now.shares_percent = percent(Number(now.shares) / total)
|
||||
next.shares_percent = percent(Number(next.shares) / total)
|
||||
return Number(next.shares) - Number(now.shares)
|
||||
})
|
||||
if (data.length === 1) {
|
||||
data[0].shares_percent = percent(Number(data[0].shares) / total)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const getSlashingValidatorsSigningInfo = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
missed_blocks_counter: data.missed_blocks_counter
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingParameters = (result) => {
|
||||
const data = commonResult(result)
|
||||
const { blocks_per_year, inflation_rate_change } = data
|
||||
return {
|
||||
blocks_per_year,
|
||||
mint_denom: '', // toDenom(data.mint_denom),
|
||||
inflation_rate_change: percent(inflation_rate_change),
|
||||
inflation_max: percent(data.inflation_max),
|
||||
inflation_min: percent(data.inflation_min),
|
||||
goal_bonded: percent(data.goal_bonded),
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingInflation = (res) => {
|
||||
let data = commonResult(res)
|
||||
data = data.value.inflation
|
||||
return {
|
||||
inflation: percent(data),
|
||||
inflation_val: Number(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingAnnualProvisionsn = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
annual_provisions: (Number(data) / 1000000).toFixed(0)
|
||||
}
|
||||
}
|
||||
// /gov/proposals 方法
|
||||
function dataFormat(item) {
|
||||
item = item.value.BasicProposal
|
||||
item.id = item.proposal_id
|
||||
item.description_sub = item.description.length > 200 ? (item.description).substr(0, 200) : item.description
|
||||
|
||||
const { voting_start_time, voting_end_time, deposit_end_time, submit_time, total_deposit } = item
|
||||
item.total_deposit_str = createDisplayCoin(total_deposit[0])
|
||||
item.submit_time = formatTime(submit_time)
|
||||
item.voting_start_time = formatTime(voting_start_time)
|
||||
item.voting_end_time = formatTime(voting_end_time)
|
||||
item.deposit_end_time = formatTime(deposit_end_time)
|
||||
const { yes, abstain, no, no_with_veto } = item.tally_result
|
||||
const total = Number(yes) + Number(abstain) + Number(no) + Number(no_with_veto)
|
||||
item.yes = twoDecimals(yes / total)
|
||||
item.yes_percent = percent(yes / total)
|
||||
item.abstain = twoDecimals(abstain / total)
|
||||
item.abstain_percent = percent(abstain / total)
|
||||
item.no = twoDecimals(no / total)
|
||||
item.no_percent = percent(no / total)
|
||||
item.no_with_veto = twoDecimals(no_with_veto / total)
|
||||
item.no_with_veto_percent = percent(no_with_veto / total)
|
||||
item.type = item.proposal_type
|
||||
// 质押总数
|
||||
const bondedTokens = store.state.bondedTokens
|
||||
if (bondedTokens) {
|
||||
item.join = twoDecimals(total / bondedTokens)
|
||||
item.join_percent = percent(total / bondedTokens)
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
export const getGovProposals = (res) => {
|
||||
const data = commonResult(res)
|
||||
const arr = []
|
||||
for (let item of data) {
|
||||
arr.push(dataFormat(item))
|
||||
}
|
||||
arr.sort((now, next) => {
|
||||
return (
|
||||
toTimestamp(next.submit_time) - toTimestamp(now.submit_time)
|
||||
);
|
||||
});
|
||||
return arr
|
||||
}
|
||||
|
||||
export const getGovProposalsId = (res) => {
|
||||
const data = commonResult(res)
|
||||
return dataFormat(data)
|
||||
}
|
||||
|
||||
export const getBlocksLatest = (res) => {
|
||||
const { block } = res
|
||||
return {
|
||||
height: Number(block.header.height)
|
||||
}
|
||||
}
|
||||
export const getSupplyTotal = (res) => {
|
||||
const data = commonResult(res)
|
||||
const amount = Number(data)
|
||||
const amount_str = amount > 1000000
|
||||
? (amount / 1000000).toFixed(2) + "M"
|
||||
: (amount / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
amount,
|
||||
amount_str
|
||||
}
|
||||
}
|
||||
export const getStakingPool = (res) => {
|
||||
const data = commonResult(res)
|
||||
let { bonded_tokens } = data
|
||||
const bonded_tokens_val = Number(bonded_tokens)
|
||||
bonded_tokens = bonded_tokens_val > 1000000
|
||||
? (bonded_tokens_val / 1000000).toFixed(2) + "M"
|
||||
: (bonded_tokens_val / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
bonded_tokens_val,
|
||||
bonded_tokens
|
||||
}
|
||||
}
|
||||
|
||||
export const getValidatorsetsHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data.validators
|
||||
}
|
||||
|
||||
|
||||
export const getTxs = (res) => (res)
|
||||
|
||||
export const getGovProposalsDeposits = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
for (const item of data) {
|
||||
item.amountCoin = createDisplayCoin(item.amount[0])
|
||||
item.amountCoin_str = item.amountCoin.amount + ' ' + item.amountCoin.denom
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// getGovProposalsVotes
|
||||
export const getGovProposalsVotes = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksHeight = (res) => {
|
||||
return res
|
||||
}
|
||||
|
||||
export const getTxsHash = (res) => (res)
|
||||
export const getStakingValidatorsValidatorAddress = (res) => {
|
||||
const data = (commonResult(res))
|
||||
formatValidator(data)
|
||||
return data
|
||||
}
|
||||
// RPC ===
|
||||
export const getRpcAbciInfo = (res) => {
|
||||
return {
|
||||
last_block_height: res.response.last_block_height
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcCommitHeight = (res) => {
|
||||
const data = res.result
|
||||
const precommits = data.signed_header.commit.precommits
|
||||
const obj = {}
|
||||
for (const item of precommits) {
|
||||
if (item) {
|
||||
const { validator_address } = item
|
||||
obj[validator_address] = true
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
export const getRpcValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data.result
|
||||
}
|
||||
|
||||
export const getValidatorsetsLatest = (res) => {
|
||||
return res
|
||||
}
|
||||
|
||||
export const getRpcBlockchain = (res) => {
|
||||
const data = commonResult(res).result
|
||||
const last_height = Number(data.last_height)
|
||||
const block_metas = []
|
||||
for (const item of data.block_metas) {
|
||||
const { header, block_id } = item
|
||||
const { num_txs, height, last_block_id, time } = header
|
||||
header.block_hash = block_id.hash
|
||||
header.num_txs = Number(num_txs)
|
||||
header.last_block_hash = last_block_id.hash
|
||||
header.time = formatTime(time)
|
||||
block_metas.push(header)
|
||||
}
|
||||
return {
|
||||
last_height,
|
||||
block_metas
|
||||
}
|
||||
}
|
145
src/api/V3/request.js
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2020-12-11 15:59:21
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /look-web/src/api/V1/request.js
|
||||
*/
|
||||
const prefixTx = '/cosmos/tx/v1beta1'
|
||||
const prefixDistribution = '/cosmos/distribution/v1beta1/v1beta1'
|
||||
const prefixGov = '/cosmos/gov/v1beta1'
|
||||
const prefixMinting = '/cosmos/minting/v1beta1'
|
||||
const prefixSlashing = '/cosmos/slashing/v1beta1'
|
||||
const prefixStaking = '/cosmos/staking/v1beta1'
|
||||
const prefiexBank = '/bank'
|
||||
|
||||
const get = (url) => ({ method: 'get', url, headers: { server: window.chain.lcd } })
|
||||
const getRpc = (url) => ({ method: 'get', url, headers: { server: window.chain.rpc } })
|
||||
|
||||
export const getKavaCdpParameters = () => (get('/cdp/parameters'))
|
||||
export const getKavaPricefeed = () => (get('/pricefeed/parameters'))
|
||||
export const getKavaIncentive = () => (get('/incentive/parameters'))
|
||||
export const getKavaBep3 = () => (get('/bep3/parameters'))
|
||||
export const getKavaAuction = () => (get('/auction/parameters'))
|
||||
|
||||
// RPC ===
|
||||
export const getRpcCommitHeight = ({ height }) => (getRpc(`/commit?height=${height}`))
|
||||
export const getRpcBlockchain = ({ minHeight, maxHeight }) => (getRpc(`/blockchain?minHeight=${minHeight}&maxHeight=${maxHeight}`))
|
||||
export const getRpcValidators = ({ height }) => (getRpc(`/validators?height=${height}`))
|
||||
export const getRpcGenesis = () => (getRpc('/genesis'))
|
||||
export const getRpcConsensus_state = () => (getRpc('/consensus_state'))
|
||||
// 获取最新高度
|
||||
export const getRpcAbciInfo = () => (getRpc('/abci_info'))
|
||||
|
||||
// LCD ===
|
||||
// node info
|
||||
// Auth
|
||||
export const getAuthAccounts = ({ address }) => (get(`/auth/accounts/${address}`))
|
||||
// Blocks
|
||||
export const getBlocksLatest = () => (get('/blocks/latest'))
|
||||
export const getBlocksHeight = ({ height }) => (get(`/blocks/${height}`))
|
||||
// Distribution
|
||||
// 未实现
|
||||
export const getDistributionParameters = () => (get('/distribution/parameters'))
|
||||
export const getDistributionDelegatorsRewards = ({ delegatorAddress }) => (get(prefixDistribution + `/delegators/${delegatorAddress}/rewards`))
|
||||
// Gov
|
||||
// 未实现
|
||||
export const getGovParametersDeposit = () => (get('/gov/parameters/deposit'))
|
||||
// 未实现
|
||||
export const getGovParametersVoting = () => (get('/gov/parameters/voting'))
|
||||
// 未实现
|
||||
export const getGovParametersTallying = () => (get('/gov/parameters/tallying'))
|
||||
// goverance
|
||||
export const getGovProposals = () => (get(prefixGov + '/proposals'))
|
||||
export const getGovProposalsId = ({ id }) => (get(prefixGov + `/proposals/${id}`))
|
||||
// 未实现
|
||||
export const getGovProposalsDeposits = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/deposits`))
|
||||
export const getGovProposalsVotes = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/votes`))
|
||||
// committee
|
||||
export const getCommitteeCommittees = () => {}
|
||||
export const getCommitteeCommitteesId = ({ id }) => (get(`/committee/committees/${id}`))
|
||||
// Slashing
|
||||
export const getSlashingParameters = () => (get('/slashing/parameters'))
|
||||
export const getSlashingValidatorsSigningInfo = ({ validatorAddress }) => {} // (get(`/slashing/validators/${validatorAddress}/signing_info`))
|
||||
export const getSupplyTotal = () => (get(prefiexBank + '/total'))
|
||||
export const getStakingPool = () => (get(prefixStaking + '/pool'))
|
||||
// 未实现
|
||||
export const getStakingParameters = () => (get('/staking/parameters'))
|
||||
export const getStakingValidators = ({ status }) => (get(prefixStaking + `/validators?status=${status ? 'BOND_STATUS_' + status.toUpperCase() : 'BOND_STATUS_BONDED'}`))
|
||||
export const getStakingValidatorsObj = ({ status }) => (get(prefixStaking + `/validators?status=${status ? 'BOND_STATUS_' + status.toUpperCase() : 'BOND_STATUS_BONDED'}`))
|
||||
export const getStakingValidatorsValidatorAddress = ({ validatorAddress }) => (get(prefixStaking + `/validators/${validatorAddress}`))
|
||||
export const getStakingDelegatorsDelegations = ({ delegatorAddress }) => (get(prefixStaking + `/delegators/${delegatorAddress}/delegations`))
|
||||
export const getStakingValidatorsDelegations = ({ validatorAddress }) => (get(prefixStaking + `/validators/${validatorAddress}/delegations`))
|
||||
// Minting
|
||||
// 未实现
|
||||
export const getMintingParameters = () => (get('/minting/parameters'))
|
||||
// 未实现
|
||||
export const getMintingInflation = () => (get('/minting/inflation'))
|
||||
export const getMintingAnnualProvisionsn = () => (get('/minting/annual-provisions'))
|
||||
// Node
|
||||
export const getNodeInfo = () => (get('/node_info'))
|
||||
export const getNodeInfoRes = () => (get('/node_info'))
|
||||
// Tx
|
||||
export const getTxs = ({ height }) => {
|
||||
const config = get(prefixTx + '/txs')
|
||||
config.params = {
|
||||
'tx.height': height
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHistory = ({ address, page, }) => {
|
||||
const config = get(prefixTx + '/txs')
|
||||
config.params = {
|
||||
page,
|
||||
limit: 10,
|
||||
'message.sender': address
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHash = ({ hash }) => (get(prefixTx + `/txs/${hash}`))
|
||||
// Validators
|
||||
export const getValidatorsetsHeight = ({ height }) => (get(`/validatorsets/${height}`))
|
||||
|
||||
// POST ===
|
||||
// post Send coins from one account to another
|
||||
export function postBankAccountsTransfers({ address, chain_id, account_number, sequence, amount, denom, memo, simulate }) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/bank/accounts/${address}/transfers`,
|
||||
data: {
|
||||
base_req: {
|
||||
"from": address,
|
||||
"memo": memo || "Sent via look.ping.pub",
|
||||
chain_id,
|
||||
account_number,
|
||||
sequence,
|
||||
"gas": "200000",
|
||||
"gas_adjustment": "2.3",
|
||||
"fees": [
|
||||
Coin({ amount, denom })
|
||||
],
|
||||
simulate
|
||||
},
|
||||
"amount": [
|
||||
Coin({ amount, denom })
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// post Broadcast a signed tx
|
||||
export function postTxs({ txBroadcast }) {
|
||||
const config = get(prefixTx + '/txs')
|
||||
config.method = 'post'
|
||||
config.data = { ...txBroadcast }
|
||||
return config
|
||||
}
|
||||
|
||||
function Coin({ amount, denom }) {
|
||||
return {
|
||||
amount: String(amount),
|
||||
denom
|
||||
};
|
||||
}
|
||||
|
475
src/api/V3/response.js
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2020-12-11 16:13:18
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: \look-web\src\api\V1\response.js
|
||||
*/
|
||||
import { timeToDay, toDenom, toTimestamp, formatTime } from '../../utils/format'
|
||||
import { createDisplayCoin, percent, twoDecimals, uatoms, atoms } from '../../utils/num'
|
||||
import { addressToHex, validatorAddressToAccount, base64ToPubkey } from '../../utils/b32'
|
||||
import dayjs from 'dayjs'
|
||||
import store from '../../store'
|
||||
|
||||
const commonResult = (res) => res.result
|
||||
|
||||
export function getNodeInfo(res) {
|
||||
const { network, version } = res.node_info || {}
|
||||
return {
|
||||
network,
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
export function getNodeInfoRes(res) {
|
||||
return res
|
||||
}
|
||||
|
||||
export function getKavaCdpParameters(res) {
|
||||
let result = commonResult(res);
|
||||
result.debt_auction_lot = timeToDay(result.debt_auction_lot)
|
||||
result.surplus_auction_lot = timeToDay(result.surplus_auction_lot)
|
||||
result.debt_auction_threshold = timeToDay(result.debt_auction_threshold)
|
||||
result.surplus_auction_threshold = timeToDay(result.surplus_auction_threshold)
|
||||
result.savings_distribution_frequency = timeToDay(result.savings_distribution_frequency)
|
||||
result.debt_param.savings_rate = percent(result.debt_param.savings_rate)
|
||||
return result
|
||||
}
|
||||
export function getKavaPricefeed(res) { let result = commonResult(res); return result }
|
||||
export function getKavaIncentive(res) {
|
||||
let result = commonResult(res);
|
||||
for (const item of result.rewards) {
|
||||
item.duration = timeToDay(item.duration)
|
||||
item.claim_duration = timeToDay(item.claim_duration)
|
||||
item.time_lock = timeToDay(item.time_lock)
|
||||
}
|
||||
return result
|
||||
}
|
||||
export function getKavaBep3(res) { let result = commonResult(res); return result }
|
||||
export function getKavaAuction(res) {
|
||||
let result = commonResult(res);
|
||||
result.max_auction_duration = timeToDay(result.max_auction_duration)
|
||||
result.bid_duration = timeToDay(result.bid_duration)
|
||||
result.increment_collateral = percent(result.increment_collateral)
|
||||
result.increment_surplus = percent(result.increment_surplus)
|
||||
result.increment_debt = percent(result.increment_debt)
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getAuthAccounts(res) {
|
||||
const result = commonResult(res)
|
||||
const { type, value } = result
|
||||
let coins = value.coins[0]
|
||||
coins = createDisplayCoin(coins)
|
||||
return {
|
||||
type,
|
||||
available: coins.amount,
|
||||
...value
|
||||
}
|
||||
}
|
||||
|
||||
export const postBankAccountsTransfers = (res) => Math.round(res.gas_estimate * 2.3)
|
||||
export const getStakingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_entries, max_validators, unbonding_time, bond_denom } = data
|
||||
return {
|
||||
max_entries,
|
||||
max_validators,
|
||||
unbonding_time: timeToDay(unbonding_time),
|
||||
bond_denom: toDenom(bond_denom)
|
||||
}
|
||||
}
|
||||
export const postTxs = (res) => (res)
|
||||
function formatValidator(item) {
|
||||
item.dailyChange = '--'
|
||||
item.rewards = '--'
|
||||
const { identity, moniker, website, details } = item.description
|
||||
item.moniker = moniker
|
||||
item.identity = identity
|
||||
item.website = website
|
||||
item.details = details
|
||||
item.voting_power = atoms(Number(item.tokens)).toFixed(2) + ' ' + window.chain.unit // TODO: 单位问题
|
||||
item.userAddress = validatorAddressToAccount(item.operator_address)
|
||||
if (item.consensus_pubkey && item.consensus_pubkey.key) {
|
||||
item.consensus_pubkey = base64ToPubkey(item.consensus_pubkey.key)
|
||||
item.hexAddress = addressToHex(item.consensus_pubkey)
|
||||
}
|
||||
item.commission_rate = Number(item.commission.commission_rates.rate)
|
||||
item.commission_rate_percent = percent(item.commission_rate)
|
||||
item.commission_rate_max = Number(item.commission.commission_rates.max_rate)
|
||||
item.commission_rate_max_percent = percent(item.commission_rate_max)
|
||||
item.commission_rate_max_change = Number(item.commission.commission_rates.max_change_rate)
|
||||
item.commission_rate_max_change_percent = percent(item.commission_rate_max_change)
|
||||
if (item.unbonding_time) {
|
||||
item.unbonding_time = formatTime(item.unbonding_time)
|
||||
}
|
||||
}
|
||||
export const getStakingValidators = (res) => {
|
||||
const data = res.validators
|
||||
data.sort((current, next) => {
|
||||
formatValidator(current)
|
||||
formatValidator(next)
|
||||
return Number(next.tokens) - Number(current.tokens);
|
||||
})
|
||||
if (data.length === 1) formatValidator(data[0])
|
||||
res.result = data
|
||||
return res
|
||||
}
|
||||
|
||||
export const getStakingValidatorsObj = (res) => {
|
||||
const data = res.validators
|
||||
const hexObj = {}
|
||||
const addressObj = {}
|
||||
const validatorObj = {}
|
||||
for (const item of data) {
|
||||
formatValidator(item)
|
||||
hexObj[item.hexAddress] = item
|
||||
addressObj[item.userAddress] = item
|
||||
validatorObj[item.operator_address] = item
|
||||
}
|
||||
return {
|
||||
hexObj,
|
||||
addressObj,
|
||||
validatorObj
|
||||
}
|
||||
}
|
||||
|
||||
export const getGovParametersDeposit = (res) => {
|
||||
const data = commonResult(res)
|
||||
const coin = createDisplayCoin(data.min_deposit[0])
|
||||
return {
|
||||
min_deposit: coin.amount + coin.denom,
|
||||
max_deposit_period: timeToDay(data.max_deposit_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersVoting = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
voting_period: timeToDay(data.voting_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersTallying = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { quorum, threshold, veto } = data
|
||||
return {
|
||||
quorum: percent(quorum),
|
||||
threshold: percent(threshold),
|
||||
veto: percent(veto)
|
||||
}
|
||||
}
|
||||
export const getSlashingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_evidence_age, slash_fraction_downtime, downtime_jail_duration, signed_blocks_window, min_signed_per_window, slash_fraction_double_sign } = data
|
||||
return {
|
||||
max_evidence_age: timeToDay(max_evidence_age),
|
||||
downtime_jail_duration: timeToDay(downtime_jail_duration),
|
||||
signed_blocks_window: Number(signed_blocks_window),
|
||||
min_signed_per_window: percent(min_signed_per_window),
|
||||
slash_fraction_double_sign: percent(slash_fraction_double_sign),
|
||||
slash_fraction_downtime: percent(slash_fraction_downtime)
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { community_tax, base_proposer_reward, bonus_proposer_reward, withdraw_addr_enabled } = data
|
||||
return {
|
||||
community_tax: percent(community_tax),
|
||||
base_proposer_reward: percent(base_proposer_reward),
|
||||
bonus_proposer_reward: percent(bonus_proposer_reward),
|
||||
withdraw_addr_enabled: withdraw_addr_enabled ? "Enabled" : "Disabled"
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsDelegations = (res) => {
|
||||
const data = res.delegation_responses
|
||||
let total = 0
|
||||
for (const item of data) {
|
||||
item.shares = item.delegation.shares
|
||||
item.delegator_address = item.delegation.delegator_address
|
||||
total += Number(item.shares)
|
||||
item.shares_str = atoms(Number(item.shares)) + ' ' + window.chain.unit
|
||||
}
|
||||
data.sort((now, next) => {
|
||||
now.shares_percent = percent(Number(now.shares) / total)
|
||||
next.shares_percent = percent(Number(next.shares) / total)
|
||||
return Number(next.shares) - Number(now.shares)
|
||||
})
|
||||
if (data.length === 1) {
|
||||
data[0].shares_percent = percent(Number(data[0].shares) / total)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const getSlashingValidatorsSigningInfo = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
missed_blocks_counter: data.missed_blocks_counter
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingParameters = (result) => {
|
||||
const data = commonResult(result)
|
||||
const { blocks_per_year, inflation_rate_change } = data
|
||||
return {
|
||||
blocks_per_year,
|
||||
mint_denom: toDenom(data.mint_denom),
|
||||
inflation_rate_change: percent(inflation_rate_change),
|
||||
inflation_max: percent(data.inflation_max),
|
||||
inflation_min: percent(data.inflation_min),
|
||||
goal_bonded: percent(data.goal_bonded),
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingInflation = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
inflation: percent(data),
|
||||
inflation_val: Number(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingAnnualProvisionsn = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
annual_provisions: (Number(data) / 1000000).toFixed(0)
|
||||
}
|
||||
}
|
||||
// /gov/proposals 方法
|
||||
function dataFormat(item) {
|
||||
const content = item.proposal_content || item.content
|
||||
item.id = item.proposal_id
|
||||
item.proposal_status = item.status
|
||||
item.title = content.title || content.value.title
|
||||
item.description = content.description || content.value.description
|
||||
item.description_sub = item.description.length > 200 ? (item.description).substr(0, 200) : item.description
|
||||
|
||||
const { voting_start_time, voting_end_time, deposit_end_time, submit_time, total_deposit } = item
|
||||
item.total_deposit_str = total_deposit && total_deposit[0] && createDisplayCoin(total_deposit[0]) || '--'
|
||||
item.submit_time = formatTime(submit_time)
|
||||
item.voting_start_time = formatTime(voting_start_time)
|
||||
item.voting_end_time = formatTime(voting_end_time)
|
||||
item.deposit_end_time = formatTime(deposit_end_time)
|
||||
|
||||
// item.final_tally_result
|
||||
const { yes, abstain, no, no_with_veto } = item.final_tally_result
|
||||
// 参与总数
|
||||
const total = yes && (Number(yes) + Number(abstain) + Number(no) + Number(no_with_veto)) || 1
|
||||
item.yes = yes && twoDecimals(yes / total) || '--'
|
||||
item.yes_percent = yes && percent(yes / total) || '--'
|
||||
item.abstain = abstain && twoDecimals(abstain / total) || '--'
|
||||
item.abstain_percent = abstain && percent(abstain / total) || '--'
|
||||
item.no = no && twoDecimals(no / total) || '--'
|
||||
item.no_percent = no && percent(no / total) || '--'
|
||||
item.no_with_veto = no_with_veto && twoDecimals(no_with_veto / total) || '--'
|
||||
item.no_with_veto_percent = no_with_veto && percent(no_with_veto / total) || '--'
|
||||
item.type = content.type
|
||||
|
||||
// 质押总数
|
||||
const bondedTokens = store.state.bondedTokens
|
||||
if (bondedTokens) {
|
||||
item.join = twoDecimals(total / bondedTokens)
|
||||
item.join_percent = percent(total / bondedTokens)
|
||||
}
|
||||
}
|
||||
|
||||
// kava 投票接口
|
||||
function formateCommitee(data) {
|
||||
for (const item of data) {
|
||||
item.vote_threshold_str = Number(item.vote_threshold).toFixed(2)
|
||||
item.proposal_duration_str = item.proposal_duration
|
||||
}
|
||||
}
|
||||
export function getCommitteeCommittees(res) {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getCommitteeCommitteesId = (res) => {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getGovProposals = (res) => {
|
||||
const data = res.proposals
|
||||
data.sort((now, next) => {
|
||||
dataFormat(now)
|
||||
dataFormat(next)
|
||||
return (
|
||||
toTimestamp(next.submit_time) - toTimestamp(now.submit_time)
|
||||
);
|
||||
});
|
||||
if (data.length === 1) dataFormat(data[0])
|
||||
return data
|
||||
}
|
||||
|
||||
export const getGovProposalsId = (res) => {
|
||||
const data = res.proposal
|
||||
dataFormat(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksLatest = (res) => {
|
||||
const { block } = res
|
||||
return {
|
||||
height: Number(block.header.height)
|
||||
}
|
||||
}
|
||||
export const getSupplyTotal = (res) => {
|
||||
const data = commonResult(res)
|
||||
const amount = Number(data[0].amount)
|
||||
const amount_str = amount > 1000000
|
||||
? (amount / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (amount / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
amount,
|
||||
amount_str
|
||||
}
|
||||
}
|
||||
export const getStakingPool = (res) => {
|
||||
const data = res.pool
|
||||
let { bonded_tokens } = data
|
||||
const bonded_tokens_val = Number(bonded_tokens)
|
||||
bonded_tokens = bonded_tokens_val > 1000000
|
||||
? (bonded_tokens_val / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (bonded_tokens_val / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
bonded_tokens_val,
|
||||
bonded_tokens
|
||||
}
|
||||
}
|
||||
|
||||
export const getValidatorsetsHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data.validators
|
||||
}
|
||||
|
||||
|
||||
export const getTxs = (res) => (res)
|
||||
|
||||
export const getTxsHistory = (res) => {
|
||||
res.txs.sort((current, next) => {
|
||||
const dayCurrent = dayjs(current.timestap).valueOf()
|
||||
const dayNext = dayjs(next.timestap).valueOf()
|
||||
return dayCurrent - dayNext
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
export const getGovProposalsDeposits = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
for (const item of data) {
|
||||
item.amountCoin = createDisplayCoin(item.amount[0])
|
||||
item.amountCoin_str = item.amountCoin.amount + ' ' + item.amountCoin.denom
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// getGovProposalsVotes
|
||||
export const getGovProposalsVotes = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksHeight = (res) => {
|
||||
return res
|
||||
}
|
||||
|
||||
export const getTxsHash = (res) => (res)
|
||||
export const getStakingValidatorsValidatorAddress = (res) => {
|
||||
const data = res.validator
|
||||
formatValidator(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getStakingDelegatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let delegated = 0
|
||||
for (const item of data) {
|
||||
item.shares = atoms(Number(item.shares))
|
||||
delegated += Number(item.shares)
|
||||
}
|
||||
delegated += ''
|
||||
return {
|
||||
delegated,
|
||||
delegations: data
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionDelegatorsRewards = (res) => {
|
||||
const data = commonResult(res)
|
||||
const rewards = data.rewards || []
|
||||
const obj = {}
|
||||
for (const item of rewards) {
|
||||
const coin = createDisplayCoin(item.reward[0])
|
||||
item.amount = coin.amount
|
||||
obj[item.validator_address] = {
|
||||
amount: item.amount
|
||||
}
|
||||
}
|
||||
const total = data.total[0] ? createDisplayCoin(data.total[0]) : { amount: '0' }
|
||||
return {
|
||||
rewardObj: obj,
|
||||
reward: total.amount,
|
||||
rewards
|
||||
}
|
||||
}
|
||||
|
||||
// RPC ===
|
||||
export const getRpcAbciInfo = (res) => {
|
||||
return {
|
||||
last_block_height: res.response.last_block_height
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcCommitHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
const precommits = (data.signed_header && data.signed_header.commit && data.signed_header.commit.precommits) || (data.signed_header && data.signed_header.commit && data.signed_header.commit.signatures)
|
||||
const obj = {}
|
||||
for (const item of precommits) {
|
||||
if (item) {
|
||||
const { validator_address } = item
|
||||
obj[validator_address] = true
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
export const getRpcValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data
|
||||
}
|
||||
|
||||
// 创世节点
|
||||
export const getRpcGenesis = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.genesis_time = data.genesis.genesis_time
|
||||
return data
|
||||
}
|
||||
|
||||
export const getRpcConsensus_state = (res) => {
|
||||
const data = commonResult(res)
|
||||
const height_vote_set = data.round_state.height_vote_set
|
||||
return {
|
||||
height_vote_set
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcBlockchain = (res) => {
|
||||
const data = commonResult(res)
|
||||
const last_height = Number(data.last_height)
|
||||
const block_metas = []
|
||||
for (const item of data.block_metas) {
|
||||
const { header, block_id } = item
|
||||
const { num_txs, height, last_block_id, time } = header
|
||||
header.block_hash = block_id.hash
|
||||
header.num_txs = num_txs && Number(num_txs) || (item.num_txs && Number(item.num_txs))
|
||||
header.last_block_hash = last_block_id.hash
|
||||
header.time = formatTime(time)
|
||||
block_metas.push(header)
|
||||
}
|
||||
return {
|
||||
last_height,
|
||||
block_metas
|
||||
}
|
||||
}
|
128
src/api/V4/request.js
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2021-02-19 15:43:35
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /look-web/src/api/V1/request.js
|
||||
*/
|
||||
const get = (url) => ({ method: 'get', url, headers: { server: window.chain.lcd } })
|
||||
const getRpc = (url) => ({ method: 'get', url, headers: { server: window.chain.rpc } })
|
||||
|
||||
export const getKavaCdpParameters = () => (get('/cdp/parameters'))
|
||||
export const getKavaPricefeed = () => (get('/pricefeed/parameters'))
|
||||
export const getKavaIncentive = () => (get('/incentive/parameters'))
|
||||
export const getKavaBep3 = () => (get('/bep3/parameters'))
|
||||
export const getKavaAuction = () => (get('/auction/parameters'))
|
||||
|
||||
// RPC ===
|
||||
export const getRpcCommitHeight = ({ height }) => (getRpc(`/commit?height=${height}`))
|
||||
export const getRpcBlockchain = ({ minHeight, maxHeight }) => (getRpc(`/blockchain?minHeight=${minHeight}&maxHeight=${maxHeight}`))
|
||||
export const getRpcValidators = ({ height }) => (getRpc(`/validators?height=${height}`))
|
||||
export const getRpcGenesis = () => (getRpc('/genesis'))
|
||||
export const getRpcConsensus_state = () => (getRpc('/consensus_state'))
|
||||
// 获取最新高度
|
||||
export const getRpcAbciInfo = () => (getRpc('/abci_info'))
|
||||
// LCD ===
|
||||
// node info
|
||||
// Auth
|
||||
export const getAuthAccounts = ({ address }) => (get(`/auth/accounts/${address}`))
|
||||
// Blocks
|
||||
export const getBlocksLatest = () => (get('/blocks/latest'))
|
||||
export const getBlocksHeight = ({ height }) => (get(`/blocks/${height}`))
|
||||
// Distribution
|
||||
export const getDistributionParameters = () => (get('/distribution/parameters'))
|
||||
export const getDistributionDelegatorsRewards = ({ delegatorAddress }) => (get(`/distribution/delegators/${delegatorAddress}/rewards`))
|
||||
// Gov
|
||||
export const getGovParametersDeposit = () => (get('/gov/parameters/deposit'))
|
||||
export const getGovParametersVoting = () => (get('/gov/parameters/voting'))
|
||||
export const getGovParametersTallying = () => (get('/gov/parameters/tallying'))
|
||||
// goverance
|
||||
export const getGovProposals = () => (get('/gov/proposals'))
|
||||
export const getGovProposalsId = ({ id }) => (get(`/gov/proposals/${id}`))
|
||||
export const getGovProposalsDeposits = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/deposits`))
|
||||
export const getGovProposalsVotes = ({ proposalId }) => (get(`/gov/proposals/${proposalId}/votes`))
|
||||
// committee
|
||||
export const getCommitteeCommittees = () => {}
|
||||
export const getCommitteeCommitteesId = ({ id }) => (get(`/committee/committees/${id}`))
|
||||
// Slashing
|
||||
export const getSlashingParameters = () => (get('/slashing/parameters'))
|
||||
export const getSlashingValidatorsSigningInfo = ({ validatorAddress }) => (get(`/slashing/validators/${validatorAddress}/signing_info`))
|
||||
export const getSupplyTotal = () => (get('/bank/total'))
|
||||
export const getStakingPool = () => (get('/staking/pool'))
|
||||
export const getStakingParameters = () => (get('/staking/parameters'))
|
||||
export const getStakingValidators = ({ status }) => (get(`/staking/validators?status=${status || 'BOND_STATUS_BONDED'}`))
|
||||
export const getStakingValidatorsObj = ({ status }) => (get(`/staking/validators?status=${status || 'BOND_STATUS_BONDED'}`))
|
||||
export const getStakingValidatorsValidatorAddress = ({ validatorAddress }) => (get(`/staking/validators/${validatorAddress}`))
|
||||
export const getStakingDelegatorsDelegations = ({ delegatorAddress }) => (get(`/staking/delegators/${delegatorAddress}/delegations`))
|
||||
export const getStakingValidatorsDelegations = ({ validatorAddress }) => (get(`/staking/validators/${validatorAddress}/delegations`))
|
||||
// Minting
|
||||
export const getMintingParameters = () => (get('/minting/parameters'))
|
||||
export const getMintingInflation = () => (get('/minting/inflation'))
|
||||
export const getMintingAnnualProvisionsn = () => (get('/minting/annual-provisions'))
|
||||
// Node
|
||||
export const getNodeInfo = () => (get('/node_info'))
|
||||
export const getNodeInfoRes = () => (get('/node_info'))
|
||||
// Tx
|
||||
export const getTxs = ({ height }) => {
|
||||
const config = get('/txs')
|
||||
config.params = {
|
||||
'tx.height': height
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHistory = ({ address, page, }) => {
|
||||
const config = get('/txs')
|
||||
config.params = {
|
||||
page,
|
||||
limit: 10,
|
||||
'message.sender': address
|
||||
}
|
||||
return config
|
||||
}
|
||||
export const getTxsHash = ({ hash }) => (get(`/txs/${hash}`))
|
||||
// Validators
|
||||
export const getValidatorsetsHeight = ({ height }) => (get(`/validatorsets/${height}`))
|
||||
|
||||
// POST ===
|
||||
// post Send coins from one account to another
|
||||
export function postBankAccountsTransfers({ address, chain_id, account_number, sequence, amount, denom, memo, simulate }) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/bank/accounts/${address}/transfers`,
|
||||
data: {
|
||||
base_req: {
|
||||
"from": address,
|
||||
"memo": memo || "Sent via look.ping.pub",
|
||||
chain_id,
|
||||
account_number,
|
||||
sequence,
|
||||
"gas": "200000",
|
||||
"gas_adjustment": "2.3",
|
||||
"fees": [
|
||||
Coin({ amount, denom })
|
||||
],
|
||||
simulate
|
||||
},
|
||||
"amount": [
|
||||
Coin({ amount, denom })
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// post Broadcast a signed tx
|
||||
export function postTxs({ txBroadcast }) {
|
||||
const config = get('/txs')
|
||||
config.method = 'post'
|
||||
config.data = { ...txBroadcast }
|
||||
return config
|
||||
}
|
||||
|
||||
function Coin({ amount, denom }) {
|
||||
return {
|
||||
amount: String(amount),
|
||||
denom
|
||||
};
|
||||
}
|
||||
|
468
src/api/V4/response.js
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2021-02-19 15:38:37
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: \look-web\src\api\V1\response.js
|
||||
*/
|
||||
import { timeToDay, toDenom, toTimestamp, formatTime } from '../../utils/format'
|
||||
import { createDisplayCoin, percent, twoDecimals, uatoms, atoms } from '../../utils/num'
|
||||
import { addressToHex, validatorAddressToAccount, base64ToPubkey } from '../../utils/b32'
|
||||
import dayjs from 'dayjs'
|
||||
import store from '../../store'
|
||||
|
||||
const commonResult = (res) => res.result
|
||||
|
||||
export function getNodeInfo(res) {
|
||||
const { network, version } = res.node_info || {}
|
||||
return {
|
||||
network,
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
export function getNodeInfoRes(res) {
|
||||
return res
|
||||
}
|
||||
|
||||
export function getKavaCdpParameters(res) {
|
||||
let result = commonResult(res);
|
||||
result.debt_auction_lot = timeToDay(result.debt_auction_lot)
|
||||
result.surplus_auction_lot = timeToDay(result.surplus_auction_lot)
|
||||
result.debt_auction_threshold = timeToDay(result.debt_auction_threshold)
|
||||
result.surplus_auction_threshold = timeToDay(result.surplus_auction_threshold)
|
||||
result.savings_distribution_frequency = timeToDay(result.savings_distribution_frequency)
|
||||
result.debt_param.savings_rate = percent(result.debt_param.savings_rate)
|
||||
return result
|
||||
}
|
||||
export function getKavaPricefeed(res) { let result = commonResult(res); return result }
|
||||
export function getKavaIncentive(res) {
|
||||
let result = commonResult(res);
|
||||
for (const item of result.rewards) {
|
||||
item.duration = timeToDay(item.duration)
|
||||
item.claim_duration = timeToDay(item.claim_duration)
|
||||
item.time_lock = timeToDay(item.time_lock)
|
||||
}
|
||||
return result }
|
||||
export function getKavaBep3(res) { let result = commonResult(res); return result }
|
||||
export function getKavaAuction(res) {
|
||||
let result = commonResult(res);
|
||||
result.max_auction_duration = timeToDay(result.max_auction_duration)
|
||||
result.bid_duration = timeToDay(result.bid_duration)
|
||||
result.increment_collateral = percent(result.increment_collateral)
|
||||
result.increment_surplus = percent(result.increment_surplus)
|
||||
result.increment_debt = percent(result.increment_debt)
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getAuthAccounts(res) {
|
||||
const result = commonResult(res)
|
||||
const { type, value } = result
|
||||
let coins = value.coins[0]
|
||||
coins = createDisplayCoin(coins)
|
||||
return {
|
||||
type,
|
||||
available: coins.amount,
|
||||
...value
|
||||
}
|
||||
}
|
||||
|
||||
export const postBankAccountsTransfers = (res) => Math.round(res.gas_estimate * 2.3)
|
||||
export const getStakingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_entries, max_validators, unbonding_time, bond_denom } = data
|
||||
return {
|
||||
max_entries,
|
||||
max_validators,
|
||||
unbonding_time: timeToDay(unbonding_time),
|
||||
bond_denom: toDenom(bond_denom)
|
||||
}
|
||||
}
|
||||
export const postTxs = (res) => (res)
|
||||
function formatValidator(item) {
|
||||
item.dailyChange = '--'
|
||||
item.rewards = '--'
|
||||
const { identity, moniker, website, details } = item.description
|
||||
item.moniker = moniker
|
||||
item.identity = identity
|
||||
item.website = website
|
||||
item.details = details
|
||||
item.voting_power = atoms(Number(item.tokens)).toFixed(2) + ' ' + window.chain.unit // TODO: 单位问题
|
||||
item.userAddress = validatorAddressToAccount(item.operator_address)
|
||||
item.hexAddress = addressToHex(base64ToPubkey(item.consensus_pubkey.value))
|
||||
item.commission_rate = Number(item.commission.commission_rates.rate)
|
||||
item.commission_rate_percent = percent(item.commission_rate)
|
||||
item.commission_rate_max = Number(item.commission.commission_rates.max_rate)
|
||||
item.commission_rate_max_percent = percent(item.commission_rate_max)
|
||||
item.commission_rate_max_change = Number(item.commission.commission_rates.max_change_rate)
|
||||
item.commission_rate_max_change_percent = percent(item.commission_rate_max_change)
|
||||
if (item.unbonding_time) {
|
||||
item.unbonding_time = formatTime(item.unbonding_time)
|
||||
}
|
||||
}
|
||||
export const getStakingValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.sort((current, next) => {
|
||||
formatValidator(current)
|
||||
formatValidator(next)
|
||||
return Number(next.tokens) - Number(current.tokens);
|
||||
})
|
||||
if (data.length === 1) formatValidator(data[0])
|
||||
return {
|
||||
result: data
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsObj = (res) => {
|
||||
const data = commonResult(res)
|
||||
const hexObj = {}
|
||||
const addressObj = {}
|
||||
const validatorObj = {}
|
||||
for (const item of data) {
|
||||
formatValidator(item)
|
||||
hexObj[item.hexAddress] = item
|
||||
addressObj[item.userAddress] = item
|
||||
validatorObj[item.operator_address] = item
|
||||
}
|
||||
return {
|
||||
hexObj,
|
||||
addressObj,
|
||||
validatorObj
|
||||
}
|
||||
}
|
||||
|
||||
export const getGovParametersDeposit = (res) => {
|
||||
const data = commonResult(res)
|
||||
const coin = createDisplayCoin(data.min_deposit[0])
|
||||
return {
|
||||
min_deposit: coin.amount + coin.denom,
|
||||
max_deposit_period: timeToDay(data.max_deposit_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersVoting = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
voting_period: timeToDay(data.voting_period)
|
||||
}
|
||||
}
|
||||
export const getGovParametersTallying = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { quorum, threshold, veto } = data
|
||||
return {
|
||||
quorum: percent(quorum),
|
||||
threshold: percent(threshold),
|
||||
veto: percent(veto)
|
||||
}
|
||||
}
|
||||
export const getSlashingParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { max_evidence_age, slash_fraction_downtime, downtime_jail_duration, signed_blocks_window, min_signed_per_window, slash_fraction_double_sign } = data
|
||||
return {
|
||||
max_evidence_age: timeToDay(max_evidence_age),
|
||||
downtime_jail_duration: timeToDay(downtime_jail_duration),
|
||||
signed_blocks_window: Number(signed_blocks_window),
|
||||
min_signed_per_window: percent(min_signed_per_window),
|
||||
slash_fraction_double_sign: percent(slash_fraction_double_sign),
|
||||
slash_fraction_downtime: percent(slash_fraction_downtime)
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionParameters = (res) => {
|
||||
const data = commonResult(res)
|
||||
const { community_tax, base_proposer_reward, bonus_proposer_reward, withdraw_addr_enabled } = data
|
||||
return {
|
||||
community_tax: percent(community_tax),
|
||||
base_proposer_reward: percent(base_proposer_reward),
|
||||
bonus_proposer_reward: percent(bonus_proposer_reward),
|
||||
withdraw_addr_enabled: withdraw_addr_enabled ? "Enabled" : "Disabled"
|
||||
}
|
||||
}
|
||||
|
||||
export const getStakingValidatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let total = 0
|
||||
for (const item of data) {
|
||||
total += Number(item.shares)
|
||||
item.shares_str = atoms(Number(item.shares)) + ' ' + window.chain.unit
|
||||
}
|
||||
data.sort((now, next) => {
|
||||
now.shares_percent = percent(Number(now.shares) / total)
|
||||
next.shares_percent = percent(Number(next.shares) / total)
|
||||
return Number(next.shares) - Number(now.shares)
|
||||
})
|
||||
if (data.length === 1) {
|
||||
data[0].shares_percent = percent(Number(data[0].shares) / total)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const getSlashingValidatorsSigningInfo = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
missed_blocks_counter: data.missed_blocks_counter
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingParameters = (result) => {
|
||||
const data = commonResult(result)
|
||||
const { blocks_per_year, inflation_rate_change } = data
|
||||
return {
|
||||
blocks_per_year,
|
||||
mint_denom: toDenom(data.mint_denom),
|
||||
inflation_rate_change: percent(inflation_rate_change),
|
||||
inflation_max: percent(data.inflation_max),
|
||||
inflation_min: percent(data.inflation_min),
|
||||
goal_bonded: percent(data.goal_bonded),
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingInflation = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
inflation: percent(data),
|
||||
inflation_val: Number(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const getMintingAnnualProvisionsn = (res) => {
|
||||
const data = commonResult(res)
|
||||
return {
|
||||
annual_provisions: (Number(data) / 1000000).toFixed(0)
|
||||
}
|
||||
}
|
||||
// /gov/proposals 方法
|
||||
function dataFormat(item) {
|
||||
const content = item.proposal_content || item.content
|
||||
item.title = content.value.title;
|
||||
item.description = content.value.description
|
||||
item.description_sub = item.description.length > 200 ? (item.description).substr(0, 200) : item.description
|
||||
|
||||
const { voting_start_time, voting_end_time, deposit_end_time, submit_time, total_deposit } = item
|
||||
item.total_deposit_str = total_deposit && total_deposit[0] && createDisplayCoin(total_deposit[0]) || '--'
|
||||
item.submit_time = formatTime(submit_time)
|
||||
item.voting_start_time = formatTime(voting_start_time)
|
||||
item.voting_end_time = formatTime(voting_end_time)
|
||||
item.deposit_end_time = formatTime(deposit_end_time)
|
||||
|
||||
// item.final_tally_result
|
||||
const { yes, abstain, no, no_with_veto } = item.final_tally_result
|
||||
// 参与总数
|
||||
const total = yes && (Number(yes) + Number(abstain) + Number(no) + Number(no_with_veto)) || 1
|
||||
item.yes = yes && twoDecimals(yes / total) || '--'
|
||||
item.yes_percent = yes && percent(yes / total) || '--'
|
||||
item.abstain = abstain && twoDecimals(abstain / total) || '--'
|
||||
item.abstain_percent = abstain && percent(abstain / total) || '--'
|
||||
item.no = no && twoDecimals(no / total) || '--'
|
||||
item.no_percent = no && percent(no / total) || '--'
|
||||
item.no_with_veto = no_with_veto && twoDecimals(no_with_veto / total) || '--'
|
||||
item.no_with_veto_percent = no_with_veto && percent(no_with_veto / total) || '--'
|
||||
item.type = content.type
|
||||
|
||||
// 质押总数
|
||||
const bondedTokens = store.state.bondedTokens
|
||||
if (bondedTokens) {
|
||||
item.join = twoDecimals(total / bondedTokens)
|
||||
item.join_percent = percent(total / bondedTokens)
|
||||
}
|
||||
}
|
||||
|
||||
// kava 投票接口
|
||||
function formateCommitee(data) {
|
||||
for (const item of data) {
|
||||
item.vote_threshold_str = Number(item.vote_threshold).toFixed(2)
|
||||
item.proposal_duration_str = item.proposal_duration
|
||||
}
|
||||
}
|
||||
export function getCommitteeCommittees(res) {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getCommitteeCommitteesId = (res) => {
|
||||
const data = commonResult(res)
|
||||
formateCommitee(data)
|
||||
return data
|
||||
}
|
||||
export const getGovProposals = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.sort((now, next) => {
|
||||
dataFormat(now)
|
||||
dataFormat(next)
|
||||
return (
|
||||
toTimestamp(next.submit_time) - toTimestamp(now.submit_time)
|
||||
);
|
||||
});
|
||||
if (data.length === 1) dataFormat(data[0])
|
||||
return data
|
||||
}
|
||||
|
||||
export const getGovProposalsId = (res) => {
|
||||
const data = commonResult(res)
|
||||
dataFormat(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksLatest = (res) => {
|
||||
const { block } = res
|
||||
return {
|
||||
height: Number(block.header.height)
|
||||
}
|
||||
}
|
||||
export const getSupplyTotal = (res) => {
|
||||
const data = commonResult(res)
|
||||
const amount = Number(data[0].amount)
|
||||
const amount_str = amount > 1000000
|
||||
? (amount / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (amount / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
amount,
|
||||
amount_str
|
||||
}
|
||||
}
|
||||
export const getStakingPool = (res) => {
|
||||
const data = commonResult(res)
|
||||
let { bonded_tokens } = data
|
||||
const bonded_tokens_val = Number(bonded_tokens)
|
||||
bonded_tokens = bonded_tokens_val > 1000000
|
||||
? (bonded_tokens_val / 1000000 / 1000000).toFixed(2) + "M"
|
||||
: (bonded_tokens_val / 1000).toFixed(2) + "K"
|
||||
return {
|
||||
bonded_tokens_val,
|
||||
bonded_tokens
|
||||
}
|
||||
}
|
||||
|
||||
export const getValidatorsetsHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data.validators
|
||||
}
|
||||
|
||||
|
||||
export const getTxs = (res) => (res)
|
||||
|
||||
export const getTxsHistory = (res) => {
|
||||
res.txs.sort((current, next) => {
|
||||
const dayCurrent = dayjs(current.timestap).valueOf()
|
||||
const dayNext = dayjs(next.timestap).valueOf()
|
||||
return dayCurrent - dayNext
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
export const getGovProposalsDeposits = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
for (const item of data) {
|
||||
item.amountCoin = createDisplayCoin(item.amount[0])
|
||||
item.amountCoin_str = item.amountCoin.amount + ' ' + item.amountCoin.denom
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// getGovProposalsVotes
|
||||
export const getGovProposalsVotes = (res) => {
|
||||
const data = commonResult(res) || []
|
||||
return data
|
||||
}
|
||||
|
||||
export const getBlocksHeight = (res) => {
|
||||
return res
|
||||
}
|
||||
|
||||
export const getTxsHash = (res) => (res)
|
||||
export const getStakingValidatorsValidatorAddress = (res) => {
|
||||
const data = (commonResult(res))
|
||||
formatValidator(data)
|
||||
return data
|
||||
}
|
||||
|
||||
export const getStakingDelegatorsDelegations = (res) => {
|
||||
const data = commonResult(res)
|
||||
let delegated = 0
|
||||
for (const item of data) {
|
||||
item.shares = atoms(Number(item.shares))
|
||||
delegated += Number(item.shares)
|
||||
}
|
||||
delegated += ''
|
||||
return {
|
||||
delegated,
|
||||
delegations: data
|
||||
}
|
||||
}
|
||||
|
||||
export const getDistributionDelegatorsRewards = (res) => {
|
||||
const data = commonResult(res)
|
||||
const rewards = data.rewards || []
|
||||
const obj = {}
|
||||
for (const item of rewards) {
|
||||
const coin = createDisplayCoin(item.reward[0])
|
||||
item.amount = coin.amount
|
||||
obj[item.validator_address] = {
|
||||
amount: item.amount
|
||||
}
|
||||
}
|
||||
const total = data.total[0] ? createDisplayCoin(data.total[0]) : { amount: '0' }
|
||||
return {
|
||||
rewardObj: obj,
|
||||
reward: total.amount,
|
||||
rewards
|
||||
}
|
||||
}
|
||||
|
||||
// RPC ===
|
||||
export const getRpcAbciInfo = (res) => {
|
||||
return {
|
||||
last_block_height: res.response.last_block_height
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcCommitHeight = (res) => {
|
||||
const data = commonResult(res)
|
||||
const precommits = (data.signed_header && data.signed_header.commit && data.signed_header.commit.precommits) || (data.signed_header && data.signed_header.commit && data.signed_header.commit.signatures)
|
||||
const obj = {}
|
||||
for (const item of precommits) {
|
||||
if (item) {
|
||||
const { validator_address } = item
|
||||
obj[validator_address] = true
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
export const getRpcValidators = (res) => {
|
||||
const data = commonResult(res)
|
||||
return data
|
||||
}
|
||||
|
||||
// 创世节点
|
||||
export const getRpcGenesis = (res) => {
|
||||
const data = commonResult(res)
|
||||
data.genesis_time = data.genesis.genesis_time
|
||||
return data
|
||||
}
|
||||
|
||||
export const getRpcConsensus_state = (res) => {
|
||||
const data = commonResult(res)
|
||||
const height_vote_set = data.round_state.height_vote_set
|
||||
return {
|
||||
height_vote_set
|
||||
}
|
||||
}
|
||||
|
||||
export const getRpcBlockchain = (res) => {
|
||||
const data = commonResult(res)
|
||||
const last_height = Number(data.last_height)
|
||||
const block_metas = []
|
||||
for (const item of data.block_metas) {
|
||||
const { header, block_id } = item
|
||||
const { num_txs, height, last_block_id, time } = header
|
||||
header.block_hash = block_id.hash
|
||||
header.num_txs = num_txs && Number(num_txs) || (item.num_txs && Number(item.num_txs))
|
||||
header.last_block_hash = last_block_id.hash
|
||||
header.time = formatTime(time)
|
||||
block_metas.push(header)
|
||||
}
|
||||
return {
|
||||
last_height,
|
||||
block_metas
|
||||
}
|
||||
}
|
27
src/api/axios.js
Normal file
@ -0,0 +1,27 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: '/api'
|
||||
});
|
||||
|
||||
// const CancelToken = axios.CancelToken;
|
||||
instance.interceptors.request.use((config) => {
|
||||
// const source = CancelToken.source();
|
||||
// config.cancelToken = source.token
|
||||
// if (!config.headers.serverCustom) {
|
||||
// const { lcd } = store.state.wallet.currentChain
|
||||
// config.headers.server = lcd
|
||||
// }
|
||||
return config;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// 请求后,统一处理
|
||||
instance.interceptors.response.use(function (response) {
|
||||
return response.data;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default instance
|
14
src/api/common/addChain.js
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-03-27 11:41:45
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-15 23:06:49
|
||||
* @FilePath: /look-web/src/api/common/addChain.js
|
||||
*/
|
||||
import axios from 'axios'
|
||||
|
||||
export async function addChain(data) {
|
||||
const res = await axios.post('/look/chain/create', data)
|
||||
return res.data
|
||||
}
|
25
src/api/common/coinPrice.js
Normal file
@ -0,0 +1,25 @@
|
||||
// https://min-api.cryptocompare.com/documentation
|
||||
// https://min-api.cryptocompare.com/data/price?fsym=ATOM&tsyms=USD,CNY&api_key=3993b9faad427d8df68c267d3e8664cd8923e6c590a4888023a14bd581ff1859
|
||||
import http from '../axios'
|
||||
|
||||
// 币价
|
||||
const request = async (unit) => {
|
||||
const coin = await http.get(`/data/price`, {
|
||||
params: {
|
||||
fsym: unit || 'ATOM',
|
||||
tsyms: 'USD,CNY',
|
||||
api_key: '3993b9faad427d8df68c267d3e8664cd8923e6c590a4888023a14bd581ff1859'
|
||||
},
|
||||
headers: {
|
||||
server: 'https://min-api.cryptocompare.com',
|
||||
serverCustom: true
|
||||
}
|
||||
})
|
||||
const { USD, CNY } = coin.data
|
||||
return {
|
||||
USD,
|
||||
CNY,
|
||||
}
|
||||
}
|
||||
|
||||
export default request
|
14
src/api/common/getChain.js
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-03-27 11:41:45
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-15 23:12:05
|
||||
* @FilePath: /look-web/src/api/common/getChain.js
|
||||
*/
|
||||
import axios from 'axios'
|
||||
|
||||
export async function getChain() {
|
||||
const res = await axios.get('/look/chain/type')
|
||||
return res.data
|
||||
}
|
20
src/api/common/keybase.js
Normal file
@ -0,0 +1,20 @@
|
||||
import http from '../axios'
|
||||
|
||||
// 头像
|
||||
const request = async ({identity}) => {
|
||||
const res = await http.get(`/_/api/1.0/user/lookup.json`, {
|
||||
params: { key_suffix: identity, fields: 'pictures' },
|
||||
headers: {
|
||||
server: 'https://keybase.io'
|
||||
}
|
||||
})
|
||||
let avatar = ''
|
||||
if (res.them && res.them.length > 0) {
|
||||
avatar = res.them[0].pictures.primary.url
|
||||
}
|
||||
return {
|
||||
avatar
|
||||
}
|
||||
}
|
||||
|
||||
export default request
|
19
src/api/common/nodeInfo.js
Normal file
@ -0,0 +1,19 @@
|
||||
// import http from '../interface'
|
||||
|
||||
// 内核版本自动获取
|
||||
const request = async (baseUrl) => {
|
||||
let res= await Promise.all([
|
||||
http.get(`/node_info`, {}, { baseUrl }).catch(() => {}),
|
||||
http.get(`/node-info`, {}, { baseUrl }).catch(() => {})
|
||||
])
|
||||
let version = ''
|
||||
for (const item of res) {
|
||||
if (item) {
|
||||
version = item.data.version || item.data.node_info.version
|
||||
}
|
||||
}
|
||||
|
||||
return version
|
||||
}
|
||||
|
||||
export default request
|
83
src/api/index.js
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* @Author: your name
|
||||
* @Date: 2020-03-06 23:47:28
|
||||
* @lastTime: 2021-02-19 15:51:03
|
||||
* @LastEditors: dingyi
|
||||
* @Description: In User Settings Edit
|
||||
* @FilePath: /look-web/src/api/index.js
|
||||
*/
|
||||
import axios from './axios'
|
||||
import * as requestV1 from './V1/request'
|
||||
import * as responseV1 from './V1/response'
|
||||
|
||||
import * as requestV2 from './V2/request'
|
||||
import * as responseV2 from './V2/response'
|
||||
|
||||
import * as requestV3 from './V3/request'
|
||||
import * as responseV3 from './V3/response'
|
||||
|
||||
import * as requestV4 from './V4/request'
|
||||
import * as responseV4 from './V4/response'
|
||||
|
||||
const version = window.chain.api
|
||||
|
||||
let config, resHandler
|
||||
switch (version) {
|
||||
case 'V1':
|
||||
config = requestV1;
|
||||
resHandler = responseV1;
|
||||
break;
|
||||
case 'V2':
|
||||
config = requestV2;
|
||||
resHandler = responseV2;
|
||||
break;
|
||||
case 'V3':
|
||||
config = requestV3;
|
||||
resHandler = responseV3;
|
||||
break;
|
||||
case 'V4':
|
||||
config = requestV4;
|
||||
resHandler = responseV4;
|
||||
break;
|
||||
default:
|
||||
config = requestV1;
|
||||
resHandler = responseV1;
|
||||
break
|
||||
}
|
||||
|
||||
export async function req(funcName, params) {
|
||||
try {
|
||||
const con = config[funcName]
|
||||
let axiosConfig
|
||||
params ? axiosConfig = con(params) : axiosConfig = con()
|
||||
// 无需发起好像
|
||||
if (!axiosConfig) return {}
|
||||
// 返回查询数组
|
||||
let res
|
||||
if (axiosConfig.type === 'array') {
|
||||
const requests = axiosConfig.requests
|
||||
const arr = []
|
||||
for (const item of requests) {
|
||||
arr.push(
|
||||
axios(item)
|
||||
)
|
||||
}
|
||||
res = await Promise.all(arr)
|
||||
if (axiosConfig.params) {
|
||||
res.push(axiosConfig.params)
|
||||
}
|
||||
}
|
||||
// 单个查询
|
||||
if (!axiosConfig.type) {
|
||||
res = await axios(axiosConfig)
|
||||
}
|
||||
const handle = resHandler[funcName]
|
||||
return handle(res)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetch(funcName, params) {
|
||||
return await req(funcName, params)
|
||||
}
|
146
src/chains.js
Normal file
@ -0,0 +1,146 @@
|
||||
const isDev = location.hostname === "localhost";
|
||||
/**
|
||||
LCD: curl https://cosmoshub.stakesystems.io/node_info
|
||||
RPC: curl https://cosmoshub.stakesystems.io:2053/status
|
||||
*/
|
||||
export default {
|
||||
"Mainnet": [{
|
||||
"hash": "5e95f8d18ee6e64f7685a4db",
|
||||
"api": "V4",
|
||||
"chainId": "cosmoshub-3",
|
||||
"name": "Cosmos Hub",
|
||||
"lcd": "https://cosmoshub.stakesystems.io",
|
||||
"rpc": "https://cosmoshub.stakesystems.io:2053",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "cosmos",
|
||||
"unit": "ATOM",
|
||||
"host": "cosmos.ping.pub"
|
||||
}, {
|
||||
"hash": "5e95f8d18ee6e64f7685a4dd",
|
||||
"api": "V2",
|
||||
"chainId": "irishub",
|
||||
"name": "IRISnet",
|
||||
"lcd": "https://rpc.irisnet.org",
|
||||
"rpc": "http://seed-1.mainnet.irisnet.org:26657",
|
||||
"logo": "/static/chains/irishub.svg",
|
||||
"prefix": "iaa",
|
||||
"unit": "IRIS",
|
||||
"host": "iris.ping.pub"
|
||||
}, {
|
||||
"hash": "5e95f8d18ee6e64f7685a4de",
|
||||
"api": "V1",
|
||||
"chainId": "e-money",
|
||||
"name": "e-money",
|
||||
"lcd": "http://emoney.validator.network/light",
|
||||
"rpc": "https://emoney.validator.network",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "",
|
||||
"unit": "",
|
||||
"host": "e-money.ping.pub"
|
||||
}, {
|
||||
"hash": "5f46381683d9d569a6ecc5dd",
|
||||
"api": "V1",
|
||||
"chainId": "iov-mainnet-2",
|
||||
"name": "IOV Name Service",
|
||||
"lcd": "http://lcd-private-iov-mainnet-2.iov.one",
|
||||
"rpc": "https://rpc-private-iov-mainnet-2.iov.one",
|
||||
"logo": "https://iov.one/static/media/logoIOV2.d25f8426.png",
|
||||
"prefix": "star",
|
||||
"unit": "IOV"
|
||||
}, {
|
||||
"hash": "5f8c078b90b5fb7856ae3a06",
|
||||
"api": "V1",
|
||||
"chainId": "kava-2",
|
||||
"name": "Kava",
|
||||
"lcd": "https://kava4.data.kava.io",
|
||||
"rpc": "http://13.125.71.131:26657",
|
||||
"logo": "/static/chains/kava.svg",
|
||||
"prefix": "kava",
|
||||
"unit": "KAVA",
|
||||
"host": "kava.ping.pub"
|
||||
}, {
|
||||
"hash": "5f8c0ef91effe87834314467",
|
||||
"api": "V4",
|
||||
"chainId": "akashnet-1",
|
||||
"name": "Akash DeCloud",
|
||||
"lcd": "http://lcd.akash.forbole.com",
|
||||
"rpc": "http://rpc.akash.forbole.com",
|
||||
"logo": "https://gblobscdn.gitbook.com/spaces%2F-LrNFlfuifzmQ_NMKu9C%2Favatar.png?alt=media",
|
||||
"prefix": "akash",
|
||||
"unit": "AKT",
|
||||
"host": "akash.ping.pub"
|
||||
}, {
|
||||
"hash": "5fa15123f559583ed7465024",
|
||||
"api": "V1",
|
||||
"chainId": "gauss",
|
||||
"name": "GAUSS",
|
||||
"lcd": "https://txs-api-dev.app.gausslab.de:1317",
|
||||
"rpc": "https://txs-api-dev.app.gausslab.de",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "gauss",
|
||||
"unit": "gauss"
|
||||
}],
|
||||
"Testnet": [{
|
||||
"hash": "5e95f8d18ee6e64f7685a4df",
|
||||
"api": "V1",
|
||||
"chainId": "sentinelhub-test",
|
||||
"name": "Sentinel Network",
|
||||
"lcd": "https://lcd.turing.sentinel.co",
|
||||
"rpc": "https://rpc.turing.sentinel.co",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "",
|
||||
"unit": "",
|
||||
"host": "sentinel-test.ping.pub"
|
||||
}, {
|
||||
"hash": "5e95f8d18ee6e64f7685a4e1",
|
||||
"api": "V1",
|
||||
"chainId": "cyber-test",
|
||||
"name": "cyber",
|
||||
"lcd": "https://titan.cybernode.ai/lcd",
|
||||
"rpc": "https://titan.cybernode.ai/api",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "",
|
||||
"unit": "",
|
||||
"host": "cyber-test.ping.pub"
|
||||
}, {
|
||||
"hash": "5eabf1d1b8eb6314e2d99264",
|
||||
"api": "V1",
|
||||
"chainId": "iovns-galaxynet",
|
||||
"name": "iovns",
|
||||
"lcd": "http://iovnscli-rest-api.cluster-galaxynet.iov.one",
|
||||
"rpc": "https://rpc.cluster-galaxynet.iov.one/",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "cosmos",
|
||||
"unit": "ATOM"
|
||||
}, {
|
||||
"hash": "5f92b494ea5b4a772bfebd01",
|
||||
"api": "V1",
|
||||
"chainId": "stargate-4",
|
||||
"name": "stargate-4",
|
||||
"lcd": "https://rest.gaiasg4.hub.hackatom.dev",
|
||||
"rpc": "https://rpc.gaiasg4.hub.hackatom.dev",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "cosmos",
|
||||
"unit": "Muon"
|
||||
}, {
|
||||
"hash": "5f92bb80ea5b4a772bfebd02",
|
||||
"api": "V1",
|
||||
"chainId": "bigbang-1",
|
||||
"name": "BigBand-1",
|
||||
"lcd": "http://47.101.10.160:1317",
|
||||
"rpc": "http://47.101.10.160:26657",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "akash",
|
||||
"unit": "STAR"
|
||||
}, {
|
||||
"hash": "5f92bb80ea5b4a772bfebd03",
|
||||
"api": "V3",
|
||||
"chainId": "stargate-final",
|
||||
"name": "stargate-final",
|
||||
"lcd": "http://47.101.10.160:1317/",
|
||||
"rpc": "http://47.101.10.160:26657/",
|
||||
"logo": "/static/chains/cosmoshub.svg",
|
||||
"prefix": "cosmos",
|
||||
"unit": "ATOM"
|
||||
}]
|
||||
};
|
100
src/components/DataTable.vue
Normal file
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-03-22 19:19:39
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-07-18 16:30:27
|
||||
* @FilePath: \look-web\src\components\DataTable.vue
|
||||
-->
|
||||
<script>
|
||||
import DataTableColumn from "./DataTableColumn";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
defaultSort: {
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
tableRowClassName: {
|
||||
default() {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
rowKey: {
|
||||
default: null
|
||||
},
|
||||
columns: {
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
datas: {
|
||||
default: null
|
||||
},
|
||||
tableSize: {
|
||||
default: "small"
|
||||
},
|
||||
loading: {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DataTableColumn
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="overflow: auto;-webkit-overflow-scrolling: touch;">
|
||||
<el-table
|
||||
style="min-width: 600px;"
|
||||
border
|
||||
:size="tableSize"
|
||||
:data="datas"
|
||||
:default-sort="defaultSort"
|
||||
v-show="columns.length > 0"
|
||||
:row-class-name="tableRowClassName"
|
||||
:header-cell-style="{ background: '#f1f5f7' }"
|
||||
>
|
||||
<el-table-column label="#" type="index" width="60"></el-table-column>
|
||||
<el-table-column
|
||||
v-for="(item, index) in columns"
|
||||
:label="item.label"
|
||||
:align="item.align"
|
||||
:key="item[rowKey] || index"
|
||||
:width="item.width"
|
||||
:sortable="item.sortable"
|
||||
:sort-method="item['sort-method']"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<data-table-column v-if="item.render" :column="item" :scope="scope" :render="item.render"></data-table-column>
|
||||
<span v-else v-text="scope.row[item.prop]"></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<div
|
||||
slot="empty"
|
||||
class="datatable-empty"
|
||||
v-loading="loading"
|
||||
element-loading-text="Loading..."
|
||||
>
|
||||
<el-image style="width: 100px; height: 100px" src="/static/icon/empty3.png" fit="contain"></el-image>
|
||||
<div style="line-height: 1;">No Data</div>
|
||||
</div>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.datatable-empty {
|
||||
text-align: center;
|
||||
padding: 80px 0;
|
||||
}
|
||||
.datatable-empty-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
.datatable-paging-wrap {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
18
src/components/DataTableColumn.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
export default {
|
||||
functional: true,
|
||||
render: (h, context) => {
|
||||
return context.props.render(h, context, context.props.scope);
|
||||
},
|
||||
props: {
|
||||
scope: {
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
render: {
|
||||
type: Function
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
26
src/components/Empty.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="datatable-empty" v-loading="loading" element-loading-text="Loading...">
|
||||
<el-image style="width: 100px; height: 100px" src="/static/icon/empty3.png" fit="contain"></el-image>
|
||||
<div style="line-height: 1;">No Data</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
loading: {
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.datatable-empty {
|
||||
text-align: center;
|
||||
margin: 30px 20px;
|
||||
}
|
||||
.datatable-empty-icon {
|
||||
font-size: 64px;
|
||||
}
|
||||
</style>
|
100
src/components/FlipClock/FlipClock.vue
Normal file
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Autor: dingyi
|
||||
* @Date: 2020-04-10 20:40:39
|
||||
* @LastEditors: dingyi
|
||||
* @LastEditTime: 2020-04-12 14:24:14
|
||||
* @FilePath: \look-web\src\components\FlipClock\FlipClock.vue
|
||||
-->
|
||||
/*
|
||||
* 翻牌时钟
|
||||
* @author: 兔子先生
|
||||
* @createDate: 2019-11-24
|
||||
*/
|
||||
<template>
|
||||
<div class="FlipClock">
|
||||
<Flipper ref="flipperDay1" frontText="9" />
|
||||
<Flipper ref="flipperDay2" />
|
||||
<Flipper ref="flipperDay3" />
|
||||
<em>-</em>
|
||||
<Flipper ref="flipperHour1" />
|
||||
<Flipper ref="flipperHour2" />
|
||||
<em>:</em>
|
||||
<Flipper ref="flipperMinute1" />
|
||||
<Flipper ref="flipperMinute2" />
|
||||
<em>:</em>
|
||||
<Flipper ref="flipperSecond1" />
|
||||
<Flipper ref="flipperSecond2" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dayjs from "dayjs";
|
||||
import Flipper from "./Flipper";
|
||||
|
||||
export default {
|
||||
name: "FlipClock",
|
||||
data() {
|
||||
return {
|
||||
target: "2020-05-01 10:30:30", // 目标时间
|
||||
timer: null,
|
||||
flipObjs: []
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Flipper
|
||||
},
|
||||
methods: {
|
||||
// 日期时间补零
|
||||
padLeftZero(str) {
|
||||
return ("00" + str).substr(str.length);
|
||||
},
|
||||
// 计算差值
|
||||
calRange() {
|
||||
const now = dayjs();
|
||||
const diff = dayjs(this.target).diff(now, "s");
|
||||
console.log(diff);
|
||||
const daySencond = 24 * 60 * 60;
|
||||
const diff_day = parseInt(diff / daySencond);
|
||||
const diff_senconds = diff - diff_day * daySencond;
|
||||
const diff_hours = parseInt(diff_senconds / 60 / 60);
|
||||
const diff_mints = diff_senconds - diff_hours * 60 * 60;
|
||||
const diff_min = parseInt(diff_mints / 60);
|
||||
const diff_s = diff_mints - diff_min * 60;
|
||||
console.log(diff_day, diff_hours, diff_min, diff_s);
|
||||
},
|
||||
testTimer() {
|
||||
let target = 9;
|
||||
const timer = setInterval(() => {
|
||||
this.$refs.flipperDay1.flipDown(target, target - 1);
|
||||
target -= 1;
|
||||
if (target === 0) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.calRange();
|
||||
this.$nextTick(() => {
|
||||
// this.testTimer()
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.FlipClock {
|
||||
text-align: center;
|
||||
}
|
||||
.FlipClock .M-Flipper {
|
||||
margin: 0 3px;
|
||||
}
|
||||
.FlipClock em {
|
||||
display: inline-block;
|
||||
line-height: 102px;
|
||||
font-size: 66px;
|
||||
font-style: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|