1 <style lang="scss" scoped>
12 justify-content: center;
15 color: rgba(0, 0, 0, 0.88);
25 border: 1px solid #EBEBEB;
29 word-break: break-all;
33 color: rgba(0, 0, 0, 0.64);
39 letter-spacing: 0.2px;
75 justify-content: space-between;
85 -webkit-border-radius: 16px;
86 -moz-border-radius: 16px;
91 justify-content: center;
93 text-transform: uppercase;
108 text-overflow: ellipsis;
119 .iconfont.icon_arrow_2 {
120 transform: rotate(90deg);
128 justify-content: space-between;
139 word-break: break-all;
140 white-space: pre-wrap;
141 white-space: -moz-pre-wrap;
142 white-space: -pre-wrap;
143 white-space: -o-pre-wrap;
144 word-wrap: break-word;
156 <section class="header">
157 <h1 v-if="prompt.data && prompt.data.type ==='signTransaction'" >{{ $t('transfer.signComfirm') }}</h1>
158 <h1 v-else-if="prompt.data && prompt.data.type ==='message'" >{{ $t('transfer.signMessage') }}</h1>
159 <h1 v-else>{{ $t('transfer.confirmTransaction') }}</h1>
162 <section v-if="dataReady">
163 <div class="tab-group">
164 <a :class="{'color-black font-bold': tab === 'details'}" v-on:click="tab = 'details'">{{ $t('transfer.detail')
166 <a :class="{'color-black font-bold': tab === 'inout'}" v-on:click="tab = 'inout'">{{ $t('transfer.requestDetail')
170 <div v-if="tab ==='details'" class="content">
175 <img class="logo" src="@/assets/logo.png" alt="">
177 <div class="col value">
178 <div v-if="currentWallet && currentWallet.alias" class="wallet color-black">{{currentWallet.alias}}</div>
179 <div>{{shortAddress}}</div>
184 <i class="iconfont icon_arrow_2"></i>
186 <div class="col divider"></div>
191 <img v-if="prompt.domain && domainsMeta[prompt.domain] && domainsMeta[prompt.domain].icon" class="logo"
192 :src="domainsMeta[prompt.domain].icon" alt="">
193 <div v-else-if="initial" class="logo">
198 <div class="col value">
199 <span class="color-black"
200 v-if="prompt.domain && domainsMeta[prompt.domain] && domainsMeta[prompt.domain].title ">{{domainsMeta[prompt.domain].title }}</span>
201 <span class="color-black" v-else-if="prompt.domain ">{{prompt.domain }}</span>
203 <div v-if="transaction.to">{{short(transaction.to)}}</div>
208 <!--transaction types-->
209 <div v-if="prompt.data && prompt.data.type ==='signTransaction'" class="amount-list">
210 <div >{{ $t('transfer.types') }}</div>
211 <div class="color-black font-bold">{{transaction.types}}</div>
215 <div v-if="prompt.data && prompt.data.type ==='message'" class="amount-list">
216 <div style="min-width: 78px;" >{{ $t('signMessage.message') }}</div>
217 <div class="color-black font-bold">{{transaction.message}}</div>
221 <div v-if="prompt.data && prompt.data.type ==='transfer'" class="amount-list">
222 <div>{{ $t('transfer.amount') }}</div>
223 <div class="color-black font-bold">{{transaction.amount}}<span class="uint uppercase">{{unit || short(transaction.asset) }}</span>
226 <div v-else v-for="(amountInput, index) in transaction.amounts" :key="index" class="amount-list">
227 <div>{{ index ==0 ? $t('transfer.amount'):'' }}</div>
228 <div class="color-black font-bold">{{amountInput.amount}}<span class="uint uppercase">{{amountInput.alias || short(amountInput.asset) }}</span>
233 <div v-if="transaction.fee" class="amount-list">
234 <div>{{ $t('transfer.fee') }}</div>
235 <div class="color-black font-bold">{{transaction.fee}}<span class="uint">BTM</span></div>
239 <div v-if="tab ==='inout'" class="content content-black">
240 <pre>{{detail}}</pre>
244 <div class="form-item">
245 <div class="form-item-content">
246 <input type="password" :placeholder="$t('transfer.password')" v-model="password" ref="password" autofocus>
251 <div class="btn btn-primary btn-round float-right" @click="transfer"><i class="iconfont icon-right-arrow"></i></div>
266 import transaction from "@/models/transaction";
267 import getLang from "@/assets/language/sdk";
268 import {apis} from '@/utils/BrowserApis';
269 import NotificationService from '../../services/NotificationService'
270 import {mapActions, mapGetters, mapState} from 'vuex'
271 import _ from 'lodash';
272 import account from "@/models/account";
273 import add from "@/utils/address";
274 import { camelize, removeFromArray } from "@/utils/utils";
275 import bytomjslib from 'bytomjs-lib'
276 import BigNumber from "bignumber.js"
295 if (this.prompt && this.prompt.data && this.prompt.data.title) {
296 return this.prompt.data.title.substring(0, 1)
297 } else if (this.prompt && this.prompt.domain) {
298 return this.prompt.domain.substring(0, 1)
301 address: function () {
302 if (this.netType === 'vapor') {
303 return this.currentAccount.vpAddress
305 return this.currentAccount.address
308 shortAddress: function () {
309 if(this.prompt.data && this.prompt.data.type ==='transfer') {
310 return add.short(this.transaction.from);
311 }else if(this.prompt.data && this.prompt.data.type ==='message'){
312 return add.short(this.transaction.address);
314 if (this.netType === 'vapor') {
315 return add.short(this.currentAccount.vpAddress);
317 return add.short(this.currentAccount.address);
322 if(this.prompt.data && this.prompt.data.type ==='signTransaction'){
323 const param = this.prompt.data[0] || this.prompt.data
324 const _tx = camelize(param)
325 const { rawTransaction, signingInstructions } = _tx
327 tx: this.transaction,
331 return JSON.stringify(obj, null, 2);
332 }else if(this.prompt.data && this.prompt.data.type ==='message'){
333 const {confirmations, ...Attr} = this.transaction
334 return JSON.stringify(Attr, null, 2);
336 return JSON.stringify(this.transaction, null, 2);
340 if(this.prompt.data && this.prompt.data.type ==='transfer'){
341 return this.bytom.keychain.findByAddress(this.transaction.from);
342 }else if(this.prompt.data && this.prompt.data.type ==='message'){
343 return this.bytom.keychain.findByAddress(this.transaction.address);
345 return this.currentAccount
361 return add.short(address)
363 transfer: function () {
366 this.$t('error.BTM0008')
368 this.$refs.password.focus();
371 let loader = this.$loading.show({
372 // Optional parameters
375 onCancel: this.onCancel
378 if(this.prompt.data.type ==='advTransfer'){
379 transaction.buildTransaction(this.address, this.transaction.input, this.transaction.output, this.transaction.fee, this.transaction.confirmations).then(async (result) => {
382 if (this.transaction.args) {
383 arrayData = await transaction.convertArgument(this.transaction.args)
386 return transaction.advancedTransfer(this.address, result[0], this.password, arrayData, this)
389 this.prompt.responder(resp);
391 this.$t("transfer.success")
393 NotificationService.close();
403 e = this.$t(`error.${error.code}`)
404 }else if(error.message){
405 e = getLang(error.message)
407 this.$toast.error(e);
409 } else if(this.prompt.data.type ==='transfer'){
410 transaction.transfer(this.transaction, this.password, this.address, this).then(result => {
412 this.prompt.responder(result);
414 this.$t("transfer.success")
416 NotificationService.close();
422 e = this.$t(`error.${error.code}`)
423 }else if(error.message){
424 e = getLang(error.message)
426 this.$toast.error(e);
428 } else if(this.prompt.data.type ==='signTransaction'){
429 const data = this.prompt.data.value
431 if(Array.isArray(data)){
432 Promise.all(data.map( (rawdata) => transaction.signTransaction(this.address, rawdata, this.password, this)))
435 this.prompt.responder(result);
436 this.$toast.success(this.$t("transfer.success"));
437 NotificationService.close();
442 getLang(error.message) || error.message || error
446 transaction.signTransaction(this.address, data, this.password, this).then( (result) => {
448 this.prompt.responder(result);
449 this.$toast.success(this.$t("transfer.success"));
451 NotificationService.close();
457 e = this.$t(`error.${error.code}`)
458 }else if(error.message){
459 e = getLang(error.message)
461 this.$toast.error(e);
465 } else if(this.prompt.data.type ==='message'){
466 transaction.signMessage(this.transaction.message, this.password, this.address, this).then((resp) => {
468 this.prompt.responder(resp);
470 this.$t("transfer.success")
472 NotificationService.close();
478 e = this.$t(`error.${error.code}`)
479 }else if(error.message){
480 e = getLang(error.message)
482 this.$toast.error(e);
493 queryAsset: function (assetID) {
494 return transaction.asset(assetID)
497 this.prompt = window.data || apis.extension.getBackgroundPage().notification || null;
498 console.log(this.prompt)
500 const params = this.prompt.data
501 if (params !== undefined) {
502 const data = params.value
506 if (inout.input !== undefined) {
507 this.transaction.input = inout.input
509 if (inout.output !== undefined) {
510 this.transaction.output = inout.output
512 if (inout.args !== undefined) {
513 this.transaction.args = inout.args
515 if (inout.gas !== undefined) {
516 this.transaction.fee = inout.gas
518 if (inout.confirmations !== undefined) {
519 this.transaction.confirmations = inout.confirmations
522 const array = inout.input.filter(action => action.type === 'spend_wallet')
524 if (array.length > 0) {
525 account.setupNet(`${this.net}${this.netType}`)
529 .map((objs, key) => {
530 return this.queryAsset(key).then(resp => {
533 'alias': resp.symbol,
534 'amount': _.sumBy(objs, 'amount')
540 Promise.all(promise).then(function (output) {
541 that.transaction.amounts = output
542 this.dataReady = true
544 this.dataReady = true
551 if (data.from != undefined) {
552 this.transaction.from = data.from
554 if (data.asset != undefined) {
555 this.transaction.asset= data.asset
557 if (data.to != undefined) {
558 this.transaction.to = data.to
560 if (data.amount != undefined) {
561 this.transaction.amount = data.amount
564 if(data.confirmations != undefined) {
565 this.transaction.confirmations = data.confirmations
568 const asset_amounts ={}
569 asset_amounts[data.asset] = data.amount
571 transaction.estimateFee( data.from, asset_amounts).then( (resp) =>{
572 this.transaction.fee = resp.fee
573 this.queryAsset(data.asset).then(resp => {
574 this.unit = resp.symbol
575 this.dataReady = true
581 this.dataReady = true
585 case "signTransaction":{
586 const param = data[0] || data
587 const _tx = camelize(param)
588 const rawTransaction = _tx.rawTransaction
590 const tx = this.netType === 'vapor'?
591 bytomjslib.vapor.Transaction.decodeRawTransaction(rawTransaction):
592 bytomjslib.bytom.Transaction.decodeRawTransaction(rawTransaction)
594 this.transaction.fee = tx.fee/100000000
595 this.transaction.input = tx.inputs
596 this.transaction.output = tx.outputs
598 const inputs = tx.inputs.filter(i => i.address === this.address)
599 const outputs = tx.outputs.filter(i => i.address === this.address)
600 const inputAsset = inputs.map(i => i.assetID);
601 const outputAsset = outputs.map(i => i.assetID);
603 const asset = _.union(inputAsset, outputAsset)
606 let types = ["transfer"]
610 return this.queryAsset(assetId).then(resp =>{
611 const assetInput = inputs.filter(i => i.assetID ===assetId)
612 const assetOutput = outputs.filter(o => o.assetID ===assetId)
613 const inputAmount = new BigNumber(_.sumBy(assetInput, 'amount'))
614 const outputAmount = new BigNumber(_.sumBy(assetOutput, 'amount'))
616 const decimals = resp.decimals
617 const amount = inputAmount.minus(outputAmount)
619 const balanced_outputs = tx.outputs.find( o => o.amount === amount.toNumber())
620 if(balanced_outputs.type == 'cross_chain_out'){
621 that.transaction.types = (that.$t('common.cross_chain'));
626 'alias': resp.symbol,
627 'amount': amount.shiftedBy(-decimals).toString()
632 const inputType = inputs.map(i => i.type);
633 const outputType = outputs.map(o => o.type);
634 types = _.union(inputType, outputType, types);
636 const remove = ['spend','control'];
637 if(inputs[0].amount ===outputs[0].amount){
638 const isVeto = inputs.find(o => o.type ==='veto')
639 const isVote = outputs.find(o => o.type ==='vote')
640 if(isVeto || isVote){
641 remove.push('transfer')
644 types = removeFromArray(types, remove);
645 types = types.map(ty => this.$t(`common.${ty}`)).join(', ');
647 this.transaction.types = types
649 Promise.all(promise).then(function(output) {
650 that.transaction.amounts = output
651 that.dataReady = true
653 that.dataReady = true
659 if(data.address !== undefined){
660 this.transaction.address = data.address;
662 if(data.message !== undefined){
663 this.transaction.message = data.message
666 this.dataReady = true