.topbar {
font-size: 19px;
+ display:flex;
}
.topbar .topbar-left {
- width: 120px;
+ width: 85px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.topbar-left .btn-menu i {
font-size: 100%;
}
-.topbar-left .alias {
+.alias {
height: 25px;
- font-size: 19px;
+ font-size: 16px;
line-height: 28px;
}
-.topbar .topbar-right {
- float: right;
+.topbar .topbar-middle {
margin-top: 20px;
margin-right: 20px;
border: 2px solid #fff;
border-radius: 18px;
- padding: 0 10px;
+ padding: 0 20px;
font: 12px system-ui;
text-align: center;
-}
-
-.topbar-right .lamp {
- display: inline-block;
- width: 6px;
- height: 6px;
- border-radius: 50%;
- background-color: #02f823;
- margin-right: 2px;
- position: relative;
- top: -2px;
+ display: flex;
+ align-items: center;
}
.content {
- margin-top: 20px;
+ margin-top: 25px;
text-align: center;
- padding: 0 30px 20px;
-}
-.content .token-icon {
- display: inline-flex;
- height: 40px;
- width: 40px;
- padding: 8px;
- margin: 8px;
+ padding: 0 30px 10px;
}
+
.content .amount {
padding-bottom: 10px;
}
.content .token-amount {
- font-size: 45px;
+ font-size: 32px;
line-height: 45px;
}
-.token-amount .asset {
- font-size: 18px;
- margin-left: 2px;
-}
-.qrcode {
- margin-left: 5px;
- vertical-align: middle;
- cursor: pointer;
+
+.btn-send-transfer {
+ display: flex;
+ align-items: center;
+ justify-content: space-evenly;
+ text-align:center;
+ position: absolute;
+ width: 320px;
+ height: 102px;
+ left: 20px;
+ top: 165px;
+ background: #FFFFFF;
+ box-shadow: 0px 2px 16px rgba(0, 0, 0, 0.08);
+ border-radius: 4px;
+ color: black;
+ font-size: 12px;
}
-.btn-transfer {
- width: 200px;
+
+.transaction-title{
+ margin-top: 55px;
}
.transaction-title h3 {
- font-size: 18px;
+ font-size: 14px;
font-weight: inherit;
- color: #cacaca;
- text-align: center;
- padding: 5px 0;
+ padding: 10px 0 10px 20px;
}
.transactions {
- font-size: 15px;
- height: 273px;
- overflow: hidden;
-}
-.transactions .list {
- padding: 0 20px;
+ font-size: 15px;
+ height: 283px;
+ overflow: auto;
}
.list-item {
+ position: relative;
display: block;
- padding: 5px 10px;
- border-bottom: 1px solid #5e5e5e;
+ padding: 10px 20px;
+ height: 52px;
+ border-bottom: solid 1px rgba(0, 0, 0, 0.04)
}
-.list-item .value {
- float: right;
- margin-top: 13px;
-}
-.account-address {
- cursor: pointer;
+.network-select{
+ text-transform: capitalize;
}
+
.btn-creation {
display: block;
- width: 200px;
- margin: 0 auto;
+ width: 310px;
+ height: 48px;
+ margin: auto;
+ padding: 15px 0;
+ position: absolute;
+ bottom: 20px;
+ left: 20px;
+}
+
+.addr{
+ font-size: 12px;
+}
+
+.no-record{
+ display: block;
+}
+
+ .bg-image{
+ height: 216px;
+ }
+
+.icon{
+ width: 40px;
+ height: 40px;
+}
+.icon-crosschain-svg{
+ background-image: url('../assets/img/icon/crosschain.svg');
}
+.icon-vote-svg{
+ background-image: url('../assets/img/icon/vote.svg');
+}
+.icon-receive-svg{
+ background-image: url('../assets/img/icon/receive.svg');
+}
+.icon-send-svg{
+ background-image: url('../assets/img/icon/send.svg');
+}
+
</style>
<template>
<div class="warp">
- <section class="bg-green">
+ <section class="bg-image">
<div class="topbar">
- <div class="topbar-right">
- <i class="lamp"></i>
- <select v-model="network" @change="networkToggle">
- <option value="mainnet">{{ $t('main.mainNet') }}</option>
- <option value="testnet">{{ $t('main.testNet') }}</option>
- <option value="solonet">{{ $t('main.soloNet') }}</option>
- </select>
- </div>
<div class="topbar-left">
<a class="btn-menu" @click="openMenu">
<i class="iconfont icon-menu"></i>
</a>
- <span class="alias">{{currentAccount.alias}}</span>
+ </div>
+ <div class="topbar-middle bg-secondary">
+ <select class="network-select" :value="netType||'bytom'" @change="netTypeToggle">
+ <option value="bytom">{{ $t('main.bytom') }} {{net}}</option>
+ <option value="vapor">{{ $t('main.vapor') }} {{net}}</option>
+ </select>
</div>
</div>
<div class="content">
- <img src="@/assets/logo.png" class="token-icon">
- <div v-if="currentAccount.address!=undefined" class="amount">
+ <div v-if="address!=undefined" class="amount color-white">
+ <span class="alias color-grey">{{currentAccount.alias}}</span>
<div class="token-amount">
{{accountBalance}}
- <span class="asset">BTM</span>
</div>
- <p class="account-address">
- <span class="address-text" :title="addressTitle" :data-clipboard-text="currentAccount.address">{{shortAddress}}</span>
- <i class="iconfont qrcode" @click="showQrcode"></i>
- </p>
</div>
- <a v-if="currentAccount.address!=undefined" class="btn btn-primary btn-transfer" @click="transferOpen">{{ $t('main.transfer') }}</a>
+ <div v-else>
+ <p style="width: 250px; margin: 45px auto; text-align: center;">{{ $t('main.noAccount') }}</p>
+
+ </div>
+ </div>
+ <div v-if="netType =='vapor' && address!=undefined" class="btn-send-transfer">
+
+ <a @click="listVoteOpen">
+ <div class="icon icon-vote-svg"></div>
+ <div>{{ $t('main.vote') }}</div>
+ </a>
+ <a @click="crossChainOpen">
+ <div class="icon icon-crosschain-svg"></div>
+ <div>{{ $t('main.crossChain') }}</div>
+ </a>
+ <a @click="showQrcode">
+ <div class="icon icon-receive-svg"></div>
+ <div>{{ $t('main.receive') }}</div>
+ </a>
+ <a @click="transferOpen">
+ <div class="icon icon-send-svg"></div>
+ <div>{{ $t('main.send') }}</div>
+ </a>
+ </div>
+ <div v-else-if="address!=undefined" class="btn-send-transfer">
+ <a @click="showQrcode">
+ <div class="icon icon-receive-svg"></div>
+ <div>{{ $t('main.receive') }}</div>
+ </a>
+ <a @click="transferOpen">
+ <div class="icon icon-send-svg"></div>
+ <div>{{ $t('main.send') }}</div>
+ </a>
</div>
</section>
+ <section v-if="address!=undefined" class="transaction-title">
+ <h3 class="color-black">{{ $t('main.asset') }}</h3>
+ </section>
+ <section class="transactions">
+ <div v-if="address!=undefined">
+ <div v-if="balances && balances.length > 0">
+ <ul class="list">
+ <li class="list-item" v-for="(asset, index) in balances" :key="index" @click="assetOpen(asset)">
+ <div class="float-right text-align-right">
+ <div class="value">{{ itemBalance(asset) }}</div>
+ <div class="addr color-grey">{{ formatCurrency(asset[ currency ]) }}</div>
+ </div>
+ <div v-if="asset.symbol!== '-'">
+ <div class="uppercase">
+ {{asset.symbol}}
+ </div>
+
+ <div class="addr color-grey">{{asset.name}}</div>
+ </div>
+ <div v-else>
+ <div>
+ Asset
+ </div>
+
+ <div class="addr color-grey uppercase">{{shortAddress(asset.asset)}}</div>
+ </div>
+
+ </li>
+ </ul>
+ </div>
+ <div v-else>
+ <ul class="list">
+ <li class="list-item" v-for="(asset, index) in defaultBalances" :key="index" @click="assetOpen(asset)">
+ <div class="float-right text-align-right">
+ <div class="value">{{ itemBalance(asset) }}</div>
+ <div class="addr color-grey">{{ formatCurrency(asset[ currency ]) }}</div>
+ </div>
+ <div v-if="asset.symbol!== '-'">
+ <div class="uppercase">
+ {{asset.symbol}}
+ </div>
+
+ <div class="addr color-grey">{{asset.name}}</div>
+ </div>
+ <div v-else>
+ <div>
+ Asset
+ </div>
- <div v-if="currentAccount.address!=undefined">
- <section class="transaction-title">
- <h3 class="bg-gray">{{ $t('main.record') }}</h3>
- </section>
- <section class="transactions">
- <vue-scroll @handle-scroll="handleScroll">
- <ul class="list">
- <li class="list-item" v-for="(transcation, index) in transactions" :key="index" @click="$router.push({name: 'transfer-info', params: {transcation: transcation, address: currentAccount.address}})">
- <div class="value">{{transcation.direct}} {{transcation.val.toFixed(2)}} BTM</div>
- <div>
- <div v-if="transcation.is_confirmed" class="time">
- <div v-if="transcation.block_timestamp === 0">
- {{ $t('main.unconfirmed') }}
- </div>
- <div v-else>
- {{transcation.block_timestamp | moment}}
- </div>
- </div>
- <div v-else class="time">
- <div v-if="transcation.submission_timestamp === 0">
- {{ $t('main.unconfirmed') }}
- </div>
- <div v-else>
- {{transcation.submission_timestamp | moment}}
- </div>
- </div>
- <div class="addr">{{transcation.address}}</div>
- </div>
- </li>
- </ul>
- </vue-scroll>
- </section>
+ <div class="addr color-grey uppercase">{{shortAddress(asset.asset)}}</div>
+ </div>
+
+ </li>
+ </ul>
+ </div>
</div>
<div v-else>
- <p style="width: 250px; margin: 30px auto; text-align: center;">{{ $t('main.noAccount') }}</p>
- <router-link :to="{name: 'menu-account-creation'}">
- <a class="btn btn-primary btn-creation bg-green">{{ $t('main.create') }}</a>
- </router-link>
+ <router-link :to="{name: 'menu-account-creation'}">
+ <div class="bg-emptytx"></div>
+ <div>
+ <span class="color-lightgrey center-text no-record">{{$t('main.noAssetRecord')}}</span>
+ </div>
+ <a class="btn btn-primary btn-creation">{{ $t('main.create') }}</a>
+ </router-link>
</div>
+ </section>
<!-- child page -->
<div class="mask" v-show="maskShow"></div>
<router-view></router-view>
</transition>
- <!-- modal -->
- <Qrcode ref="qrcode"></Qrcode>
</div>
</template>
<script>
-import ClipboardJS from "clipboard";
-import Menu from "@/views/homeMenu";
-import Qrcode from "@/views/qrcode";
-import Transfer from "@/views/transfer";
-import TxInfo from "@/views/transferDetail";
import address from "@/utils/address";
import account from "@/models/account";
import transaction from "@/models/transaction";
import { BTM } from "@/utils/constants";
+import { mapActions, mapGetters, mapState } from 'vuex'
+import * as Actions from '@/store/constants';
+import _ from 'lodash';
+import { Number as Num } from "@/utils/Number"
+
const EnterActive = 'animated faster fadeInLeft';
const LeaveActive = 'animated faster fadeOutLeft';
export default {
name: "",
- components: {
- Qrcode,
- },
data() {
return {
- network: "mainnet",
- clipboard: new ClipboardJS(".address-text"),
- addressTitle: this.$t("main.copy"),
- accounts: [],
- currentAccount: {},
transactions: [],
maskShow: false,
start: 0,
limit: 10,
enterActive: EnterActive,
leaveActive: LeaveActive,
+ defaultBalances: [
+ {
+ alias: "btm",
+ asset: BTM,
+ name: "Bytom",
+ symbol: "BTM",
+ balance: 0,
+ decimals: 8,
+ in_btc: "0",
+ in_cny: "0",
+ in_usd: "0"
+ }
+ ],
};
},
watch: {
this.maskShow = false
}
- //account toggle by the list from menu
- if (to.name == 'home' && to.params.selectedAccount != undefined) {
- this.currentAccount = to.params.selectedAccount
- this.refreshAccounts();
- }
-
// remove transition for some page
this.enterActive = EnterActive
this.leaveActive = LeaveActive
this.enterActive = ''
this.leaveActive = ''
}
+ if (from.name == 'transfer-confirm') {
+ this.setupNetwork()
+ }
},
currentAccount(newVal, oldVal) {
if (newVal.guid == undefined){
- localStorage.currentAccount = {}
return;
}
- localStorage.currentAccount = JSON.stringify(newVal);
- this.refreshTransactions(newVal.guid, newVal.address).then(transactions => {
- this.transactions = transactions
- });
+ let addr
+ if(this.netType === 'vapor'){
+ addr = newVal.vpAddress
+ }else{
+ addr = newVal.address
+ }
},
- 'currentAccount.guid'(guid) {
- if (guid == undefined) return;
-
- this.refreshBalance(guid);
- }
},
computed: {
- shortAddress: function () {
- return address.short(this.currentAccount.address)
- },
accountBalance: function () {
- return this.currentAccount.balance != 0 ? this.currentAccount.balance : '0.00'
- }
+ let balance
+ const balances = this.balances
+
+ if(balances && balances.length >0 ){
+ const currency = this.currency
+ balance = _.sumBy(balances, function(o) { return Number(o[currency]); })
+ }
+ return Num.formatCurrency( (balance != null && balance != 0)? balance : '0.00', this.currency)
+ },
+ address: function(){
+ if(this.netType === 'vapor'){
+ return this.currentAccount.vpAddress
+ }else{
+ return this.currentAccount.address
+ }
+ },
+ balances: function(){
+ if(this.netType === 'vapor'){
+ return this.currentAccount.vpBalances
+ }else{
+ return this.currentAccount.balances
+ }
+ },
+ ...mapState([
+ 'bytom'
+ ]),
+ ...mapGetters([
+ 'currentAccount',
+ 'accountList',
+ 'net',
+ 'netType',
+ 'currency'
+ ])
},
methods: {
- setupClipboard() {
- this.clipboard.on("success", e => {
- this.$dialog.show({
- header: this.$t("dialog.header"),
- body: this.$t("dialog.copy.success")
- });
- });
- this.clipboard.on("error", e => {
- this.$dialog.show({
- header: this.$t("dialog.header"),
- body: this.$t("dialog.copy.fail")
- });
- });
- },
+ shortAddress: function (add) {
+ return address.short(add)
+ },
+ formatCurrency: function (num) {
+ return Num.formatCurrency(num, this.currency)
+ },
+ itemBalance: function(asset){
+ if(asset.asset === BTM){
+ return Num.formatNue(asset.balance,8)
+ }else{
+ return Num.formatNue(asset.balance,asset.decimals)
+ }
+ },
setupRefreshTimer() {
- // todo refresh all accounts
-
setInterval(() => {
this.refreshBalance(this.currentAccount.guid)
}, 10000)
},
setupNetwork() {
- this.network = localStorage.bytomNet;
- account.setupNet(this.network);
+ account.setupNet(`${this.net}${this.netType}`);
},
- networkToggle: function (val) {
- localStorage.bytomNet = this.network;
- account.setupNet(this.network);
- this.currentAccount = {}
- this.refreshAccounts();
+ netTypeToggle: function (event) {
+ const newNetType = event.target.value ==='bytom'? '' :event.target.value;
+
+ if( newNetType !== this.netType){
+ const bytom = this.bytom.clone();
+
+ bytom.settings.netType = newNetType;
+
+ account.setupNet(`${this.net}${newNetType}`)
+ if(newNetType === 'vapor'&& !this.currentAccount.vpAddress){
+ account.copy(this.currentAccount.guid).then(accounts => {
+ //update currentAccount
+ bytom.currentAccount = accounts
+
+ //update AccountList
+ const objectIndex = bytom.accountList.findIndex(a => a.guid == this.currentAccount.guid)
+ bytom.accountList[objectIndex].vpAddress = accounts.vpAddress
+
+ this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
+ this.refreshBalance(this.currentAccount.guid)
+ })
+ }).catch(e =>{
+ if(e.message == 'Error: wallet has exist'){
+ account.listVapor(this.currentAccount.guid).then(accounts => {
+ //update currentAccount
+ bytom.currentAccount = accounts
+
+ const objectIndex = bytom.accountList.findIndex(a => a.guid == this.currentAccount.guid)
+ bytom.accountList[objectIndex].vpAddress = accounts.vpAddress
+
+ this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
+ this.refreshBalance(this.currentAccount.guid)
+ })
+ })
+
+ }
+ })
+ }else{
+ this[Actions.UPDATE_STORED_BYTOM](bytom).then(()=>{
+ this.refreshBalance(this.currentAccount.guid)
+ })
+ }
+ }
},
showQrcode: function () {
- this.$refs.qrcode.open(this.currentAccount.address);
+ this.$router.push('received')
},
openMenu: function () {
- this.$router.push({ name: 'menu', params: { accounts: this.accounts, selected: this.currentAccount } })
+ this.$router.push('menu')
},
transferOpen: function () {
- this.$router.push({ name: 'transfer', params: { account: this.currentAccount } })
+ this.$router.push('transfer')
},
- handleScroll(vertical, horizontal, nativeEvent) {
- if (vertical.process == 0) {
- this.start = 0;
- this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address).then(transactions => {
- this.transactions = transactions
- });
- return;
- }
-
- if (vertical.process == 1) {
- this.start += this.limit;
- this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address, this.start, this.limit).then(transactions => {
- transactions.forEach(transaction => {
- this.transactions.push(transaction);
- });
- });
- }
+ crossChainOpen: function () {
+ this.$router.push('crossChain')
},
- refreshAccounts: function () {
- account.list().then(accounts => {
- this.accounts = accounts;
- if (accounts.length == 0) {
- return;
- }
-
- if (this.currentAccount.guid == undefined) {
- this.currentAccount = accounts[0];
- }
- })
+ listVoteOpen: function () {
+ this.$router.push('listVote')
},
- refreshBalance: function (guid) {
- account.balance(guid).then(balance => {
- this.currentAccount.balance = balance;
- this.currentAccount = Object.assign({}, this.currentAccount);
- }).catch(error => {
- console.log(error);
- });
+ assetOpen: function (asset) {
+ this[Actions.SET_CURRENT_ASSET](asset)
+ this.$router.push('asset')
},
- refreshTransactions: function (guid, address, start, limit) {
- return new Promise((resolve, reject) => {
- transaction.list(guid, address, start, limit).then(ret => {
- let transactions = ret.result.data;
- if (transactions == null) {
- return;
- }
+ refreshBalance: function (guid) {
+ if(guid){
+ account.balance(guid)
+ .then((obj)=>{
+ const balances = obj.balances
+ const votes = obj.votes
- const formattedTx = this.transactionsFormat(transactions);
- console.log("formatTx", formattedTx);
- resolve(formattedTx)
- }).catch(error => {
- console.log(error);
- reject(error)
- });
- })
- },
- transactionsFormat: function (transactions) {
- const formattedTransactions = []
- const assetID = BTM
+ const balanceNotEqual = !_.isEqual(this.balances, balances)
- transactions.forEach(transaction => {
- const balanceObject = transaction.balances
- .filter(b => b.asset === assetID);
+ const voteNotEqual = (this.netType === 'vapor' && !_.isEqual(this.currentAccount.votes, votes))
- if(balanceObject.length ===1 ){
+ if(balanceNotEqual || voteNotEqual){
+ //update AccountList
- const inputAddresses = transaction.inputs
- .filter(input => input.asset === assetID && input.address !== this.currentAccount.address)
- .map(input => input.address)
+ const bytom = this.bytom.clone();
- const outputAddresses = transaction.outputs
- .filter(output => output.asset === assetID && output.address !== this.currentAccount.address)
- .map(output => output.address)
+ const objectIndex = bytom.accountList.findIndex(a => a.guid == this.currentAccount.guid)
+ if(balanceNotEqual){
+ if(this.netType === 'vapor'){
+ bytom.currentAccount.vpBalances = balances;
+ bytom.accountList[objectIndex].vpBalances = balances
+ }else{
+ bytom.currentAccount.balances = balances;
+ bytom.accountList[objectIndex].balances = balances
+ }
+ }
- const val = assetID===BTM ? Number(balanceObject[0].amount)/ 100000000 : Number(balanceObject[0].amount);
+ if(voteNotEqual){
+ bytom.currentAccount.votes = votes;
+ bytom.accountList[objectIndex].votes = votes
+ }
- if (val > 0) {
- transaction.direct = "+";
- transaction.address = address.short(inputAddresses.pop());
- } else {
- transaction.direct = "-";
- transaction.address = address.short(outputAddresses.pop());
+ this[Actions.UPDATE_STORED_BYTOM](bytom)
}
-
- transaction.val = Math.abs(val);
- transaction.fee = transaction.fee / 100000000;
-
- formattedTransactions.push(transaction);
- }
+ })
+ .catch(error => {
+ console.log(error);
});
- return formattedTransactions;
+ }
},
+ ...mapActions([
+ Actions.UPDATE_STORED_BYTOM,
+ Actions.SET_CURRENT_ASSET,
+ ])
},
mounted() {
- this.currentAccount = JSON.parse(localStorage.currentAccount);
this.setupNetwork();
- this.setupClipboard();
this.setupRefreshTimer();
- this.refreshAccounts();
+ this.refreshBalance(this.currentAccount.guid)
},
- beforeDestroy() {
- this.clipboard.destroy();
- }
-};
+ };
</script>