view:'展示全部',
hide:'隐藏全部'
},
+ crossChain:{
+ title:'跨链',
+ amountPlaceHolder:"链可用",
+ amountHint:'跨链交易预计24小时内完成',
+ toVapor:'转入\nVapor链',
+ toBytom:'转出至\nBytom链',
+ asset:'选择资产'
+ },
signMessage:{
title:'请求签名',
address: '签名地址',
},
receive:{
address: '地址',
- tips:'提示:点击地址进行拷贝。'
+ tips:'提示:点击地址进行拷贝。',
+ vpWarning:'Vapor钱包地址请勿用于交易所充值提现'
},
main: {
mainNet: '主网络',
view:'View All',
hide:'Hide All'
},
+ crossChain:{
+ title:'Cross Chain',
+ amountPlaceHolder:" available amount: ",
+ amountHint:'Cross Chain Transaction will be completed in 24 hrs.',
+ toVapor:'Transfer to \n Vapor Chain',
+ toBytom:'Transfer to \n Bytom Chain',
+ asset:'Select Asset'
+ },
signMessage:{
title:'Request Signature',
address: 'Sign Address',
},
receive:{
address: 'Address',
- tips:'Tips: Click address to copy directly.'
+ tips:'Tips: Click address to copy directly.',
+ vpWarning:'Please don\'t use Vapor address in the real transaction.'
},
main: {
mainNet: 'Mainnet',
.color-lightgrey {
color: #e0e0e0;
}
+.color-red {
+ color: #d84c4c;
+}
.bg-red {
background-color: #d84c4c !important;
margin-bottom: 5px;
}
.form-item-content input{
- border-bottom: 1px solid #E0E0E0;
+ border-bottom: 1px solid #c7c7c7;
padding-bottom: 5px;
}
.form-item-content input:focus{
border-bottom: 1px solid #035BD4;
}
+.form-item-content input::placeholder{
+ color:#E0E0E0;
+}
+
.center-text{
text-align: center;
}
return Promise.all(actionFunction);
};
-transaction.blockCount = function() {
+transaction.chainStatus = function() {
return bytom.query.getblockcount();
};
return retPromise;
};
+transaction.buildCrossChain = function(guid, to, asset, amount, confirmations) {
+ let retPromise = new Promise((resolve, reject) => {
+ bytom.transaction
+ .buildCrossChain(guid, to, asset, Number(amount), confirmations)
+ .then(res => {
+ resolve(res);
+ })
+ .catch(error => {
+ reject(error);
+ });
+ });
+ return retPromise;
+};
+
transaction.buildTransaction = function(guid, inputs, outputs, gas, confirmations) {
let retPromise = new Promise((resolve, reject) => {
bytom.transaction
}
},
{
+ path: '/crossChain',
+ name: 'cross-chain',
+ meta: { title: '跨链' },
+ component: resolve => {
+ require(['@/views/sendTransaction/crossChainTransaction.vue'], resolve)
+ }
+ },
+ {
path: '/signMessage',
name: 'sign-message',
meta: { title: '请求签名' },
</div>
</div>
<div class="content">
- <div v-if="currentAccount.address!=undefined" class="amount color-white">
+ <div v-if="address!=undefined" class="amount color-white">
<span class="alias color-grey">{{currentAccount.alias}}</span>
<div class="token-amount">
{{accountBalance}}
</div>
</div>
- <div class="btn-send-transfer">
+ <div v-if="netType =='vapor'" class="btn-send-transfer">
- <a v-if="(currentAccount.address!=undefined) && (netType =='vapor')" class="btn btn-primary btn-received" @click="showQrcode">
- <i class="iconfont icon-receive"></i>
+ <a v-if="address!=undefined" class="btn btn-primary btn-received" @click="showQrcode">
vote
</a>
- <a v-if="currentAccount.address!=undefined && (netType =='vapor')" class="btn btn-primary btn-transfer" @click="transferOpen">
- <i class="iconfont icon-send"></i>
- cross-chain
- </a><a v-if="currentAccount.address!=undefined" class="btn btn-primary btn-received" @click="showQrcode">
+ <a v-if="address!=undefined " class="btn btn-primary btn-transfer" @click="crossChainOpen">
+ cross
+ </a><a v-if="address!=undefined" class="btn btn-primary btn-received" @click="showQrcode">
+ {{ $t('main.receive') }}
+ </a>
+ <a v-if="address!=undefined" class="btn btn-primary btn-transfer" @click="transferOpen">
+ {{ $t('main.send') }}
+ </a>
+ </div>
+ <div v-else class="btn-send-transfer">
+ <a v-if="address!=undefined" class="btn btn-primary btn-received" @click="showQrcode">
<i class="iconfont icon-receive"></i>
{{ $t('main.receive') }}
</a>
- <a v-if="currentAccount.address!=undefined" class="btn btn-primary btn-transfer" @click="transferOpen">
+ <a v-if="address!=undefined" class="btn btn-primary btn-transfer" @click="transferOpen">
<i class="iconfont icon-send"></i>
{{ $t('main.send') }}
</a>
<h3 class="bg-gray color-grey">{{ $t('main.record') }}</h3>
</section>
<section class="transactions">
- <div v-if="currentAccount.address!=undefined">
+ <div v-if="address!=undefined">
<div v-if="transactions.length != 0">
<vue-scroll @handle-scroll="handleScroll">
<ul class="list">
this.leaveActive = ''
}
if (from.name == 'transfer-confirm') {
- this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address).then(transactions => {
+ this.setupNetwork()
+ this.refreshTransactions(this.currentAccount.guid, this.address).then(transactions => {
this.transactions = transactions
});
}
return;
}
- this.refreshTransactions(newVal.guid, newVal.address).then(transactions => {
+ let addr
+ if(this.netType === 'vapor'){
+ addr = newVal.vpAddress
+ }else{
+ addr = newVal.address
+ }
+
+ this.refreshTransactions(newVal.guid, addr).then(transactions => {
this.transactions = transactions
});
},
},
computed: {
shortAddress: function () {
- return address.short(this.currentAccount.address)
+ return address.short(this.address)
},
accountBalance: function () {
let balance
- const balances = this.currentAccount.balances
+ const balances = this.balances
if(balances && balances.length >0 ){
const balanceObject = balances.filter(b => b.asset === BTM)[0]
balance = balanceObject.balance/Math.pow(10,balanceObject.decimals)
}
return (balance != null && balance != 0) ? balance : '0.00'
},
+ 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'
]),
transferOpen: function () {
this.$router.push('transfer')
},
+ crossChainOpen: function () {
+ this.$router.push('crossChain')
+ },
handleScroll(vertical, horizontal, nativeEvent) {
if (vertical.process == 0) {
this.start = 0;
- this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address).then(transactions => {
+ this.refreshTransactions(this.currentAccount.guid, this.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 => {
+ this.refreshTransactions(this.currentAccount.guid, this.address, this.start, this.limit).then(transactions => {
transactions.forEach(transaction => {
this.transactions.push(transaction);
});
refreshBalance: function (guid) {
account.balance(guid)
.then((balances)=>{
- if(!_.isEqual(this.currentAccount.balances, balances)){
+ if(!_.isEqual(this.balances, balances)){
const bytom = this.bytom.clone();
- bytom.currentAccount.balances = balances;
+ //update AccountList
+ const objectIndex = bytom.accountList.findIndex(a => a.guid == this.currentAccount.guid)
+
+ if(this.netType === 'vapor'){
+ bytom.currentAccount.vpBalances = balances;
+ bytom.accountList[objectIndex].vpBalances = balances
+ }else{
+ bytom.currentAccount.balances = balances;
+ bytom.accountList[objectIndex].balances = balances
+ }
+
+
this[Actions.UPDATE_STORED_BYTOM](bytom)
}
})
if(balanceObject.length ===1 ){
const inputAddresses = transaction.inputs
- .filter(input => input.asset === assetID && input.address !== this.currentAccount.address)
+ .filter(input => input.asset === assetID && input.address !== this.address)
.map(input => input.address)
const outputAddresses = transaction.outputs
- .filter(output => output.asset === assetID && output.address !== this.currentAccount.address)
+ .filter(output => output.asset === assetID && output.address !== this.address)
.map(output => output.address)
mounted() {
this.setupNetwork();
this.setupRefreshTimer();
- this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address).then(transactions => {
+ this.refreshTransactions(this.currentAccount.guid, this.address).then(transactions => {
this.transactions = transactions
});
},
margin: 30px auto;
}
+ .vp-warning {
+ text-align: center;
+ width: 100%;
+ font-size: 12px;
+ }
+
.address-text{
cursor: pointer;
}
<p>{{$t('receive.address')}}</p>
<span class="color-black font-medium address-text" :title="addressTitle" :data-clipboard-text="addr">{{addr}}</span>
</div>
+ <div v-if="netType === 'vapor'" class="vp-warning color-red"> {{$t('receive.vpWarning')}}</div>
<div class="footer color-grey"> {{$t('receive.tips')}}</div>
</div>
</template>
computed: {
...mapGetters([
'currentAccount',
+ 'netType'
])
},
methods: {
},
mounted() {
if (this.currentAccount.address != undefined) {
- this.addr = this.currentAccount.address;
+ if(this.netType === 'vapor'){
+ this.addr = this.currentAccount.vpAddress;
+ }else{
+ this.addr = this.currentAccount.address;
+ }
this.qrcode = new QRCode( "qrcode", {
text: this.addr,
width: 150,
--- /dev/null
+<style lang="" scoped>
+.header {
+ display: flex;
+}
+.header p{
+ text-align: center;
+ width: 270px;
+ padding-top: 17px;
+}
+.transferType {
+ /*width: 280px;*/
+ /*height: 40px;*/
+ margin: 20px;
+ display: flex;
+}
+
+.transferType input[type=radio] {
+ position: absolute;
+ visibility: hidden;
+}
+
+.transferType input[type="radio"]:checked+label{
+ color:white;
+ background-color: #333333;
+}
+
+.choice {
+ border: 1px solid;
+ border-radius: 6px;
+ cursor: pointer;
+ padding: 20px;
+ font-size: 14px;
+ white-space:pre-wrap;
+ display: block;
+ background-color: white;
+ width:108px;
+ margin-right:20px;
+}
+
+.choice:hover {
+ background-color: #f7f7f7;
+ }
+
+.form-container{
+ margin: 20px;
+}
+.form {
+ margin-bottom: 20px;
+ padding: 10px 15px;
+ border-radius:4px;
+}
+.form-container .btn{
+ height: 48px;
+ bottom: 20px;
+ position: absolute;
+ width: 320px;
+}
+ .small{
+ font-size: 12px;
+ }
+.wallet{
+ width: 40px;
+ height: 40px;
+ background: rgba(255,255,255,0.1);
+ border-radius: 50%;
+ color: white;
+ margin-right: 20px;
+ line-height: 40px;
+ text-align: center;
+}
+</style>
+
+<template>
+ <div class="warp-chlid bg-gray">
+ <section class="header bg-header">
+ <i class="iconfont icon-back" @click="close"></i>
+ <p>{{ $t('crossChain.title') }}</p>
+ </section>
+
+ <section class="transferType">
+ <div>
+ <input type="radio" id="typeChoice1"
+ value="toVapor" v-model="transaction.type">
+ <label class="choice" for="typeChoice1">{{$t('crossChain.toVapor')}}</label>
+
+ </div>
+ <div>
+ <input type="radio" id="typeChoice2"
+ value="toBytom" v-model="transaction.type">
+ <label class="choice" for="typeChoice2">{{$t('crossChain.toBytom')}}</label>
+
+ </div>
+ </section>
+
+ <section class="form-container">
+ <div class="form bg-white">
+ <div class="form-item">
+ <label class="form-item-label">{{ $t('crossChain.asset') }}</label>
+ <!--<div class="form-item-content" >-->
+ <v-select style="height: 32px;" class="v-select" v-bind:colorBlack="true" :clearable="false" :value="aOptions[0]" :options="aOptions"></v-select>
+ <!--</div>-->
+ </div>
+ <div class="form-item">
+ <label class="form-item-label">
+ {{ $t('transfer.quantity') }}
+
+ <small class="float-right" style="margin-right: 8px;">{{ transaction.cost||0 }} CNY</small>
+ </label>
+ <div class="form-item-content" style=" display: flex;">
+ <input type="number" v-model="transaction.amount" :placeholder="bytomBalance">
+ <span class="color-grey" style="width: 40px; font-size: 15px;position: absolute;right: 0;">{{unit}}</span>
+ </div>
+ <p class="small color-grey">{{$t('crossChain.amountHint')}}</p>
+ </div>
+ </div>
+ <a class="btn btn-primary" @click="send">{{ $t('transfer.send') }}</a>
+ </section>
+ </div>
+</template>
+
+<script>
+import account from "@/models/account";
+import transaction from "@/models/transaction";
+import getLang from "@/assets/language/sdk";
+import Confirm from "./transferConfirm";
+import { BTM } from "@/utils/constants";
+import { mapActions, mapGetters, mapState } from 'vuex'
+import * as Actions from '@/store/constants';
+
+export default {
+ components: {
+ Confirm
+ },
+ data() {
+ const ASSET_BTM =
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ return {
+ selectAsset: {
+ assets: ASSET_BTM,
+ name: "BTM"
+ },
+ assetOptions: [
+ {
+ assets: ASSET_BTM,
+ name: "BTM"
+ }
+ ],
+ aOptions: [
+ { label: "BTM", value: ASSET_BTM },
+ ],
+ show: false,
+ assets: {
+ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff: "BTM"
+ },
+ guid: null,
+ account: {},
+ accountBalance: 0.00,
+ fee: this.$t("transfer.feeType"),
+ feeTypeOptions: [this.$t("transfer.feeType")],
+ transaction: {
+ type:'toVapor',
+ asset: ASSET_BTM,
+ fee: 0,
+ amount: "",
+ to:'',
+ confirmations: 1
+ }
+ };
+ },
+ computed: {
+ unit() {
+ return this.assets[this.transaction.asset];
+ },
+ bytomBalance: function () {
+ let balance, balances
+ if(this.transaction.type === 'toVapor'){
+ balances = this.currentAccount.balances
+ }else if(this.transaction.type === 'toBytom'){
+ balances = this.currentAccount.vpBalances
+ }
+ if(balances && balances.length >0 ){
+ const balanceObject = balances.filter(b => b.asset === BTM)[0]
+ balance = balanceObject.balance/Math.pow(10,balanceObject.decimals)
+ }
+
+ if(this.transaction.type === 'toVapor'){
+ return `Bytom${this.$t("crossChain.amountPlaceHolder")}${(balance != null && balance != 0) ? balance : '0.00'}`
+ }else{
+ return `Vapor${this.$t("crossChain.amountPlaceHolder")}${(balance != null && balance != 0) ? balance : '0.00'}`
+ }
+ },
+ ...mapState([
+ 'bytom'
+ ]),
+ ...mapGetters([
+ 'currentAccount',
+ 'accountList',
+ 'net',
+ 'netType'
+ ])
+ },
+ watch: {
+ selectAsset: function (val) {
+ this.transaction.asset = val.assets;
+ },
+ "transaction.amount": function (newAmount) {
+ transaction.asset(this.transaction.asset).then(ret => {
+ this.transaction.cost = Number(ret.cny_price * newAmount).toFixed(2);
+ });
+ },
+ account: function (newAccount) {
+ this.guid = newAccount.guid;
+ },
+ guid: function (newGuid) {
+ this.accountList.forEach(account => {
+ if (account.guid == newGuid.guid) {
+ this.account = account;
+ return;
+ }
+ });
+
+ account.balance(newGuid).then(balances => {
+ let balance = 0.00
+ if(balances.length >0 ) {
+ const balanceObject = balances.filter(b => b.asset === BTM)[0]
+ balance = balanceObject.balance / Math.pow(10, balanceObject.decimals)
+ }
+ this.accountBalance = balance;
+ }).catch(error => {
+ console.log(error);
+ });
+ }
+ },
+ methods: {
+ close: function () {
+ this.$router.go(-1)
+ this.transaction.to = "";
+ this.transaction.amount = "";
+ account.setupNet(`${this.net}${this.netType}`);
+ if(this.$route.query.type == 'popup'){
+ window.close();
+ }
+ },
+ send: function () {
+ if (this.transaction.amount <= 0) {
+ this.$dialog.show({
+ body: this.$t("transfer.noneBTM")
+ });
+ return;
+ }
+
+ let loader = this.$loading.show({
+ // Optional parameters
+ container: null,
+ canCancel: true,
+ onCancel: this.onCancel
+ });
+
+ // Bytom => Vapor
+ if(this.transaction.type === 'toVapor'){
+ transaction.chainStatus().then((resp)=>{
+ const address = resp.federation_address
+ account.setupNet(`${this.net}bytom`)
+ this.transaction.to = address
+ transaction.build(this.account.guid, address, this.transaction.asset, this.transaction.amount*100000000, this.transaction.confirmations).then(result => {
+ loader.hide();
+ this.transaction.fee = Number(result.fee / 100000000);
+ this.$router.push({ name: 'transfer-confirm', params: { account: this.account, transaction: this.transaction, rawData: result, type: this.$route.query.type } })
+ }).catch(error => {
+ loader.hide();
+ this.$dialog.show({
+ body: getLang(error.message)
+ });
+ });
+ })
+ }
+
+ // Vapor => Bytom
+ else{
+ const address = this.account.address
+ account.setupNet(`${this.net}vapor`)
+ this.transaction.to = address
+ transaction.buildCrossChain(this.account.guid, address, this.transaction.asset, this.transaction.amount*100000000, this.transaction.confirmations).then(result => {
+ loader.hide();
+ this.transaction.fee = Number(result.fee / 100000000);
+ this.$router.push({ name: 'transfer-confirm', params: { account: this.account, transaction: this.transaction, rawData: result, type: this.$route.query.type } })
+ }).catch(error => {
+ loader.hide();
+ this.$dialog.show({
+ body: getLang(error.message)
+ });
+ });
+ }
+
+ }
+ }, mounted() {
+ //detect injection
+ if(this.$route.query.type === 'popup'){
+ if (this.$route.query.from != undefined) {
+ this.guid = this.$route.query.from
+ this.account = this.accountList.filter(e => e.guid === this.guid)[0]
+ }
+
+ if (this.$route.query.asset != undefined) {
+ this.transaction.asset= this.$route.query.asset
+ }
+ if (this.$route.query.to != undefined) {
+ this.transaction.to = this.$route.query.to
+ }
+ if (this.$route.query.amount != undefined) {
+ this.transaction.amount = this.$route.query.amount /100000000
+ }
+ if (this.$route.query.gas != undefined) {
+ this.transaction.fee = this.$route.query.gas /100000000
+ }
+ if(this.$route.query.confirmations != undefined) {
+ this.transaction.confirmations = this.$route.query.confirmations
+ }
+ }else{
+ this.account = this.currentAccount
+ }
+ }
+};
+</script>
<script>
import transaction from "@/models/transaction";
+import account from "@/models/account";
import modalPasswd from "@/components/modal-passwd";
import getLang from "@/assets/language/sdk";
import { LocalStream } from 'extension-streams';
},
computed: {
...mapGetters([
- 'language'
+ 'language',
+ 'net'
])
},
methods: {
body: this.$t("transfer.success")
});
this.$router.push('/')
+ if(this.transaction.type === 'toVapor'){
+ account.setupNet(`${this.net}vapor`)
+ }
})
.catch(error => {
loader.hide();
if (bytom.settings.network != val.value) {
bytom.settings.network = val.value;
this.network = val;
- account.setupNet(`${val.value}${this.netType}`);
+ account.setupNet(`${val.value}bytom`);
bytom.currentAccount = {}
account.list()
</template>
<script>
-export default {
+ import { mapGetters } from 'vuex'
+
+ export default {
name: "",
data() {
return {
'pending-header': !this.transaction.status_fail && !this.transaction.hasOwnProperty('block_timestamp') ,
'fail-header': this.transaction.status_fail
}
- }
+ },
+ ...mapGetters([
+ 'currentAccount',
+ 'netType'
+ ])
},
mounted() {
let params = this.$route.params;
this.transaction = params.transaction;
- this.selfAddress = params.address;
+ if(this.netType === 'vapor'){
+ this.selfAddress = this.currentAccount.vpAddress;
+ }else{
+ this.selfAddress = this.currentAccount.address;
+ }
console.log(params.transaction)
}
};