OSDN Git Service

update the cross chain
authorZhiting Lin <zlin035@uottawa.ca>
Tue, 13 Aug 2019 06:48:22 +0000 (14:48 +0800)
committerZhiting Lin <zlin035@uottawa.ca>
Tue, 13 Aug 2019 06:48:22 +0000 (14:48 +0800)
src/assets/language/cn.js
src/assets/language/en.js
src/assets/style.css
src/models/transaction.js
src/router.js
src/views/home.vue
src/views/received.vue
src/views/sendTransaction/crossChainTransaction.vue [new file with mode: 0644]
src/views/sendTransaction/transferConfirm.vue
src/views/sideMenu/menuSettings.vue
src/views/transferDetail.vue

index 68df30e..a77d4ae 100644 (file)
@@ -45,6 +45,14 @@ const cn = {
     view:'展示全部',
     hide:'隐藏全部'
   },
+  crossChain:{
+    title:'跨链',
+    amountPlaceHolder:"链可用",
+    amountHint:'跨链交易预计24小时内完成',
+    toVapor:'转入\nVapor链',
+    toBytom:'转出至\nBytom链',
+    asset:'选择资产'
+  },
   signMessage:{
     title:'请求签名',
     address: '签名地址',
@@ -60,7 +68,8 @@ const cn = {
   },
   receive:{
     address: '地址',
-    tips:'提示:点击地址进行拷贝。'
+    tips:'提示:点击地址进行拷贝。',
+    vpWarning:'Vapor钱包地址请勿用于交易所充值提现'
   },
   main: {
     mainNet: '主网络',
index 4b432cc..23af18e 100644 (file)
@@ -45,6 +45,14 @@ const en = {
     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',
@@ -60,7 +68,8 @@ const en = {
   },
   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',
index 51a07d8..0cc3d6c 100644 (file)
@@ -223,6 +223,9 @@ hr {
 .color-lightgrey {
   color: #e0e0e0;
 }
+.color-red {
+  color: #d84c4c;
+}
 
 .bg-red {
   background-color: #d84c4c !important;
@@ -457,13 +460,17 @@ select {
   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;
 }
index 641bb74..8eaa30d 100644 (file)
@@ -18,7 +18,7 @@ transaction.convertArgument = function(argArray) {
   return Promise.all(actionFunction);
 };
 
-transaction.blockCount = function() {
+transaction.chainStatus = function() {
   return bytom.query.getblockcount();
 };
 
@@ -40,6 +40,20 @@ transaction.build = function(guid, to, asset, amount, fee, confirmations) {
   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
index 16758bb..319ea3f 100644 (file)
@@ -18,6 +18,14 @@ const routers = [
         }
       },
       {
+        path: '/crossChain',
+        name: 'cross-chain',
+        meta: { title: '跨链' },
+        component: resolve => {
+          require(['@/views/sendTransaction/crossChainTransaction.vue'], resolve)
+        }
+      },
+      {
         path: '/signMessage',
         name: 'sign-message',
         meta: { title: '请求签名' },
index e237204..d05400c 100644 (file)
                 </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">
@@ -304,7 +310,8 @@ export default {
                 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
               });
             }
@@ -314,24 +321,45 @@ export default {
               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'
         ]),
@@ -385,10 +413,13 @@ export default {
         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;
@@ -396,7 +427,7 @@ export default {
 
             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);
                     });
@@ -406,10 +437,21 @@ export default {
         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)
                 }
               })
@@ -443,11 +485,11 @@ export default {
             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)
 
 
@@ -476,7 +518,7 @@ export default {
     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
         });
     },
index e648cdd..20ec790 100644 (file)
     margin: 30px auto;
   }
 
+  .vp-warning {
+    text-align: center;
+    width: 100%;
+    font-size: 12px;
+  }
+
   .address-text{
     cursor: pointer;
   }
@@ -42,6 +48,7 @@
       <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>
@@ -63,6 +70,7 @@
     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,
diff --git a/src/views/sendTransaction/crossChainTransaction.vue b/src/views/sendTransaction/crossChainTransaction.vue
new file mode 100644 (file)
index 0000000..3056a85
--- /dev/null
@@ -0,0 +1,324 @@
+<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>
index 0d69097..35b8a9c 100644 (file)
 
 <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';
@@ -179,7 +180,8 @@ export default {
     },
     computed: {
       ...mapGetters([
-        'language'
+        'language',
+        'net'
       ])
     },
     methods: {
@@ -210,6 +212,9 @@ export default {
                       body: this.$t("transfer.success")
                     });
                     this.$router.push('/')
+                    if(this.transaction.type === 'toVapor'){
+                      account.setupNet(`${this.net}vapor`)
+                    }
                 })
                 .catch(error => {
                     loader.hide();
index e6fdb4e..6b4114a 100644 (file)
@@ -104,7 +104,7 @@ export default {
           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()
index 0b0a87d..6613865 100644 (file)
 </template>
 
 <script>
-export default {
+  import {  mapGetters } from 'vuex'
+
+  export default {
     name: "",
     data() {
         return {
@@ -215,13 +217,21 @@ export default {
           '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)
     }
 };