open source

This commit is contained in:
dingyi 2021-03-15 01:14:32 +08:00
commit f4f0d29a40
208 changed files with 24908 additions and 0 deletions

21
.gitignore vendored Normal file
View 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
View 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
View 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浏览器。2LOOK浏览器计划在未来支持成百上千条区块链因此对我们团队来说不可能为所有这些链去提供一个验证人节点或者全节点。
## 项目贡献者
开发者: @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
Email18786721#qq.com

5
babel.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

43
package.json Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

38
public/index.html Normal file
View 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

File diff suppressed because one or more lines are too long

10
public/static/cdn/core@2.6.11.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
public/static/cdn/vue@2.6.11.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
public/static/cdn/vuex@3.1.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
public/static/cdp/risk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View 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

View 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

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
public/static/wallet/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 KiB

13
server/.env Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Binary file not shown.

7
server/dist/index.html vendored Normal file
View 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>

File diff suppressed because one or more lines are too long

1
server/dist/js/h5.2e45d230.js vendored Normal file

File diff suppressed because one or more lines are too long

21
server/dist/js/index.9398c703.js vendored Normal file

File diff suppressed because one or more lines are too long

21
server/dist/js/m.6108a2ad.js vendored Normal file

File diff suppressed because one or more lines are too long

8
server/dist/js/pc.3b9cf088.js vendored Normal file

File diff suppressed because one or more lines are too long

7
server/dist/m.html vendored Normal file
View 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>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
server/dist/static/cdp/risk.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

109
server/dist/static/chains/cosmoshub.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 161 KiB

BIN
server/dist/static/chains/default.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

29
server/dist/static/chains/irishub.svg vendored Normal file
View 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
View 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

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
server/dist/static/icon/empty.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
server/dist/static/icon/empty2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
server/dist/static/icon/empty3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
server/dist/static/wallet/asset1.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
server/dist/static/wallet/asset2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
server/dist/static/wallet/asset3.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
server/dist/static/wallet/bg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
server/dist/static/wallet/bg2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
server/dist/static/wallet/link.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
server/dist/static/wallet/usb.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
server/dist/static/wallet/wafe.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 KiB

28
server/package.json Normal file
View 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
View File

@ -0,0 +1,10 @@
{
"apps": [{
"name": "look",
"script": "./src/main.js",
"out_fil": "~/look.log",
"watch": true,
"instances" : "1",
"exec_mode" : "cluster"
}]
}

View 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
View 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
View 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
View 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
View 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);
});

View 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);

View 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)
};

View 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)
};

View 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)
};

View 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)
};

View 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)
};

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
}

View 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

View 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
View 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

View 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
View 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
View 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"
}]
};

View 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>

View 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
View 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>

View 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>

Some files were not shown because too many files have changed in this diff Show More